/* ══════════════════════════════════════════════════════════════
   Keln — topbar: shell, logo toggle, avatar, dropdown menu.

   ══ WHAT CHANGED AND WHY ════════════════════════════════════
   This file previously owned only `.avatar` and `.menu`. The
   `.topbar`, `.logo`, `.logo__img` and `.chip` rules lived as
   inline <style> blocks inside dashboard.html and settings.html —
   duplicated in both, and present in neither landing.html.

   landing.html links /topbar.css and uses the identical markup
   (`<a class="logo" id="logoToggle">` wrapping `.logo__img`), but
   because those rules were never in the linked file, the landing
   logo had NO styles at all: no hover glow, no focus ring, no
   press feedback, no open-state affordance. That is the "sidebar
   logo up top doesn't even get the click animation" bug. It was
   never a scripting problem — sidebar.js has always been adding
   the class correctly. There was simply nothing listening.

   The rules now live here, once, for every page that links this
   file. dashboard.html and settings.html keep working unchanged
   because their inline <style> loads after this link and still
   wins on the properties it sets — you can delete those blocks
   whenever you like, one page at a time, with no flag day.

   ══ THE PRESS ANIMATION ═════════════════════════════════════
   Three distinct states, because a toggle that only has hover is
   a toggle nobody trusts:

     :hover           the mark warms — a teal drop-shadow lifts in
     :active          it compresses to .94 in 90ms. Fast, because
                      the compression IS the tactile feedback and a
                      slow one reads as lag
     .sidebar--open   a single ring expands out of the mark once,
                      and the wordmark nudges 3px toward the panel
                      it just opened

   The ring fires on class-add, so it plays exactly once per open
   and never on close. It is drawn on a pseudo-element with
   `pointer-events:none`, so it can never eat the second click.
   ══════════════════════════════════════════════════════════════ */

/* ── Shell ──────────────────────────────────────────────────
   Any page that sets its own .topbar rules after this link keeps
   winning; this is the shared baseline, not an override. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-8);
  padding: var(--s-7) 26px;
  background: rgba(10, 14, 20, .8);
  border-bottom: 1px solid var(--border, rgba(91, 140, 255, .12));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.topbar__left {
  display: flex;
  align-items: center;
  gap: var(--s-8);
}

.topbar__right {
  position: relative;          /* anchors .menu — load-bearing */
  display: flex;
  align-items: center;
  gap: var(--s-6);
}

/* ── Logo toggle ────────────────────────────────────────────
   Negative margin against the padding so the generous hit area
   does not push the mark off the optical left edge of the bar. */
.logo {
  position: relative;
  display: flex;
  align-items: center;
  padding: var(--s-3) var(--s-5);
  margin: calc(-1 * var(--s-3)) calc(-1 * var(--s-5));
  border-radius: 10px;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  transition:
    background .25s ease,
    transform  .09s cubic-bezier(.4, 0, .2, 1);
}

.logo:hover { background: rgba(91, 140, 255, .08); }

.logo:focus-visible {
  outline: 2px solid var(--accent2, #22d3a6);
  outline-offset: 2px;
}

/* The press. Applied to the anchor rather than the image so the
   whole hit area compresses together — compressing only the
   artwork inside a static box reads as a glitch. */
.logo:active { transform: scale(.94); }

.logo__img {
  display: block;
  height: 34px;
  width: auto;
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  transition:
    transform .35s cubic-bezier(.4, 0, .2, 1),
    filter    .25s ease;
}

.logo:hover .logo__img {
  filter: drop-shadow(0 0 14px rgba(34, 211, 166, .45));
}

/* Open state. The old SVG mark mirrored itself to signal the
   toggle; mirroring a wordmark just looks broken, so the
   affordance is a nudge toward the panel plus a sustained glow. */
.logo.sidebar--open .logo__img {
  transform: translateX(3px);
  filter: drop-shadow(0 0 16px rgba(34, 211, 166, .55));
}

/* ── Open pulse ─────────────────────────────────────────────
   One ring, once, on open. `animation` on a pseudo-element that
   only exists in the open state means it cannot replay on close
   and cannot stack if the user hammers the toggle. */
.logo::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--r-md);
  border: 1px solid rgba(34, 211, 166, .7);
  opacity: 0;
  pointer-events: none;
}

.logo.sidebar--open::after {
  animation: logo-pulse .62s cubic-bezier(.16, .86, .22, 1);
}

@keyframes logo-pulse {
  0%   { opacity: .85; transform: scale(.86); }
  70%  { opacity: .22; }
  100% { opacity: 0;   transform: scale(1.22); }
}

@media (max-width: 560px) {
  .logo__img { height: 28px; }
  .topbar    { padding: var(--s-6) var(--s-8); }
}

/* ── Chips (XP / streak) ────────────────────────────────────
   Member-only surfaces render these; landing does not. Shared
   here so dashboard and settings cannot drift apart again. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: 7px var(--s-6);
  border: 1px solid var(--border, rgba(91, 140, 255, .12));
  border-radius: 999px;
  font-family: var(--mono, 'JetBrains Mono', ui-monospace, monospace);
  font-size: 12.5px;
  transition: border-color .3s ease, background .3s ease, color .3s ease;
}
.chip--xp {
  color: var(--accent2, #22d3a6);
  background: rgba(34, 211, 166, .08);
}
.chip--streak {
  color: var(--warn, #ffb454);
  background: rgba(255, 180, 84, .08);
  border-color: rgba(255, 180, 84, .25);
}

/* ── Avatar ────────────────────────────────────────────────── */
.avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent, #5b8cff), var(--accent3, #00e0c6));
  border: none;
  display: grid;
  place-items: center;
  font-family: var(--font, 'Inter', system-ui, sans-serif);
  font-weight: 800;
  font-size: var(--t-md);
  color: #04121a;
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
  transition: transform .2s cubic-bezier(.2, .7, .2, 1), box-shadow .2s;
}
.avatar:hover { transform: scale(1.08); box-shadow: 0 0 20px rgba(34, 211, 166, .40); }
.avatar:active { transform: scale(1.02); }
.avatar:focus-visible { outline: 2px solid var(--accent2, #22d3a6); outline-offset: 3px; }

/* Subtle ring that intensifies while the menu is open. */
.avatar[aria-expanded="true"] {
  box-shadow: 0 0 0 3px rgba(34, 211, 166, .22), 0 0 22px rgba(34, 211, 166, .35);
}

/* ── Dropdown ───────────────────────────────────────────────
   Show/hide via opacity + transform, never `display`, because
   `display:none` cancels transitions — which is why the old menu
   popped instead of sliding. */
.menu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  min-width: 224px;
  padding: var(--s-3);
  background: var(--panel, rgba(14, 20, 30, .9));
  border: 1px solid var(--border, rgba(91, 140, 255, .12));
  border-radius: 14px;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .55);
  z-index: 60;

  opacity: 0;
  transform: translateY(-8px) scale(.97);
  pointer-events: none;
  transform-origin: top right;
  transition: opacity .18s cubic-bezier(.2, .7, .2, 1),
              transform .18s cubic-bezier(.2, .7, .2, 1);
}
.menu.menu--open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.menu__header { padding: 11px var(--s-7) 9px; }
.menu__name {
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--ink, #e7eef8);
  margin-bottom: var(--s-1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu__email {
  font-size: var(--t-sm);
  color: var(--dim, #5a6b80);
  margin-bottom: var(--s-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu__plan {
  display: inline-block;
  font-family: var(--mono, 'JetBrains Mono', ui-monospace, monospace);
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--accent2, #22d3a6);
  background: rgba(34, 211, 166, .10);
  border: 1px solid rgba(34, 211, 166, .22);
  border-radius: 999px;
  padding: 3px 9px;
}

.menu__divider { height: 1px; background: var(--border, rgba(91,140,255,.12)); margin: 5px var(--s-3); }

.menu a {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  padding: 9px var(--s-7);
  border-radius: 9px;
  color: var(--muted, #8b9bb0);
  text-decoration: none;
  font-size: var(--t-md);
  transition: background .15s, color .15s, padding-left .15s;
}
.menu a:hover { background: rgba(34, 211, 166, .08); color: var(--ink, #e7eef8); padding-left: 17px; }
.menu a:focus-visible { outline: 2px solid var(--accent2, #22d3a6); outline-offset: -2px; }
.menu a .menu__ico { font-size: var(--t-lg); width: 18px; text-align: center; flex-shrink: 0; }

.menu__logout:hover { background: rgba(255, 107, 139, .09); color: var(--hot, #ff6b8b); }

@media (prefers-reduced-motion: reduce) {
  .menu { transition: opacity .01ms; transform: none; }
  .menu.menu--open { transform: none; }
  .avatar { transition: none; }
  .menu a:hover { padding-left: var(--s-7); }
  .logo, .logo__img { transition: none; }
  .logo:active { transform: none; }
  .logo.sidebar--open::after { animation: none; }
}

@media (max-width: 480px) {
  .menu { min-width: 0; width: calc(100vw - 32px); right: -8px; }
}
