@layer components {
    .avatar {
        width: 30px;
        height: 30px;
        border-radius: 50%;
        background: var(--bg-active);
        color: var(--fg);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
        flex-shrink: 0;
        font-size: var(--text-xs);
        font-weight: var(--weight-semibold);
        letter-spacing: -0.02em;
        line-height: 1;
    }

    /* Coloured initials. Pick .avatar-cN where N = userID % 12 so the
     * same person always gets the same chip in any list. Hues are
     * evenly spaced on the OKLCH wheel; lightness/chroma tuned per
     * theme so foreground text stays at WCAG AA in both. Index 0..11
     * maps to: warm-pink, peach, amber, lime, mint, cyan, sky, blue,
     * indigo, lavender, purple, rose. */
    .avatar-c0  { background: var(--avatar-c0);  color: var(--avatar-fg); }
    .avatar-c1  { background: var(--avatar-c1);  color: var(--avatar-fg); }
    .avatar-c2  { background: var(--avatar-c2);  color: var(--avatar-fg); }
    .avatar-c3  { background: var(--avatar-c3);  color: var(--avatar-fg); }
    .avatar-c4  { background: var(--avatar-c4);  color: var(--avatar-fg); }
    .avatar-c5  { background: var(--avatar-c5);  color: var(--avatar-fg); }
    .avatar-c6  { background: var(--avatar-c6);  color: var(--avatar-fg); }
    .avatar-c7  { background: var(--avatar-c7);  color: var(--avatar-fg); }
    .avatar-c8  { background: var(--avatar-c8);  color: var(--avatar-fg); }
    .avatar-c9  { background: var(--avatar-c9);  color: var(--avatar-fg); }
    .avatar-c10 { background: var(--avatar-c10); color: var(--avatar-fg); }
    .avatar-c11 { background: var(--avatar-c11); color: var(--avatar-fg); }

    /* Gravatar variant — <img> tag uses the same .avatar class so the
     * border-radius / overflow rules apply uniformly. object-fit
     * keeps non-square sources from squishing. */
    img.avatar {
        background: transparent;
        object-fit: cover;
    }

    /* Size modifiers. Font-size scales with the circle so initials
     * look balanced at every size. */
    .avatar-lg {
        width: 160px;
        height: 160px;
        font-size: 3.75rem;
    }

    /* Wrapper for an avatar that needs an action overlay (upload,
     * clear, etc.). The child .menu-host floats to the top-right.
     * While the host carries [data-busy], the default toggle icon
     * is replaced by the second one (intended to be a spinner —
     * pair with .spin from utilities). */
    .avatar-frame {
        position: relative;
        display: inline-block;
    }
    .avatar-frame > .menu-host {
        position: absolute;
        top: 4px;
        right: 4px;
    }
    .avatar-frame > .menu-host > .menu-toggle {
        background: var(--bg-elevated);
        border: 1px solid var(--border);
        width: 28px;
        height: 28px;
        padding: 0;
        border-radius: 50%;
        justify-content: center;
    }
}

/* Default vs busy icon swap on the avatar-frame's overflow toggle.
 * Lives in @layer utilities so it wins over .icon's display rule
 * (also in utilities) — components layer comes earlier in the
 * cascade and would lose to it regardless of specificity. */
@layer utilities {
    .avatar-frame .toggle-busy { display: none; }
    .avatar-frame[data-busy] .toggle-default { display: none; }
    .avatar-frame[data-busy] .toggle-busy { display: inline-block; }
}
