/* ============================================
   Dashboard (/dashboard/) styles
   Split out of global.css; loaded after it by includes/header.php
   on this page only. Rules keep their original relative order.
   ============================================ */

/* ============================================
   DASHBOARD
   ============================================ */

/* --- Dashboard: Panel variants --- */
/* Character details: the whole character, over a glow in the class color.
   The frame fills the column (columns change with the account count) and
   is 3/4 as tall as it is wide, between 260 and 380px; the render is sized by the
   frame's height and centered, so it never stretches with a wide column.
   Renders are 1600x1200 with the feet at y≈980; this shows y 250-990. */
.character-media:has(.media-full) {
    container-type: inline-size;
}

.character-media .media-full {
    --tint: var(--color-primary);
    position: relative;
    width: 100%;
    /* 3/4 of the column's width, between 260 and 380px. (Not aspect-ratio:
       with a min height it would demand a minimum width and widen the column.) */
    height: clamp(260px, 75cqi, 380px);
    overflow: hidden;
    border-radius: var(--radius-md);
    background:
        radial-gradient(45% 60% at 50% 88%, color-mix(in srgb, var(--tint) 34%, transparent), transparent 70%),
        rgba(255, 255, 255, 0.03);
}

.character-media .media-full img {
    position: absolute;
    top: -33.78%;       /* 250 of the render's 740 visible rows */
    left: 50%;
    width: auto;
    height: 162.16%;    /* 1200 / 740 */
    max-width: none;
    border-radius: 0;
    transform: translateX(-50.6%);   /* the body sits a touch left of the render's center */
}

.character-tile[data-class="Death Knight"] .media-full { --tint: var(--class-death-knight); }
.character-tile[data-class="Demon Hunter"] .media-full { --tint: var(--class-demon-hunter); }
.character-tile[data-class="Druid"] .media-full { --tint: var(--class-druid); }
.character-tile[data-class="Evoker"] .media-full { --tint: var(--class-evoker); }
.character-tile[data-class="Hunter"] .media-full { --tint: var(--class-hunter); }
.character-tile[data-class="Mage"] .media-full { --tint: var(--class-mage); }
.character-tile[data-class="Monk"] .media-full { --tint: var(--class-monk); }
.character-tile[data-class="Paladin"] .media-full { --tint: var(--class-paladin); }
.character-tile[data-class="Priest"] .media-full { --tint: var(--class-priest); }
.character-tile[data-class="Rogue"] .media-full { --tint: var(--class-rogue); }
.character-tile[data-class="Shaman"] .media-full { --tint: var(--class-shaman); }
.character-tile[data-class="Warlock"] .media-full { --tint: var(--class-warlock); }
.character-tile[data-class="Warrior"] .media-full { --tint: var(--class-warrior); }


@media (max-width: 959px) {
    /* The header stacks and centers here; keep the flag centered with it */
    .panel-status .status-meta:has(> .demo-flag) { align-items: center; }
}

/* Floating sign-in for the signed-out sample (layout.js boot.demoSigninBar):
   hidden above the viewport until the intro has scrolled away. */
.demo-signin-bar {
    position: fixed;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    z-index: 10000;
    width: min(760px, calc(100% - 24px));
    transform: translate(-50%, calc(100% + 24px));
    opacity: 0;
    visibility: hidden;
    transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease, visibility 0s linear 0.45s;
}

.demo-signin-bar.is-visible {
    transform: translate(-50%, 0);
    opacity: 1;
    visibility: visible;
    transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease, visibility 0s;
}

.demo-signin-bar__inner {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 10px 10px 10px 20px;
    border: 1px solid rgba(39, 170, 226, 0.45);
    border-radius: 14px;
    background: rgba(8, 12, 20, 0.97);
    box-shadow: 0 -8px 40px -12px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(0, 0, 0, 0.4);
}

.demo-signin-bar__text {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.4;
    color: var(--color-text-light);
}

.demo-signin-bar__text strong {
    color: var(--color-text-light);
    font-weight: 600;
}

.demo-signin-bar .dash-intro__cta {
    flex: none;
    padding: 11px 20px;
    font-size: 0.95rem;
}

/* This smaller button centers its label without the 1px lift the bigger
   CTAs use (measured at 3x: the lift left the text ~1px high here), and
   its icon sits half a pixel low to match */
.demo-signin-bar .dash-intro__cta .btn-label {
    top: 0;
}

.demo-signin-bar .dash-intro__cta img {
    transform: translateY(0.5px);
}

.demo-signin-bar__close {
    display: grid;
    place-items: center;
    flex: none;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
}

.demo-signin-bar__close:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--color-text-light);
}

.demo-signin-bar__close svg {
    width: 16px;
    height: 16px;
}

@media (prefers-reduced-motion: reduce) {
    .demo-signin-bar,
    .demo-signin-bar.is-visible {
        transition: opacity 0.2s ease, visibility 0s;
    }
}

@media (max-width: 640px) {
    .demo-signin-bar__inner {
        padding: 10px 8px 10px 14px;
        gap: 10px;
    }
    /* Keep it to one line: the button says it all */
    .demo-signin-bar__text {
        display: none;
    }
    .demo-signin-bar .dash-intro__cta {
        flex: 1 1 auto;
        justify-content: center;
    }
}

/* Read-only: hide every control that would change or re-fetch data */
.is-demo .account-edit-icon,
.is-demo .account-edit-form,
.is-demo #btn-reorder-accounts,
.is-demo #btn-reorder-accounts-reserved,
.is-demo #btn-batch-check-reserved {
    display: none !important;
}

.is-demo .account-label-group {
    cursor: default;
}

.panel-status .panel-header { flex-wrap: wrap; }

.refresh-progress { margin-top: 12px; }
.status-error strong {
    display: block;
    margin-bottom: 6px;
    color: #f99;
}
.status-error ul {
    margin: 0;
    padding-left: 20px;
}
.status-error li {
    margin: 2px 0;
}

/* --- Dashboard: Stats loading --- */
.panel-stats-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 150px;
}

.stats-loading-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-sm);
}

.stats-loader-spinner {
    width: 32px;
    height: 32px;
    animation: spin 1s linear infinite;
}
.stat-wide { width: 100%; }
.stats-row.stats-row-classes { display: block; margin-top: 30px; }

.stat-favorite-content {
    display: flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
}

.stat-favorite-content .class-icon { width: 20px; height: 20px; margin-top: 3px; }
.stat-favorite-content .faction-icon { width: 20px; height: 20px; }
.stat-favorite-content .stat-icon { width: 20px; height: 20px; }

.stat.achievements .achievements-icon {
    width: 20px; height: 20px;
    filter: brightness(0) saturate(100%) invert(73%) sepia(97%) saturate(567%) hue-rotate(358deg) brightness(101%) contrast(96%);
}
.stat.horde .stat-favorite-content { gap: 5px; }

/* --- Dashboard: Class chips --- */
.stat-classes {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
    margin-top: 8px;
}

.class-details {
    flex: 100%;
    gap: 5px;
    align-items: center;
    display: flex;
    justify-content: center;
}

.class-details img { margin-top: 2px; }

/* --- Dashboard: Spec overview --- */
.spec-overview { display: flex; flex-direction: column; align-items: center; }
.spec-details { align-items: center; gap: 5px; justify-content: center; display: flex; }
.spec-icon { width: 16px; height: 16px; }
.spec-name { display: none; }
.active .spec-name { display: block; }
.spec-count { color: #ddd; }
.spec-characters { display: none; flex-direction: column; align-items: center; }


.filter-group label {
    color: #ddd;
    display: block;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 0.75;
    margin-bottom: 4px !important;
}

.filter-group input, .filter-group select {
    background: var(--color-bg-input);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-input);
    color: #fff;
    padding: 6px 10px;
    min-height: 36px;
    font-size: 0.9rem;
    width: 100%;
}

.filter-group select[multiple] { min-height: 100px; padding: 6px 8px; }

/* Touch devices: tappable stand-in for <select multiple> (touch-select.js).
   The real select stays in the DOM, hidden, and holds the selection. */
select.touch-multi-source { display: none !important; }
.touch-multi {
    display: flex;
    flex-direction: column;
    max-height: 220px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 4px;
    border: 1px solid var(--color-border-input);
    border-radius: var(--radius-md);
    background: var(--color-bg-input);
}
.touch-multi__opt {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 40px;
    padding: 8px 10px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    font: inherit;
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
}
/* Zero specificity so the class-color classes (.death-knight, …) still win */
:where(.touch-multi__opt) { color: var(--color-text-light); }
.touch-multi__opt::before {
    content: '';
    flex: none;
    width: 16px;
    height: 16px;
    border-radius: 4px;
    border: 2px solid rgba(255, 255, 255, 0.3);
}
.touch-multi__opt[aria-pressed="true"] { background: rgba(39, 170, 226, 0.14); }
.touch-multi__opt[aria-pressed="true"]::before {
    border-color: var(--color-primary);
    background: var(--color-primary);
    box-shadow: inset 0 0 0 2px var(--color-bg-input);
}
/* Class/Race/Profession: fill the column down to the bottom of the filters row */
.touch-multi__opt.filter-spec-option { padding-left: 28px; font-size: 0.85rem; }
.touch-multi__opt:disabled { opacity: 0.4; cursor: default; }

/* --- Dashboard: Level range slider --- */
.filter-group.filter-level-range { display: flex; flex-direction: column; gap: 0.25rem; }
#level-range-slider { margin: 0.75rem 0 0.25rem; }
#level-range-slider.ui-slider { position: relative; height: 0.5rem; border-radius: var(--radius-full); background: rgba(255, 255, 255, 0.12); border: none; }
#level-range-slider .ui-slider-range { background: var(--color-primary); border-radius: var(--radius-full); }
#level-range-slider .ui-slider-handle { top: 50%; transform: translate(-50%, -50%); width: 1rem; height: 1rem; border-radius: 50%; border: 2px solid var(--color-primary); background: #0f1722; cursor: pointer; box-shadow: none; }
#level-range-slider .ui-slider-handle:focus-visible { outline: 2px solid #ffffff; outline-offset: 2px; }

/* --- Dashboard: Accounts grid --- */
.accounts-grid { display: grid; gap: 10px; grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Desktop: size columns by how many accounts are showing (5+ stays 4-wide).
   4 → 2×2, 3 → thirds, 2 → halves, 1 → half width. Counted live with :has(),
   so hiding an account re-flows the grid. Tablet/phone breakpoints below win. */
@media (min-width: 1151px) {
    .accounts-grid:has(> .account-column:nth-child(4):last-child),
    .accounts-grid:has(> .account-column:nth-child(2):last-child),
    .accounts-grid:has(> .account-column:only-child) {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .accounts-grid:has(> .account-column:nth-child(3):last-child) {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.account-column {
    background: var(--color-bg-dark);
    border-radius: 10px;
    padding: 10px;
    border: 1px solid var(--color-border-light);
    min-height: 60px;
}

.account-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.03);
    gap: 8px;
}
.account-header h3:focus { box-shadow: 0 0 0 1px var(--color-primary); }

/* Account label with edit icon */
.account-label-group {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
}

.account-edit-icon {
    width: 14px;
    height: 14px;
    opacity: 0.5;
    transition: opacity var(--transition-normal), filter var(--transition-normal);
    filter: brightness(0) invert(1); /* white */
}

.account-label-group:hover .account-edit-icon {
    opacity: 1;
    filter: brightness(0) saturate(100%) invert(62%) sepia(93%) saturate(456%) hue-rotate(161deg) brightness(95%) contrast(87%); /* --color-primary #27aae2 */
}

/* Account edit mode */
.account-edit-form {
    display: none;
    align-items: center;
    gap: 8px;
    flex: 1;
}

.account-header.editing .account-label-group,
.account-header.editing .account-faction-summary { display: none; }
.account-header.editing .account-edit-form { display: flex; }

.account-edit-input {
    flex: 1;
    min-width: 0;
    padding: 6px 10px;
    font-size: 0.9rem;
    font-family: inherit;
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    color: var(--color-text-light);
    outline: none;
}

.account-save-icon {
    width: 18px;
    height: 18px;
    cursor: pointer;
    transition: filter var(--transition-normal);
    filter: brightness(0) saturate(100%) invert(68%) sepia(52%) saturate(405%) hue-rotate(51deg) brightness(95%) contrast(89%); /* --color-success #80c342 */
}

.account-hide-icon,
.account-show-icon {
    width: 18px;
    height: 18px;
    cursor: pointer;
    transition: filter var(--transition-normal);
    filter: brightness(0) invert(1); /* white */
}

.reorder-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.reorder-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    cursor: grab;
    transition: background var(--transition-normal), border-color var(--transition-normal);
}

.reorder-item.drag-over {
    border-color: var(--color-primary);
    background: rgba(39, 170, 226, 0.05);
}

.reorder-handle {
    color: var(--color-text-muted);
    font-size: 1.2rem;
    cursor: grab;
}

.reorder-label {
    flex: 1;
    font-size: 0.9rem;
    text-transform: uppercase;
}

.reorder-position {
    color: var(--color-text-muted);
    font-size: 0.8rem;
    min-width: 20px;
    text-align: right;
}

.account-faction-summary, .server-faction-summary {
    display: flex;
    align-items: center;
    font-size: 0.8rem;
    opacity: 0.9;
    margin: 0;
    padding: 0;
}

.panel-reserved .server-faction-summary { display: none; }
.panel-reserved .server-header .server-label { flex: 100%; }
#btn-batch-check-reserved { display: none; }

/* Hidden Accounts Panel */
.panel-hidden .server-faction-summary { display: none; }
.panel-hidden .server-header .server-label { flex: 100%; }

.hidden-tile {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    background: rgba(255, 255, 255, 0.02);
    border-radius: var(--radius-sm);
}

.hidden-name { flex: 1; }
.hidden-level {
    font-size: 0.79rem;
    color: var(--color-text-muted);
}

.hidden-tile .character-name {
    font-size: 0.79rem;
}

.account-faction-breakdown, .server-faction-breakdown {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
}

.account-faction-summary .faction-icon, .server-faction-summary .faction-icon {
    height: 16px;
    width: auto;
}

.account-total-label, .server-total-label, .account-total-count, .server-total-count {
    color: var(--color-success);
    font-weight: 600;
}

/* --- Dashboard: Server groups --- */
.server-group { display: flex; flex-direction: column; gap: 10px; }

.server-header {
    padding: 0.5rem 0.75rem;
    border-radius: 6px;
    background: rgba(255,255,255,0.03);
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 10px 0 0 0;
}

.server-header .server-label { font-size: 0.75rem; text-transform: uppercase; margin: 0; }

/* --- Dashboard: Character list --- */
.character-list { display: flex; flex-direction: column; gap: 8px; }

.character-tile {
    background: rgba(255,255,255,0.03);
    border-radius: var(--radius-md);
    padding: 0.5rem 0.75rem;
    cursor: pointer;
    transition: background var(--transition-fast);
    overflow: hidden;
}

.character-tile:hover { background: var(--color-bg-hover); }
.character-tile.inactive .char-loader { display: flex; }
.character-tile.inactive .char-faction { display: none; }

.character-header { display: flex; justify-content: space-between; align-items: center; gap: 6px; margin-bottom: 4px; }
.character-name { font-size: 0.95rem; margin: 0; }
.character-meta { font-size: 0.75rem; opacity: 0.8; display: flex; gap: 6px; }
.character-summary { font-size: 0.75rem; opacity: 0.9; display: flex; flex-direction: column; gap: 4px; }
.character-summary-top, .character-summary-profs, .character-summary-gold { display: flex; flex-wrap: wrap; gap: 6px; }

.character-class, .character-race, .character-profs, .character-gold, .character-gender {
    padding: 2px 6px;
    border-radius: var(--radius-full);
    background: rgba(255,255,255,0.04);
}

/* --- Dashboard: Character tile (WoW-style) --- */
.char-tile {
    display: flex;
    align-items: stretch;
    padding: 0.75rem 1rem;
    background: #111820;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,0.15);
    gap: 1%;
    flex-wrap: wrap;
}

.char-main { flex: 84%; }
.char-faction img.faction-icon { max-height: 40px; max-width: 100%; width: auto; }
.reserved-tile .character-name { font-size: 0.79rem; }
.char-faction, .char-loader { flex: 14%; display: flex; justify-content: center; align-items: center; }
.char-loader { display: none; }

.character-details {
    flex: 100%;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
    margin-top: 15px;
    padding-top: 15px;
    font-size: 0.85rem;
}
.guild span:first-of-type, .spec-label, .ilvl span:first-of-type, .profession span:first-of-type, .mythic span:first-of-type { color: #ddd; opacity: 0.7; }
.spec { display: flex; gap: 5px; align-items: center; width: 100%; order: 0; }
.guild { width: 100%; order: 2; }
.guild a:hover, .guild a:focus { text-decoration: underline; }
.spec-label { color: #ddd; }
.ilvl { color: #ddd; width: 100%; order: 1; }
.profession { color: #ddd; width: 100%; order: 3; }
.mythic { color: #ddd; width: 100%; order: 4; }

.char-name { display: inline-block; font-size: 1.05rem; font-weight: 600; color: var(--color-wow-gold); text-decoration: none; }
.char-name:hover { text-decoration: underline; }
.char-level-class { margin-top: 0.15rem; font-size: 0.9rem; }
.char-level-label { color: #ddd; margin-right: 0; }
.char-level-value { color: #ddd; margin-right: 0; }
.char-class-name { font-weight: 600; }
.char-line { margin-top: 0.15rem; font-size: 0.85rem; }
.char-race-gender { display: flex; align-items: center; }
.char-race-gender .gender-icon.female { width: 15px; height: 15px; }
.char-race { color: #ddd; }
.char-guild-link { color: #ddd; text-decoration: none; }
.char-guild-link:hover { text-decoration: underline; }

.char-title { display: none; font-size: 0.75rem; color: var(--color-wow-gold); }
.character-tile.expanded .char-title { display: block; }
.char-title.no-title { color: #888; }
.media-avatar, .media-main { display: none; }

.reserved-tile { cursor: default; }
.reserved-tile .character-header { justify-content: flex-start; }

/* --- Dashboard: Collection grids (Mounts, Pets, Toys) --- */
.mounts-filters-row, .pets-filters-row, .toys-filters-row {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin-bottom: 15px;
    padding-bottom: 15px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
}

.mounts-grid, .pets-grid, .toys-grid {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

.pet-card, .toy-card {
    background: var(--color-bg-dark);
    border-radius: 10px;
    padding: 12px;
    border: 1px solid var(--color-border-light);
    display: flex;
    gap: 12px;
}

.mount-card.is-favorite, .pet-card.is-favorite, .toy-card.is-favorite { border-color: rgba(255, 215, 0, 0.3); }
.pet-card.unowned, .toy-card.unowned { opacity: 0.5; }
.pet-card.unowned:hover,
.pet-card.unowned:focus,
.toy-card.unowned:hover,
.toy-card.unowned:focus { opacity: 1; }
.mount-card.unknown-source, .pet-card.unknown-source, .toy-card.unknown-source { display: none; }

.pet-card > a, .toy-card > a {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    display: block;
    background: #1a1f2e url('/img/ui/icon-missing.svg') center center no-repeat;
    background-size: 20px 20px;
    border-radius: 6px;
}

.mount-icon, .pet-icon, .toy-icon { width: 40px; height: 40px; border-radius: 6px; display: block; background: var(--color-bg); }
.mount-icon[src=""], .pet-icon[src=""], .toy-icon[src=""],
.mount-icon:not([src]), .pet-icon:not([src]), .toy-icon:not([src]) { visibility: hidden; }
/* Hide alt text on broken images */
.mount-icon, .pet-icon, .toy-icon { color: transparent; text-indent: -9999px; overflow: hidden; }

.mount-content, .pet-content, .toy-content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.mount-header, .pet-header, .toy-header { display: flex; align-items: flex-start; gap: 6px; }

.pet-name, .toy-name {
    font-weight: 600;
    font-size: 0.95rem;
    color: #fff;
    text-decoration: none;
}

.pet-name:hover, .toy-name:hover { text-decoration: underline; }
.mount-favorite, .pet-favorite, .toy-favorite { color: gold; margin-left: auto; }

.mount-faction-icon { width: 16px; height: 16px; margin-top: 5px; }
.mount-faction-icon.horde { filter: brightness(0) saturate(100%) invert(23%) sepia(96%) saturate(2641%) hue-rotate(347deg) brightness(87%) contrast(92%); }

.mount-description, .pet-description { font-size: 0.8rem; color: rgba(255,255,255,0.6); line-height: 1.3; padding-bottom: 10px; }
.toy-source { font-size: 0.8rem; color: rgba(255,255,255,0.6); margin-top: auto; }
.pet-source { font-size: 0.75rem; color: rgba(255,255,255,0.5); margin-top: auto; }

.mounts-grid .loading-message, .pets-grid .loading-message, .toys-grid .loading-message {
    grid-column: 1 / -1;
    text-align: center;
    padding: 20px;
    color: rgba(255,255,255,0.5);
}

.toy-content { gap: 5px; }
.header-count { font-size: 0.7em; font-weight: 400; opacity: 0.7; }

/* --- Dashboard: Pets specific --- */
.pet-family-icon { width: 20px; height: 20px; flex-shrink: 0; }
.pet-family-icon[title="Dragonkin"] { margin-top: 1px; }
.pet-family-icon[title="Mechanical"] { margin-top: 2px; }
.pet-family-icon[title="Humanoid"] { margin-top: 1px; }
.pet-family-icon[title="Undead"] { margin-top: 2px; }
.pet-family-icon[title="Flying"] { margin-top: 1px; }
.pet-family-icon[title="Magic"] { margin-top: 1px; }
.pet-family-icon[title="Aquatic"] { margin-top: 1px; }
.pet-family-icon[title="Critter"] { margin-top: 1px; }

.pet-details { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.pet-tag { font-size: 0.7rem; padding: 2px 6px; border-radius: 4px; }
.pet-tag.positive { background: rgba(25, 244, 105, 0.15); color: #19f469; }
.pet-tag.negative { background: rgba(244, 67, 54, 0.15); color: #f44336; }

/* --- Dashboard: Race/Class combos --- */
.panel-combos .combos-textarea {
    display: none;
    width: 100%;
    min-height: 220px;
    margin-top: 10px;
    margin-bottom: 15px;
    padding: 8px;
    border-radius: 6px;
    border: 1px solid rgba(255,255,255,0.2);
    background: rgba(0, 0, 0, 0.35);
    color: #fff;
    font-size: 0.8rem;
    font-family: Menlo, Monaco, Consolas, monospace;
    resize: vertical;
}

.hover-tooltip {
    position: absolute;
    z-index: 9999;
    background: #1f3d1f;
    border: 1px solid var(--color-success);
    color: #e6ffe6;
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 0.8rem;
    pointer-events: none;
    box-shadow: 0 2px 6px rgba(0,0,0,0.4);
    white-space: nowrap;
    display: none;
    transition: opacity 0.2s ease;
}

/* --- Dashboard: Section navigation --- */
.panel-section-nav .panel-body { padding-top: 12px; padding-bottom: 12px; }

.section-nav-links {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
    align-items: center;
    text-align: center;
}

.section-nav-links a {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    display: inline-block;
    padding: 5px;
    border-radius: var(--radius-full);
    font-size: 0.95rem;
    text-decoration: none;
    cursor: pointer;
}

.section-nav-links a:hover, .section-nav-links a:focus-visible {
    background-color: var(--color-primary);
    color: #000;
}

.panel-section-nav {
    display: none;
    background: rgba(8, 12, 20, 1.0);
    position: sticky;
    top: 0;
    z-index: 9999;
    padding: 0 20px;
}

/* --- Dashboard: Collapsible panels --- */
.panel-collapsible .panel-collapsible-content { display: none; }
.panel-collapsible .panel-header { padding-bottom: 0; }
.panel-collapsible.is-expanded .panel-header { padding-bottom: 1rem; }
.panel-collapsible.is-expanded .panel-collapsible-content { display: block; }
.panel-collapsible .btn-collapse { display: none; }
.panel-collapsible.is-expanded .btn-collapse { display: inline-flex; }
.panel-collapsible.is-expanded .btn-expand { display: none; }

@media (max-width: 1150px) {
    .mounts-filters-row, .pets-filters-row, .toys-filters-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    
    .accounts-grid, .mounts-grid, .pets-grid, .toys-grid,
    .stat-classes, .combo-class-list, .duplicates-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .panel-stats .stats-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    
    .section-nav-links {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 1100px) and (min-width: 960px) {
    /* Stack title and buttons for non-collapsible panels */
    .panel-header-accounts,
    .panel-header-reserved {
        flex-wrap: wrap;
    }

    .panel-header-accounts h2,
    .panel-header-reserved h2 {
        width: 100%;
        margin-bottom: 10px;
    }

    .panel-header-accounts .panel-header-actions,
    .panel-header-reserved .panel-header-actions {
        margin-left: 0;
        width: 100%;
    }

    .panel-header-accounts .panel-header-actions .btn,
    .panel-header-reserved .panel-header-actions .btn {
        flex: 1;
    }

    /* Collapsible panels with multiple buttons: stack when expanded */
    .panel-combos.is-expanded .panel-header,
    .panel-mounts.is-expanded .panel-header,
    .panel-pets.is-expanded .panel-header,
    .panel-toys.is-expanded .panel-header {
        flex-wrap: wrap;
    }

    .panel-combos.is-expanded .panel-header h2,
    .panel-mounts.is-expanded .panel-header h2,
    .panel-pets.is-expanded .panel-header h2,
    .panel-toys.is-expanded .panel-header h2 {
        width: 100%;
        margin-bottom: 10px;
    }

    .panel-combos.is-expanded .panel-header-actions,
    .panel-mounts.is-expanded .panel-header-actions,
    .panel-pets.is-expanded .panel-header-actions,
    .panel-toys.is-expanded .panel-header-actions {
        margin-left: 0;
        width: 100%;
    }

    .panel-combos.is-expanded .panel-header-actions .btn,
    .panel-mounts.is-expanded .panel-header-actions .btn,
    .panel-pets.is-expanded .panel-header-actions .btn,
    .panel-toys.is-expanded .panel-header-actions .btn {
        flex: 1;
    }
}

@media (max-width: 959px) {
    .mounts-filters-row,
    .pets-filters-row,
    .toys-filters-row,
    .accounts-grid,
    .mounts-grid,
    .pets-grid,
    .toys-grid,
    .stat-classes,
    .combo-class-list,
    .duplicates-list,
    .panel-stats .stats-row,
    .section-nav-links {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    #btn-refresh-data,
    #btn-reset-filters {
        width: 100%;
    }

    .pet-card,
    .toy-card {
        flex-direction: column;
        text-align: center;
        align-items: center;
    }

    .mount-favorite,
    .pet-favorite,
    .toy-favorite {
        margin-left: 0;
    }

    .pet-details {
        justify-content: center;
    }
}

@media (max-width: 640px) {
    .panel-combos .combos-columns { grid-template-columns: 1fr; }
    .mounts-filters-row,
    .pets-filters-row,
    .toys-filters-row,
    .accounts-grid,
    .mounts-grid,
    .pets-grid,
    .toys-grid,
    .stat-classes,
    .combo-class-list,
    .duplicates-list,
    .panel-stats .stats-row,
    .section-nav-links {
        grid-template-columns: 1fr;
    }
    .combo-race-title { text-align: center; }
    .toy-content { gap: 4px; }
    .mount-description, .pet-description { padding-bottom: 0; }
    .spec-details { flex-direction: column; }
}

@media (max-width: 350px) {
    .combo-faction-row, .account-header, .server-header { flex-direction: column; gap: 8px; }
    .account-header h3 { margin: 0; }
}

@media (max-width: 299px) {
    .character-dashboard .panel { padding: 5%; }
    .stats-row { text-align: center; }
    .stat-favorite-content { flex-direction: column; gap: 2px; }
    .char-tile { align-items: center; text-align: center; gap: 15px; }
    .char-main, .char-faction, .char-loader { flex: 100%; max-width: 100%; }
    .character-name { text-align: center; }
    .class-name, .spec-name { display: none; }
    .guild, .spec, .ilvl, .profession { justify-content: center; width: 100%; }
    .character-race,
    .character-profs,
    .character-gold,
    .character-gender,
    .combo-gender-flag,
    #level-range-slider.ui-slider,
    #level-range-slider .ui-slider-range,
    .section-nav-links a { border-radius: var(--radius-md); }
}

@media (max-width: 959px) {
    .mount-favorite,
    .pet-favorite,
    .toy-favorite {
        width: 100%;
    }
    
    .mount-header,
    .pet-header,
    .toy-header {
        flex-direction: column;
        align-items: center;
    }
    
    #refresh-progress {
        text-align: center;
    }
    
    .header-count {
        display: block;
    }
    
    .view-as-select {
        max-width: none;
    }
    
    .character-dashboard .panel-header {
        text-align: center;
        align-content: center;
        justify-content: center;
    }

    .status-item {
        text-align: center;
    }
    
    .status-meta {
        flex-direction: column;
        align-items: flex-start;
    }
    
    .status-meta {
        order: 3;
        margin-left: 0;
        width: 100%;
        flex-wrap: wrap;
    }
}

/* Session-expired sign-in link in the refresh progress text (refresh.js) */
.refresh-progress .refresh-signin-link {
    color: var(--color-primary);
    font-weight: 600;
    text-decoration: underline;
}

/* Keyboard focus on character tiles (tabindex="0"; Enter/Space toggles details) */
.character-tile[tabindex]:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* ==========================================================================
   Account Overview hero (#dashboard-status)
   Themed by faction: data-faction="alliance" leans blue, "horde" leans red.
   The theme is saved per player (layout.json faction_theme, save-config.php)
   and defaults to whichever faction has more characters. Both themes' glows
   and crests are always in the DOM and crossfade, so a toggle never flashes.
   ========================================================================== */
.dash-overview {
    --alliance-rgb: 72, 146, 255;
    --horde-rgb: 232, 52, 44;
    --faction-rgb: var(--alliance-rgb);
    --faction-ink: #9cc4ff;
    position: relative;
    isolation: isolate;
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    grid-template-areas: "copy art";
    padding: 0;
    overflow: hidden;
    border-color: rgba(var(--faction-rgb), 0.3);
    transition: border-color 0.6s ease;
}

.dash-overview[data-faction="horde"] {
    --faction-rgb: var(--horde-rgb);
    --faction-ink: #ff9a8f;
}

/* Two glow layers, one per faction, crossfaded. A fixed height anchored to the
   top: opening the class breakdown makes the panel taller, and glows sized in
   percent of the whole panel would stretch and jump when it does. */
.dash-overview::before,
.dash-overview::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 760px;
    z-index: -1;
    pointer-events: none;
    transition: opacity 0.6s ease;
}

.dash-overview::before {
    background:
        radial-gradient(60% 58% at 74% 58%, rgba(var(--alliance-rgb), 0.24), transparent 70%),
        radial-gradient(40% 45% at 100% 0%, rgba(var(--alliance-rgb), 0.12), transparent 70%),
        radial-gradient(35% 40% at 0% 0%, rgba(var(--alliance-rgb), 0.07), transparent 70%);
}

.dash-overview::after {
    opacity: 0;
    background:
        radial-gradient(60% 58% at 74% 58%, rgba(var(--horde-rgb), 0.24), transparent 70%),
        radial-gradient(40% 45% at 100% 0%, rgba(var(--horde-rgb), 0.12), transparent 70%),
        radial-gradient(35% 40% at 0% 0%, rgba(var(--horde-rgb), 0.07), transparent 70%);
}

.dash-overview[data-faction="horde"]::before { opacity: 0; }
.dash-overview[data-faction="horde"]::after { opacity: 1; }

/* A huge faint crest behind the line-up (the SVGs are solid black, so they work
   as masks). It lives in the art box, pinned to its top and centered over the
   characters, so it stays behind them whatever height the copy gives the hero. */
.dash-overview__crest {
    position: absolute;
    top: 78px;          /* clear of the Line-up / Sample / View as pills */
    left: 50%;
    z-index: -1;
    height: calc(100% - 78px);
    max-height: 440px;
    aspect-ratio: 4 / 5;
    transform: translateX(-50%);
    opacity: 0;
    pointer-events: none;
    -webkit-mask: var(--crest) center / contain no-repeat;
    mask: var(--crest) center / contain no-repeat;
    transition: opacity 0.6s ease;
}

.dash-overview__crest--alliance {
    --crest: url("/img/ui/alliance.svg");
    background: linear-gradient(180deg, rgba(var(--alliance-rgb), 1), rgba(var(--alliance-rgb), 0.2));
}

.dash-overview__crest--horde {
    --crest: url("/img/ui/horde.svg");
    background: linear-gradient(180deg, rgba(var(--horde-rgb), 1), rgba(var(--horde-rgb), 0.2));
}

.dash-overview[data-faction="alliance"] .dash-overview__crest--alliance,
.dash-overview[data-faction="horde"] .dash-overview__crest--horde {
    opacity: 0.1;
}

/* Sample flag and the admin's view-as select, top right over the art */
.dash-overview__meta {
    position: absolute;
    top: 18px;
    right: 20px;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 10px;
}

.dash-overview__meta:empty { display: none; }

/* Line-up picker: which five characters stand in the art */
.lineup-sort {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 4px 4px 4px 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 9999px;
    background: rgba(5, 9, 16, 0.72);
    font-size: 0.78rem;
    cursor: pointer;
}

.lineup-sort__label {
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.panel .lineup-sort select {
    width: auto;
    min-height: 0;
    height: 28px;
    padding: 0 26px 0 10px;
    border: 0;
    border-radius: 9999px;
    background-color: rgba(255, 255, 255, 0.06);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--color-text-light);
    cursor: pointer;
}

/* Line-up picker + shuffle button */
.lineup-pick {
    display: flex;
    align-items: center;
    gap: 6px;
}

.lineup-shuffle {
    display: grid;
    flex: none;
    place-items: center;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 50%;
    background: rgba(5, 9, 16, 0.72);
    color: var(--color-text-light);
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}

.lineup-shuffle:hover {
    border-color: rgba(var(--faction-rgb), 0.55);
    background: rgba(var(--faction-rgb), 0.16);
}

.lineup-shuffle svg {
    width: 18px;
    height: 18px;
}

.lineup-shuffle.is-rolling svg {
    animation: lineup-roll 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes lineup-roll {
    from { transform: rotate(-180deg) scale(0.7); }
    to { transform: rotate(0) scale(1); }
}

.panel .lineup-sort .view-as-select {
    max-width: 180px;
}

/* The open list: desktop browsers draw it from the select's own colors, and
   the see-through background above left white text on a white list. A dark
   color scheme plus solid option colors fix it (iPad uses its own picker). */
.panel .lineup-sort select {
    color-scheme: dark;
}

.panel .lineup-sort select option,
.panel .lineup-sort select optgroup {
    background-color: #111723;
    color: var(--color-text-light);
}

.panel .lineup-sort select optgroup {
    color: var(--color-text-muted);
    font-style: normal;
}

.panel .lineup-sort select:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

.dash-overview__copy {
    grid-area: copy;
    position: relative;
    z-index: 2;
    padding: 28px 12px 30px 20px;
}

.dash-overview__eyebrow {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 8px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--faction-ink);
    transition: color 0.6s ease;
}

.dash-overview__eyebrow .viewing-as {
    margin: 0;
    letter-spacing: 0.02em;
    text-transform: none;
    font-weight: 500;
    color: var(--color-text-muted);
}

.panel .dash-overview__name {
    margin: 0 0 12px;
    text-align: left;
    font-size: clamp(2rem, 1.1rem + 2.4vw, 3.2rem);
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.03em;
    color: var(--color-text-light);
    overflow-wrap: anywhere;
}

.dash-overview__tag {
    /* About 4px tighter than before (it was +0.12em): the name's last letter and the
       # carry their own side space, so the tag sits a touch into it */
    margin-left: -0.08em;
    font-size: 0.4em;
    font-weight: 500;
    letter-spacing: 0;
    color: var(--color-text-muted);
}

.dash-overview__lede {
    max-width: 46ch;
    margin: 0 0 20px;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--color-text-muted);
}

/* Two rows of three: factions and achievements, then the collections */
.dash-overview__stats {
    display: grid;
    grid-template-columns: repeat(3, max-content);
    gap: 16px 40px;
    margin: 0 0 20px;
}

.dash-overview__stats div {
    display: flex;
    flex-direction: column-reverse;
    gap: 3px;
}

.dash-overview__stats dt {
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.dash-overview__stats dd {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-light);
}

.dash-overview__stats .faction-glyph {
    font-size: 1.05rem;
}

.dash-overview__stats .stat-icon {
    flex: none;
    width: 20px;
    height: 20px;
}

/* Same tints the old stat tiles used */
.dash-overview__stats .achievements-icon {
    filter: brightness(0) saturate(100%) invert(80%) sepia(52%) saturate(640%) hue-rotate(356deg) brightness(101%) contrast(96%);
}

.dash-overview__stats .mounts-icon {
    filter: brightness(0) saturate(100%) invert(67%) sepia(25%) saturate(549%) hue-rotate(346deg) brightness(93%) contrast(86%);
}

.dash-overview__stats .pets-icon {
    filter: brightness(0) saturate(100%) invert(76%) sepia(69%) saturate(462%) hue-rotate(88deg) brightness(102%) contrast(94%);
}

.dash-overview__stats .toys-icon {
    filter: brightness(0) saturate(100%) invert(76%) sepia(44%) saturate(420%) hue-rotate(166deg) brightness(98%) contrast(92%);
}

/* Faction crests as small glyphs, tinted (the SVGs themselves are black) */
.faction-glyph {
    display: inline-block;
    flex: none;
    width: 0.8em;
    height: 1em;
    background: currentColor;
    -webkit-mask: var(--glyph) center / contain no-repeat;
    mask: var(--glyph) center / contain no-repeat;
}

.faction-glyph--alliance { --glyph: url("/img/ui/alliance.svg"); color: #6ea8ff; }
.faction-glyph--horde { --glyph: url("/img/ui/horde.svg"); color: #ff5b4f; }

.dash-overview .account-lockup {
    display: inline-flex;
    min-width: 236px;
}

.dash-overview .account-lockup .dash-intro__cta {
    box-shadow: 0 8px 24px -8px rgba(var(--faction-rgb), 0.6);
    transition: box-shadow 0.6s ease;
}

.dash-overview .account-lockup > .dash-intro__cta {
    margin-top: 12px;
}

.dash-overview .account-lockup .dash-intro__cta:disabled {
    cursor: not-allowed;
    opacity: 0.7;
}

/* Alliance / Horde theme switch, under Settings and Sign out */
.faction-toggle {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 3px;
    padding: 3px;
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.28);
}

.faction-toggle__opt {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 7px 10px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease;
}

.faction-toggle__opt:hover {
    color: var(--color-text-light);
    background: rgba(255, 255, 255, 0.05);
}

.faction-toggle__opt[data-faction-choice="alliance"][aria-pressed="true"] {
    color: var(--color-text-light);
    background: rgba(var(--alliance-rgb), 0.22);
    box-shadow: inset 0 0 0 1px rgba(var(--alliance-rgb), 0.55);
}

.faction-toggle__opt[data-faction-choice="horde"][aria-pressed="true"] {
    color: var(--color-text-light);
    background: rgba(var(--horde-rgb), 0.22);
    box-shadow: inset 0 0 0 1px rgba(var(--horde-rgb), 0.55);
}

.faction-toggle__opt .faction-glyph {
    font-size: 0.95rem;
}

.dash-overview__updated {
    margin: 12px 0 0;
    text-align: center;
    font-size: 0.78rem;
    color: var(--color-text-muted);
}

/* The line-up: the player's five best-geared characters from Blizzard's
   1600x1200 transparent renders. Every render puts the feet at y≈980 and
   the body around x 520-1080, so one crop fits all of them and keeps each
   race's true height. Best-geared stands in the middle, in front. */
.dash-overview__art {
    grid-area: art;
    position: relative;
    z-index: 1;
    align-self: stretch;
    display: flex;
    align-items: flex-end;
    min-height: 300px;
    padding-bottom: 26px;
    container-type: inline-size;
}

/* Class breakdown and the refresh bar run full width along the bottom */
.dash-overview > .refresh-progress {
    grid-column: 1 / -1;
    position: relative;
    z-index: 2;
}

.dash-overview > .refresh-progress {
    margin: 0;
    padding: 0 20px 18px;
}

/* Loading, in faction colors. The fill is a long gradient that slides under
   itself, so the colors run together: Alliance blue and gold, Horde embers
   burning through red into black. */
.dash-overview .progress-bar {
    height: 8px;
    background: rgba(255, 255, 255, 0.07);
}

.dash-overview .progress-bar .bar-fill {
    background-size: 200% 100%;
    animation: faction-flow 1.6s linear infinite;
}

.dash-overview[data-faction="alliance"] .progress-bar .bar-fill {
    background-image: linear-gradient(90deg, #1b3f9e, #3d7dff, #f3c64f, #ffe8a3, #f3c64f, #3d7dff, #1b3f9e);
    box-shadow: 0 0 10px rgba(61, 125, 255, 0.65), 0 0 18px rgba(243, 198, 79, 0.35);
}

.dash-overview[data-faction="horde"] .progress-bar .bar-fill {
    background-image: linear-gradient(90deg, #3a0705, #8f1010, #e0271b, #ff7a1a, #ffc24a, #ff7a1a, #e0271b, #8f1010, #3a0705);
    box-shadow: 0 0 10px rgba(255, 90, 26, 0.7), 0 0 20px rgba(224, 39, 27, 0.4);
}

@keyframes faction-flow {
    from { background-position: 0% 0; }
    to { background-position: -200% 0; }
}

.dash-overview .refresh-progress .progress-text {
    margin-top: 10px;
    text-align: center;
}

/* Stats spinner: a ring in the same two colors */
.dash-overview .stats-loader-spinner {
    display: none;
}

.dash-overview .stats-loading-content::before {
    content: "";
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0 10%, var(--spin-a) 45%, var(--spin-b) 80%, var(--spin-a) 100%);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    animation: spin 0.9s linear infinite;
}

.dash-overview[data-faction="alliance"] .stats-loading-content::before {
    --spin-a: #3d7dff;
    --spin-b: #f3c64f;
}

.dash-overview[data-faction="horde"] .stats-loading-content::before {
    --spin-a: #e0271b;
    --spin-b: #ffb02e;
}

/* Reduced motion: the bar holds still and keeps its colors, and it jumps to
   each new width instead of sliding. (The global reduced-motion rule in
   global.css also stops the spinner; the "Loading stats" text stays.) */
@media (prefers-reduced-motion: reduce) {
    .dash-overview .progress-bar .bar-fill {
        animation: none;
        background-position: 0 0;
        transition: none;
    }
}

@media (max-width: 959px) {
    .dash-overview {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: "copy" "art";
    }
    .dash-overview__copy {
        padding: 24px 20px 8px;
    }
    .dash-overview__art {
        min-height: 0;
    }
    /* Stacked: the Line-up and View as pickers move under the characters,
       full width; the Sample data flag stays pinned top right */
    .dash-overview {
        grid-template-areas: "copy" "art" "meta";
    }
    .dash-overview__meta {
        grid-area: meta;
        position: static;
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        padding: 0 20px 20px;
    }
    .dash-overview__meta .demo-flag {
        position: absolute;
        top: 18px;
        right: 20px;
    }
    .dash-overview__meta .lineup-pick {
        width: 100%;
    }
    .dash-overview__meta .lineup-sort {
        display: flex;
        flex: 1 1 auto;
        width: 100%;
    }
    .panel .dash-overview__meta .lineup-sort select {
        flex: 1 1 auto;
        width: auto;
        max-width: none;
    }
    .dash-overview__art {
        padding-top: 64px;      /* air above the heads, and the crest shows through */
        padding-bottom: 18px;
    }
    .dash-overview__crest {
        top: 0;
        height: 100%;
    }
}

@media (max-width: 560px) {
    .dash-overview__stats {
        gap: 12px 22px;
    }
    .dash-overview__stats dd {
        font-size: 1.35rem;
    }
    .dash-overview .account-lockup {
        display: flex;
    }
}

@media (prefers-reduced-motion: reduce) {
    .dash-overview,
    .dash-overview::before,
    .dash-overview::after,
    .dash-overview__crest,
    .dash-overview__eyebrow {
        transition: none;
    }
}

/* ============================================================
   Class roster (#nav-classes, its own panel under the hero)
   Every class the player has, ranked by count. Each row is a button: rank,
   class icon, name in the class color, count, and a bar scaled to the top
   class and split into specs in shades of the class color (tiles.js fills
   the segments; a faint remainder is characters with no spec data yet).
   Opening a row shows each spec's characters, highest level first.
   ============================================================ */
.class-roster {
    padding: 22px 24px 24px;
}

.class-roster__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 28px;
    margin-bottom: 18px;
}

.class-roster__intro {
    flex: 1 1 280px;
    min-width: 0;
}

.panel .class-roster__title {
    margin: 0 0 4px;
    text-align: left;
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--color-text-light);
}

.class-roster__hint {
    margin: 0;
    font-size: 0.86rem;
    line-height: 1.5;
    color: var(--color-text-muted);
}

.class-roster__summary {
    display: flex;
    gap: 26px;
    margin: 0;
}

.class-roster__summary div {
    display: flex;
    flex-direction: column-reverse;
    gap: 2px;
}

.class-roster__summary dt {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.class-roster__summary dd {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-light);
}

.class-roster__summary dd span {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--color-text-muted);
}

.class-roster__summary .class-roster__top {
    color: var(--cc, var(--color-text-light));
}

.class-roster__toggle {
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: 9px;
    padding: 10px 16px 10px 18px;
    border: 1px solid var(--color-border-light);
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.04);
    font: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--color-text-light);
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.class-roster__toggle:hover {
    background: rgba(255, 255, 255, 0.09);
}

.class-roster__toggle svg {
    width: 17px;
    height: 17px;
    transition: transform 0.25s ease;
}



.class-roster__toggle-close,
.class-roster__toggle[aria-expanded="true"] .class-roster__toggle-open {
    display: none;
}

.class-roster__toggle[aria-expanded="true"] .class-roster__toggle-close {
    display: inline;
}

/* Loading: the faction ring (see "Every dashboard loader" below) */
.class-roster .panel-stats-loading {
    min-height: 120px;
}

.class-roster .stats-loader-spinner {
    display: none;
}

.class-roster .stats-loading-content::before {
    content: "";
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0 10%, var(--spin-a) 45%, var(--spin-b) 80%, var(--spin-a) 100%);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    animation: spin 0.9s linear infinite;
}

/* Two ranked columns, read top to bottom; a row opens in place */
.class-roster__cols {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    gap: 8px 22px;
}

.class-roster__list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.class-row {
    --cc: var(--color-primary);
    border: 1px solid transparent;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.02);
    transition: background-color 0.2s ease, border-color 0.2s ease;
}

.class-row:hover,
.class-row.is-open {
    background: color-mix(in srgb, var(--cc) 6%, rgba(255, 255, 255, 0.02));
    border-color: color-mix(in srgb, var(--cc) 22%, transparent);
}

.class-row__head {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 14px 10px 10px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.class-row__rank {
    flex: none;
    width: 20px;
    font-size: 0.78rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: right;
    color: var(--color-text-muted);
}

.class-row__icon {
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: 9px;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--cc) 55%, transparent), 0 4px 14px color-mix(in srgb, var(--cc) 22%, transparent);
}

.class-row__main {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 7px;
    min-width: 0;
}

.class-row__line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.class-row__name {
    overflow: hidden;
    font-size: 0.95rem;
    font-weight: 700;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--cc);
}

.class-row__count {
    flex: none;
    font-size: 1.05rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-light);
}

/* The bar: its length is the class's share of the top class; inside it,
   the specs take their share of the class */
.class-row__track {
    display: block;
    height: 8px;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.05);
    overflow: hidden;
}

.class-row__bar {
    display: flex;
    gap: 2px;
    width: calc(var(--share, 0) * 100%);
    min-width: 8px;
    height: 100%;
    border-radius: inherit;
    overflow: hidden;
}

.class-row__seg {
    flex-basis: 0;
    min-width: 3px;
    background: color-mix(in srgb, var(--cc) calc(var(--shade, 1) * 100%), rgba(255, 255, 255, 0.06));
}

.class-row__seg--unknown {
    background: rgba(255, 255, 255, 0.12);
}

.class-row__chev {
    flex: none;
    width: 16px;
    height: 16px;
    color: var(--color-text-muted);
    transition: transform 0.25s ease, color 0.2s ease;
}

.class-row__head[aria-expanded="true"] .class-row__chev {
    transform: rotate(180deg);
    color: var(--cc);
}

/* Open: a column per spec with its characters, from the class icon's left
   edge to the bar's right edge (head padding + rank + gap on the left,
   head padding + chevron + gap on the right) */
.class-row__detail {
    padding: 4px 42px 16px 42px;
}

.class-roster__cols .class-row__specs {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.class-row__specs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px 18px;
}

.class-spec__head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 7px;
    margin-bottom: 7px;
    border-bottom: 2px solid color-mix(in srgb, var(--cc) calc(var(--shade, 1) * 100%), rgba(255, 255, 255, 0.06));
}

.class-spec__icon {
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 5px;
}

.class-spec__name {
    flex: 1 1 auto;
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--color-text-light);
}

.class-spec__count {
    font-size: 0.86rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}

.class-spec--empty .class-spec__head {
    opacity: 0.55;
}

.class-spec__chars {
    display: flex;
    flex-direction: column;
    gap: 3px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.class-spec__chars li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    font-size: 0.84rem;
}

.class-spec__char {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--color-text-light);
}

.class-spec__level {
    flex: none;
    font-size: 0.76rem;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}

.class-spec__none,
.class-row__unknown {
    margin: 0;
    font-size: 0.8rem;
    color: var(--color-text-muted);
}

.class-row__unknown {
    grid-column: 1 / -1;
    font-style: italic;
}

/* Below 1100px the header stacks: title and hint on top, then the stats
   on the left and the switch on the right */
@media (max-width: 1100px) {
    .class-roster__head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        gap: 14px 20px;
    }
    .class-roster__intro {
        grid-column: 1 / -1;
    }
}

@media (max-width: 900px) {
    .class-roster__cols {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 560px) {
    .class-roster {
        padding: 20px 16px 18px;
    }
    .class-roster__summary {
        gap: 20px;
    }
    .class-roster__head {
        grid-template-columns: minmax(0, 1fr);
    }
    .class-roster__toggle {
        width: 100%;
        justify-content: center;
    }
    .class-row__head {
        gap: 10px;
        padding: 9px 10px 9px 6px;
    }
    .class-row__icon {
        width: 30px;
        height: 30px;
    }
    .class-row__detail {
        padding: 4px 36px 14px 36px;  /* phone head: 6 + 20 + 10, and 10 + 16 + 10 */
    }
    .class-roster__cols .class-row__specs {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .class-row,
    .class-row__chev,
    .class-roster__toggle,
    .class-roster__toggle svg {
        transition: none;
    }
}

/* ============================================================
   Sample bar (signed out): sits above the sample dashboard and is the
   anchor the home page links to (#sample). A neutral panel; only the
   Sample data pill is green (the same pill as the hero's flag).
   ============================================================ */
.sample-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 18px;
    margin-bottom: 20px;
    padding: 12px 18px;
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-lg);
    background: var(--color-bg-panel);
    scroll-margin-top: 16px;
}

.sample-bar__tag {
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: 7px;
    padding: 5px 11px 5px 9px;
    border-radius: var(--radius-full);
    background: rgba(128, 195, 66, 0.14);
    color: #b5e58a;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
}

.sample-bar__tag svg {
    width: 14px;
    height: 14px;
}

.sample-bar__text {
    flex: 1 1 320px;
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--color-text-muted);
}

.sample-bar__text strong {
    font-weight: 600;
    color: var(--color-text-light);
}

/* Sample hero: the figures are drawn a little smaller, so the tallest
   heads clear the Line-up picker and Sample flag row above them (signed in,
   the art sits lower and doesn't need it) */
.is-demo .overview-cast__fig {
    --fw: min(100cqi / 2.85, 225px);
}

/* Below full desktop the bar keeps to one line: the second sentence goes */
@media (max-width: 1280px) {
    .sample-bar__more {
        display: none;
    }
}

/* 880px and below: three lines stacked (pill, sentence, link), left aligned */
@media (max-width: 880px) {
    .sample-bar {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        justify-items: start;
        gap: 8px;
        padding: 14px 16px;
    }
}

/* Phones: centered */
@media (max-width: 560px) {
    .sample-bar {
        justify-items: center;
        margin-bottom: 14px;
        text-align: center;
    }
    .sample-bar__text {
        font-size: 0.86rem;
    }
}


/* ============================================================
   Filters panel: a toolbar (name, level range, faction, gender, server,
   sort), then facets of chips for class and spec, race and profession
   (filter-picks.js; the native multi-selects stay hidden as the source of
   truth). The header counts the characters shown.
   ============================================================ */
.filters-title {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 14px;
}

.filters-count {
    margin: 0;
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}

.filters-count.is-filtered {
    color: var(--color-primary);
    font-weight: 600;
}

.filters-bar {
    display: grid;
    grid-template-columns: minmax(200px, 1.6fr) minmax(170px, 1fr) repeat(4, minmax(120px, 1fr));
    gap: 12px 14px;
    align-items: end;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--color-border-light);
}

.filters-bar .filter-group label,
.filter-label,
.facet__head label {
    display: block;
    margin-bottom: 6px !important;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    opacity: 1;
}

.filters-bar input,
.filters-bar select {
    height: 40px;
    min-height: 40px;
}

.filter-search {
    position: relative;
}

.filter-search svg {
    position: absolute;
    left: 12px;
    top: 50%;
    width: 16px;
    height: 16px;
    margin-top: -8px;
    color: var(--color-text-muted);
    pointer-events: none;
}

.filters-bar .filter-search input {
    padding-left: 36px;
}

.filter-range {
    display: flex;
    align-items: center;
    gap: 8px;
}

.filters-bar .filter-range input {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.filter-range__dash {
    flex: none;
    font-size: 0.8rem;
    color: var(--color-text-muted);
}

/* --- Facets --- */
.filters-facets {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 18px 28px;
    padding-top: 18px;
}

.facet--class {
    grid-column: 1 / -1;
    /* the same divider as between the toolbar and the facets */
    padding-bottom: 18px;
    border-bottom: 1px solid var(--color-border-light);
}

.facet__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 12px;
    margin-bottom: 10px;
}

.facet__head label {
    margin-bottom: 0 !important;
}

.facet__hint {
    font-size: 0.8rem;
    color: var(--color-text-muted);
}

select.picks-source {
    display: none !important;
}

.picks {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

/* A chip: quiet until picked, then the site blue */
.pick {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-full);
    background: rgba(255, 255, 255, 0.03);
    color: var(--color-text-light);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.pick:hover {
    border-color: rgba(255, 255, 255, 0.24);
    background: rgba(255, 255, 255, 0.07);
}

.pick[aria-pressed="true"] {
    border-color: rgba(39, 170, 226, 0.7);
    background: rgba(39, 170, 226, 0.16);
    color: #fff;
}

.pick[aria-pressed="true"]::before {
    content: "";
    width: 12px;
    height: 12px;
    margin-left: -2px;
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E") center / contain no-repeat;
}

.pick:disabled {
    opacity: 0.4;
    cursor: default;
}

/* Classes: one card per class, its specs as smaller chips, all in the
   class color */
.picks--class {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 8px;
}

.pick-class {
    --cc: var(--color-primary);
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 8px 9px 9px;
    border: 1px solid var(--color-border-light);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.02);
}

.pick-class:has(.pick[aria-pressed="true"]) {
    border-color: color-mix(in srgb, var(--cc) 45%, transparent);
    background: color-mix(in srgb, var(--cc) 6%, rgba(255, 255, 255, 0.02));
}

.pick--class {
    align-self: flex-start;
    border-color: transparent;
    background: none;
    padding: 2px 4px;
    font-weight: 700;
    color: var(--cc);
}

.pick--class:hover {
    border-color: transparent;
    background: color-mix(in srgb, var(--cc) 10%, transparent);
}

.pick--class[aria-pressed="true"] {
    padding: 4px 10px;
    border-color: color-mix(in srgb, var(--cc) 70%, transparent);
    background: color-mix(in srgb, var(--cc) 18%, transparent);
    color: #fff;
}

.pick-class__specs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.pick--spec {
    padding: 3px 9px;
    font-size: 0.74rem;
    gap: 5px;
    color: color-mix(in srgb, var(--cc) 55%, var(--color-text-light));
}

.pick--spec[aria-pressed="true"] {
    border-color: color-mix(in srgb, var(--cc) 70%, transparent);
    background: color-mix(in srgb, var(--cc) 18%, transparent);
    color: #fff;
}

/* The six toolbar fields always fill whole rows: all six across on wide
   screens, then two rows of three (Name, Level, Faction / Gender, Server,
   Sort), then three rows of two, then one per row on phones, where Level
   keeps its two boxes side by side across the full width */
@media (max-width: 1280px) {
    .filters-bar {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 900px) {
    .filters-bar {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .filters-facets {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 560px) {
    .filters-bar {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 560px) {
    /* Phones: each class is one wrapped row, name inline with its specs */
    .picks--class {
        grid-template-columns: minmax(0, 1fr);
        gap: 6px;
    }
    .pick-class {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 4px;
        padding: 6px 8px;
    }
    .pick--class {
        margin-right: 2px;
    }
    .pick-class__specs {
        display: contents;
    }
    .panel-filters .panel-header-filters {
        align-items: stretch;
    }
    .panel-filters .filters-title {
        flex-direction: column;
        align-items: center;
        gap: 2px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .pick {
        transition: none;
    }
}

/* Filters: our own select chevron, inset from the edge (as on the home page) */
.filters-bar select {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 38px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
    background-size: 15px 15px;
    text-overflow: ellipsis;
    cursor: pointer;
}

/* Reset: the same pill as the class roster's Open all */
.panel-filters #btn-reset-filters {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 10px 18px 10px 16px;
    border: 1px solid var(--color-border-light);
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.04);
    font: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--color-text-light);
    box-shadow: none;
}

.panel-filters #btn-reset-filters:hover {
    background: rgba(255, 255, 255, 0.09);
}

.panel-filters #btn-reset-filters svg {
    width: 17px;
    height: 17px;
}

/* Filters header: the title and count, and Reset, share a center line */
.panel-filters .panel-header-filters {
    align-items: center;
}

/* Class and spec icons in the chips: the icon carries the picked state (a
   ring in the class color), so those chips skip the check mark */
.pick__icon {
    flex: none;
    display: block;
    border-radius: 50%;
}

.pick--icon[aria-pressed="true"]::before {
    content: none;
}

.pick--class.pick--icon {
    gap: 7px;
    padding: 2px 8px 2px 2px;
}

.pick--class .pick__icon {
    width: 22px;
    height: 22px;
    border-radius: 6px;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--cc) 45%, transparent);
}

.pick--class[aria-pressed="true"].pick--icon {
    padding: 2px 10px 2px 2px;
}

.pick--spec.pick--icon {
    padding: 2px 9px 2px 2px;
}

.pick--spec .pick__icon {
    width: 18px;
    height: 18px;
    opacity: 0.75;
    filter: saturate(0.7);
    transition: opacity 0.15s ease, filter 0.15s ease;
}

.pick--spec:hover .pick__icon,
.pick--spec[aria-pressed="true"] .pick__icon {
    opacity: 1;
    filter: none;
}

.pick--icon[aria-pressed="true"] .pick__icon {
    box-shadow: 0 0 0 2px var(--cc);
}

/* Cards tighter: header chip and specs close together */
.pick-class {
    gap: 6px;
    padding: 7px 8px 8px;
}

.pick-class__specs {
    gap: 4px;
}

@media (prefers-reduced-motion: reduce) {
    .pick--spec .pick__icon {
        transition: none;
    }
}

/* Open all and Reset: the icon turns the site blue on hover */
.class-roster__toggle svg,
.panel-filters #btn-reset-filters svg {
    transition: transform 0.25s ease, color 0.2s ease;
}

.class-roster__toggle:hover svg,
.panel-filters #btn-reset-filters:hover svg {
    color: var(--color-primary);
}

/* Optical tuning, measured per button at this size (0.92rem, 17px icons):
   - Reset: the label needs only half the usual lift; the ring icon reads by
     its circle, whose box sat 0.5px low, so it rises 0.5px.
   - Open all: half the usual lift too; the chevron is already centered. */
.panel-filters #btn-reset-filters .btn-label,
.class-roster__toggle .btn-label {
    top: -0.5px;
}

.panel-filters #btn-reset-filters svg {
    transform: translateY(-0.5px);
}

/* Line-up and View as: our own chevron, inset from the pill's edge (the
   native arrow hugs it) */
.panel .lineup-sort select {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 30px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 11px center;
    background-size: 13px 13px;
    text-overflow: ellipsis;
}

/* Reset is disabled (greyed out) until a filter or the sort changes
   (filters.js syncResetButton) */
.panel-filters #btn-reset-filters:disabled {
    opacity: 0.4;
    cursor: default;
}

.panel-filters #btn-reset-filters:disabled:hover {
    background: rgba(255, 255, 255, 0.04);
}

.panel-filters #btn-reset-filters:disabled:hover svg {
    color: currentColor;
    stroke: currentColor;
}

/* Filters type scale, matched to the buttons (Reset, Open all: 0.92rem/600):
   - toolbar values share the buttons' size at 500 (typed values shouldn't
     read as buttons);
   - the class name heads its card (0.86rem/700);
   - every other chip (spec, race, profession) is one size, 0.8rem/500.
   Labels stay 0.72rem caps, the hint and count 0.8-0.86rem. */
.filters-bar input,
.filters-bar select {
    font-size: 0.92rem;
    font-weight: 500;
}

.filters-bar input::placeholder {
    font-weight: 400;
}

.pick,
.pick--spec {
    font-size: 0.8rem;
}

.pick--class {
    font-size: 0.86rem;
}

/* Utility buttons in the section headers (Accounts & Characters down:
   Reorder, Toggle details, Copy, Export, Batch check, Show / Hide, Reset,
   Duplicates): the tool-button type (0.92rem/600), 17px icons that turn
   the site blue on hover (.btn:hover svg), the label lift measured below */
.panel-header-actions .btn {
    gap: 8px;
    font-size: 0.92rem;
    font-weight: 600;
}

.panel-header-actions .btn svg {
    width: 17px;
    height: 17px;
    transition: stroke 0.2s ease, color 0.2s ease;
}

/* Measured (ink, 1x and 2x): with no lift the labels' weight sat 0.6 to
   0.9px low, so they rise 0.5px. The icons sat within 0.5px either way
   (the same icon lands +0.5 or -0.5 depending on the header's pixel
   phase), so they're left alone. */
.panel-header-actions .btn .btn-label {
    top: -0.5px;
}

/* ...except labels with no descenders (Reorder accounts, Show, Hide,
   Reset): the lift snaps to a full pixel and put them 0.5px high, while
   no lift measured closer to center */
:is(#btn-reorder-accounts, #btn-reorder-accounts-reserved,
    #btn-reset-mount-filters, #btn-reset-pet-filters, #btn-reset-toy-filters,
    .panel-header-actions .btn-expand,
    .panel-header-actions .btn-collapse[data-panel]) .btn-label {
    top: 0;
}

/* ============================================================
   Mounts, Pets and Toys filters: the Filters panel's type and controls.
   Name and Sort stacked on the left, then Faction / Family, Source and
   Details as chips (filter-picks.js; the list boxes stay hidden as the
   source of truth). Source and Family take the spare width.
   ============================================================ */
:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: 16px 40px;
    align-items: start;
    margin-bottom: 20px;
    padding-bottom: 20px;
}

/* Name and Sort on the left, spanning the chip rows beside them */
:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) .filter-column-main {
    display: flex;
    flex-direction: column;
    gap: 14px;
    grid-column: 1;
    grid-row: 1 / span 3;
    min-width: 0;
}

:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) .filter-column-single {
    grid-column: 2;
    min-width: 0;
}

:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) .filter-group label {
    margin-bottom: 8px !important;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--color-text-muted);
    opacity: 1;
}

:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) .filter-group :is(input, select:not([multiple])) {
    height: 40px;
    min-height: 40px;
    font-size: 0.92rem;
    font-weight: 500;
}

:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) .filter-group input::placeholder {
    font-weight: 400;
}

:is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) .filter-group select:not([multiple]) {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 38px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
    background-size: 15px 15px;
    text-overflow: ellipsis;
    cursor: pointer;
}

/* Tablets and phones: one column, Name and Sort first */
@media (max-width: 800px) {
    :is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) {
        grid-template-columns: minmax(0, 1fr);
        gap: 18px;
    }
    :is(.mounts-filters-row, .pets-filters-row, .toys-filters-row) :is(.filter-column-main, .filter-column-single) {
        grid-column: 1;
        grid-row: auto;
    }
}

/* Mounts, Pets and Toys Reset: greyed out until a filter or the sort
   changes (panels-collections.js syncCollectionReset), like the Filters
   panel's Reset */
:is(#btn-reset-mount-filters, #btn-reset-pet-filters, #btn-reset-toy-filters):disabled {
    opacity: 0.4;
    cursor: default;
}

/* ============================================================
   Race & Class Combos (combos.js): a collection matrix.
   A summary (played, both genders, duplicates) with a legend and an
   All / Missing / Played switch; then one table with the classes across
   the top (icon, and the name when there's room) and the races down the
   side under Alliance and Horde headers, each with a progress bar. Each
   cell is a male and a female glyph (the gender SVGs as masks), lit in
   blue and pink when played; a cell with both fills in the class color.
   Combos the game doesn't allow show a faint dot. On narrow screens the
   table scrolls sideways under a sticky race column. Duplicates follow
   as cards in the class color.
   ============================================================ */
.panel-combos {
    --combo-solid: #0a0e16; /* the panel's color, opaque, under the sticky column */
}

.combo-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px 32px;
    padding: 4px 0 18px;
}

.combo-stats {
    display: flex;
    gap: 32px;
    margin: 0;
}

.combo-stat {
    display: flex;
    flex-direction: column-reverse;
    gap: 2px;
}

.combo-stat dt {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

.combo-stat dd {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-light);
}

.combo-stat dd span {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-text-muted);
}

.combo-stat__link {
    color: var(--color-primary);
    text-decoration: underline;
    text-decoration-color: rgba(39, 170, 226, 0.4);
    text-underline-offset: 4px;
}

.combo-stat__link:hover {
    text-decoration-color: currentColor;
}

.combo-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 20px;
}

.combo-legend {
    display: flex;
    gap: 16px;
    font-size: 0.8rem;
    color: var(--color-text-muted);
}

.combo-legend span {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}

.combo-legend span .combo-g:last-of-type {
    margin-right: 5px;
}

/* All / Missing / Played: a segmented pill */
.combo-view {
    display: inline-flex;
    padding: 3px;
    border: 1px solid var(--color-border-light);
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.03);
}

.combo-view button {
    padding: 6px 14px;
    border: 1px solid transparent;
    border-radius: 9999px;
    background: none;
    color: var(--color-text-muted);
    font: inherit;
    font-size: 0.84rem;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.combo-view button:hover {
    color: var(--color-text-light);
}

.combo-view button[aria-pressed="true"] {
    border-color: rgba(39, 170, 226, 0.6);
    background: rgba(39, 170, 226, 0.16);
    color: #fff;
}

/* Gender glyphs: the gender SVGs as masks, dim until played */
.combo-g {
    display: inline-block;
    flex: none;
    width: 15px;
    height: 15px;
    background: rgba(255, 255, 255, 0.14);
    -webkit-mask: var(--g) center / contain no-repeat;
    mask: var(--g) center / contain no-repeat;
}

.combo-g--male { --g: url("/img/icon-male.svg"); }
.combo-g--female { --g: url("/img/icon-female.svg"); }
.combo-g--male.is-on { background: #5cb3ff; }
.combo-g--female.is-on { background: #ff7ac8; }
.combo-g.has-tooltip { cursor: help; }

/* --- The matrix --- */
.combo-matrix-wrap {
    container-type: inline-size;
    overflow-x: auto;
    border: 1px solid var(--color-border-light);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.015);
}

.combo-matrix-wrap:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.combo-matrix {
    width: 100%;
    min-width: 720px;
    border-collapse: separate;
    border-spacing: 0;
    table-layout: fixed;
}

.combo-matrix__corner,
.combo-race {
    width: 176px;
}

.combo-matrix__corner {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--combo-solid);
}

.combo-col {
    padding: 14px 2px 12px;
    vertical-align: bottom;
    text-align: center;
    font-weight: 400;
}

.combo-col__icon {
    display: block;
    width: 26px;
    height: 26px;
    margin: 0 auto;
    border-radius: 7px;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--cc) 55%, transparent), 0 3px 10px color-mix(in srgb, var(--cc) 25%, transparent);
}

.combo-col__name {
    display: block;
    margin-top: 7px;
    font-size: 0.66rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--cc);
}

/* Class names under the icons only when every column has room */
@container (max-width: 1080px) {
    .combo-col__name {
        display: none;
    }
}

/* Faction header rows */
.combo-faction--alliance { --fc: 110, 168, 255; }
.combo-faction--horde { --fc: 255, 91, 79; }

.combo-faction__head th {
    padding: 0;
    border-top: 1px solid var(--color-border-light);
    background: linear-gradient(90deg, rgba(var(--fc), 0.12), transparent 55%);
    text-align: left;
    font-weight: 400;
}

.combo-faction__inner {
    position: sticky;
    left: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 18px;
    width: min(100%, 100cqi);
    box-sizing: border-box;
    padding: 16px 16px 12px;
}

.combo-faction__title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 1rem;
    font-weight: 700;
    color: var(--color-text-light);
}

.combo-faction__title .faction-glyph {
    font-size: 1.15rem;
}

.combo-faction__count {
    font-size: 0.82rem;
    color: var(--color-text-muted);
}

.combo-faction__bar {
    position: relative;
    flex: 1 1 140px;
    max-width: 320px;
    height: 6px;
    margin-left: auto;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.07);
    overflow: hidden;
}

.combo-faction__bar span {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--p);
    border-radius: inherit;
    background: rgba(var(--fc), 0.4);
}

.combo-faction__bar span.is-complete {
    background: rgb(var(--fc));
}

/* Race rows */
.combo-race {
    position: sticky;
    left: 0;
    z-index: 1;
    padding: 0 12px 0 16px;
    border-top: 1px solid rgba(255, 255, 255, 0.04);
    background: var(--combo-solid);
    text-align: left;
    white-space: nowrap;
}

.combo-race__name {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--color-text-light);
}

.combo-race__count {
    margin-left: 8px;
    font-size: 0.74rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}

.combo-race__count span {
    opacity: 0.7;
}

.combo-row.is-full .combo-race__count {
    color: var(--color-success);
}

.combo-cell {
    height: 42px;
    padding: 4px 3px;
    border-top: 1px solid rgba(255, 255, 255, 0.04);
    text-align: center;
}

.combo-row:hover > * {
    background-color: rgba(255, 255, 255, 0.025);
}

.combo-row:hover > .combo-race {
    background-color: #10141c;
}

.combo-cell__pair {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    width: 100%;
    max-width: 64px;
    height: 30px;
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.015);
    transition: opacity 0.2s ease;
}

.combo-cell.is-partial .combo-cell__pair {
    border-color: color-mix(in srgb, var(--cc) 32%, transparent);
    background: color-mix(in srgb, var(--cc) 9%, transparent);
}

.combo-cell.is-complete .combo-cell__pair {
    border-color: color-mix(in srgb, var(--cc) 70%, transparent);
    background: color-mix(in srgb, var(--cc) 24%, transparent);
    box-shadow: inset 0 0 14px color-mix(in srgb, var(--cc) 18%, transparent);
}

.combo-cell.is-na::before {
    content: "";
    display: inline-block;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    vertical-align: middle;
}

/* Missing: fade what's done; Played: fade what isn't started */
.combo-matrix[data-view="missing"] .combo-cell.is-complete .combo-cell__pair,
.combo-matrix[data-view="played"] .combo-cell.is-empty .combo-cell__pair {
    opacity: 0.12;
}

/* Names on hover (core.js) */
.hover-tooltip {
    padding: 6px 10px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 8px;
    background: #0f1520;
    color: var(--color-text-light);
    font-size: 0.8rem;
    font-weight: 600;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}

/* --- Duplicates --- */
.combos-duplicates {
    margin-top: 28px;
    padding-top: 22px;
    border-top: 1px solid var(--color-border-light);
    scroll-margin-top: 20px;
}

.panel .combos-duplicates__head h3 {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 4px;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--color-text-light);
}

.combos-duplicates__count {
    padding: 2px 9px;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.07);
    font-size: 0.78rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}

.combos-duplicates__head p {
    margin: 0 0 14px;
    font-size: 0.84rem;
    color: var(--color-text-muted);
}

.dup-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 12px;
}

.dup-card {
    position: relative;
    display: flex;
    gap: 14px;
    padding: 14px 16px;
    border: 1px solid color-mix(in srgb, var(--cc) 28%, transparent);
    border-radius: 12px;
    background:
        linear-gradient(135deg, color-mix(in srgb, var(--cc) 10%, transparent), transparent 60%),
        rgba(255, 255, 255, 0.02);
}

.dup-card__icon {
    flex: none;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--cc) 55%, transparent), 0 4px 14px color-mix(in srgb, var(--cc) 25%, transparent);
}

.dup-card__body {
    flex: 1 1 auto;
    min-width: 0;
}

.panel .dup-card__title {
    margin: 0;
    padding-right: 40px;
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--color-text-light);
}

.dup-card__title span {
    color: var(--cc);
}

.dup-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin: 4px 0 10px;
    font-size: 0.78rem;
    color: var(--color-text-muted);
}

.dup-card__tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.dup-card__tag .faction-glyph {
    font-size: 0.95rem;
}

.dup-card__tag .combo-g {
    width: 13px;
    height: 13px;
}

.dup-card__chars {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.dup-card__chars li {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 4px 10px;
    border: 1px solid var(--color-border-light);
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.05);
    font-size: 0.8rem;
}

.dup-char__name {
    font-weight: 600;
    color: var(--color-text-light);
}

.dup-char__realm {
    font-size: 0.74rem;
    color: var(--color-text-muted);
}

.dup-card__count {
    position: absolute;
    top: 12px;
    right: 14px;
    padding: 2px 8px;
    border-radius: 9999px;
    background: color-mix(in srgb, var(--cc) 16%, transparent);
    font-size: 0.8rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--cc);
}

@media (max-width: 560px) {
    .combo-summary {
        align-items: stretch;
    }
    .combo-stats {
        justify-content: space-between;
        width: 100%;
        gap: 16px;
    }
    .combo-stat dd {
        font-size: 1.25rem;
    }
    .combo-tools {
        width: 100%;
        justify-content: space-between;
    }
    .combo-matrix {
        min-width: 640px;
    }
    .combo-matrix__corner,
    .combo-race {
        width: 118px;
    }
    .combo-race {
        padding-left: 12px;
        white-space: normal;
    }
    .combo-race__name {
        font-size: 0.82rem;
    }
    .combo-race__count {
        display: block;
        margin-left: 0;
    }
    .dup-list {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (prefers-reduced-motion: reduce) {
    .combo-cell__pair,
    .combo-view button {
        transition: none;
    }
}

/* The site's table defaults (caps headers, bottom borders, padding) don't
   belong in the matrix */
.combo-matrix :is(th, td) {
    border-bottom: 0;
    letter-spacing: normal;
    text-transform: none;
}

.combo-matrix th {
    font-size: inherit;
}

/* Race column: the name, then its count pinned right so long names
   (Lightforged Draenei, Highmountain Tauren) never run into the cells */
.combo-matrix__corner,
.combo-race {
    width: 204px;
}

.combo-race__count {
    float: right;
    margin-left: 10px;
    line-height: 1.7;
}

/* Not-yet cells stay quiet so the played ones read first */
.combo-cell.is-empty .combo-cell__pair {
    border-color: transparent;
    background: rgba(255, 255, 255, 0.02);
}

.combo-cell.is-empty .combo-g {
    background: rgba(255, 255, 255, 0.1);
}

@media (max-width: 560px) {
    .combo-matrix__corner,
    .combo-race {
        width: 124px;
    }
    .combo-race__count {
        float: none;
        margin-left: 0;
        line-height: 1.4;
    }
}

/* Faction header bands: even padding. With 16px over 12px the title, the
   count and the progress bar all measured 2 to 2.75px below the band's
   middle (ink, 1x and 2x) */
.combo-faction__inner {
    padding-top: 14px;
    padding-bottom: 14px;
}

/* ...then the bold title (with its crest) still sat 0.8px low and the bar
   0.5px low (the band's 1px top border), so they rise */
.combo-faction__title {
    position: relative;
    top: -1px;
}

.combo-faction__bar {
    transform: translateY(-0.5px); /* a half-pixel top offset rounds away */
}

/* Race names: the table's race column uses what players call the long
   ones (Lightforged, Highmountain); the full name is its title and the
   screen-reader text, and the card layout below has room for it */
.combo-race__full {
    display: none;
}

.combo-cell__icon {
    display: none;
}

/* ============================================================
   Below 900px: no sideways table. Each race is a card row: its name and
   count, then only the classes it can be, as chips (class icon, then the
   male and female glyphs) in the same states as the table's cells. The
   faction header becomes a rounded band above its races.
   ============================================================ */
@media (max-width: 900px) {
    .combo-matrix-wrap {
        overflow: visible;
        border: 0;
        border-radius: 0;
        background: none;
    }
    .combo-matrix,
    .combo-matrix tbody,
    .combo-faction__head,
    .combo-faction__head th {
        display: block;
        width: 100%;
        min-width: 0;
    }
    .combo-matrix thead {
        display: none;
    }
    .combo-faction + .combo-faction {
        margin-top: 22px;
    }
    .combo-faction__head th {
        border: 1px solid var(--color-border-light);
        border-radius: 12px;
    }
    .combo-faction__inner {
        position: static;
        width: auto;
        padding: 13px 14px;
    }
    .combo-row {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        padding: 14px 2px;
        border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    }
    .combo-row:last-child {
        border-bottom: 0;
    }
    .combo-row:hover > *,
    .combo-row:hover > .combo-race {
        background-color: transparent;
    }
    .combo-race {
        position: static;
        display: flex;
        flex: 1 1 100%;
        align-items: baseline;
        justify-content: space-between;
        gap: 12px;
        width: auto;
        padding: 0 2px 4px;
        border: 0;
        background: none;
        white-space: normal;
    }
    .combo-race__name {
        font-size: 0.92rem;
    }
    .combo-race__full {
        display: inline;
    }
    .combo-race__short {
        display: none;
    }
    .combo-race__count {
        float: none;
        margin: 0;
        font-size: 0.78rem;
        line-height: normal;
    }
    .combo-cell {
        display: block;
        height: auto;
        padding: 0;
        border: 0;
    }
    .combo-cell.is-na {
        display: none;
    }
    .combo-cell__pair {
        width: auto;
        max-width: none;
        height: 32px;
        gap: 4px;
        padding: 0 9px 0 6px;
        border-radius: 9px;
    }
    .combo-cell.is-empty .combo-cell__pair {
        border-color: rgba(255, 255, 255, 0.06);
    }
    .combo-cell__icon {
        display: block;
        flex: none;
        width: 20px;
        height: 20px;
        margin-right: 3px;
        border-radius: 5px;
    }
    .combo-cell.is-empty .combo-cell__icon {
        opacity: 0.5;
    }
    .combo-cell .combo-g {
        width: 14px;
        height: 14px;
    }
}

/* Phones: tighter chips, four to a row instead of three */
@media (max-width: 560px) {
    .combo-row {
        gap: 5px;
        padding: 12px 0;
    }
    .combo-cell__pair {
        height: 30px;
        gap: 3px;
        padding: 0 7px 0 5px;
        border-radius: 8px;
    }
    .combo-cell__icon {
        width: 18px;
        height: 18px;
        margin-right: 2px;
    }
    .combo-cell .combo-g {
        width: 13px;
        height: 13px;
    }
}

/* ============================================================
   Every dashboard loader follows the hero's Alliance / Horde choice: the
   page reads it straight off the hero with :has(), so there's no flash
   before scripts run and it switches the moment the toggle does. One ring
   (.wd-ring colors via --spin-a / --spin-b) for the class roster, the
   character tiles still fetching their details, and the Mounts, Pets and
   Toys panels. The hero's bar and spinner already use the same colors.
   ============================================================ */
:root {
    --spin-a: var(--color-primary);
    --spin-b: var(--color-wow-gold);
}

:root:has(.dash-overview[data-faction="alliance"]) {
    --spin-a: #3d7dff;
    --spin-b: #f3c64f;
}

:root:has(.dash-overview[data-faction="horde"]) {
    --spin-a: #e0271b;
    --spin-b: #ffb02e;
}

.class-roster .stats-loading-content::before,
.character-tile .char-loader::before,
:is(.mounts-grid, .pets-grid, .toys-grid) .loading-message::before {
    content: "";
    flex: none;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0 10%, var(--spin-a) 45%, var(--spin-b) 80%, var(--spin-a) 100%);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    animation: spin 0.9s linear infinite;
}

/* Character tiles: the ring replaces the old static loader image */
.character-tile .char-loader img {
    display: none;
}

.character-tile .char-loader::before {
    width: 22px;
    height: 22px;
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2px));
}

/* Collections: ring above "Loading mounts..." */
:is(.mounts-grid, .pets-grid, .toys-grid) .loading-message {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

:is(.mounts-grid, .pets-grid, .toys-grid) .loading-message::before {
    width: 28px;
    height: 28px;
}

/* Race count centered on the race name (measured, ink at 1x and 2x). A
   float sat 3.3px high and box centering drifted with the fonts, so the
   name and count share one baseline in a flex row (table and cards alike),
   and the count, whose digits sit on that baseline with no descenders,
   rises 1px to center on the name. */
.combo-race__inner {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.combo-race__count {
    position: relative;
    top: -1px;
    float: none;
    flex: none;
    margin: 0;
    line-height: 1;
    transform: none;
}

@media (max-width: 900px) {
    .combo-race {
        display: block;
        padding-right: 2px;
    }
}

/* The flex row lifted the table's race name 1px from where it sat; put
   the pair back (the cards didn't move) */
@media (min-width: 901px) {
    .combo-race__inner {
        position: relative;
        top: 1px;
    }
}

/* Faction band: once the bar can't sit beside the title and count at a
   useful width (the band 600px or narrower), it takes its own line at
   full width instead of wrapping at its 320px cap */
@media (max-width: 900px) {
    .combo-faction__head th {
        container-type: inline-size;
    }
}

@container (max-width: 600px) {
    .combo-faction__bar {
        flex: 1 1 100%;
        max-width: none;
        margin-left: 0;
    }
}

/* Card rows (900px and below): chips fill the row edge to edge. A grid of
   equal columns (auto-fit collapses spare tracks), each chip stretched to
   its column with its icon and glyphs centered, so wrapped lines end flush
   with the content instead of leaving a gap on the right. The race name
   and count span the full row above. */
@media (max-width: 900px) {
    .combo-row {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
    }
    .combo-race {
        grid-column: 1 / -1;
    }
    .combo-cell__pair {
        width: 100%;
    }
}

@media (max-width: 560px) {
    .combo-row {
        grid-template-columns: repeat(auto-fit, minmax(66px, 1fr));
    }
}

/* ...the race name can't span the grid: a full-width item keeps auto-fit
   from collapsing spare columns (a seven-class race at 900px left a 181px
   gap). It sits above the chips out of the grid instead. */
@media (max-width: 900px) {
    .combo-row {
        position: relative;
        padding-top: 46px;
    }
    .combo-race {
        position: absolute;
        top: 14px;
        right: 2px;
        left: 2px;
        grid-column: auto;
        padding: 0;
    }
}

@media (max-width: 560px) {
    .combo-row {
        padding-top: 44px;
    }
    .combo-race {
        top: 12px;
        right: 0;
        left: 0;
    }
}

/* ==========================================================================
   Accounts & Characters, Reserved Names, Hidden Accounts (2026-09-30)
   The compact card carries what an altaholic scans for: a small faction crest
   by the name, spec icon and spec before the class, "Level 90" quiet at max
   level (amber while leveling), and item level plus last played on the right.
   A Cards / Details / Table switch replaces "Toggle details" (char-views.js).
   ========================================================================== */

/* --- The card: text left, numbers right, details full width below --- */
.char-tile {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 14px;
    align-items: center;
    padding: 0.72rem 0.95rem 0.78rem;
}
.char-tile > .char-main { grid-column: 1; grid-row: 1; min-width: 0; }
.char-tile > .char-stats,
.char-tile > .char-loader { grid-column: 2; grid-row: 1; }
.char-tile > .character-details { grid-column: 1 / -1; }
.char-tile > .char-loader { flex: none; }
.character-tile.inactive .char-stats { display: none; }

.char-name-row {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
}
.char-crest {
    flex: none;
    width: 16px;
    height: 16px;
    object-fit: contain;
}
.char-name-row .char-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The title (Details view) sits on its own line under the name row */
.char-main > .char-title { margin-top: 1px; }

.char-level-class {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 6px;
    margin-top: 0.2rem;
}
.char-level { font-size: 0.82rem; font-variant-numeric: tabular-nums; }
.char-level-class.is-max .char-level,
.char-level-class.is-max .char-level-value,
.char-level-class.is-max .char-level-label { color: var(--color-text-dark); }
.char-level-class.is-leveling .char-level,
.char-level-class.is-leveling .char-level-value,
.char-level-class.is-leveling .char-level-label { color: var(--color-warning); font-weight: 600; }
.char-spec-icon {
    flex: none;
    width: 16px;
    height: 16px;
    border-radius: 4px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
}
.char-spec-icon[hidden] { display: none; }

.char-stats {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    min-width: 4.5rem;
}
.char-ilvl {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1;
}
.char-ilvl[hidden], .char-seen[hidden] { display: none; }
.char-ilvl-value {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--color-text-light, #e8edf5);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.char-ilvl-label {
    margin-top: 4px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-dark);
}
.char-seen {
    margin-top: 7px;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* --- Faction counts on account and realm bars: no "=" sum; the total stands apart --- */
.account-faction-breakdown .account-total-count,
.server-faction-breakdown .server-total-count {
    margin-left: 4px;
    padding-left: 9px;
    border-left: 1px solid rgba(255, 255, 255, 0.16);
    color: var(--color-text-light, #e8edf5);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.account-faction-count, .server-faction-count {
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    margin-right: 3px;
}

/* --- Cards / Details / Table: the combo switch's shape at the header buttons' size --- */
.view-switch {
    display: inline-flex;
    align-items: center;
    padding: 3px;
    gap: 2px;
    border: 1px solid var(--color-border-light);
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.03);
}
.view-switch__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 7px 14px;
    border: 1px solid transparent;
    border-radius: 9999px;
    background: none;
    color: var(--color-text-muted);
    font: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.view-switch__btn svg { width: 16px; height: 16px; flex: none; }
.view-switch__btn .btn-label { position: relative; top: -0.5px; }
.view-switch__btn:hover { color: var(--color-text-light, #e8edf5); }
.view-switch__btn[aria-pressed="true"] {
    border-color: rgba(39, 170, 226, 0.6);
    background: rgba(39, 170, 226, 0.16);
    color: #fff;
}
.view-switch__btn:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

/* --- Table view --- */
.char-table-wrap[hidden] { display: none; }
.char-table__scroll {
    overflow-x: auto;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    background: #0e141b;
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}
.char-table__scroll:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.char-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}
.char-table th,
.char-table td {
    padding: 10px 14px;
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    background: #0e141b;
}
.char-table tbody tr:last-child > * { border-bottom: 0; }
.char-table tbody tr:hover > * { background: #141c26; }
.char-table thead th {
    padding: 0;
    background: #121a23;
    border-bottom-color: rgba(255, 255, 255, 0.1);
}
.char-table .is-num { text-align: right; }
.char-table td.is-quiet { color: var(--color-text-muted); }
.char-table td.is-strong { color: #fff; font-weight: 700; }
.char-table td.is-leveling { color: var(--color-warning); font-weight: 600; }

.char-table__sort {
    display: flex;
    align-items: center;
    gap: 5px;
    width: 100%;
    padding: 12px 14px 11px;
    border: 0;
    background: none;
    color: var(--color-text-muted);
    font: inherit;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    cursor: pointer;
    white-space: nowrap;
}
.is-num > .char-table__sort { justify-content: flex-end; }
.char-table__sort:hover,
.char-table__sort.is-active { color: #fff; }
.char-table__sort:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; border-radius: 6px; }
.char-table__chev { width: 12px; height: 12px; flex: none; opacity: 0; transition: transform 0.15s ease, opacity 0.15s ease; }
.char-table__sort:hover .char-table__chev { opacity: 0.45; }
.char-table__sort.is-active .char-table__chev { opacity: 1; color: var(--color-primary); }
.char-table__sort.is-asc .char-table__chev { transform: rotate(180deg); }

/* The name column stays put while the rest scrolls sideways on narrow screens */
.char-table th:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    box-shadow: 1px 0 0 rgba(255, 255, 255, 0.06);
}
.char-table__who { display: inline-flex; align-items: center; gap: 8px; }
.char-table__name {
    color: var(--color-wow-gold);
    font-weight: 600;
    text-decoration: none;
}
a.char-table__name:hover { text-decoration: underline; }
.char-table__spec { display: inline-flex; align-items: center; gap: 8px; }
.char-table__spec-icon {
    width: 18px;
    height: 18px;
    border-radius: 4px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
    flex: none;
}
.char-table__spec-icon.is-empty { display: inline-block; background: rgba(255, 255, 255, 0.06); box-shadow: none; }
.char-table__class { color: var(--cc, #e8edf5); font-weight: 600; }
.char-table__cell--seen { color: var(--color-text-muted); }
.char-table__empty {
    margin: 0;
    padding: 28px 16px;
    text-align: center;
    color: var(--color-text-muted);
}

/* --- Reserved Names: name tags by realm --- */
.panel-title-stack { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.panel-title-stack h2 { margin: 0; }
.panel-header-note {
    margin: 0;
    font-size: 0.85rem;
    color: var(--color-text-muted);
}
.reserved-server-group { gap: 10px; }
.reserved-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 2px 2px 4px;
}
.character-tile.reserved-tile {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    padding: 5px 12px 5px 6px;
    border-radius: 9999px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: #111820;
    cursor: pointer;
    overflow: visible;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.character-tile.reserved-tile:hover {
    background: #16202b;
    border-color: color-mix(in srgb, var(--cc, #8a93a3) 55%, transparent);
}
.reserved-class-icon {
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--cc, #8a93a3) 70%, transparent);
}
.reserved-tile .character-name.reserved-name {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-text-light, #e8edf5);
}
.reserved-seen {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    white-space: nowrap;
}
.reserved-seen[hidden] { display: none; }
.reserved-copy {
    flex: none;
    color: var(--color-text-muted);
    opacity: 0;
    transition: opacity 0.15s ease;
}
.reserved-tile:hover .reserved-copy,
.reserved-tile:focus-visible .reserved-copy { opacity: 0.8; }

/* --- Hidden Accounts: a quiet strip, not a peer of the panels above --- */
.panel.panel-hidden {
    background: transparent;
    border-style: dashed;
    border-color: rgba(255, 255, 255, 0.12);
    box-shadow: none;
}
.panel-hidden__title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 10px;
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-text-light, #e8edf5);
}
.panel-hidden__icon {
    width: 18px;
    height: 18px;
    opacity: 0.6;
    filter: brightness(0) invert(1);
}
.panel-hidden__note {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--color-text-muted);
}
.panel-hidden .account-header .account-show-icon {
    width: auto;
    height: auto;
    filter: none;
    padding: 6px 12px;
    gap: 6px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--color-text-light, #e8edf5);
}
.panel-hidden .account-header .account-show-icon svg { width: 15px; height: 15px; }
.panel-hidden .account-header.editing .account-show-icon { display: none; }

@media (max-width: 1100px) and (min-width: 960px) {
    .panel-header-reserved .panel-title-stack { width: 100%; margin-bottom: 10px; }
    .panel-header-accounts .view-switch { flex: 1 1 100%; }
    .panel-header-accounts .view-switch__btn { flex: 1; }
}

@media (max-width: 959px) {
    .panel-header-accounts .view-switch { display: flex; width: 100%; }
    .panel-header-accounts .view-switch__btn { flex: 1; }
    .panel-header-reserved .panel-title-stack { text-align: center; align-items: center; }
}

@media (max-width: 600px) {
    .char-tile { padding: 0.65rem 0.85rem 0.7rem; column-gap: 10px; }
    .char-ilvl-value { font-size: 1.15rem; }
    .view-switch__btn { padding: 8px 10px; gap: 6px; }
}

/* --- Mounts, Pets, Toys: collection progress beside the title (visible while closed)
       and a By source breakdown at the top of the open panel (panels-collections.js) --- */
.collection-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 20px;
    min-width: 0;
    flex: 1 1 auto;
}
.collection-head h2 { margin: 0; }
.collection-progress {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}
.collection-progress[hidden] { display: none; }
.collection-progress__text {
    font-size: 0.88rem;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.collection-progress__text strong { color: var(--color-text-light, #e8edf5); font-weight: 700; }
.collection-progress__pct {
    color: var(--color-wow-gold);
    font-weight: 700;
    font-size: 0.88rem;
    font-variant-numeric: tabular-nums;
}
.collection-progress__bar {
    position: relative;
    width: 150px;
    height: 6px;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}
.collection-progress__fill {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: inherit;
    background: linear-gradient(90deg, #b8860b, var(--color-wow-gold));
}
.collection-progress__toggle {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 2px;
    border: 0;
    background: none;
    color: var(--color-text-muted);
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}
.collection-progress__toggle:hover { color: #fff; }
.collection-progress__toggle svg { transition: transform 0.15s ease; }
.collection-progress__toggle[aria-expanded="true"] { color: #fff; }
.collection-progress__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
.collection-progress__toggle:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: 4px; }

.collection-sources[hidden] { display: none; }
.collection-sources__list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 8px 12px;
    margin: 0 0 16px;
    padding: 0 0 16px;
    list-style: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.collection-source {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 7px 10px;
    width: 100%;
    padding: 9px 11px 10px;
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.02);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.collection-source:hover { border-color: rgba(255, 255, 255, 0.18); background: rgba(255, 255, 255, 0.04); }
.collection-source[aria-pressed="true"] { border-color: rgba(39, 170, 226, 0.6); background: rgba(39, 170, 226, 0.12); }
.collection-source:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.collection-source__name {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--color-text-light, #e8edf5);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.collection-source__count {
    font-size: 0.8rem;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.collection-source__count strong { color: var(--color-text-light, #e8edf5); }
.collection-source__bar {
    grid-column: 1 / -1;
    position: relative;
    height: 4px;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.07);
    overflow: hidden;
}
.collection-source__bar > span {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: inherit;
    background: var(--color-wow-gold);
    opacity: 0.85;
}
.collection-source.is-complete .collection-source__bar > span { background: var(--color-success); opacity: 1; }

@media (max-width: 959px) {
    .panel-header-collection .collection-head { flex-direction: column; align-items: center; width: 100%; }
    .collection-progress { flex-wrap: wrap; justify-content: center; }
}

/*
 * Desktop: Mounts, Pets and Toys are three separate panels, so their headers only
 * line up if every piece sits in a column of its own width. Fixed columns put the
 * counts, percents and bars on the same verticals down the page whether the panels
 * are open or closed. Widths are in ch against the progress row's own 0.88rem, so
 * they track the type rather than a guessed pixel.
 */
@media (min-width: 960px) {
    .panel-header-collection .collection-head {
        /* Wide enough for the longest of the three titles, "Mounts", and no wider */
        --collection-title-col: 5rem;
        --collection-count-col: 14ch;
        --collection-pct-col: 4ch;
        --collection-bar-col: 150px;
        display: grid;
        grid-template-columns: minmax(var(--collection-title-col), max-content) max-content;
        align-items: center;
        column-gap: 20px;
    }
    .panel-header-collection .collection-head h2 { min-width: 0; }
    .panel-header-collection .collection-progress {
        display: grid;
        grid-template-columns:
            var(--collection-count-col)
            var(--collection-pct-col)
            var(--collection-bar-col)
            max-content;
        align-items: center;
        font-size: 0.88rem;
    }
    /* Counts end on the same vertical, so the totals read as one column */
    .panel-header-collection .collection-progress__text,
    .panel-header-collection .collection-progress__pct { justify-self: end; }
    .panel-header-collection .collection-progress__bar { width: 100%; }
}
.accounts-grid[hidden] { display: none; }
.accounts-grid[hidden] { display: none; }
/* Spec icon and class wrap together; the name row takes a title (Details) on a new line when tight */
.char-spec { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.char-name-row { flex-wrap: wrap; row-gap: 2px; }
/* The card already shows spec and item level, so the details list skips them */
.char-tile .character-details .spec,
.char-tile .character-details .ilvl { display: none; }
/* Row headers in the table read as names, not column labels */
.char-table th, .char-table td { vertical-align: middle; }
.char-table tbody th {
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: inherit;
}
/* Hidden accounts on phones: the label and "Stop hiding" never break mid-word */
.panel-hidden .account-label { white-space: nowrap; }
.panel-hidden .account-header .account-show-icon { white-space: nowrap; flex: none; }
@media (max-width: 1100px) and (min-width: 960px) {
    /* The view switch takes its own row; Copy and Export share the next */
    .panel-header-accounts .panel-header-actions { flex-wrap: wrap; row-gap: 10px; }
}

/* ==========================================================================
   Second pass (2026-09-30, owner's notes): max level reads as finished, not
   greyed; item level smaller and top right, locked to the name's baseline;
   last played as small as it can go and still read; the title shares the
   name's baseline on either side; Reserved Names tags in equal columns.
   ========================================================================== */

/* Max level: a finished, readable level. Leveling stays amber */
.char-level-class.is-max .char-level,
.char-level-class.is-max .char-level-value { color: #dde5ee; }
.char-level-class.is-max .char-level-label { color: #b4c0ce; }

/* Name row: everything on the name's baseline; the crest centers on the name */
.char-name-row { align-items: baseline; column-gap: 7px; }
.char-name-row .char-crest { align-self: center; }
.char-name-row .char-title {
    font-size: 0.78rem;
    line-height: 1;
    white-space: nowrap;
}

/* Numbers top right, sharing the name's first line; last seen sits on the floor of
   that same block, so the right column is bound to the left one at both ends rather
   than trailing off under the item level. Expanded, the floor is the top block's,
   not the whole card's, because the stats stay in row 1. */
.char-tile { align-items: start; }
.char-name-row { line-height: 1.35; }
.char-stats { padding-top: 0; }
.char-tile > .char-stats {
    align-self: stretch;
    justify-content: space-between;
    gap: 7px;
}
.char-ilvl-value {
    font-size: 1rem;
    line-height: calc(1.05rem * 1.35);
    letter-spacing: 0;
}
.char-ilvl-label { margin-top: 0; font-size: 0.58rem; letter-spacing: 0.09em; }
.char-seen { margin-top: 0; font-size: 0.68rem; letter-spacing: 0.01em; }

@media (max-width: 600px) {
    .char-ilvl-value { font-size: 0.95rem; }
}

/* Reserved Names: tags fill equal columns, two across when the account column has
   room, one when it doesn't (so many accounts still line up) */
.reserved-account-column { container-type: inline-size; }
.reserved-tags {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
}
@container (min-width: 400px) {
    .reserved-tags { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container (min-width: 760px) {
    .reserved-tags { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.reserved-tags > .character-tile.reserved-tile {
    display: flex;
    width: 100%;
    min-width: 0;
}
.reserved-tile .character-name.reserved-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.reserved-tile .reserved-seen { margin-left: auto; font-size: 0.7rem; }

/* Reserved table: names copy on click */
.char-table__copy {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
}
.char-table__copy svg { color: var(--color-text-muted); opacity: 0; transition: opacity 0.15s ease; }
.char-table__copy:hover svg,
.char-table__copy:focus-visible svg { opacity: 0.8; }
.char-table__copy:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 3px; border-radius: 4px; }
.char-table__name.is-plain { color: var(--color-text-light, #e8edf5); }
.char-table__spec-icon.is-round { border-radius: 50%; box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--cc, #8a93a3) 70%, transparent); }
.reserved-grid[hidden] { display: none; }

/* Reserved header: the switch behaves like the Accounts one at every width */
@media (max-width: 1100px) and (min-width: 960px) {
    .panel-header-reserved .panel-header-actions { flex-wrap: wrap; row-gap: 10px; }
    .panel-header-reserved .view-switch { flex: 1 1 100%; }
    .panel-header-reserved .view-switch__btn { flex: 1; }
}
@media (max-width: 959px) {
    .panel-reserved.is-expanded .panel-header-reserved .view-switch { display: flex; width: 100%; }
    .panel-header-reserved .view-switch__btn { flex: 1; }
}
@media (max-width: 600px) {
    /* Measured: at 0.95rem the number sat 1px above the name's baseline */
    .char-ilvl-value { position: relative; top: 1px; }
}
@media (max-width: 959px) {
    /* The stacked header centers its title: the title block spans the header so it centers on the panel, not on itself */
    .panel-header-reserved .panel-title-stack { width: 100%; }
}
@media (max-width: 959px) {
    /* Phones and tablets: count and percent on one line over the bar, centered under the title */
    .panel-header-collection .collection-progress { flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 8px 8px; }
    .panel-header-collection .collection-progress__bar { flex: 0 0 100%; width: 100%; max-width: 240px; }
}

/* --- Collections: batched grids and linked sources (2026-09-30) --- */
/* "Source: Drop": the source is a Wowhead link, underlined, with an external mark */
.source-link {
    color: var(--color-text-light, #e8edf5);
    text-decoration: underline;
    text-decoration-color: rgba(255, 255, 255, 0.35);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    white-space: nowrap;
    transition: color 0.15s ease, text-decoration-color 0.15s ease;
}
.source-link:hover,
.source-link:focus-visible {
    color: #fff;
    text-decoration-color: var(--color-primary);
}
.source-link:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: 3px; }
.source-link__icon {
    display: inline-block;
    margin-left: 4px;
    vertical-align: -1px;
    opacity: 0.7;
}
.source-link:hover .source-link__icon { opacity: 1; color: var(--color-primary); }

/* The row after a grid that loads the next batch as it nears the screen */
.collection-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 18px 0 4px;
}
.collection-more[hidden] { display: none; }
.collection-more__status {
    font-size: 0.8rem;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   In-page nav for signed-in players (2026-09-30, dash-nav.js): the sample's
   sign-in bar shape and entrance, floating once the Account Overview has
   scrolled away. The page keeps its height free, so nothing moves.
   ========================================================================== */
body.has-dash-nav .site-main { padding-bottom: 88px; }

.dash-nav {
    position: fixed;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    z-index: 10000;
    max-width: calc(100% - 24px);
    transform: translate(-50%, calc(100% + 24px));
    opacity: 0;
    visibility: hidden;
    transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease, visibility 0s linear 0.45s;
}
.dash-nav.is-visible {
    transform: translate(-50%, 0);
    opacity: 1;
    visibility: visible;
    transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease, visibility 0s;
}
.dash-nav__inner {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px;
    border: 1px solid rgba(39, 170, 226, 0.45);
    border-radius: 16px;
    background: rgba(8, 12, 20, 0.97);
    box-shadow: 0 -8px 40px -12px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(0, 0, 0, 0.4);
}

.dash-nav__top,
.dash-nav__filters {
    position: relative;
    display: grid;
    place-items: center;
    flex: none;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 0;
    border-radius: 11px;
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color 0.15s ease, background-color 0.15s ease;
}
.dash-nav__top:hover,
.dash-nav__filters:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }
.dash-nav__top { margin-right: 2px; }
/* A hairline between the sections and the Filters shortcut */
.dash-nav__filters { margin-left: 6px; }
.dash-nav__filters::before {
    content: "";
    position: absolute;
    left: -6px;
    top: 9px;
    bottom: 9px;
    width: 1px;
    background: rgba(255, 255, 255, 0.12);
}
.dash-nav__filters[aria-current] { color: #fff; }
.dash-nav__dot {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--color-wow-gold);
    box-shadow: 0 0 0 2px rgba(8, 12, 20, 0.97);
}
.dash-nav__dot[hidden] { display: none; }

.dash-nav__track {
    position: relative;
    display: flex;
    align-items: center;
    gap: 2px;
}
.dash-nav__pill {
    position: absolute;
    inset: 0;
    background: rgba(39, 170, 226, 0.16);
    clip-path: inset(0 100% 0 0 round 11px);
    opacity: 0;
    pointer-events: none;
    transition: clip-path 0.38s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.2s ease;
}
.dash-nav__item {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 38px;
    padding: 0 13px;
    border-radius: 11px;
    color: var(--color-text-muted);
    font-size: 0.86rem;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.15s ease;
}
.dash-nav__item[hidden] { display: none; }
.dash-nav__item svg { flex: none; }
.dash-nav__item:hover { color: var(--color-text-light, #e8edf5); }
.dash-nav__item[aria-current] { color: #fff; box-shadow: inset 0 0 0 1px rgba(39, 170, 226, 0.55); }
.dash-nav__item[aria-current] svg { color: var(--color-primary); }
.dash-nav__label { position: relative; top: -0.5px; }

.dash-nav a:focus-visible,
.dash-nav button:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

/* The phone button and its sheet */
.dash-nav__current {
    display: none;
    align-items: center;
    gap: 9px;
    flex: 1 1 auto;
    min-width: 0;
    height: 38px;
    padding: 0 12px;
    border: 1px solid rgba(39, 170, 226, 0.55);
    border-radius: 11px;
    background: rgba(39, 170, 226, 0.16);
    color: #fff;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}
.dash-nav__current-icon { display: inline-flex; color: var(--color-primary); }
.dash-nav__current-label { flex: 1 1 auto; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-nav__chev { flex: none; opacity: 0.7; transition: transform 0.2s ease; }
.dash-nav.is-sheet-open .dash-nav__chev { transform: rotate(180deg); }

.dash-nav__sheet {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + 8px);
    padding: 6px;
    border: 1px solid rgba(39, 170, 226, 0.45);
    border-radius: 16px;
    background: rgba(8, 12, 20, 0.98);
    box-shadow: 0 -12px 40px -12px rgba(0, 0, 0, 0.9);
}
.dash-nav__sheet[hidden] { display: none; }
.dash-nav__list { margin: 0; padding: 0; list-style: none; }
.dash-nav__list li[hidden] { display: none; }
.dash-nav__row {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    padding: 0 12px;
    border-radius: 11px;
    color: var(--color-text-light, #e8edf5);
    font-size: 0.92rem;
    font-weight: 600;
    text-decoration: none;
}
.dash-nav__row svg { color: var(--color-text-muted); }
.dash-nav__row:hover { background: rgba(255, 255, 255, 0.05); }
.dash-nav__row[aria-current] { background: rgba(39, 170, 226, 0.14); }
.dash-nav__row[aria-current] svg { color: var(--color-primary); }
.dash-nav__row-meta {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Tablets and small laptops: icons only (the names stay for screen readers and tooltips) */
@media (max-width: 1100px) and (min-width: 761px) {
    .dash-nav__item { padding: 0 12px; }
    .dash-nav__label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }
}

/* Phones: one button naming where you are, and the sheet */
@media (max-width: 760px) {
    .dash-nav { width: calc(100% - 24px); }
    .dash-nav__track { display: none; }
    .dash-nav__current { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
    .dash-nav, .dash-nav.is-visible, .dash-nav__pill { transition: none; }
}
/* Nav links never take the site's link underline */
.dash-nav__item, .dash-nav__item:hover, .dash-nav__item:focus, .dash-nav__row, .dash-nav__row:hover, .dash-nav__filters:hover { text-decoration: none; }

/* Nav order (owner, 2026-09-30): Filters first, Back to top last. The hairline sits
   between Filters and the sections */
.dash-nav__filters { margin-left: 0; margin-right: 6px; }
.dash-nav__filters::before { left: auto; right: -6px; }
.dash-nav__top { margin-right: 0; margin-left: 2px; }

/* Phones: a bar that holds the bottom edge of the screen, full width, only its top
   edge drawn, so it reads as part of the screen rather than a floating panel */
@media (max-width: 760px) {
    body.has-dash-nav .site-main { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
    .dash-nav {
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        max-width: none;
        transform: translateY(100%);
    }
    .dash-nav.is-visible { transform: translateY(0); }
    .dash-nav__inner {
        gap: 6px;
        padding: 7px 10px calc(7px + env(safe-area-inset-bottom, 0px));
        border: 0;
        border-top: 1px solid rgba(39, 170, 226, 0.45);
        border-radius: 0;
        box-shadow: 0 -10px 30px -10px rgba(0, 0, 0, 0.9);
    }
    /* Filters looks and spaces exactly like Back to top: no divider */
    .dash-nav__filters { margin: 0; }
    .dash-nav__filters::before { display: none; }
    .dash-nav__top { margin: 0; }
    .dash-nav__sheet {
        left: 0;
        right: 0;
        bottom: 100%;
        border: 0;
        border-top: 1px solid rgba(39, 170, 226, 0.45);
        border-radius: 0;
        padding: 6px 10px;
        box-shadow: 0 -16px 40px -12px rgba(0, 0, 0, 0.9);
    }
}

/* Phones: the sample's sign-in bar docks to the bottom edge like the section nav:
   full width, only its top edge drawn, the home-indicator inset below it (2026-09-30) */
@media (max-width: 760px) {
    .site-main.is-demo { padding-bottom: calc(68px + env(safe-area-inset-bottom, 0px)); }
    .demo-signin-bar {
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        transform: translateY(100%);
    }
    .demo-signin-bar.is-visible { transform: translateY(0); }
    .demo-signin-bar__inner {
        padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px)) 16px;
        border: 0;
        border-top: 1px solid rgba(39, 170, 226, 0.45);
        border-radius: 0;
        box-shadow: 0 -10px 30px -10px rgba(0, 0, 0, 0.9);
    }
}
@media (max-width: 640px) {
    .demo-signin-bar__inner { padding-left: 10px; }
}

/* Level (owner's pick B, 2026-09-30): max level is light with a green check; below max it
   goes quiet slate with a ring filled to its share of max. Icon and text share one middle */
.char-level { display: inline-flex; align-items: center; gap: 5px; }
.lv-icon { flex: none; width: 14px; height: 14px; display: block; }
.char-level-class.is-max .char-level,
.char-level-class.is-max .char-level-value { color: #e6edf5; }
.char-level-class.is-max .char-level-label { color: #b4c0ce; }
.char-level-class.is-max .lv-icon { color: #8fd16a; }
.char-level-class.is-leveling .char-level,
.char-level-class.is-leveling .char-level-value,
.char-level-class.is-leveling .char-level-label { color: #8d99ab; font-weight: 500; }
.char-level-class.is-leveling .lv-icon { color: #7f9bb8; }
.char-table td.is-leveling { color: #8d99ab; font-weight: 500; }
/* Measured (ink, 1x and 2x): "Level 90" sat 0.5px above the icon and class name, so it drops 0.5px */
.char-level-label, .char-level-value { position: relative; top: 0.5px; }

/* ==========================================================================
   Item level badge (owner's pick 21, 2026-09-30): a two-part badge, shield and
   "ILVL" in the lighter half, the number in the darker half. Level sits on its
   own line above spec and class
   ========================================================================== */
.char-level-class {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
}
.char-level-class .char-spec { margin: 0; }

.char-tile .char-ilvl {
    flex-direction: row;
    align-items: stretch;
    height: 24px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 7px;
    overflow: hidden;
    line-height: 1;
}
.char-tile .char-ilvl[hidden] { display: none; }
.char-tile .char-ilvl-label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 0;
    padding: 0 8px;
    background: rgba(255, 255, 255, 0.07);
    color: #c9d3df;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.char-ilvl-icon { flex: none; display: block; width: 12px; height: 12px; }
.char-tile .char-ilvl-value {
    display: inline-flex;
    align-items: center;
    padding: 0 8px;
    background: rgba(0, 0, 0, 0.25);
    color: #eef2f7;
    font-size: 0.88rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0;
    top: 0;
}
.char-tile .char-seen { margin-top: 6px; }
@media (max-width: 600px) {
    .char-tile .char-ilvl-value { font-size: 0.85rem; top: 0; }
}
/* Measured by ink at 1x, 1.25x, 1.5x and 2x (2026-09-30): each icon's middle against
   its text's middle (cap top to baseline). The crest, level icon and gender icon sat
   about 0.5px low; the badge sat about 1.3px below the name's middle; inside the badge
   "ILVL" and the number sat about 0.3px high */
.char-name-row .char-crest,
.char-level .lv-icon,
.char-race-gender .gender-icon { position: relative; top: -0.5px; }
.char-tile .char-ilvl { transform: translateY(-1.25px); }
.char-ilvl-text, .char-tile .char-ilvl-value > * { position: relative; }
.char-ilvl-text { top: 0.3px; }
.char-tile .char-ilvl-value { padding-top: 0.6px; }

/* One icon column for the card's four lines (owner, 2026-09-30): crest, level icon,
   spec icon and gender icon each sit centered in the same 16px slot, and every line
   uses the same 8px gap, so the icons share one vertical center and the name, level,
   spec and race all start at the same x */
.char-tile { --icon-col: 16px; --icon-gap: 8px; }
.char-name-row { column-gap: var(--icon-gap); }
.char-level, .char-spec { gap: var(--icon-gap); }
.char-race-gender { display: flex; align-items: center; gap: var(--icon-gap); }
.char-name-row .char-crest { flex: 0 0 var(--icon-col); width: var(--icon-col); height: 16px; object-fit: contain; }
.char-level .lv-icon { flex: 0 0 var(--icon-col); width: var(--icon-col); height: 14px; }
.char-spec .char-spec-icon { flex: 0 0 var(--icon-col); width: var(--icon-col); height: 16px; }
.char-race-gender .gender-icon { flex: 0 0 var(--icon-col); width: var(--icon-col); height: 12px; margin: 0; object-fit: contain; }
.char-race-gender .gender-icon.female { width: var(--icon-col); height: 15px; }
/* The gap belongs after the level icon only, not between "Level" and its number */
.char-level { gap: 0; }
.char-level .lv-icon { margin-right: var(--icon-gap); }
.char-level .char-level-value { margin-left: 0.28em; }
/* The title sits 4px from the name, before or after it; the crest keeps the 8px icon gap */

/* Mythic+ badge (owner's pick A1, 2026-09-30): the item level badge's twin with crossed
   swords, shown only when there's a rating. Both badges share fixed halves (measured:
   labels up to 56.1px, a four-digit rating 52.4px) so the pair lines up on both edges */
.char-tile .char-ilvl { display: grid; grid-template-columns: 57px 53px; }
.char-tile .char-ilvl[hidden] { display: none; }
.char-tile .char-ilvl-value { justify-content: flex-end; }
.char-tile .char-mplus { margin-top: 5px; }
/* The stats column spaces its own pieces: 5px between badges, 6px to last played */
.char-tile .char-stats { gap: 0; }
.char-tile .char-stats { align-self: start; justify-content: flex-start; }
/* Name row (2026-09-30): the crest sits outside the row's flow, beside the first line, and
   the row starts at the text column. When the name and its title wrap onto two lines, both
   start at the same x as the level, spec and race lines, never under the crest. The row's
   own 4px gap spaces the name and title (the old -4px pulls are gone) */
.char-name-row {
    position: relative;
    padding-left: calc(var(--icon-col) + var(--icon-gap));
    column-gap: 4px;
}
/* The crest belongs to the name (crest + name share .char-name-wrap), hanging in the icon
   column beside whichever line the name lands on, so a title before the name ("Gladiator")
   can wrap above it without taking the crest along */
.char-name-wrap {
    display: inline-flex;
    align-items: baseline;
    min-width: 0;
    max-width: 100%;
}
/* Positioned against the row, not the wrapper: left is pinned to the icon column, and top is
   left at auto, so it stays on the name's own line (the first line, or the second when a
   title before the name wraps above it) */
.char-name-row .char-crest {
    position: absolute;
    left: 0;
    top: auto;
    margin-top: calc((1.05rem * 1.35 - 16px) / 2 - 3.6px); /* measured: the crest box sits 0.2px above the name box middle, the same spot that measured within half a pixel by ink before the wrap fix */
}

/* ==========================================================================
   Character card, owner's pick H10 (2026-09-30)
   Closed: a class-color glow rising from the card's lower right corner, the
   class stamp in that corner, no last played. Open: no divider; the same glow
   carries straight down (it's pinned at the closed card's corner, so it never
   moves), facts on the left, the character on the right in a pool of class
   light, and the stamp grows at the card's new bottom right.
   ========================================================================== */
.char-tile { position: relative; isolation: isolate; }
.char-tile .char-seen { display: none; }

/* The glow sits after the race line with no top set, so its static position is the
   closed card's content bottom; pushed to the card's right edge and centered there
   (0.78rem = the card's bottom padding). It stays put when the card opens */
.char-glow {
    position: absolute;
    z-index: -1;
    right: -340px;
    width: 680px;
    height: 640px;
    margin-top: calc(-320px + 0.78rem);
    pointer-events: none;
    background: radial-gradient(340px 320px at 50% 50%, color-mix(in srgb, var(--cc) 20%, transparent), transparent 72%);
}

.char-stamp {
    position: absolute;
    right: 14px;
    bottom: 12px;
    z-index: 1;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--cc) 65%, transparent);
    pointer-events: none;
}
.character-tile.expanded .char-stamp {
    width: 30px;
    height: 30px;
    right: 12px;
    bottom: 12px;
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--cc) 70%, transparent), 0 0 18px -2px color-mix(in srgb, var(--cc) 55%, transparent);
}
.character-tile.inactive .char-stamp { opacity: 0.5; }

/* The open part: no rule, the glow carries on */
.char-tile > .character-details {
    border-top: 0;
    margin-top: 14px;
    padding-top: 0;
    font-size: inherit;
    container-type: inline-size;
}
.cd-stage {
    position: relative;
    min-height: 250px;
    height: 100%;
    overflow: hidden;
    background: radial-gradient(42% 16% at 50% 93%, color-mix(in srgb, var(--cc) 32%, transparent), transparent 70%);
}
/* Renders are 1600x1200 with the feet at y 980; this shows y 250 to 990 */
.cd-stage img {
    position: absolute;
    top: -33.78%;
    left: 50%;
    width: auto;
    height: 162.16%;
    max-width: none;
    transform: translateX(-50.6%);
}
.cd-stage.is-inset img { top: 0; height: 100%; left: 50%; transform: translateX(-50%); }


/* Account Overview stacked (959px and below, 2026-09-30): the main faction glow moves
   from the desktop's upper right to center behind the line-up, which now sits under the
   copy. The glow box grows to reach it; the two faint corner glows stay where they were */
@media (max-width: 959px) {
    .dash-overview::before,
    .dash-overview::after { height: 1100px; }
    .dash-overview::before {
        background:
            radial-gradient(78% 26% at 50% 56%, rgba(var(--alliance-rgb), 0.24), transparent 70%),
            radial-gradient(40% 30% at 100% 0%, rgba(var(--alliance-rgb), 0.12), transparent 70%),
            radial-gradient(35% 28% at 0% 0%, rgba(var(--alliance-rgb), 0.07), transparent 70%);
    }
    .dash-overview::after {
        background:
            radial-gradient(78% 26% at 50% 56%, rgba(var(--horde-rgb), 0.24), transparent 70%),
            radial-gradient(40% 30% at 100% 0%, rgba(var(--horde-rgb), 0.12), transparent 70%),
            radial-gradient(35% 28% at 0% 0%, rgba(var(--horde-rgb), 0.07), transparent 70%);
    }
}

/* Narrow phones: the Sample data flag steps aside (the sample bar and the sign-in intro
   already say it's a sample) */
@media (max-width: 399px) {
    .dash-overview__meta .demo-flag { display: none; }
}

/* View as (admins) on narrow screens (2026-09-30): a select is as wide as its longest
   option by default, so a long BattleTag pushed it off screen. It may shrink now, and the
   chosen name is cut with an ellipsis */
@media (max-width: 959px) {
    .dash-overview__meta .lineup-sort,
    .panel .dash-overview__meta .lineup-sort select { min-width: 0; }
    .panel .dash-overview__meta .lineup-sort select {
        flex: 1 1 0;
        width: 0;
        text-overflow: ellipsis;
        white-space: nowrap;
        overflow: hidden;
    }
    .dash-overview__meta .lineup-sort__label { flex: none; }
}

/* The character shows whole (2026-09-30): measured on 40 real renders, a quarter of
   characters start above row 250 (horns, antlers, raised weapons, as high as 196) and
   feet reach 1024, so the window is rows 180 to 1030 now, in a taller stage */
.cd-stage { min-height: 300px; }
.cd-stage img { top: -21.18%; height: 141.18%; }

/* Account Overview numbers on narrow phones: two columns that wrap, not three squeezed */
@media (max-width: 399px) {
    .dash-overview__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 16px; }
}


/* The race line runs under the badge column (2026-09-30): it's the card's last line, and
   the item level and Mythic+ badges end well above it, so a long race ("Lightforged
   Draenei", "Highmountain Tauren") gets the room instead of wrapping in the name column.
   88px = the badges' 110px (57 + 53) plus the 14px column gap, less 36px kept clear for
   the class stamp in the bottom right corner. */
.char-tile > .char-main > .char-race-gender { margin-right: -77px; } /* 99px badges since 1.0.213 (was 88 at 110px) */

/* Floor light, refined (2026-09-30): the old pool (16% tall, centered at 93%) ran past the
   stage's bottom and was cut in a straight line. The feet sit at 94% of the stage (row 980
   of the 180 to 1030 window), so the pool is now a flat ellipse there that fades to nothing
   by 99.5%, with a wide, faint wash above it that's also gone before the edge. */
.cd-stage {
    background:
        radial-gradient(40% 7.5% at 50% 92%, color-mix(in srgb, var(--cc) 34%, transparent), color-mix(in srgb, var(--cc) 12%, transparent) 55%, transparent 100%),
        radial-gradient(55% 26% at 50% 72%, color-mix(in srgb, var(--cc) 9%, transparent), transparent 100%);
}

/* Narrow phones (399px and below, 2026-09-30): the card goes to one column so the name,
   spec and race get the full width. The item level and Mythic+ badges go on their own row
   under the race line, left-aligned with the icons above, stacked (two 110px badges beside
   each other ran into the class stamp in the corner); the spec line names only
   the spec ("Havoc", not "Havoc Demon Hunter") once it has loaded, and a long race may wrap. */
@media (max-width: 399px) {
    .char-tile { grid-template-columns: minmax(0, 1fr); }
    .char-tile > .char-stats,
    .char-tile > .char-loader { grid-column: 1; grid-row: 2; }
    .char-tile > .char-stats {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 5px 6px;
        min-width: 0;
        margin-top: 8px;
        padding-right: 40px; /* the class stamp's corner (22px at 14px from the edge) */
    }
    .char-tile .char-mplus { margin-top: 0; }
    .char-tile > .char-main > .char-race-gender { margin-right: 0; }
    .char-spec-name:not(:empty) + .char-class-text { display: none; }
}

/* The opened card, S0 (owner's pick, 2026-09-30): one centered column, 18px between every
   block: the class icon on a divider, Guild, the character with the faction crest peeking
   out behind, Professions, Last played. Labels sit between short class-color rules. The
   closed card's class stamp hides once the card opens (the divider's icon takes over). */
.character-tile.expanded .char-stamp { display: none; }
.cd {
    display: grid;
    gap: 18px;
    text-align: center;
}
.cd-orn { display: flex; align-items: center; gap: 10px; }
.cd-orn::before,
.cd-orn::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, transparent, color-mix(in srgb, var(--cc) 60%, transparent));
}
.cd-orn::after { transform: scaleX(-1); }
.cd-orn img {
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--cc) 70%, transparent), 0 0 14px -2px var(--cc);
}
.cd-block { position: relative; z-index: 1; }
.cd-lab {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--cc) 70%, #c9d3df);
}
.cd-lab::before,
.cd-lab::after { content: ''; width: 22px; height: 1px; background: color-mix(in srgb, var(--cc) 50%, transparent); }
.cd-val { margin-top: 3px; font-size: 0.92rem; font-weight: 500; line-height: 1.35; color: #e6edf5; }
.cd-val a { color: inherit; text-decoration: none; }
.cd-val a:hover { text-decoration: underline; }
.cd-dot { margin: 0 5px; color: var(--color-text-dark); }
.cd-when { display: block; font-weight: 700; color: #fff; }
.cd-sub { display: block; margin-top: 2px; font-size: 0.74rem; font-weight: 500; color: var(--color-text-muted); }
.cd-stage { min-height: 290px; }
.cd-stage img { z-index: 1; }
/* The crest: wider than the character (-4% each side) and fading down, so its wings and
   tips show around the character and it's gone before the floor light */
.cd-crest {
    position: absolute;
    left: -4%;
    right: -4%;
    top: 0;
    bottom: 8%;
    z-index: 0;
    pointer-events: none;
    background: linear-gradient(to bottom, color-mix(in srgb, var(--fc) 30%, transparent), color-mix(in srgb, var(--fc) 8%, transparent) 70%, transparent 92%);
    -webkit-mask: var(--glyph) center / contain no-repeat;
    mask: var(--glyph) center / contain no-repeat;
}
.cd-crest--alliance { --glyph: url("/img/ui/alliance.svg"); --fc: rgb(72, 146, 255); }
.cd-crest--horde { --glyph: url("/img/ui/horde.svg"); --fc: rgb(232, 52, 44); }

/* Item level and Mythic+ badges 10% smaller (2026-09-30, owner's call). zoom, not a
   transform, so the badge column itself narrows (99px, was 110) and nothing leaves a gap;
   the long-race reach above follows it. */
.char-tile .char-stats > .char-ilvl { zoom: 0.9; }

/* Open cards: the title always gets its own line (2026-09-30, owner's call), under the name
   ("Ashvale" / "the Unbroken") or above it when it comes first ("Gladiator" / "Ashvale").
   Both lines start at the text column, and the crest stays on the name's line. */
.character-tile.expanded .char-name-row .char-title { flex-basis: 100%; }
.cd-none { color: var(--color-text-muted); font-weight: 500; }
/* A little more room under Last played's date, the card's closing line (2026-09-30) */
.cd { padding-bottom: 8px; }

/* The background fill's countdown under Accounts & Characters (tiles.js fillStatus) */
.char-fill-status { margin: -4px 0 12px; font-size: 0.8rem; color: var(--color-text-muted); }
.char-fill-status[hidden] { display: none; }

/* Waiting on Battle.net (2026-09-30, owner's picks W3, D4, T4). One look in all three views:
   the character's class color. Cards: a class-color ring where the badges will be, the card
   at full strength. Details: the sheet's own shape (tiles.js renderWaitingSheetHtml), bars
   where the values will be and the ring where the character will stand, in front of the
   crest. Table: class-color bars in the detail columns. */
.character-tile.inactive .char-stamp { opacity: 1; }
.character-tile .char-loader::before {
    width: 20px;
    height: 20px;
    box-sizing: border-box;
    border-radius: 50%;
    background: none;
    border: 2px solid color-mix(in srgb, var(--cc, #8a93a3) 25%, transparent);
    border-top-color: var(--cc, #8a93a3);
    -webkit-mask: none;
    mask: none;
    animation: spin 0.75s linear infinite;
}
.char-tile > .char-loader { align-self: start; justify-content: flex-end; padding-top: 2px; }
.cd-wait-bar {
    position: relative;
    display: inline-block;
    height: 11px;
    border-radius: 6px;
    vertical-align: middle;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.08);
}
.cd-wait-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--cc, #8a93a3) 38%, transparent) 50%, transparent 80%);
    background-size: 220% 100%;
    animation: cd-wait-sweep 1.4s linear infinite;
}
.cd.is-waiting .cd-stage { display: grid; place-items: center; }
.cd-wait-ring {
    position: relative;
    z-index: 1;
    width: 26px;
    height: 26px;
    box-sizing: border-box;
    border-radius: 50%;
    border: 2.5px solid color-mix(in srgb, var(--cc) 25%, transparent);
    border-top-color: var(--cc);
    animation: spin 0.75s linear infinite;
}
@keyframes cd-wait-sweep { from { background-position: 130% 0; } to { background-position: -30% 0; } }
@media (prefers-reduced-motion: reduce) {
    .character-tile .char-loader::before,
    .cd-wait-ring,
    .cd-wait-bar::after { animation: cd-wait-still 1.6s ease-in-out infinite; }
    @keyframes cd-wait-still { 50% { opacity: 0.45; } }
}

/* W3: the waiting card stays at full strength (global.css halves it) and can still be opened
   (its waiting sheet shows); the class name keeps the icon column while the spec icon waits */
.character-tile.inactive { opacity: 1; cursor: pointer; }
.char-spec-icon[hidden] { display: inline-block; visibility: hidden; }

/* No characters in this region (2026-09-30, dashboard/index.php $isEmptyFetch): said in the
   hero, with a button per region that has characters. */
.dash-empty { margin: 4px 0 20px; max-width: 460px; }
.dash-empty__title { margin: 0 0 6px; font-size: 1.15rem; font-weight: 700; color: #fff; }
.dash-empty__text { margin: 0; font-size: 0.95rem; line-height: 1.55; color: var(--color-text-muted); }
.dash-empty__regions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.dash-empty__region {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px 8px 8px;
    border: 1px solid var(--color-border-input);
    border-radius: var(--radius-lg);
    background: rgba(255, 255, 255, 0.04);
    color: var(--color-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.dash-empty__region:hover,
.dash-empty__region:focus-visible {
    background: rgba(255, 255, 255, 0.08);
    border-color: color-mix(in srgb, var(--color-primary) 55%, transparent);
}
.dash-empty__code {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 9px;
    background: rgba(39, 170, 226, 0.14);
    color: var(--color-primary);
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.04em;
}
.dash-empty__region-text { display: grid; line-height: 1.25; }
.dash-empty__region-name { font-size: 0.92rem; font-weight: 600; }
.dash-empty__region-count { font-size: 0.78rem; color: var(--color-text-muted); }
.dash-empty__note { margin: 14px 0 0; font-size: 0.8rem; color: var(--color-text-dark); }

/* Classic dashboards (2026-09-30, <html data-dash-classic>): Blizzard's Classic API has no
   mounts, pets, toys or professions, and the race and class combos differ per version, so those
   panels, their nav items and hero numbers aren't shown. !important: setPanelsVisible() shows
   panels with jQuery after a fetch. Achievements only exist for MoP Classic. */
:root[data-dash-classic] :is(.panel-combos, .panel-mounts, .panel-pets, .panel-toys) { display: none !important; }
:root[data-dash-classic] .dash-nav :is([data-dash-key="combos"], [data-dash-key="mounts"], [data-dash-key="pets"], [data-dash-key="toys"]) { display: none !important; }
:root[data-dash-classic] .dash-nav__sheet li:has(:is([data-dash-key="combos"], [data-dash-key="mounts"], [data-dash-key="pets"], [data-dash-key="toys"])) { display: none !important; }
:root[data-dash-classic] .dash-overview__stats > div:has(:is(.mounts-icon, .pets-icon, .toys-icon)) { display: none; }
:root[data-dash-classic]:not([data-dash-classic="mop"]) .dash-overview__stats > div:has(.achievements-icon) { display: none; }

/* Characters Blizzard has no details for (2026-09-30, tiles.js markUnavailableTiles): a muted
   pill where the badges go, and an opened card that explains instead of staying empty */
.char-nodetails {
    display: inline-flex;
    align-items: center;
    height: 22px;
    padding: 0 9px;
    border-radius: 999px;
    border: 1px dashed rgba(255, 255, 255, 0.18);
    color: var(--color-text-muted);
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}
.cd--nodetails { padding-bottom: 8px; }
.cd-nodetails__text { margin: 8px auto 0; max-width: 380px; font-size: 0.9rem; line-height: 1.55; color: #cfd8e3; }
.cd-nodetails__sub { margin: 8px auto 0; max-width: 380px; font-size: 0.8rem; color: var(--color-text-muted); }

/* Game pills at the top of the hero (owner's pick G2, 2026-09-30): Retail, MoP, TBC, Era with
   each game's character count; the current one lit in its game color (Retail blue, Classic
   gold). Scrolls sideways on a narrow phone. */
.dash-games {
    display: inline-flex;
    gap: 2px;
    max-width: 100%;
    margin: 0 0 14px;
    padding: 3px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.35);
    border: 1px solid rgba(255, 255, 255, 0.1);
    overflow-x: auto;
    scrollbar-width: none;
}
.dash-games::-webkit-scrollbar { display: none; }
.dash-games__opt {
    --ga: var(--game-classic, #e0b35a);
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: 7px;
    padding: 6px 12px;
    border: 0;
    border-radius: 999px;
    background: none;
    color: var(--color-text-muted);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.dash-games__opt[data-g="retail"] { --ga: var(--color-primary); }
.dash-games__opt:hover { color: #fff; background: rgba(255, 255, 255, 0.05); }
.dash-games__opt[aria-pressed="true"] { background: color-mix(in srgb, var(--ga) 22%, #121922); color: #fff; }
.dash-games__icon { display: inline-flex; color: var(--ga); }
.dash-games__count { font-size: 0.7rem; font-weight: 600; color: var(--color-text-muted); }
.dash-games__count.is-none { color: var(--color-text-dark); font-weight: 500; }
.dash-games__opt[aria-pressed="true"] .dash-games__count:not(.is-none) { color: #dfe6ee; }

/* WoW Forever in the game pills, after Retail, in its violet and marked Soon. Pickable since
   1.0.229: the hero then says it's coming (dashboard/index.php $isForever). */
.dash-games__opt[data-g="forever"] { --ga: var(--game-forever, #a98bf5); }
.dash-games__soon { font-size: 0.6rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--game-forever, #a98bf5); }

/* Game pills aligned by ink (2026-10-01, measured in WebKit and Chromium with Inter loaded):
   a fixed height and line-height 1, and each piece of text trimmed to its capitals and baseline
   (text-box), so flex centering centers the letters themselves. Without the trim, Chromium put
   the labels about 1px above the middle while WebKit (iPhone) had them centered, and no pixel
   nudge suits both. Browsers without text-box fall back to the untrimmed line box. */
.dash-games__opt { height: 31px; padding-top: 0; padding-bottom: 0; line-height: 1; }
.dash-games__opt :is(.dash-games__name, .dash-games__count, .dash-games__soon) { text-box: trim-both cap alphabetic; }

/* Game pills on a phone (2026-09-30, 1.0.229): below 475px the icons go (the lit pill's color
   already says which game) and Forever shrinks to its violet icon, so all five fit on a 360px
   screen. Narrower than that the row scrolls: init.js gamePills() brings the lit pill into view
   and fades whichever edge has more pills behind it. */
.dash-games { position: relative; }
.dash-games.has-more-end { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); }
.dash-games.has-more-start { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 36px), transparent); }
.dash-games.has-more-start.has-more-end { -webkit-mask-image: linear-gradient(to right, transparent, #000 36px, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to right, transparent, #000 36px, #000 calc(100% - 36px), transparent); }
@media (max-width: 474px) {
    .dash-games__opt { gap: 4px; padding: 0 8px; }
    .dash-games__opt:not([data-g="forever"]) .dash-games__icon { display: none; }
    .dash-games__opt[data-g="forever"] :is(.dash-games__name, .dash-games__soon) { display: none; }
}

/* WoW Forever picked (2026-09-30, 1.0.229): the hero's coming-soon state, the same pattern as an
   empty region, with a button back to each game that has characters, in that game's color */
.dash-forever__icon { display: inline-flex; margin-right: 8px; color: var(--game-forever, #a98bf5); vertical-align: -2px; }
.dash-forever .dash-empty__region { --ga: var(--game-classic, #e0b35a); }
.dash-forever .dash-empty__region[data-g="retail"] { --ga: var(--color-primary); }
.dash-forever .dash-empty__region:hover,
.dash-forever .dash-empty__region:focus-visible { border-color: color-mix(in srgb, var(--ga) 55%, transparent); }
.dash-empty__code--game { background: color-mix(in srgb, var(--ga) 14%, transparent); color: var(--ga); }
.dash-forever .dash-empty__note a { color: var(--game-forever, #a98bf5); text-underline-offset: 3px; }
