/* Avatar builder + "Currently Wearing" shelf.
 *
 * LIGHT THEME IS THE DEFAULT, dark is an override under .av-dark. Not the other
 * way round: the apex renders light by default, and a page whose variables only
 * exist for dark chrome is unreadable there — that is exactly how the
 * leaderboard ended up broken. Every colour below resolves in both modes.
 */

.av-page {
    --av-bg: #faf8f3;
    --av-surface: #ffffff;
    --av-border: #e5e0d2;
    --av-text: #1a1610;
    --av-muted: #6a6458;
    --av-accent: var(--primary, #d4af37);
    --av-locked: #a89e88;

    background: var(--av-bg);
    color: var(--av-text);
}

.av-page.av-dark {
    --av-bg: #0d0b08;
    --av-surface: #1a1610;
    --av-border: #332e25;
    --av-text: #f3f0e8;
    --av-muted: #a89e88;
    --av-locked: #56503f;
}

.av-wrap {
    max-width: 1100px;
    margin: 0 auto;
    padding: 2rem 1.25rem 4rem;
}

.av-head {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 2rem;
}
.av-head h1 { font-size: clamp(1.6rem, 3vw, 2.2rem); margin: 0 0 .35rem; }
.av-sub { color: var(--av-muted); margin: 0; max-width: 56ch; }

.av-grid {
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: 2rem;
    align-items: start;
}

/* ─── Preview ─────────────────────────────────────────────────────── */
.av-preview {
    position: sticky;
    top: 1.5rem;
    background: var(--av-surface);
    border: 1px solid var(--av-border);
    border-radius: 16px;
    padding: 1.25rem;
}
.av-stage {
    aspect-ratio: 1;
    display: grid;
    place-items: center;
    margin-bottom: 1rem;
}
/* Circular mask, matching how avatars are shown everywhere else on the site —
   the frames are rendered inset specifically so this crop does not clip them. */
.av-stage img {
    width: 100%;
    border-radius: 50%;
    image-rendering: pixelated;
    background: transparent;
}
.av-actions { display: grid; gap: .6rem; }
.av-status { margin: 0; min-height: 1.2em; font-size: .875rem; color: var(--av-muted); }
.av-note {
    margin: 1rem 0 0;
    font-size: .8125rem;
    color: var(--av-muted);
    line-height: 1.5;
}

/* ─── Buttons ─────────────────────────────────────────────────────── */
.av-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: .6rem 1.2rem;
    border-radius: 999px;
    border: 1px solid transparent;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    transition: filter .2s, border-color .2s;
}
.av-btn-primary { background: var(--av-accent); color: #0d0b08; }
.av-btn-primary:hover { filter: brightness(1.08); }
.av-btn-primary:disabled { opacity: .6; cursor: default; }
.av-btn-ghost {
    background: transparent;
    border-color: var(--av-border);
    color: var(--av-text);
}
.av-btn-ghost:hover { border-color: var(--av-accent); color: var(--av-text); }

/* ─── Tabs + panels ───────────────────────────────────────────────── */
.av-tabs { display: flex; gap: .5rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.av-tab {
    min-height: 44px;
    padding: .5rem 1.1rem;
    border-radius: 999px;
    border: 1px solid var(--av-border);
    background: transparent;
    color: var(--av-muted);
    font-weight: 600;
    cursor: pointer;
}
.av-tab.is-active {
    border-color: var(--av-accent);
    color: var(--av-text);
    background: color-mix(in srgb, var(--av-accent) 12%, transparent);
}

.av-panel { display: none; }
.av-panel.is-active { display: block; }
.av-empty { color: var(--av-muted); padding: 1.5rem 0; }

.av-section-title { font-size: 1.1rem; margin: 2rem 0 1rem; }

/* ─── Choice grids ────────────────────────────────────────────────── */
.av-choices {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: .75rem;
}
.av-choice {
    position: relative;
    padding: .35rem;
    border-radius: 14px;
    border: 2px solid var(--av-border);
    background: var(--av-surface);
    cursor: pointer;
    transition: border-color .15s, transform .15s;
}
.av-choice:hover { transform: translateY(-2px); border-color: var(--av-accent); }
.av-choice.is-selected { border-color: var(--av-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--av-accent) 30%, transparent); }
.av-choice img { width: 100%; border-radius: 10px; display: block; image-rendering: pixelated; }

/* Paging control under the face grid. */
.av-more {
    display: flex;
    align-items: center;
    gap: .85rem;
    margin-top: 1rem;
}
.av-count { font-size: .8125rem; color: var(--av-muted); }

/* Frames are wide cards, not thumbnails: the unlock CONDITION is the point, so
   it has to be readable rather than a tooltip. */
.av-frames { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
.av-frame {
    display: grid;
    gap: .25rem;
    text-align: left;
    padding: .85rem 1rem;
    min-height: 76px;
}
.av-frame-name { font-weight: 700; }
.av-frame-hint { font-size: .8125rem; color: var(--av-muted); line-height: 1.35; }

/* Locked frames stay VISIBLE and legible — dimmed, not hidden. A frame you
   cannot see cannot motivate you to earn it. */
.av-frame.is-locked {
    cursor: not-allowed;
    border-style: dashed;
    opacity: .7;
}
.av-frame.is-locked:hover { transform: none; border-color: var(--av-border); }
.av-frame.is-locked .av-frame-name { color: var(--av-locked); }
.av-lock { position: absolute; top: .5rem; right: .6rem; font-size: .8rem; opacity: .7; }

/* ─── Live preview ────────────────────────────────────────────────── */
/* Face and frame are two STACKED inline SVGs, not one composited image: the
   face is regenerated on every click and the frame is geometry that does not
   depend on it, so swapping either costs no round trip. The render pipeline
   composites them for real at save time — this is only the on-screen stand-in. */
.av-live { position: relative; width: 100%; aspect-ratio: 1; }
.av-live-face,
.av-live-frame { position: absolute; inset: 0; }
.av-live-face svg,
.av-live-frame svg { width: 100%; height: 100%; display: block; }
/* The face is inset and circularly masked to match avatarRender's CHARACTER_INSET
   and the circular crop used everywhere else on the site — without it the ring
   would overlap the head on screen but not in the saved PNG. */
.av-live-face {
    inset: 6%;
    border-radius: 50%;
    overflow: hidden;
    image-rendering: pixelated;
}
.av-live-frame { pointer-events: none; }

/* ─── Option groups ───────────────────────────────────────────────── */
.av-group {
    border: 1px solid var(--av-border);
    border-radius: 14px;
    background: var(--av-surface);
    margin-bottom: .6rem;
    overflow: hidden;
}
.av-group-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    min-height: 52px;
    padding: .75rem 1rem;
    background: transparent;
    border: 0;
    color: var(--av-text);
    cursor: pointer;
    text-align: left;
}
.av-group-label { font-weight: 700; }
.av-group-value { font-size: .8125rem; color: var(--av-muted); }
/* The caret is the only affordance saying these open, so it must invert when
   they do — an accordion with no state indicator reads as a dead heading. */
.av-group-head::after {
    content: '\25BE';
    color: var(--av-muted);
    transition: transform .15s;
}
.av-group.is-open .av-group-head::after { transform: rotate(180deg); }

.av-group-body { display: none; padding: 0 1rem 1rem; }
.av-group.is-open .av-group-body { display: block; }

/* Tighter than .av-choices: these are 16px faces, and at 84px each a 45-variant
   hair group becomes a scroll rather than a glance. */
.av-options { grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: .5rem; }
.av-option { padding: .25rem; }
/* Inline SVG, so the .av-choice img rules do not reach it. */
.av-option svg {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 10px;
    image-rendering: pixelated;
}
.av-option-name {
    display: block;
    font-size: .6875rem;
    color: var(--av-muted);
    text-align: center;
    padding-top: .15rem;
}

/* ─── Colour swatches ─────────────────────────────────────────────── */
.av-swatches {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin-bottom: 1rem;
}
.av-swatch-label {
    font-size: .75rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--av-muted);
    width: 100%;
}
.av-swatch {
    width: 32px;
    height: 32px;
    padding: 0;
    border-radius: 50%;
    border: 2px solid var(--av-border);
    background: var(--sw, transparent);
    cursor: pointer;
    transition: transform .15s, border-color .15s;
}
.av-swatch:hover { transform: scale(1.1); border-color: var(--av-accent); }
.av-swatch.is-selected {
    border-color: var(--av-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--av-accent) 30%, transparent);
}

/* Swatches are pure colour, so the hex has to reach a screen reader some other
   way — title= is not announced on a button with no accessible name. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ─── "Currently Wearing" shelf (profile) ─────────────────────────── */
.av-wearing { margin: 1.25rem 0; }
.av-wearing-title {
    font-size: .75rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--av-muted, #6a6458);
    margin: 0 0 .6rem;
}
.av-wearing-items { display: flex; flex-wrap: wrap; gap: .5rem; }
.av-wearing-item {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .85rem;
    border-radius: 999px;
    border: 1px solid var(--av-border, #e5e0d2);
    font-size: .8125rem;
    text-decoration: none;
    color: inherit;
}
.av-wearing-item:hover { border-color: var(--primary, #d4af37); color: inherit; }
.av-wearing-item img { width: 22px; height: 22px; border-radius: 50%; image-rendering: pixelated; }
/* Frames are inlined as SVG rather than a thumbnail image — the art is geometry,
   so there is no file to fetch and it stays crisp at chip size. */
.av-wearing-item svg { width: 22px; height: 22px; display: block; flex: 0 0 auto; }

/* The shelf also renders on the profile, which has no .av-page wrapper and so no
   --av-* vars. The literal fallbacks above cover light; this covers the apex/hub
   dark chrome, where the light muted grey would be unreadable. */
body.fs-dark .av-wearing-title { color: #a89e88; }
body.fs-dark .av-wearing-item { border-color: #332e25; }

@media (max-width: 860px) {
    .av-grid { grid-template-columns: 1fr; }
    .av-preview { position: static; max-width: 320px; }
}

/* ─── Styles (character families) ─────────────────────────────────── */
/* Pixel | Cartoon. Shown only on hubs that offer more than one family. */
.av-styles { display: flex; gap: .4rem; margin-bottom: 1rem; }
.av-style {
    flex: 1;
    padding: .6rem .9rem;
    border: 1px solid var(--av-border);
    border-radius: 999px;
    background: var(--av-surface);
    color: var(--av-text);
    font-weight: 600;
    cursor: pointer;
}
.av-style.is-selected { border-color: var(--av-accent); box-shadow: inset 0 0 0 1px var(--av-accent); }
.av-style-panel[hidden], .av-live-face[hidden], .av-live-fighter[hidden] { display: none; }

/* A cartoon fighter is a full body in smooth line art: shown whole (contain),
   on the same inset as the saved render, and never pixelated. */
.av-live-fighter {
    position: absolute;
    inset: 6%;
    width: 88%;
    height: 88%;
    object-fit: contain;
}
.av-fighters { display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: .5rem; }
.av-fighter { padding: .25rem; aspect-ratio: 1; }
.av-fighter img { width: 100%; height: 100%; object-fit: contain; display: block; image-rendering: auto; }
