/* ==========================================================================
   Skynet nav v2 — the redesigned site header (views/partials/header-v2.ejs)

   Loaded only by the v2 pages. public/css/index-v2.css, leaderboard-v2.css,
   dashboard-v2.css and admin-panel-v2.css each declare the `skynet` theme, so
   every colour below is a Skynet UI token and follows whichever page it is on.

   The 60px bar height is not a free choice: dashboard-v2.css and
   admin-panel-v2.css size their layouts off `--dv2-header`/`--apv2-header`
   (60px, 104px with the partnership widget) and index-v2.css uses the same
   figures for scroll-margin. Change it here and change it there.
   ========================================================================== */

:root {
  --skv2-h: 60px;
}

/* --------------------------------------------------------------------------
   Bar
   -------------------------------------------------------------------------- */
.skv2 {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10000;
  height: var(--skv2-h);
  background: color-mix(in srgb, var(--sk-bg) 88%, transparent);
  border-bottom: 1px solid transparent;
  transition: background var(--sk-transition), border-color var(--sk-transition),
              box-shadow var(--sk-transition);
}
/* A translucent bar over a bright hero is unreadable without the blur, and
   unreadable WITH it on a browser that has no backdrop-filter. So the
   translucency is the enhancement: opaque by default, glassy where supported. */
@supports (backdrop-filter: blur(14px)) or (-webkit-backdrop-filter: blur(14px)) {
  .skv2 {
    background: color-mix(in srgb, var(--sk-bg) 72%, transparent);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    backdrop-filter: blur(14px) saturate(140%);
  }
}
/* Flat while the page is at the top, lifted once it scrolls — set by
   public/js/header-v2.js. Without JS the bar simply stays flat. */
.skv2.is-stuck {
  background: color-mix(in srgb, var(--sk-bg) 94%, transparent);
  border-bottom-color: var(--sk-border);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
}
/* The partnership widget is a 44px strip fixed above everything (40px on a
   phone); partnerships.css pads the body, which a fixed header does not see. */
body.has-partnership-widget .skv2 { top: 44px; }
@media (max-width: 640px) {
  body.has-partnership-widget .skv2 { top: 40px; }
}

.skv2-bar {
  height: var(--skv2-h);
  max-width: 1600px;
  margin: 0 auto;
  padding: 0 clamp(12px, 3vw, 24px);
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Every page below the header starts here. website-announcements.js measures
   this element, so it stays a real element with a real height. */
.nav-spacer { height: var(--skv2-h); }
body.has-partnership-widget .nav-spacer { height: calc(var(--skv2-h) + 44px); }
@media (max-width: 640px) {
  body.has-partnership-widget .nav-spacer { height: calc(var(--skv2-h) + 40px); }
}

/* :where() so these resets carry no specificity: a `.skv2 button` selector
   would outrank `.skv2-link`, and the two dropdown triggers — which ARE
   buttons sitting between links — would render in a different font and
   weight from the links beside them.

   The colour reset still skips `.sk-btn`, though: `:where()` zeroes its own
   argument, not the `.skv2` in front of it, so the rule lands at (0,1,0) —
   level with `.sk-btn-primary`, and this file loads after skynet-ui.css.
   Without the exclusion every filled button that is an anchor loses its white
   label to the bar's text colour, which is what happened to the "Add to
   Discord" CTA: 4.4:1 on the accent in dark, 2.4:1 in light. */
.skv2 :where(a:not(.sk-btn)) { text-decoration: none; color: inherit; }
.skv2 :where(a.sk-btn) { text-decoration: none; }
.skv2 :where(button) {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.skv2 :focus-visible,
.skv2-drawer :focus-visible {
  outline: 2px solid var(--sk-primary-text);
  outline-offset: 2px;
  border-radius: var(--sk-radius-sm);
}

/* --------------------------------------------------------------------------
   Brand
   -------------------------------------------------------------------------- */
.skv2-brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex: 0 0 auto;
  padding: 4px;
  margin-left: -4px;
}
.skv2-mark {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 15px;
  color: #fff;
  background: linear-gradient(135deg, var(--sk-primary), #6d28d9);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--sk-primary) 45%, transparent),
              0 4px 14px color-mix(in srgb, var(--sk-primary) 35%, transparent);
}
.skv2-word {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--sk-text);
}

/* --------------------------------------------------------------------------
   Primary links
   -------------------------------------------------------------------------- */
.skv2-nav {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: 2px;
  margin-left: 8px;
}
.skv2-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  color: var(--sk-text-2);
  white-space: nowrap;
  transition: color var(--sk-transition), background var(--sk-transition);
}
.skv2-link:hover { color: var(--sk-text); background: var(--sk-surface-2); }
.skv2-link.is-on {
  color: var(--sk-text);
  background: var(--sk-primary-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sk-primary) 40%, transparent);
}
/* A dropdown trigger is a <button> where its siblings are links; it needs the
   same box, and it stays highlighted for as long as its menu is open. */
.skv2-trig { cursor: pointer; }
.sk-dropdown.sk-open .skv2-trig { color: var(--sk-text); background: var(--sk-surface-2); }
.skv2-chev {
  font-size: 10px;
  opacity: 0.65;
  transition: transform var(--sk-transition);
}
.sk-dropdown.sk-open .skv2-chev { transform: rotate(180deg); }

/* --------------------------------------------------------------------------
   Mega menus — a Skynet UI dropdown with a grid inside it
   -------------------------------------------------------------------------- */
.skv2-drop { display: inline-flex; }
.skv2-mega {
  width: min(760px, calc(100vw - 2rem));
  padding: 14px;
  margin-top: 10px;
  border-radius: var(--sk-radius-lg);
  box-shadow: var(--sk-shadow-lg);
}
.skv2-mega-sm { width: min(520px, calc(100vw - 2rem)); }
.skv2-mega-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}
.skv2-mega-sm .skv2-mega-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.skv2-mega-col { min-width: 0; }
.skv2-mega-head {
  margin: 0 0 6px;
  padding: 0 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sk-muted);
}
/* Skynet UI already styles `.sk-dropdown-menu a` as a padded block row; these
   rows carry an icon and a second line, so they re-declare the layout. */
.skv2-mega .skv2-mega-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px;
  border-radius: var(--sk-radius-sm);
  color: var(--sk-text);
}
.skv2-mega .skv2-mega-item:hover { background: var(--sk-surface-2); }
.skv2-mega-item > i {
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  font-size: 12px;
  color: var(--sk-primary-text);
  background: var(--sk-primary-soft);
}
.skv2-mega-item span { display: block; min-width: 0; }
.skv2-mega-item b {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.3;
}
.skv2-mega-item small {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--sk-muted);
}
/* The numbered path at the top of More. Full width above the columns, so it
   reads as the thing to do rather than as one more column of links. */
.skv2-mega-start {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--sk-border);
}
/* The two steps sit side by side, lined up with the two columns under them,
   so they read as one flow (1 then 2) rather than a list with a gap beside it. */
.skv2-mega-steps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 12px;
}
@media (max-width: 560px) {
  .skv2-mega-steps { grid-template-columns: minmax(0, 1fr); }
}
.skv2-mega .skv2-step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: var(--sk-radius-sm);
  color: var(--sk-text);
}
.skv2-mega .skv2-step:hover { background: var(--sk-surface-2); }
.skv2-mega .skv2-step:hover .skv2-step-n { background: var(--sk-primary-hover, var(--sk-primary)); }
/* Two class selectors, deliberately: `.skv2-step span` below is (0,1,1) and
   used to beat a lone `.skv2-step-n` (0,1,0), turning the badge's grid back
   into a block, so the digit sat in the top-left corner of its circle. */
.skv2-step .skv2-step-n {
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  /* A solid accent with a white digit: the one call to action in the menu.
     White on --sk-primary clears 4.5:1 in every palette (npm run test:themes). */
  color: #fff;
  background: var(--sk-primary);
}
.skv2-step > span:not(.skv2-step-n) { display: block; min-width: 0; }
.skv2-step b { display: block; font-size: 13.5px; font-weight: 600; line-height: 1.3; }
.skv2-step small {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--sk-muted);
}

.skv2-mega-foot {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--sk-border);
}
.skv2-mega .skv2-classic {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: var(--sk-radius-sm);
  color: var(--sk-text-2);
}
.skv2-mega .skv2-classic:hover { background: var(--sk-surface-2); color: var(--sk-text); }
.skv2-classic b { display: block; font-size: 13px; font-weight: 600; }
.skv2-classic small { display: block; font-size: 11.5px; color: var(--sk-muted); }

/* --------------------------------------------------------------------------
   Right-hand actions
   -------------------------------------------------------------------------- */
.skv2-acts {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: 8px;
  margin-left: auto;
}

.skv2-status {
  display: inline-flex;
  white-space: nowrap;
  align-items: center;
  gap: 7px;
  height: 30px;
  padding: 0 11px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--sk-success-text);
  background: var(--sk-success-soft);
  white-space: nowrap;
}
.skv2-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sk-success-text);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sk-success) 22%, transparent);
  animation: skv2-pulse 2.4s ease-in-out infinite;
}
@keyframes skv2-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

/* Skynet UI buttons are ~28px at sk-btn-sm; this bar is touch-first, and 36px
   in a 60px bar is the most a row of them can take without crowding. The
   drawer, which is where a phone actually navigates, uses the full 44px. */
.skv2 .skv2-btn {
  height: 36px;
  padding: 0 12px;
  gap: 7px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
/* Adding the bot is the site's conversion action, so it is the only filled
   button in the bar and it never shares that weight with anything else.

   The label is stated here rather than left to `.sk-btn-primary`, which does
   set `color: #fff` but does not win on this element — in the bar the button
   inherits body text instead, which is dark-on-purple at 1.71:1 on a light
   palette and 3.92:1 on a dark one. This is the only filled button in the bar,
   so it is the only one that needs it; the outlined Setup button beside it
   reads its colour from a token and is fine. Found by npm run audit:themes. */
.skv2 .skv2-cta {
  font-weight: 700;
  color: #fff;
  box-shadow: 0 2px 12px color-mix(in srgb, var(--sk-primary) 35%, transparent);
}
/* Setup reads as the CTA's second half rather than as another nav button:
   tinted, but outlined, so the order of the two is never in question. */
.skv2 .skv2-setup {
  color: var(--sk-primary-text);
  border-color: color-mix(in srgb, var(--sk-primary) 45%, transparent);
  background: var(--sk-primary-soft);
}
.skv2 .skv2-setup:hover {
  border-color: color-mix(in srgb, var(--sk-primary) 70%, transparent);
}
/* Log in used to be the filled button. It is not any more: the CTA carries
   that weight, and two filled purple buttons side by side is no primary at
   all. Signing in is still one tap, just not the loudest thing on screen. */
.skv2 .skv2-login {
  color: var(--sk-text);
  border-color: var(--sk-border-2);
}
.skv2 .skv2-login:hover { background: var(--sk-surface-2); }
.skv2 .skv2-btn.is-on {
  color: var(--sk-primary-text);
  border-color: color-mix(in srgb, var(--sk-primary) 55%, transparent);
  background: var(--sk-primary-soft);
}

.skv2-icon {
  position: relative;
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 15px;
  color: var(--sk-text-2);
  transition: color var(--sk-transition), background var(--sk-transition);
}
.skv2-icon:hover { color: var(--sk-text); background: var(--sk-surface-2); }

/* notifications.js toggles `.hidden` on these and writes the count into them. */
.skv2-bell .badge,
.skv2-bell .mobile-badge {
  position: absolute;
  top: 3px;
  right: 2px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  background: var(--sk-danger);
  box-shadow: 0 0 0 2px var(--sk-bg);
}

/* --------------------------------------------------------------------------
   Account chip
   -------------------------------------------------------------------------- */
.skv2-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 10px 0 4px;
  border-radius: 999px;
  border: 1px solid var(--sk-border);
  background: var(--sk-surface);
  transition: border-color var(--sk-transition), background var(--sk-transition);
}
.skv2-chip:hover { border-color: var(--sk-border-2); background: var(--sk-surface-2); }
.skv2-chip .sk-avatar { width: 28px; height: 28px; }
.skv2-chip-name {
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 600;
}
.verified-badge { color: var(--sk-info-text); font-size: 12px; }

.skv2-menu {
  width: 248px;
  margin-top: 10px;
  padding: 8px;
  border-radius: var(--sk-radius-lg);
  box-shadow: var(--sk-shadow-lg);
}
.skv2-menu-who {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
}
.skv2-menu-who .sk-avatar { width: 36px; height: 36px; }
.skv2-menu-who b {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}
.skv2-menu-who small { display: block; font-size: 11.5px; color: var(--sk-muted); }
.skv2-menu a {
  display: flex;
  align-items: center;
  gap: 10px;
  border-radius: var(--sk-radius-sm);
  font-size: 13.5px;
}
.skv2-menu a > i { width: 16px; text-align: center; color: var(--sk-muted); }
.skv2-menu .skv2-menu-admin { color: var(--sk-warning-text); }
.skv2-menu .skv2-menu-admin > i { color: var(--sk-warning-text); }
.skv2-menu .skv2-menu-admin.is-on { background: var(--sk-warning-soft); }
.skv2-menu .skv2-danger { color: var(--sk-danger-text); }
.skv2-menu .skv2-danger > i { color: var(--sk-danger-text); }

/* --------------------------------------------------------------------------
   Responsive bar
   -------------------------------------------------------------------------- */
.skv2-burger { display: none; }
.skv2-only-mobile { display: none; }

/* Every breakpoint below is measured, not chosen: scripts/header-v2/measure.js
   walks the bar's real geometry at 25 widths and fails on the first overlap or
   overflow. Each one fires just before the layout above it runs out of room.

   The pill goes first. Reduced to its dot it would sit in a row of icon-only
   buttons looking like one more of them, which is worse than not being there —
   Status is one tap away in More and in the drawer.

   Both of the first two numbers moved up when the theme picker joined the row:
   it is 38px plus an 8px gap, and the bar had about 10px of slack left at
   1240. Measuring against the viewport (not the bar's own column) showed the
   account chip 10px off the right of a 1240px screen BEFORE the picker and
   56px off it after, with 1280/1440/1500 newly over as well — clipped, so
   `scrollWidth` never noticed. 1400→1520 and 1200→1320 each fire one step
   earlier and put every audited width back on screen. */
@media (max-width: 1520px) {
  .skv2-status { display: none; }
}
/* "Support" took a seat in the bar. Below 1440 the Home link gives it back:
   the SKYNET mark beside it is the same link, and the drawer keeps "Home". */
@media (max-width: 1439px) {
  .skv2-nav .skv2-home { display: none; }
}
/* The two funnel buttons are exempt here. Dashboard and Admin are for people
   who already know what they are; "Add to Discord" and "Setup" are for people
   who do not, and an unlabelled gear teaches nobody anything. They collapse
   later, and on their own schedule. */
@media (max-width: 1320px) {
  .skv2-btn:not(.skv2-cta):not(.skv2-setup) span { display: none; }
  .skv2 .skv2-btn:not(.skv2-cta):not(.skv2-setup) {
    width: 38px;
    padding: 0;
    justify-content: center;
  }
}
/* Setup goes icon-only before the CTA does: by here its label is the last
   thing the row can spend width on, and a gear next to a filled "Add to
   Discord" still reads as the step after it. */
@media (max-width: 1150px) {
  .skv2-setup span { display: none; }
  .skv2 .skv2-setup { width: 38px; padding: 0; justify-content: center; }
}
@media (max-width: 1250px) {
  .skv2-chip-name { display: none; }
  .skv2-chip { padding: 0 4px; }
}
/* A mega menu is 760px anchored to the left edge of a nav link that sits about
   470px in, so under roughly 1250px it hangs off the right of the screen —
   clipped, which is why nothing caught it until the audit started opening the
   menus it measures. Below that it stops being trigger-relative and centres
   under the bar, which fits at any width because it is already capped to the
   viewport. Centred with auto margins rather than a transform: Skynet UI's
   open animation animates `transform`, and translateX(-50%) would be thrown
   away for its first 150ms. */
@media (max-width: 1320px) {
  .skv2-drop .skv2-mega {
    position: fixed;
    top: calc(var(--skv2-h) + 10px);
    left: 1rem;
    right: 1rem;
    width: auto;
    max-width: 760px;
    margin: 0 auto;
  }
  .skv2-drop .skv2-mega-sm { max-width: 520px; }
  body.has-partnership-widget .skv2-drop .skv2-mega { top: calc(var(--skv2-h) + 54px); }
}
/* Below this the whole link row moves into the drawer, so the bar keeps only
   what a phone taps most: the bell and the menu. The number is measured, not
   picked: at 1040px the icon-only actions and the last nav link are already
   touching (see scripts/header-v2/measure.js). */
@media (max-width: 1100px) {
  .skv2-nav,
  .skv2-btn:not(.skv2-cta),
  .skv2-user,
  .skv2-bell:not(.skv2-only-mobile) { display: none; }
  .skv2-only-mobile { display: grid; }
  .skv2-burger { display: grid; }
  .skv2 .skv2-login { display: inline-flex; width: auto; min-height: 44px; padding: 0 14px; }
  .skv2 .skv2-login span { display: inline; }
  /* Everything else in the bar goes behind the burger; the CTA does not. It is
     the one thing a first-time visitor is here to do, and behind a menu is the
     same as gone. Setup rides along at the top of the drawer, one tap away. */
  .skv2 .skv2-cta {
    display: inline-flex;
    width: auto;
    min-height: 44px;
    padding: 0 14px;
  }
  .skv2 .skv2-cta span { display: inline; }
  /* The bar is down to a handful of controls here; each gets a 44px target. */
  .skv2-icon { width: 44px; height: 44px; flex-basis: 44px; }
  .skv2-brand { padding: 6px 4px; }
}
/* Phone. "Add" keeps the verb — the robot mark carries the rest, and the full
   wording is the first thing in the drawer either way. */
@media (max-width: 560px) {
  .skv2 .skv2-cta { padding: 0 12px; }
  .skv2 .skv2-cta span { font-size: 0; }
  .skv2 .skv2-cta span::after { content: "Add"; font-size: 13px; }
}
@media (max-width: 380px) {
  .skv2-word { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .skv2,
  .skv2-link,
  .skv2-icon,
  .skv2-chev,
  .skv2-dot { transition: none; animation: none; }
}

/* Nothing in the site chrome belongs on paper, and the spacer would print as
   a 60px gap at the top of the page. dashboard-v2.css used to carry this for
   `.skh` alone; it belongs with the nav, so all four v2 pages get it. */
@media print {
  .skv2,
  .nav-spacer,
  .sk-drawer,
  .notif-panel,
  .notif-overlay,
  .notif-modal,
  .global-toast-container { display: none !important; }
}

/* --------------------------------------------------------------------------
   Mobile drawer
   -------------------------------------------------------------------------- */
/* Skynet UI puts its drawer at z-index 290; this header sits at 10000, so the
   drawer would open behind it. Raise the whole drawer, not the header — the
   pages under it assume a header above their own stacking contexts. */
#skv2Drawer { z-index: 10020; }
.skv2-drawer {
  width: min(340px, 92vw);
  display: flex;
  flex-direction: column;
}
.skv2-drawer .sk-drawer-body {
  padding: 12px;
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
.skv2-drawer-title {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.12em;
}
.skv2-drawer-who {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  margin-bottom: 10px;
  border-radius: var(--sk-radius);
  background: var(--sk-surface-2);
}
.skv2-drawer-who .sk-avatar { width: 38px; height: 38px; }
.skv2-drawer-who b { display: block; font-size: 14px; font-weight: 600; }
.skv2-drawer-who small { display: block; font-size: 11.5px; color: var(--sk-muted); }
.skv2-drawer-login {
  width: 100%;
  min-height: 44px;
  gap: 8px;
  margin-bottom: 10px;
}
.skv2-drawer-head {
  margin: 14px 0 4px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sk-muted);
}
.skv2-drawer-head:first-of-type { margin-top: 4px; }
.skv2-drawer-link {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 10px;
  border-radius: var(--sk-radius-sm);
  font-size: 14.5px;
  font-weight: 500;
  color: var(--sk-text-2);
}
.skv2-drawer-link:hover,
.skv2-drawer-link:active { background: var(--sk-surface-2); color: var(--sk-text); }
.skv2-drawer-link > i { width: 18px; text-align: center; font-size: 14px; color: var(--sk-muted); }
.skv2-drawer-link.is-on {
  color: var(--sk-text);
  background: var(--sk-primary-soft);
}
.skv2-drawer-link.is-on > i { color: var(--sk-primary-text); }
.skv2-drawer-classic {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--sk-border);
  border-radius: 0;
  color: var(--sk-muted);
}
.skv2-drawer .sk-drawer-footer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
.skv2-drawer-cta,
.skv2-drawer-logout {
  width: 100%;
  min-height: 44px;
  gap: 8px;
}
/* It sits in the body now, above "Navigate", not in the footer. */
.skv2-drawer-body .skv2-drawer-cta { margin-bottom: 4px; font-weight: 700; }
/* Step two, reading as the CTA's partner rather than as one more list row. */
.skv2-drawer-setup {
  color: var(--sk-primary-text);
  background: var(--sk-primary-soft);
}
.skv2-drawer-setup > i { color: var(--sk-primary-text); }
.skv2-drawer-logout { color: var(--sk-danger-text); }

/* --------------------------------------------------------------------------
   Notifications panel — the markup public/js/notifications.js binds, restyled
   -------------------------------------------------------------------------- */
.notif-overlay {
  position: fixed;
  inset: 0;
  z-index: 10001;
  background: rgba(3, 6, 12, 0.55);
  opacity: 0;
  transition: opacity 0.25s ease;
}
.notif-overlay.visible { opacity: 1; }

.notif-panel {
  position: fixed;
  top: calc(var(--skv2-h) + 10px);
  right: 16px;
  z-index: 10002;
  width: min(390px, calc(100vw - 32px));
  max-height: min(560px, calc(100vh - var(--skv2-h) - 26px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--sk-border);
  border-radius: var(--sk-radius-lg);
  background: var(--sk-surface);
  box-shadow: var(--sk-shadow-lg);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.notif-panel.visible { opacity: 1; transform: translateY(0); }
body.has-partnership-widget .notif-panel { top: calc(var(--skv2-h) + 54px); }
@media (max-width: 560px) {
  .notif-panel {
    left: 12px;
    right: 12px;
    width: auto;
  }
}

.notif-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--sk-border);
}
.notif-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--sk-text);
}
.notif-title i { color: var(--sk-primary-text); }
.notif-count-badge {
  min-width: 20px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: var(--sk-danger);
}
.notif-close-btn {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 999px;
  color: var(--sk-muted);
  background: none;
  cursor: pointer;
}
.notif-close-btn:hover { color: var(--sk-text); background: var(--sk-surface-2); }

.notif-tabs {
  display: flex;
  gap: 4px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--sk-border);
}
.notif-tab {
  flex: 1;
  min-height: 32px;
  border: 0;
  border-radius: var(--sk-radius-sm);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sk-muted);
  background: none;
  cursor: pointer;
}
.notif-tab:hover { color: var(--sk-text); background: var(--sk-surface-2); }
.notif-tab.active { color: var(--sk-primary-text); background: var(--sk-primary-soft); }

.notif-body {
  flex: 1;
  min-height: 80px;
  overflow-y: auto;
  padding: 8px;
}
.notif-footer {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--sk-border);
}
.notif-action-btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 36px;
  border: 1px solid var(--sk-border);
  border-radius: var(--sk-radius-sm);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sk-text-2);
  background: var(--sk-surface-2);
  cursor: pointer;
}
.notif-action-btn:hover { color: var(--sk-text); border-color: var(--sk-border-2); }
.notif-delete-btn { color: var(--sk-danger-text); }

/* notifications.js renders these rows. The classic header never styled them;
   in here they are laid out so an unread item actually reads as one. */
.notification-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px;
  border-radius: var(--sk-radius-sm);
}
.notification-item:hover { background: var(--sk-surface-2); }
.notification-item.unread { background: var(--sk-primary-soft); }
.notification-item-icon {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 12px;
  color: var(--sk-primary-text);
  background: var(--sk-surface-2);
}
.notification-item-content { flex: 1; min-width: 0; }
.notification-item-message { font-size: 13px; line-height: 1.45; color: var(--sk-text); }
.notification-item-server,
.notification-item-time {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 3px;
  margin-right: 10px;
  font-size: 11.5px;
  color: var(--sk-muted);
}
.notification-item-actions { display: flex; gap: 4px; flex: 0 0 auto; }
.notification-item-action {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 999px;
  font-size: 11px;
  color: var(--sk-muted);
  background: none;
  cursor: pointer;
}
.notification-item-action:hover { color: var(--sk-text); background: var(--sk-surface-2); }
.notification-item-delete:hover { color: var(--sk-danger-text); }
.notification-empty,
.notification-empty-icon {
  text-align: center;
  color: var(--sk-muted);
}
.notification-empty-icon { font-size: 26px; margin: 22px 0 8px; opacity: 0.5; }

.notif-modal {
  position: fixed;
  inset: 0;
  z-index: 10030;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(3, 6, 12, 0.65);
}
.notif-modal-content {
  width: min(400px, 100%);
  padding: 22px;
  text-align: center;
  border: 1px solid var(--sk-border);
  border-radius: var(--sk-radius-lg);
  background: var(--sk-surface);
  box-shadow: var(--sk-shadow-lg);
}
.notif-modal-icon {
  width: 48px;
  height: 48px;
  margin: 0 auto 12px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 19px;
  color: var(--sk-danger-text);
  background: var(--sk-danger-soft);
}
.notif-modal-content h3 { margin: 0 0 8px; font-size: 17px; color: var(--sk-text); }
.notif-modal-content p { margin: 0 0 18px; font-size: 13.5px; color: var(--sk-muted); }
.notif-modal-actions { display: flex; gap: 10px; }
.notif-modal-btn {
  flex: 1;
  min-height: 44px;
  border: 1px solid var(--sk-border);
  border-radius: var(--sk-radius-sm);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.notif-modal-cancel { color: var(--sk-text-2); background: var(--sk-surface-2); }
.notif-modal-confirm { color: #fff; border-color: var(--sk-danger); background: var(--sk-danger); }

/* Skynet UI declares `.hidden` ahead of its component display rules, so a
   hidden flex/grid element would still paint. Same override the v2 page
   stylesheets carry, scoped to the chrome this file owns. */
.notif-panel.hidden,
.notif-overlay.hidden,
.notif-modal.hidden,
.notif-count-badge.hidden,
.skv2-bell .badge.hidden,
.skv2-bell .mobile-badge.hidden { display: none !important; }

/* --------------------------------------------------------------------------
   Global toasts — public/js/global-error-handler.js builds these
   -------------------------------------------------------------------------- */
.global-toast-container {
  position: fixed;
  top: calc(var(--skv2-h) + 16px);
  right: 16px;
  z-index: 10040;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 400px;
}
.global-toast {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--sk-border);
  border-radius: var(--sk-radius);
  background: var(--sk-surface);
  box-shadow: var(--sk-shadow-lg);
  opacity: 0;
  transform: translateX(100%);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.global-toast-visible { opacity: 1; transform: translateX(0); }
.global-toast-hiding { opacity: 0; transform: translateX(100%); }
.global-toast-icon {
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 15px;
}
.global-toast-warning .global-toast-icon { color: var(--sk-warning-text); background: var(--sk-warning-soft); }
.global-toast-error .global-toast-icon { color: var(--sk-danger-text); background: var(--sk-danger-soft); }
.global-toast-success .global-toast-icon { color: var(--sk-success-text); background: var(--sk-success-soft); }
.global-toast-info .global-toast-icon { color: var(--sk-info-text); background: var(--sk-info-soft); }
.global-toast-content { flex: 1; min-width: 0; }
.global-toast-title { margin-bottom: 4px; font-size: 13.5px; font-weight: 600; color: var(--sk-text); }
.global-toast-message { font-size: 12.5px; line-height: 1.45; color: var(--sk-muted); }
.global-toast-close {
  margin: -4px -4px -4px 0;
  padding: 4px;
  border: 0;
  border-radius: var(--sk-radius-sm);
  color: var(--sk-faint);
  background: none;
  cursor: pointer;
}
.global-toast-close:hover { color: var(--sk-text); background: var(--sk-surface-2); }
@media (max-width: 480px) {
  .global-toast-container { left: 12px; right: 12px; max-width: none; }
}

/* ==========================================================================
   Theme picker
   Present for signed-out visitors too — their choice lives in a cookie.
   Icon-only: audit:header-v2 measures this bar at 25 widths and a labelled
   control here is what pushed the first nav into an overlap at 1440.
   ========================================================================== */
/* The wrapper is also theme-v2.js's hook for the control. */
.skv2-theme { display: inline-flex; }
.skv2-theme-dot {
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  display: block;
  background: var(--sk-primary);
  box-shadow: 0 0 0 2px var(--sk-surface-2), 0 0 0 3px var(--sk-border-2);
}
/* Twelve palettes under two headings is about 960px of rows — taller than a
   1080p browser viewport, let alone a laptop's. The menu hangs below a 60px
   bar, so that is the height it may have; past it the list scrolls and the
   group headings stay put so it is always clear which half you are in. Six
   themes did not need this and a seventh would have broken it silently: the
   overflow is inside an absolutely positioned box, so it neither widens the
   document nor shows up in the audit's off-screen check. */
.skv2-theme-menu {
  min-width: 15rem;
  padding: 0.4rem;
  max-height: calc(100vh - var(--skv2-h) - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
body.has-partnership-widget .skv2-theme-menu {
  max-height: calc(100vh - var(--skv2-h) - 68px);
}
/* On a phone this menu cannot be anchored to its trigger at all. Measured with
   the menu OPEN (a closed one measures zero, which is how this got shipped in
   the first place): at 360px the trigger sits at 200..244, so a left-anchored
   248px menu ends at 448 — 88px off the screen — and a right-anchored one
   starts at -4. At 320px it is 128px off one side or 44px off the other. There
   is no anchor that fits.
   So below 26em it stops being trigger-relative and pins to the bar, the way
   .notif-panel and the toast stack already do, with a width that cannot
   outgrow the viewport. audit:header-v2 measures it open at every width. */
@media (max-width: 26em) {
  .skv2-theme .skv2-theme-menu {
    position: fixed;
    top: calc(var(--skv2-h) + 8px);
    right: 8px;
    left: auto;
    width: min(248px, calc(100vw - 16px));
  }
  body.has-partnership-widget .skv2-theme .skv2-theme-menu {
    top: calc(var(--skv2-h) + 52px);
  }
}
.skv2-theme-head,
.skv2-theme-foot {
  margin: 0;
  padding: 0.35rem 0.6rem;
  color: var(--sk-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Sticky so the half you are scrolling through is always named. The menu's own
   background, or the rows would show through it. */
.skv2-theme-head {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--sk-surface);
}
.skv2-theme-head + [role="group"] + .skv2-theme-head {
  margin-top: 0.3rem;
  border-top: 1px solid var(--sk-border);
  padding-top: 0.5rem;
}
.skv2-theme-foot {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  border-top: 1px solid var(--sk-border);
  margin-top: 0.3rem;
  padding-top: 0.5rem;
}
.skv2-theme-opt {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  min-height: 44px;
  padding: 0.4rem 0.6rem;
  border: 0;
  border-radius: var(--sk-radius-sm);
  background: transparent;
  color: var(--sk-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.skv2-theme-opt:hover,
.skv2-theme-opt:focus-visible { background: var(--sk-surface-2); }
.skv2-theme-swatch {
  width: 1.1rem;
  height: 1.1rem;
  flex: none;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);
}
.skv2-theme-label { display: flex; flex-direction: column; min-width: 0; flex: 1; line-height: 1.25; }
.skv2-theme-label small { color: var(--sk-muted); font-size: 0.75rem; }
.skv2-theme-tick { opacity: 0; color: var(--sk-primary-text); flex: none; }
.skv2-theme-opt.is-on .skv2-theme-tick { opacity: 1; }

/* ==========================================================================
   Bare <button> reset — site-wide on the v2 pages.

   The classic pages get this from Tailwind's Preflight, which sets
   `button { background-color: transparent }`. The v2 pages load Skynet UI
   instead, which styles its own `.sk-btn` and leaves an unclassed <button>
   to the user agent — and the user agent's ButtonFace follows `color-scheme`,
   which themes-v2.css sets to `dark` on six palettes. So a shared partial's
   plain `<button>` painted itself mid-grey.

   `npm run audit:themes` measured "View all" inside the trader panel at
   **2.17:1** because of it. That markup is rendered by /dashboard/v2 as well,
   and the dashboard's own preview had never filled that card — a button
   nothing ever built is a button nothing ever measured.

   It lives here because header-v2.css is the one stylesheet every v2 page
   loads (through partials/header-v2.ejs) — the same reason .global-toast's
   styles moved across.

   THE SELECTOR IS THE ELEMENT ALONE, deliberately. Preflight also lists
   [type="button"], [type="reset"] and [type="submit"], and that is safe only
   because Preflight is loaded FIRST. This sheet is loaded after Skynet UI, and
   an attribute selector ties with a class on specificity — so
   `[type="submit"] { background-color: transparent }` beat
   `.sk-btn-primary { background: … }` on source order and stripped the fill
   off every submit button on the site. audit:themes measured /dashboard/v2's
   "Save Token" at 1:1 on all six LIGHT palettes. A bare element selector
   loses to any class, which is exactly the rule wanted: a button with a fill
   keeps it, a button with none stops borrowing the user agent's.
   ========================================================================== */
button {
  background-color: transparent;
  background-image: none;
}
