/* ═══════════════════════════════════════════════════════════════════════════
   ACCOUNT MENU  (`.profile-*`)  —  ONE component, two pages
   ═══════════════════════════════════════════════════════════════════════════

   The trigger chip and the dropdown it opens, shared verbatim by the dashboard
   topbar and the landing page nav. It was split across two files and one page
   until 2026-08-16: the menu lived in dashboard.css, the chip in shell.css, and
   the marketing site had a bare avatar with nothing behind it.

   ⚠️ BOTH COPIES WERE DELETED, not left in place. Two stylesheets declaring the
   same component is a drift trap with a specificity winner — shell.css scoped
   the chip as `.navbar .profile-btn`, so a later edit here would have been
   silently inert on the dashboard, which is exactly the failure the deleted
   dashboard.css block documents happening once already.

   Requires: nb-tokens.css (--nb-*) and z-index.css (--z-dropdown). Both pages
   load this AFTER their own sheets.

   The markup is identical on both pages — `.profile-dropdown > .profile-btn +
   .profile-menu` — so the two stay one component rather than two lookalikes.
   The dashboard adds a stats row and a couple of rows the marketing site has
   no route for; everything else is shared.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- Trigger chip ------------------------------------------------------ */
/* Unscoped, so the landing nav gets it too. It was `.navbar .profile-btn`. */
/* ---- Profile chip ------------------------------------------------------- */
.profile-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    padding: 0 8px 0 4px;
    border: none;
    border-radius: 8px;
    background: none;
    box-shadow: none;
    cursor: pointer;
    transition: background-color 0.16s cubic-bezier(0.4, 0, 0.2, 1);
}
.profile-btn:hover { background-color: rgba(255, 255, 255, 0.055); }
.profile-btn .user-avatar {
    width: 25px;
    height: 25px;
    border-radius: 50%;
    border: none;
    flex: none;
}
/* A brand ring on hover — the one purple accent up here, and only while the
   pointer is on the thing it belongs to. */
.profile-btn:hover .user-avatar { box-shadow: 0 0 0 2px rgba(167, 139, 250, 0.45); }
.profile-btn .user-name {
    font-size: 0.78rem;
    font-weight: 600;
    color: #c8cbd1;
    max-width: 130px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.profile-btn svg { flex: none; color: #5b5f67; transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1); }
.profile-btn.active svg { transform: rotate(180deg); }

/* ═══════════════════════════════════════════════════════════════════════════
   ACCOUNT MENU  (`.profile-*`)  —  migrated onto the design system

   ⚠️ THE TRIGGER CHIP IS NOT STYLED HERE. shell.css:193-227 declares
   `.navbar .profile-btn` in full and wins on specificity; the ~25 lines that
   used to sit here were 100% inert and were the first thing anyone editing
   this component found. Only `.profile-dropdown` (the positioning context)
   and the menu itself belong to this file now.

   ─── WHAT WAS DELETED ────────────────────────────────────────────────────
   About a third of the component was dead code, and one dead rule leaked
   data:

     · `.user-avatar::after` built an "ID: <snowflake>" tooltip on an <img> —
       a replaced element, which never renders pseudo-elements. It has never
       worked, and dashboard.js was still writing the user's Discord id into
       a DOM attribute to feed it. Both are gone.
     · `.menu-toggle-*` and `.profile-menu-toggle-item` (68 lines) styled
       controls that are not in the markup. Their loader, loadUserSettings(),
       targets two ids that do not exist either.
     · `.logout-btn` and the inert `.profile-btn` block.

   ─── AND WHAT CHANGED ────────────────────────────────────────────────────
   The top 120px carried FOUR stacked box borders plus a ring: the menu's own
   border, a second hairline from its box-shadow, the header's bottom rule,
   the stats box's full border and the badge's border, with two more verticals
   inside the stats tile. Depth is the surface now.

   Every group boundary was also marked twice — a divider AND a label — and
   nothing lined up on the left: the header padded 16px and the rows 17.6px,
   so the avatar and the icon column started on different verticals. One
   gutter now, and the label alone opens a group.
   ═══════════════════════════════════════════════════════════════════════════ */

.user-avatar {
    width: 28px;
    height: 28px;
    border-radius: var(--nb-r-avatar);
    border: none;
    cursor: pointer;
    flex-shrink: 0;
}

.user-name {
    font-weight: 500;
    font-size: 0.88rem;
    color: var(--nb-ink-2);
}

.profile-dropdown { position: relative; }

.profile-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 272px;
    box-sizing: border-box;
    padding: var(--nb-sp-2);
    background: var(--nb-surface-float);
    border: 1px solid var(--nb-line);
    border-radius: var(--nb-r-menu);
    opacity: 0;
    visibility: hidden;
    transform: translateY(calc(var(--nb-pop-slide) * -1)) scale(var(--nb-pop-scale));
    transition: opacity var(--nb-t-pop) var(--nb-ease-out),
                transform var(--nb-t-pop) var(--nb-ease-out),
                visibility var(--nb-t-pop);
    box-shadow: var(--nb-elev-float);
    z-index: var(--z-dropdown);
    /* A short viewport must scroll the menu rather than clip it. The old
       build hid the overflow and guarded it with a @media (max-height: 600px)
       rule, which left a 7px band where the menu was cut with no scrollbar
       and no indication anything was missing. */
    max-height: calc(100vh - 70px);
    max-height: calc(100dvh - 70px);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.profile-menu.show {
    opacity: 1;
    visibility: visible;
    transform: translateY(0) scale(1);
}

/* ---- Identity ---------------------------------------------------------- */
.profile-menu-header {
    display: flex;
    align-items: center;
    gap: var(--nb-sp-3);
    padding: var(--nb-sp-2) var(--nb-sp-2) var(--nb-sp-3);
}

.profile-menu-avatar {
    width: 38px;
    height: 38px;
    border-radius: var(--nb-r-avatar);
    border: none;
    flex-shrink: 0;
}

.profile-menu-header-info {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    flex: 1;
}

.profile-menu-name {
    font-weight: 650;
    font-size: 0.875rem;
    color: var(--nb-ink-1);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The handle was on the same payload all along and was never rendered, so
   the whole 120px header added exactly one item of information. */
.profile-menu-handle {
    font-size: 0.775rem;
    color: var(--nb-ink-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.profile-menu-badge {
    flex: none;
    align-self: center;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--nb-brand-ink);
    background: var(--nb-brand-soft);
    padding: 3px 7px;
    border: none;
    border-radius: var(--nb-r-pill);
    white-space: nowrap;
}
.profile-menu-badge[hidden] { display: none; }

/* ---- Mini stats -------------------------------------------------------- */
/* Value over label, not value beside label: at 0.82rem/700 next to
   0.7rem/500 on one line the cell read as a single run of text. Each cell can
   shrink, so a six-figure XP total no longer widens the whole menu after it
   loads — the old build resized under the cursor on every open. */
.profile-menu-stats {
    display: flex;
    align-items: stretch;
    gap: var(--nb-sp-1);
    margin-bottom: var(--nb-sp-2);
    padding: 0 var(--nb-sp-1);
}

.profile-menu-stat {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    flex: 1 1 0;
    min-width: 0;
    padding: var(--nb-sp-2);
    border-radius: var(--nb-r-btn);
    background: var(--nb-surface-hover);
}

.profile-menu-stat-value {
    font-weight: 650;
    font-size: 0.85rem;
    color: var(--nb-ink-1);
    font-variant-numeric: var(--nb-num);
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.profile-menu-stat-label {
    font-size: 0.68rem;
    font-weight: 500;
    color: var(--nb-ink-faint);
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---- Groups ------------------------------------------------------------ */
/* --nb-ink-faint at 4.86:1. The old rule set var(--text-dim) AND
   opacity: 0.6; the two attenuations compounded to ~3.4:1 at 10.9px. */
.profile-menu-section-label {
    padding: var(--nb-sp-2) var(--nb-sp-2) var(--nb-sp-1);
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--nb-ink-faint);
}

/* A boundary is marked once. Every group carried a divider AND a label. */
.profile-menu-divider {
    height: 1px;
    background: var(--nb-line-faint);
    margin: var(--nb-sp-2) var(--nb-sp-2) 0;
}

/* ---- Rows -------------------------------------------------------------- */
.profile-menu-item {
    display: flex;
    align-items: center;
    gap: var(--nb-sp-3);
    width: 100%;
    min-height: var(--nb-h-lg);
    padding: var(--nb-sp-2);
    background: transparent;
    border: none;
    border-radius: var(--nb-r-btn);
    color: var(--nb-ink-2);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--nb-t-hover) var(--nb-ease),
                color var(--nb-t-hover) var(--nb-ease);
    font-weight: 500;
    font-size: 0.845rem;
    box-sizing: border-box;
    font-family: inherit;
}

.profile-menu-item:hover { background: var(--nb-surface-hover); color: var(--nb-ink-1); }
.profile-menu-item:active { background: var(--nb-surface-active); }
/* There was no focus style anywhere in this component, while a sibling
   element four pixels away in the same topbar uses a proper ring. */
.profile-menu-item:focus-visible { outline: var(--nb-focus-ring); outline-offset: -2px; }

.menu-item-icon {
    flex-shrink: 0;
    color: var(--nb-ink-4);
    transition: color var(--nb-t-hover) var(--nb-ease);
}
/* Ink, not the legacy purple. Purple as a generic interaction accent is what
   the token layer reserves for the assistant and the paid tier. */
.profile-menu-item:hover .menu-item-icon { color: var(--nb-ink-2); }

/* Says the row leaves the dashboard, so the new tab is not a surprise. */
.menu-item-out { flex: none; margin-left: auto; color: var(--nb-ink-4); }

.profile-menu-item.logout-item { color: var(--nb-ink-2); }
.profile-menu-item.logout-item:hover {
    background: var(--nb-danger-soft);
    color: var(--nb-danger-ink);
}
.profile-menu-item.logout-item:hover .menu-item-icon { color: var(--nb-danger-ink); }

/* Responsive. 767, matching the shell's phone boundary — this was 480px, so
   every phone in landscape and every small tablet got the desktop menu.
   `width`, not `min-width`: a min-width could not shrink and the menu is
   right-anchored, so on a narrow screen it grew off the left edge.

   ⚠️ The short-viewport rule that used to live here is gone. `.profile-menu`
   now caps its own height against the viewport and scrolls, at every size —
   the old @media (max-height: 600px) guard left a band between 601px and
   ~607px where the menu was clipped by its own overflow:hidden with no
   scrollbar and nothing to say content was missing. */
@media (max-width: 767px) {
    .profile-menu {
        width: min(320px, calc(100vw - 16px));
        right: -4px;
    }
    /* Thumb-sized. These are the primary targets inside the mobile sheet and
       they were 40px, under the --nb-h-tap floor the token layer sets. */
    .profile-menu-item { min-height: var(--nb-h-tap); }
}

