/* ==========================================================================
   NECROWLS HUB, THEME
   The design system. Loaded LAST, after app.css, on every page.
   --------------------------------------------------------------------------
   This file owns how the Hub LOOKS. app.css still owns layout mechanics that
   predate it (grid tracks, flow, the bits JS measures); theme.css owns every
   surface, every radius, every shadow, every piece of colour.

   The rule that keeps this maintainable: a page file should never contain a
   colour, a radius or a shadow. If a page needs a new look, it gets a class
   from here. Nothing in js/page-*.js should ever set one inline.

   Reference language, from the boards:
     · a soft lavender PAGE with the app floating on it as one rounded SHELL
     · content that sits on the shell with no outline anywhere
     · circular icon nav, active state a filled circle
     · pill everything: search, tags, buttons, toggles
     · glass for controls that float above content
     · soft double-shadow depth instead of borders

   Sections
     01 Tokens          07 Cards
     02 Page + shell    08 Tiles & stats
     03 Rail            09 History rows
     04 Header          10 Members
     05 Glass toggle    11 Profile
     06 Mobile dock     12 Controls, motion, focus
   ========================================================================== */

/* ── 01 TOKENS ─────────────────────────────────────────────────────────────
   Two themes, same variable names. Every component below reads these and
   nothing else, so the whole Hub re-skins from this block alone.           */

:root,
[data-theme="dark"] {
  color-scheme: dark;

  /* Page is the deepest layer, what everything floats ON. No green here:
     the green lives on the rail only. A faint two-tone ambient keeps the
     page from reading as dead flat, and gives the glass surfaces above it
     something to actually reveal. */
  --page:        #0c0a11;
  /* The two soft blobs that used to sit here showed through the gap between
     the rail and the panel as random patches of colour -- which is exactly
     what they looked like: a stain behind the app rather than a background.
     One clean linear gradient instead, top to bottom, no hotspots.

     --hub-bg is the user override (Settings -> Appearance). When someone
     designs their own it lands here and nothing else in the theme changes. */
  --page-grad:   linear-gradient(168deg, #17122099 0%, #0c0a1100 58%);
  --page-glow:   var(--hub-bg, var(--page-grad));

  /* Glass surfaces. These are TRANSLUCENT on purpose, every component that
     uses one also carries a backdrop-filter, so the page's colour reads
     through the whole interface instead of being sealed off by opaque
     panels. Alpha is kept high enough that body text still clears contrast. */
  --shell:       rgba(255, 255, 255, .055);
  --surface:     rgba(255, 255, 255, .075);
  --surface-2:   rgba(255, 255, 255, .115);
  --surface-3:   rgba(255, 255, 255, .17);
  --surface-4:   rgba(255, 255, 255, .24);

  --text:        #f4f0f8;
  --text-2:      #bdb2cb;
  --text-3:      #8d81a0;

  /* ONE source of truth for the accent. --brand-user is set by the inline
     script in every page's <head> when someone has chosen their own; when
     they have not, this crimson is the default. Everything else is DERIVED
     from it, so changing the accent is genuinely one value and not a hunt
     through forty rules for hardcoded reds. */
  --brand:       var(--brand-user, #e0244f);
  --brand-2:     color-mix(in srgb, var(--brand) 72%, #ffffff);
  --brand-soft:  color-mix(in srgb, var(--brand) 16%, transparent);
  --grad-brand:  linear-gradient(135deg,
                   color-mix(in srgb, var(--brand) 96%, #ffffff),
                   color-mix(in srgb, var(--brand) 68%, #000000));

  --mint:        #4fd6a0;
  --amber:       #f0b24a;
  --violet:      #a78bfa;

  /* Glass: for controls that float above content. */
  --glass:       rgba(255, 255, 255, .07);
  --glass-2:     rgba(255, 255, 255, .13);
  --glass-line:  rgba(255, 255, 255, .14);
  --glass-blur:  blur(18px) saturate(160%);

  /* Depth. Two shadows: a tight contact shadow and a wide soft one. That
     pairing is what reads as "floating" instead of "outlined". */
  --lift-1: 0 1px 2px rgba(0,0,0,.34), 0 6px 18px -10px rgba(0,0,0,.6);
  --lift-2: 0 2px 6px rgba(0,0,0,.36), 0 18px 40px -18px rgba(0,0,0,.72);
  --lift-3: 0 4px 12px rgba(0,0,0,.4),  0 40px 90px -30px rgba(0,0,0,.85);
  --inset-1: inset 0 1px 0 rgba(255,255,255,.05);
}

[data-theme="light"] {
  color-scheme: light;

  /* Light mode: a pale neutral page, same two-tone ambient lifted. Still no
     green, the rail carries it in both themes. */
  --page:        #e7e4ef;
  --page-grad:   linear-gradient(168deg, #ffffffcc 0%, #e7e4ef00 58%);
  --page-glow:   var(--hub-bg-light, var(--hub-bg, var(--page-grad)));

  --shell:       rgba(255, 255, 255, .58);
  --surface:     rgba(255, 255, 255, .66);
  --surface-2:   rgba(255, 255, 255, .48);
  --surface-3:   rgba(255, 255, 255, .84);
  --surface-4:   rgba(120, 100, 150, .18);

  --text:        #1c1626;
  --text-2:      #574d67;
  --text-3:      #867a99;

  /* Light mode darkens the same chosen hue rather than using a different
     one, so an accent picked in one theme still reads correctly in the
     other instead of glowing off a pale background. */
  --brand:       color-mix(in srgb, var(--brand-user, #c31432) 88%, #000000);
  --brand-2:     var(--brand-user, #e0244f);
  --brand-soft:  color-mix(in srgb, var(--brand) 10%, transparent);
  --grad-brand:  linear-gradient(135deg,
                   var(--brand),
                   color-mix(in srgb, var(--brand) 62%, #000000));

  --mint:        #1d9b6c;
  --amber:       #b07216;
  --violet:      #6d4fd6;

  --glass:       rgba(255, 255, 255, .58);
  --glass-2:     rgba(255, 255, 255, .78);
  --glass-line:  rgba(255, 255, 255, .85);
  --glass-blur:  blur(18px) saturate(180%);

  /* Light mode gets the soft neumorphic pairing from the board: a warm
     shadow below, a white highlight above. */
  --lift-1: 0 1px 2px rgba(60,40,90,.06),  0 6px 16px -8px rgba(60,40,90,.14);
  --lift-2: 0 2px 6px rgba(60,40,90,.07),  0 18px 38px -16px rgba(60,40,90,.20);
  --lift-3: 0 4px 12px rgba(60,40,90,.09), 0 40px 80px -28px rgba(60,40,90,.28);
  --inset-1: inset 0 1px 0 rgba(255,255,255,.9);
}

:root {
  /* Radii. Generous and consistent, the single biggest tell of the
     reference language. Nothing in the Hub is squarer than --r-md. */
  --r-sm:   10px;
  --r-md:   16px;
  --r-lg:   22px;
  --r-xl:   28px;
  --r-2xl:  30px;
  --r-3xl:  38px;
  --r-shell: 40px;
  --r-pill: 999px;

  --rail-w:  84px;
  --rail-open: 216px;

  /* Derived, not per-theme: it resolves through --brand, which each theme
     sets for itself. Keeping it here means the two theme blocks stay
     symmetric -- a token in one and not the other resolves to nothing the
     moment someone switches, and there is a test guarding that. */
  --ring: 0 0 0 2px var(--brand);

  --ease:      cubic-bezier(.22, .61, .36, 1);
  --ease-out:  cubic-bezier(.16, 1, .3, 1);
  --t-fast:    .16s;
  --t-med:     .28s;

  /* Legacy aliases, older rules in app.css still read these names. Mapped
     here so there is exactly one place colour is decided. */
  --bg: var(--shell);
  --line: transparent;
  --shadow:      var(--lift-1);
  --shadow-lg:   var(--lift-3);
  --shadow-card: var(--lift-1);
  --shadow-card-hover: var(--lift-2);
  --tile-tint: transparent;
}

/* ── 02 PAGE + SHELL ───────────────────────────────────────────────────────
   The app is a rounded panel floating on a tinted page. On a phone the
   shell goes full-bleed, a floating panel inside a 390px viewport is just
   wasted margin.                                                           */

/* ── The page behind the hub ───────────────────────────────────────────────
   ONE element paints it: <html>. Not html AND body, two elements painting
   near-identical backgrounds is what produced the visible band across the
   top of the page, because their gradients resolved against different boxes
   and met at a seam.

   html also gets `min-height: 100%` and the gradient is `fixed`, so the
   colour is continuous from the very first pixel of the viewport to the
   last, with nothing to line up and nothing to leave a strip. */
html {
  min-height: 100%;
  background: var(--page-glow), var(--page);
  background-attachment: fixed;
  /* Patterns tile, washes cover. --hub-bg-size is set only by a pattern, so
     everything else keeps covering the viewport exactly as before. */
  background-repeat: var(--hub-bg-repeat, no-repeat);
  background-size: var(--hub-bg-size, cover);
}
/* A pattern needs to repeat, and a single value cannot say "cover AND tile",
   so choosing a pattern flips both together. */
html[style*="--hub-bg-size"] { background-repeat: repeat; }
body {
  background: transparent;   /* never paint a second page layer here */
  color: var(--text);
  min-height: 100vh;
  transition: color var(--t-med) var(--ease);
}
.app { background: transparent; box-shadow: none; border-radius: 0; min-height: 0; }

@media (min-width: 901px) {
  /* The rail and the body are two SEPARATE floating panels with a gap
     between them, not one shell with a rail sitting inside it. The body
     panel carries the shell surface; .app is only a positioning context. */
  .app { background: transparent; box-shadow: none; }

  .app-main {
    background: var(--shell);
    border-radius: var(--r-shell);
    box-shadow: var(--lift-3);
    margin: 18px 18px 18px calc(var(--rail-w) + 30px);
    padding: 4px 34px 72px;
    min-height: calc(100vh - 36px);
    /* BUG FIXED HERE: a 1320px cap (and app.css's own narrower one) left a
       band of dead page down the right-hand side on a wide display, and
       because the panel is left-margined off the rail the whole Hub looked
       shoved to one side. The shell fills the width it is given; content
       inside it stays readable through its own grids, not by starving the
       panel. */
    max-width: none;
    width: auto;
  }

  /* Its own pill, floating clear of the body. */
  .rail { inset: 18px auto 18px 18px; }

  /* Expanding must never push the body: the rail overlays it, exactly as in
     the reference. z-index keeps it above the sticky header too. */
  .rail:hover, .rail:focus-within { z-index: 70; }

  .app-head { background: transparent; backdrop-filter: none; }
}

/* ── 03 RAIL ───────────────────────────────────────────────────────────────
   A floating pill of circular icons that expands on hover to reveal labels
   (board 4). Collapsed it is icon-only and unmistakable; expanded it names
   everything without a permanent sidebar eating the width.                 */

.rail {
  width: var(--rail-w);
  padding: 18px 12px calc(18px + env(safe-area-inset-bottom));
  background: transparent;
  gap: 6px;
  align-items: stretch;
  overflow: visible;
  transition: width var(--t-med) var(--ease-out);
}
.rail::before { display: none; }

/* The pill itself is a pseudo-element so the expand animation never
   reflows the links inside it. */
.rail::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: var(--r-3xl);
  background: var(--surface);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-line);
  box-shadow: var(--lift-2), var(--inset-1);
  z-index: -1;
}

@media (min-width: 901px) {
  .rail:hover, .rail:focus-within { width: var(--rail-open); }
}

/* Collapsed: the owl glyph alone, centred. Expanded: the glyph with the
   wordmark beside it, the rail is the one place with room for both, and
   only once it has opened. */
.rail { color: var(--text); }
.rail .navlink { color: var(--text-2); }
.rail .navlink:hover { background: var(--surface-2); color: var(--text); }
.rail .navlink.on { background: var(--grad-brand); color: #fff; box-shadow: 0 10px 24px -8px var(--brand); }

.rail-brand {
  padding: 8px 0 20px;
  display: flex; align-items: center; justify-content: center;
  gap: 0;
  color: var(--text);
  overflow: hidden;
  transition: gap var(--t-med) var(--ease-out), justify-content var(--t-med);
}
/* THE MARK is 120x47 -- wide, not square. Everywhere else in the Hub an
   icon is a square <svg>, so the mark needs its own sizing wherever one of
   those square rules would otherwise squash it. */
.brand-glyph { height: 26px; width: auto; flex: none; }
.navlink svg.ico-owl, .nav-panel-tile svg.ico-owl, .dock-side svg.ico-owl { width: 27px; height: auto; }
.rowitem-ico svg.ico-owl, .member-badges svg.ico-owl { width: 20px; height: auto; }
svg.ico-owl { width: 24px; height: auto; }
/* ── The wordmark ──────────────────────────────────────────────────────────
   NO SHEEN. The travelling highlight was a pseudo-element wider than the
   element itself, and `forwards` parked it at its end position, so it sat
   there permanently as a pale rectangle floating to the right of the word.
   There is no overlay, no bar, no moving part in this version at all.

   The glass is in the LETTERS instead, which is where it belongs:

     · the fill is translucent, so whatever is behind the word shows faintly
       through the strokes, on the rail that is the glass panel, on a page
       header it is the page itself
     · a bright top edge and a soft dark base give the letterform thickness,
       the way a real glass slab catches light along one edge
     · a hairline stroke around each glyph reads as the cut edge
     · the capital O is the owl's letter, in brand colour

   Falls back to solid currentColor with a coloured O where background-clip
   on text is unsupported, still the design, just flat.                    */
.brand-wordmark {
  display: inline-block;
  font-family: var(--font-display, "Space Grotesk", system-ui, sans-serif);
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -.04em;
  line-height: 1;
  white-space: nowrap;
  color: currentColor;
}
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .brand-wordmark {
    background: linear-gradient(180deg,
      rgba(255,255,255,.98) 0%,
      rgba(255,255,255,.78) 42%,
      rgba(255,255,255,.52) 72%,
      rgba(255,255,255,.86) 100%);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent;
    -webkit-text-stroke: .4px rgba(255,255,255,.34);
    filter: drop-shadow(0 1px 1px rgba(0,0,0,.35));
  }
  [data-theme="light"] .brand-wordmark {
    background: linear-gradient(180deg,
      rgba(28,22,38,.96) 0%,
      rgba(28,22,38,.78) 42%,
      rgba(28,22,38,.55) 72%,
      rgba(28,22,38,.9) 100%);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-stroke: .4px rgba(255,255,255,.55);
    filter: drop-shadow(0 1px 1px rgba(255,255,255,.7));
  }
}

/* The owl's own letter. Colour, not ornament. */
.brand-wordmark > span {
  -webkit-text-fill-color: var(--brand-2);
  color: var(--brand-2);
  -webkit-text-stroke: .4px rgba(255,255,255,.28);
}
[data-theme="light"] .brand-wordmark > span {
  -webkit-text-fill-color: var(--brand);
  color: var(--brand);
}

/* The lock-up: mark and word, optically aligned. */
.rail-brand, .head-brand, .nav-sheet-brand { align-items: center; }
.rail-wordmark {
  max-width: 0; opacity: 0; overflow: hidden; display: block; flex: none;
  transition: max-width var(--t-med) var(--ease-out), opacity var(--t-fast) var(--ease);
}
@media (min-width: 901px) {
  .rail:hover .rail-brand,
  .rail:focus-within .rail-brand { gap: 11px; justify-content: flex-start; padding-left: 15px; }
  .rail:hover .rail-wordmark,
  .rail:focus-within .rail-wordmark { max-width: 130px; opacity: 1; }
}

/* BUG FIXED HERE: .navlink was `width: auto` with a `gap` and a label that
   was only faded to opacity 0, an invisible label still occupies layout
   width. Inside the rail's ~60px content box that pushed each icon out of
   its own button and clipped it, and stretched the active pill into a blob
   bleeding past the rail's edge. Collapsed, a link is now a fixed 52px
   circle and the label is width-zero; both grow together on hover. */
.navlink {
  width: 52px; height: 52px;
  margin: 0 auto;
  border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  gap: 0;
  padding: 0;
  color: var(--text-2);
  overflow: hidden;
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease),
              width var(--t-med) var(--ease-out),
              padding var(--t-med) var(--ease-out),
              gap var(--t-med) var(--ease-out);
}
.navlink svg { width: 21px; height: 21px; flex: none; opacity: 1; }
.navlink-label {
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  font-size: 14px; font-weight: 600; letter-spacing: -.01em;
  transition: max-width var(--t-med) var(--ease-out), opacity var(--t-fast) var(--ease);
}

@media (min-width: 901px) {
  .rail:hover .navlink,
  .rail:focus-within .navlink {
    width: 100%;
    justify-content: flex-start;
    padding: 0 15px;
    gap: 13px;
  }
  .rail:hover .navlink-label,
  .rail:focus-within .navlink-label { max-width: 140px; opacity: 1; }
}

.navlink:hover { background: var(--surface-2); color: var(--text); transform: none; }
.navlink.on {
  background: var(--grad-brand); color: #fff;
  box-shadow: 0 8px 20px -8px var(--brand);
}

@media (min-width: 901px) {
  /* The rail clips again now that nothing reaches out of it. The label must
     still clip so it can collapse to zero width when the rail is closed. */
  .rail { overflow: visible; }
  .navlink { overflow: hidden; }
  .navlink-label { overflow: hidden; }
}
.navlink .dot { right: 12px; top: 12px; }

.rail-foot { margin-top: auto; padding-top: 10px; gap: 6px; flex-direction: column; align-items: center; width: 100%; }
.rail-foot .navlink { flex: none; }

/* ── 04 HEADER ─────────────────────────────────────────────────────────────
   Title, then floating pill controls. Nothing boxed, nothing ruled.        */

.app-head { padding: 22px 0 16px; margin-bottom: 20px; }
.app-head h1 {
  font-size: clamp(22px, 3vw, 30px);
  letter-spacing: -.035em;
}

.head-actions { display: flex; align-items: center; gap: 8px; flex: none; }
.app-head > .row { min-width: 0; }

/* Account button: avatar + name + chevron in one pill, as asked. */
.head-account {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 5px 15px 5px 5px;
  border-radius: var(--r-pill);
  background: var(--surface);
  box-shadow: var(--lift-1), var(--inset-1);
  border: 0;
  font-weight: 650; font-size: 13.5px; color: var(--text);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.head-account:hover { transform: translateY(-1px); box-shadow: var(--lift-2), var(--inset-1); }
.head-account .avatar { width: 32px; height: 32px; border-radius: 50%; overflow: hidden; flex: none; }
.head-account .avatar img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; }

.searchbar {
  background: var(--surface);
  box-shadow: var(--lift-1), var(--inset-1);
  padding: 4px 6px 4px 18px;
}
.searchbar input { color: var(--text); }
.searchbar input::placeholder { color: var(--text-3); }

.segmented {
  background: var(--surface);
  box-shadow: var(--lift-1), var(--inset-1);
  padding: 4px;
  border: 0;
}
.segmented-btn {
  border-radius: var(--r-pill);
  padding: 9px 18px;
  font-weight: 650; font-size: 13.5px;
  color: var(--text-3);
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.segmented-btn.on {
  background: var(--surface-3);
  color: var(--text);
  box-shadow: var(--lift-1);
}

/* ── 05 GLASS TOGGLE ───────────────────────────────────────────────────────
   Boards 2 and 3: a frosted bubble that slides across a pill. The bubble is
   a real element so it can animate; the icons cross-fade underneath it.    */

.glass-toggle {
  position: relative;
  display: inline-flex; align-items: center;
  width: 74px; height: 38px;
  padding: 0;
  border: 1px solid var(--glass-line);
  border-radius: var(--r-pill);
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--lift-1), var(--inset-1);
  cursor: pointer;
  overflow: hidden;
  flex: none;
}
.glass-toggle-bubble {
  position: absolute; top: 3px; left: 3px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--glass-2);
  border: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: 0 4px 12px rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.5);
  transition: transform var(--t-med) var(--ease-out);
}
[data-theme="light"] .glass-toggle-bubble { transform: translateX(36px); }
.glass-toggle svg {
  position: absolute; width: 16px; height: 16px;
  color: var(--text);
  transition: opacity var(--t-med) var(--ease);
  pointer-events: none;
}
.glass-toggle .ico-moon { left: 11px; }
.glass-toggle .ico-sun  { right: 11px; }
[data-theme="dark"]  .glass-toggle .ico-sun  { opacity: .45; }
[data-theme="light"] .glass-toggle .ico-moon { opacity: .45; }

/* In the rail's footer the toggle sits inside the pill, so it drops the
   glass chrome and behaves like the nav buttons around it. */
.rail-foot .glass-toggle { width: 52px; height: 30px; transition: width var(--t-med) var(--ease-out); }
.rail-foot .glass-toggle-bubble { width: 24px; height: 24px; top: 2px; left: 2px; }
[data-theme="light"] .rail-foot .glass-toggle-bubble { transform: translateX(22px); }
.rail-foot .glass-toggle .ico-moon { left: 8px; }
.rail-foot .glass-toggle .ico-sun  { right: 8px; }
@media (min-width: 901px) {
  .rail:hover .rail-foot .glass-toggle,
  .rail:focus-within .rail-foot .glass-toggle { width: 74px; }
  [data-theme="light"] .rail:hover .rail-foot .glass-toggle-bubble,
  [data-theme="light"] .rail:focus-within .rail-foot .glass-toggle-bubble { transform: translateX(44px); }
}

/* ── 06 MOBILE DOCK ────────────────────────────────────────────────────────
   A floating glass pill, not a bar welded to the bottom edge.              */

@media (max-width: 900px) {
  .app { background: transparent; }
  .app-main { padding: 0 16px 130px; }
  .app-head { padding: 16px 0 12px; }

  /* PHONE: no sidebar. A sidebar on a 390px screen eats a third of the
     width and is the wrong shape for a thumb. The rail is desktop-only.

     What a phone gets is the reference's own bottom chrome: a soft curved
     bar pinned to the bottom edge with a raised circular button sitting
     proud of its top edge. Home on the left, the account on the right, and
     the big button in the middle opens the full menu. */
  .rail { display: none !important; }

  /* Brand top-left, account top-right, page controls on a full-width row of
     their own beneath. A grid rather than wrapped flex, so the two corners
     are PINNED rather than merely tending to end up there. */
  .app-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "brand actions" "ctrl ctrl";
    align-items: center;
    gap: 12px 10px;
    padding: 14px 0 12px;
    margin-bottom: 16px;
  }
  .app-head > .grow { grid-area: brand; min-width: 0; }
  .app-head > .head-actions { grid-area: actions; }
  .app-head > .row {
    grid-area: ctrl;
    /* Tabs and filter chips scroll sideways instead of wrapping into a
       ragged block or squeezing every label until it clips. */
    display: flex; flex-wrap: nowrap;
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none;
    margin: 0 -16px; padding: 2px 16px;
  }
  .app-head > .row::-webkit-scrollbar { display: none; }
  .app-head > .row > .row,
  .app-head > .row > .segmented { flex-wrap: nowrap; flex: 0 0 auto; }
  .app-head .chip, .app-head .segmented-btn { white-space: nowrap; flex: none; }
  .head-account { padding: 4px 12px 4px 4px; font-size: 13px; }
  .head-account .avatar { width: 28px; height: 28px; }

  /* BUG FIXED HERE: app.css collapses .rowitem to two columns on mobile and
     moves .rowitem-end onto the second row, which put the ↗ on its own line
     under every About link. Three columns hold fine -- the end column is
     auto-width and its content is a single glyph. */
  .rowitem { grid-template-columns: 38px minmax(0, 1fr) auto; }
  .rowitem-end { grid-column: auto; text-align: right; }

  .tabbar {
    display: flex !important;
    align-items: center; justify-content: space-between;
    position: fixed;
    inset: auto 0 0 0;
    height: auto;
    width: 100%;
    margin: 0;
    padding: 14px 34px calc(14px + env(safe-area-inset-bottom));
    gap: 0;
    /* The sweep from the reference: the bar's top edge is an arc, not a
       straight line. A large elliptical radius on the two top corners is
       what draws it. */
    border-radius: 46% 46% 0 0 / 34px 34px 0 0;
    background: var(--surface);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-line);
    border-bottom: 0;
    box-shadow: var(--lift-3), var(--inset-1);
    z-index: 60;
    overflow: visible;
  }

  /* The two flanking controls. */
  .dock-side {
    width: 46px; height: 46px; flex: none;
    display: grid; place-items: center;
    border-radius: 50%;
    background: transparent;
    color: var(--text-3);
    transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
  }
  .dock-side svg { width: 22px; height: 22px; }
  .dock-side.on { color: var(--brand); background: var(--brand-soft); }
  .dock-side .avatar { width: 30px; height: 30px; border-radius: 50%; overflow: hidden; }
  .dock-side .avatar img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; }

  /* The raised button. It sits ABOVE the bar's top edge, as in the sample. */
  .dock-fab {
    position: relative;
    width: 66px; height: 66px; flex: none;
    margin-top: -40px;
    border-radius: 50%;
    display: grid; place-items: center; gap: 0;
    border: 1px solid var(--glass-line);
    background: var(--surface-3);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    box-shadow: var(--lift-3), inset 0 2px 0 rgba(255,255,255,.35);
    color: var(--text);
    cursor: pointer;
    transition: transform var(--t-fast) var(--ease);
  }
  .dock-fab:active { transform: scale(.93); }
  .dock-fab svg { width: 26px; height: 26px; }
  .dock-fab .dot { position: absolute; top: 8px; right: 8px; width: 10px; height: 10px; }

  .app-main { margin-left: 0; padding: 4px 16px calc(116px + env(safe-area-inset-bottom)); }
}

/* ── Navigation panel (phone) ──────────────────────────────────────────────
   The reference's own content shape: a grid of soft rounded-square tiles,
   icon above, label below. Opens from the raised button. The panel's top
   edge carries the same arc the bar does, so the two read as one system. */
.nav-panel-modal { align-items: flex-end; padding: 0; }
.nav-panel {
  width: 100%; max-width: 560px; margin: 0 auto;
  border-radius: 40% 40% 0 0 / 54px 54px 0 0;
  padding: 30px 20px calc(30px + env(safe-area-inset-bottom));
  background: var(--surface);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-line);
  border-bottom: 0;
  box-shadow: var(--lift-3), var(--inset-1);
  animation: nav-panel-in .32s var(--ease-out);
}
@keyframes nav-panel-in { from { transform: translateY(16%); opacity: 0; } }

.nav-panel-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px 12px;
  margin-top: 6px;
}
.nav-panel-item {
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  color: var(--text-2);
  min-width: 0;
}
.nav-panel-tile {
  width: 62px; height: 62px;
  border-radius: 20px;
  display: grid; place-items: center;
  background: var(--surface-3);
  border: 1px solid var(--glass-line);
  box-shadow: var(--lift-1), inset 0 1px 0 rgba(255,255,255,.4);
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.nav-panel-item:active .nav-panel-tile { transform: scale(.94); }
.nav-panel-tile svg { width: 25px; height: 25px; }
.nav-panel-label {
  font-size: 12.5px; font-weight: 650; letter-spacing: -.01em;
  text-align: center; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nav-panel-item.on { color: var(--brand); }
.nav-panel-item.on .nav-panel-tile {
  background: var(--grad-brand); color: #fff; border-color: transparent;
  box-shadow: 0 12px 26px -10px var(--brand);
}
.nav-panel-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 26px;
}

/* ── 07 CARDS ──────────────────────────────────────────────────────────────
   One owl card, everywhere. Art on top, meta strip below, pills floating on
   the art. Built by NWApp.ncard(), never hand-rolled in a page file.      */

.ncard {
  background: var(--surface);
  border-radius: var(--r-2xl);
  box-shadow: var(--lift-1), var(--inset-1);
  transition: transform var(--t-fast) var(--ease-out),
              box-shadow var(--t-fast) var(--ease);
}
.ncard:hover { transform: translateY(-5px); box-shadow: var(--lift-2), var(--inset-1); }
.ncard.sel    { box-shadow: var(--ring), var(--lift-2); }
.ncard.listed { box-shadow: 0 0 0 2px var(--amber), var(--lift-2); }

.ncard-art { background: var(--surface-2); }
.ncard-art > img { border-radius: 0; }

.ncard-tag {
  background: rgba(10, 7, 14, .55);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
  border: 1px solid rgba(255,255,255,.12);
  padding: 5px 12px;
  font-size: 11px; font-weight: 700;
  box-shadow: 0 2px 8px rgba(0,0,0,.25);
}
.ncard-tag.legend { background: rgba(240,178,74,.92); color: #241802; border-color: transparent; }
.ncard-tag.rare   { background: rgba(167,139,250,.92); color: #17092e; border-color: transparent; }
.ncard-tag.listed { background: var(--amber); color: #241804; border-color: transparent; }

.ncard-foot, .ncard-foot-col { background: var(--surface); padding: 12px 14px 14px; }
.ncard-id { font-size: 13.5px; letter-spacing: -.01em; }

.ncard-round {
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-line);
  color: var(--text);
  width: 32px; height: 32px;
  box-shadow: var(--lift-1);
}
.ncard.sel .ncard-round { background: var(--brand); border-color: transparent; color: #fff; }

.state-pill { padding: 4px 11px; font-size: 11px; font-weight: 700; border-radius: var(--r-pill); }
.state-idle    { background: var(--surface-3); color: var(--text-2); }
.state-staked  { background: color-mix(in srgb, var(--mint) 18%, transparent); color: var(--mint); }
.state-cooling { background: color-mix(in srgb, var(--amber) 18%, transparent); color: var(--amber); }
.state-ready   { background: var(--mint); color: #05231a; }

/* ── 08 TILES & STATS ──────────────────────────────────────────────────────*/

.card {
  background: var(--surface);
  border-radius: var(--r-2xl);
  box-shadow: var(--lift-1), var(--inset-1);
  border: 1px solid transparent;   /* inline border-color accents still work */
  padding: 22px;
}
.card-title { font-size: 15px; font-weight: 700; letter-spacing: -.02em; }

.stat {
  background: var(--surface);
  border-radius: var(--r-xl);
  box-shadow: var(--lift-1), var(--inset-1);
  padding: 18px;
}
.stat-k { font-size: 12px; font-weight: 650; color: var(--text-3); letter-spacing: .01em; }
.stat-v { font-size: clamp(20px, 2.4vw, 27px); letter-spacing: -.035em; }

/* ── The hero ──────────────────────────────────────────────────────────────
   A flat crimson rectangle with eight identical boxes on it was doing the
   job of a table, not a hero. Four changes make it carry the page:

     · a layered field instead of a flat fill -- two soft light sources plus
       a diagonal sweep, so the panel has a direction and a depth to it
     · a slow drifting highlight, the only ambient motion in the Hub
     · the FIRST figure is the headline one: it spans wide, sets large, and
       the rest sit around it, so the eye lands somewhere deliberate
     · figures in the display face at a real size, with the label small and
       quiet beneath -- previously both were nearly the same weight         */
.pitch {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Derived from --brand like everything else. This was three hardcoded
     crimsons, which meant the biggest panel on the home page would have
     stayed red no matter what accent someone chose -- the one place the
     change would be most obvious. */
  background:
    radial-gradient(90% 120% at 8% 0%,
      color-mix(in srgb, var(--brand) 78%, #ffffff) 0%,
      color-mix(in srgb, var(--brand) 0%, transparent) 55%),
    radial-gradient(70% 100% at 100% 100%,
      color-mix(in srgb, var(--brand) 42%, #000000) 0%,
      transparent 60%),
    linear-gradient(135deg,
      color-mix(in srgb, var(--brand) 92%, #ffffff) 0%,
      var(--brand) 45%,
      color-mix(in srgb, var(--brand) 58%, #000000) 100%);
  border-radius: var(--r-3xl);
  box-shadow: var(--lift-3), inset 0 1px 0 rgba(255,255,255,.22);
  padding: clamp(26px, 4vw, 48px);
  color: #fff;
}
/* A slow highlight drifting across the panel. Big, soft and cheap: one
   transformed pseudo-element, no repaint of anything under it. */
.pitch::before {
  content: "";
  position: absolute; z-index: -1;
  width: 70%; aspect-ratio: 1; left: -10%; top: -45%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.22), transparent 62%);
  animation: pitch-drift 22s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes pitch-drift {
  to { transform: translate(55%, 28%) scale(1.25); }
}
/* A fine grain over the gradient stops it banding on wide screens. */
.pitch::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background-image: radial-gradient(rgba(255,255,255,.055) 1px, transparent 1px);
  background-size: 4px 4px;
  opacity: .5;
  pointer-events: none;
}
.pitch h2 {
  font-size: clamp(30px, 5vw, 52px);
  letter-spacing: -.045em;
  line-height: 1.02;
  text-shadow: 0 2px 20px rgba(0,0,0,.25);
}
.pitch > div > p { font-size: clamp(14px, 1.5vw, 16.5px); opacity: .88; }

.pitch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(146px, 1fr));
  gap: 10px;
  max-width: 900px;
}
.pitch-item {
  position: relative;
  display: flex; flex-direction: column; justify-content: center;
  min-width: 0;
  padding: 15px 17px;
  border-radius: var(--r-lg);
  background: linear-gradient(160deg, rgba(255,255,255,.22), rgba(255,255,255,.08));
  border: 1px solid rgba(255,255,255,.2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.pitch-item:hover { transform: translateY(-2px); background: linear-gradient(160deg, rgba(255,255,255,.3), rgba(255,255,255,.12)); }
.pitch-item b {
  font-family: var(--font-display, "Space Grotesk", sans-serif);
  font-size: 21px; font-weight: 700; letter-spacing: -.035em;
  line-height: 1.1;
  overflow-wrap: anywhere;
}
.pitch-item span {
  font-size: 11.5px; font-weight: 600;
  opacity: .74; margin-top: 3px;
  text-transform: uppercase; letter-spacing: .06em;
}

/* The headline figure. First child, twice the width, twice the presence. */
.pitch-item:first-child {
  grid-column: span 2;
  padding: 20px 22px;
  background: linear-gradient(160deg, rgba(255,255,255,.34), rgba(255,255,255,.14));
  border-color: rgba(255,255,255,.34);
}
.pitch-item:first-child b { font-size: clamp(30px, 4vw, 42px); }
.pitch-item:first-child span { font-size: 12px; opacity: .85; }

@media (max-width: 560px) {
  .pitch-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pitch-item:first-child { grid-column: span 2; }
}
@media (prefers-reduced-motion: reduce) { .pitch::before { animation: none; } }

/* ── 09 HISTORY ROWS ───────────────────────────────────────────────────────
   Board 1's History block: a soft container, rows inside it, no rules.     */

.history-table { padding: 8px; }
.history-head {
  padding: 12px 18px 14px;
  font-size: 11.5px; font-weight: 650; color: var(--text-3);
  letter-spacing: .04em; text-transform: uppercase;
}
.history-row {
  border-radius: var(--r-lg);
  padding: 14px 18px;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.history-row:nth-child(odd) { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.history-row:hover { background: var(--surface-2); transform: translateX(3px); }
.history-ico {
  width: 34px; height: 34px;
  background: color-mix(in srgb, currentColor 16%, var(--surface-3));
  box-shadow: var(--inset-1);
}
.rowitem { border-radius: var(--r-lg); padding: 14px; }
.rowitem:nth-child(odd) { background: color-mix(in srgb, var(--surface-2) 50%, transparent); }

/* ── 10 MEMBERS ────────────────────────────────────────────────────────────*/

.member-card {
  background: var(--surface);
  border-radius: var(--r-2xl);
  box-shadow: var(--lift-1), var(--inset-1);
}
.member-card:hover { box-shadow: var(--lift-2), var(--inset-1); }
.member-cover { height: 78px; background: var(--grad-brand); background-size: cover; background-position: center; }
.member-avatar { border-color: var(--surface); box-shadow: var(--lift-1); }
.member-name { font-size: 16px; letter-spacing: -.02em; }
.member-tag { background: var(--surface-2); padding: 5px 11px; }
.member-badges span { background: var(--surface-2); box-shadow: var(--inset-1); }
.member-crown {
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-line);
}

/* ── 11 PROFILE ────────────────────────────────────────────────────────────*/

.cover { border-radius: var(--r-3xl); box-shadow: var(--lift-2); }
.avatar-xl { border-color: var(--shell); box-shadow: var(--lift-2); }
.profile-name { letter-spacing: -.035em; }
.profile-verified { background: var(--brand); box-shadow: 0 2px 8px -2px var(--brand); }
.badge-pill { border-radius: var(--r-pill); padding: 5px 12px; font-weight: 700; font-size: 11.5px; }

/* ── 12 CONTROLS, MOTION, FOCUS ────────────────────────────────────────────*/

.btn {
  border-radius: var(--r-pill);
  border: 0;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 650;
  box-shadow: var(--lift-1), var(--inset-1);
  transition: transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease);
}
.btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--lift-2), var(--inset-1); }
.btn:active:not(:disabled) { transform: translateY(0); box-shadow: var(--lift-1); }
.btn-primary { background: var(--grad-brand); color: #fff; box-shadow: 0 8px 22px -10px var(--brand); }
.btn-ghost { background: transparent; box-shadow: none; color: var(--text-2); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-2); box-shadow: var(--lift-1); }
.btn:disabled { opacity: .45; box-shadow: none; }
.btn-icon { border-radius: 50%; }

.chip {
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 0;
  padding: 8px 15px;
  font-weight: 600;
  color: var(--text-2);
  box-shadow: var(--inset-1);
}
.chip:hover { background: var(--surface-3); color: var(--text); }
.chip.on { background: var(--grad-brand); color: #fff; box-shadow: 0 6px 16px -8px var(--brand); }

.input, .field input, .field textarea, .field select {
  background: var(--surface-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  color: var(--text);
  box-shadow: var(--inset-1);
}
.input:focus, .field input:focus, .field textarea:focus { outline: none; box-shadow: var(--ring); }

.modal { background: rgba(6, 4, 9, .62); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.modal-card {
  background: var(--shell);
  border-radius: var(--r-3xl);
  box-shadow: var(--lift-3);
  border: 1px solid transparent;
}
.modal-x { border-radius: 50%; background: var(--surface-2); border: 0; box-shadow: var(--inset-1); }

.toast { border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--lift-3), var(--inset-1); border: 0; }
.gas-bar { background: var(--surface); box-shadow: var(--inset-1); border: 0; }
.empty { background: var(--surface); border-radius: var(--r-2xl); box-shadow: var(--inset-1); border: 0; }
.skel {
  background: linear-gradient(100deg, var(--surface-2) 30%, var(--surface-3) 50%, var(--surface-2) 70%);
  background-size: 220% 100%;
  border-radius: var(--r-2xl);
  animation: theme-shimmer 1.3s linear infinite;
}
@keyframes theme-shimmer { to { background-position: -220% 0; } }

/* Keyboard focus is never removed, only restyled. */
:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
  .rail { transition: none; }
}

/* ── Stake section accent ──────────────────────────────────────────────────
   BUG FIXED HERE: .stake-section-accent is absolutely positioned, but its
   parent .panel never established a positioning context. It escaped to the
   nearest positioned ancestor and drew a 4px red bar down the whole page,
   straight through the "Idle · 248" heading. The parent is now relative, the
   bar is inset to the heading block only, and it is rounded rather than a
   raw rectangle butted against the text. */
.stake-section { position: relative; padding-left: 18px; }
.stake-section-accent {
  position: absolute;
  left: 0; top: 6px; bottom: auto;
  width: 4px; height: 38px;
  border-radius: var(--r-pill);
}
.stake-section-accent-brand { background: var(--grad-brand); }
.stake-section-accent-amber { background: var(--amber); }
.stake-section-accent-mint  { background: var(--mint); }
@media (max-width: 560px) { .stake-section { padding-left: 14px; } }

/* ── GLASS PASS ────────────────────────────────────────────────────────────
   Every surface token is translucent now, so each component that paints one
   must also blur what is behind it, otherwise the page shows through as a
   muddy wash rather than as glass. Applied at CONTAINER level only (panels,
   cards, controls, overlays); small children inherit the effect by sitting
   on top of an already-blurred parent, which keeps the number of live
   backdrop-filters bounded rather than one per pill.                        */
.app-main,
.card,
.stat,
.ncard,
.member-card,
.modal-card,
.nav-sheet,
.searchbar,
.head-account,
.segmented,
.gas-bar,
.toast,
.empty,
.history-table,
.btn:not(.btn-primary):not(.btn-on-brand):not(.btn-ghost),
.chip:not(.on) {
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}

/* A hairline of light along the top edge is what separates one pane of glass
   from the next once neither of them is opaque. */
.app-main, .card, .stat, .ncard, .member-card, .modal-card {
  border: 1px solid var(--glass-line);
}

/* Children sitting on an already-blurred parent must NOT blur again, a
   nested backdrop-filter samples its parent, not the page, and the result
   is a grey slab. These stay flat translucent. */
.ncard-foot, .ncard-foot-col, .ncard-art,
.history-row, .rowitem, .pitch-item, .member-cover, .member-body {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.ncard-art { background: rgba(255,255,255,.06); }
[data-theme="light"] .ncard-art { background: rgba(255,255,255,.5); }
.ncard-foot, .ncard-foot-col { background: transparent; }

/* The hero stays solid. It is the one deliberately opaque panel: a
   saturated gradient read through glass loses the punch it exists for.
   Its own border and layered field are set in §08 and must survive this. */
.pitch { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* ── Profile picture shapes ────────────────────────────────────────────────
   Three, set per profile and stored on it. Circle is the default and the
   fallback for any value the CSS does not recognise, so an unknown stored
   shape can never render as a raw square. */
.avatar.pfp-circle  { border-radius: 50%; }
.avatar.pfp-rounded { border-radius: 26%; }
.avatar.pfp-hex {
  border-radius: 0;
  /* A regular flat-top hexagon. clip-path removes the element's own border,
     so the ring is redrawn as a filter drop-shadow that follows the clip. */
  clip-path: polygon(25% 3%, 75% 3%, 100% 50%, 75% 97%, 25% 97%, 0% 50%);
  border: 0;
  filter: drop-shadow(0 0 2px var(--surface)) drop-shadow(0 6px 14px rgba(0,0,0,.45));
}
.avatar.pfp-hex img, .avatar.pfp-hex canvas { border-radius: 0; }

/* The member cards use the same vocabulary, at their own size. */
.member-avatar.pfp-rounded { border-radius: 26%; }
.member-avatar.pfp-hex {
  border-radius: 0; border: 0;
  clip-path: polygon(25% 3%, 75% 3%, 100% 50%, 75% 97%, 25% 97%, 0% 50%);
  filter: drop-shadow(0 0 2px var(--surface));
}

/* ── Cover editor ──────────────────────────────────────────────────────────
   BUG FIXED HERE: the editor is tall, a picker strip, a live banner and a
   row of controls, and the modal had no scroll of its own, so on a short
   viewport the bottom half was unreachable and the banner could not even be
   seen whole. The card scrolls now and is capped to the viewport. */
#cover-modal .modal-card,
#edit-modal .modal-card,
.cover-editor-card {
  max-height: min(92vh, 900px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* The overlay itself scrolls when a tall card cannot fit, and the card is
   pinned to the top on short viewports so its header is always reachable. */
.modal { overflow-y: auto; overscroll-behavior: contain; align-items: start; }
.modal > .modal-card { margin: auto; }
@media (max-height: 760px) { .modal > .modal-card { margin: 12px auto; } }

/* ── Holdings breakdown ────────────────────────────────────────────────────
   One bar showing the tier split, then the same three figures as a list. The
   bar is for shape, the list is for numbers, asking one element to do both
   is what makes charts unreadable at this size. */
.tierbar {
  display: flex; gap: 3px; height: 14px; margin: 4px 0 16px;
  border-radius: var(--r-pill); overflow: hidden;
}
.tierbar > i { display: block; min-width: 3px; }
.tierbar-legendary { background: var(--amber); }
.tierbar-rare      { background: var(--violet); }
.tierbar-normal    { background: var(--surface-4); }

.tierlist { display: flex; flex-direction: column; gap: 9px; }
.tierlist-row { display: grid; grid-template-columns: 12px 1fr auto auto; gap: 11px; align-items: center; font-size: 13.5px; }
.tierdot { width: 10px; height: 10px; border-radius: 3px; }
.tierlist-name { font-weight: 600; }
.tierlist-n { font-weight: 700; }
.tierlist-pct { font-size: 12px; min-width: 52px; text-align: right; }

.callout-ico {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, currentColor 16%, var(--surface-2));
}
.callout-ico svg { width: 20px; height: 20px; }

/* ── Milestones ────────────────────────────────────────────────────────────*/
.milestones { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.milestone { padding: 14px 16px; border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.milestone-k { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); }
.milestone-v {
  font-family: var(--font-display, "Space Grotesk", sans-serif);
  font-size: 21px; font-weight: 700; letter-spacing: -.03em; margin-top: 4px;
  overflow-wrap: anywhere;
}
.milestone-note { font-size: 11.5px; color: var(--text-3); margin-top: 3px; line-height: 1.45; }

/* ── Members: collection totals and owl lookup ─────────────────────────────*/
.dir-totals {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px; margin-bottom: 16px;
}
.dir-total {
  padding: 13px 15px; border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.dir-total b {
  display: block;
  font-family: var(--font-display, "Space Grotesk", sans-serif);
  font-size: 19px; font-weight: 700; letter-spacing: -.03em;
}
.dir-total span { font-size: 11px; color: var(--text-3); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }

.dir-lookup { margin-bottom: 14px; padding: 14px 16px; }
.dir-lookup-art { width: 52px; height: 52px; border-radius: var(--r-md); image-rendering: pixelated; flex: none; }

/* ── Showcase ──────────────────────────────────────────────────────────────
   A ranking nobody can see is just a list. #1 spans two columns and two rows
   so the choice is visible at a glance, and the rank number sits on the art
   rather than under it. */
.showcase {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}
.show-item {
  position: relative; margin: 0; min-width: 0; cursor: pointer;
  border-radius: var(--r-xl); overflow: hidden;
  background: var(--surface-2);
  box-shadow: var(--lift-1);
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease);
}
.show-item:hover { transform: translateY(-4px); box-shadow: var(--lift-2); }
.show-item img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; image-rendering: pixelated; }
.show-hero { grid-column: span 2; grid-row: span 2; }
.show-rank {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  min-width: 24px; height: 24px; padding: 0 7px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: rgba(10,7,14,.62); color: #fff;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  font-family: var(--font-mono); font-size: 12px; font-weight: 700;
}
.show-hero .show-rank {
  background: var(--grad-brand);
  min-width: 30px; height: 30px; font-size: 14px;
}
.show-item figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 18px 10px 8px;
  background: linear-gradient(to top, rgba(8,6,12,.9), transparent);
  font-size: 11.5px; color: #fff;
}
.show-hero figcaption { font-size: 14px; padding: 26px 14px 12px; }
@media (max-width: 560px) {
  .showcase { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .show-hero { grid-column: span 3; grid-row: span 1; }
}

/* ── Showcase picker ───────────────────────────────────────────────────────*/
.fav-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; min-height: 42px; align-items: center; }
.fav-chip {
  position: relative; width: 46px; height: 46px; padding: 0; border: 0;
  border-radius: 13px; overflow: hidden; cursor: pointer;
  background: var(--surface-2); box-shadow: var(--lift-1);
}
.fav-chip img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; display: block; }
.fav-rank {
  position: absolute; top: 2px; left: 2px; z-index: 2;
  width: 17px; height: 17px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--grad-brand); color: #fff;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
}
.fav-x {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(8,6,12,.62); color: #fff; font-size: 20px;
  opacity: 0; transition: opacity var(--t-fast) var(--ease);
}
.fav-chip:hover .fav-x { opacity: 1; }
.fav-order:empty { display: none; }

/* ── Standing ──────────────────────────────────────────────────────────────
   A scoreboard, not a report. The ordinal is the largest thing on the tile;
   the bar underneath converts it to a percentile so nobody has to divide. */
.rankrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.ranktile {
  position: relative; overflow: hidden;
  padding: 18px 20px; border-radius: var(--r-2xl);
  background: var(--surface); border: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: var(--lift-1);
}
.ranktile-k { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--text-3); }
.ranktile-v {
  font-family: var(--font-display, "Space Grotesk", sans-serif);
  font-size: clamp(30px, 4vw, 40px); font-weight: 700; letter-spacing: -.045em;
  line-height: 1.05; margin: 4px 0 10px; display: flex; align-items: baseline; gap: 8px;
}
.ranktile-hash { font-size: .55em; opacity: .45; }
.ranktile-of { font-size: 12.5px; font-weight: 600; letter-spacing: 0; color: var(--text-3); font-family: var(--font-body); }
.ranktile-bar { height: 6px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.ranktile-bar > i { display: block; height: 100%; border-radius: inherit; background: var(--grad-brand); }
.ranktile-note { font-size: 11.5px; color: var(--text-3); margin-top: 8px; line-height: 1.45; }

/* The top of the board earns its own colour. Gold for first, then silver,
   then a brand tint for the top decile -- so position is readable before a
   single number is. */
.ranktile.gold   { box-shadow: 0 0 0 1px #f5c542, var(--lift-2); }
.ranktile.gold   .ranktile-bar > i { background: linear-gradient(90deg, #f5c542, #d99b12); }
.ranktile.gold::after, .ranktile.silver::after, .ranktile.top::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(90% 70% at 100% 0%, currentColor, transparent 62%);
  opacity: .1;
}
.ranktile.gold   { color: #f5c542; }
.ranktile.silver { color: #c3cad9; box-shadow: 0 0 0 1px rgba(195,202,217,.5), var(--lift-1); }
.ranktile.top    { color: var(--brand-2); }
.ranktile-k, .ranktile-v, .ranktile-note { color: var(--text); }
.ranktile-k, .ranktile-note, .ranktile-of { color: var(--text-3); }

/* ── Background picker ─────────────────────────────────────────────────────
   Grouped by family, with a live preview of whatever you are building. A row
   of small squares tells you nothing about a gradient, these are wide and
   tall enough to actually show the falloff. */
.settings-sub {
  margin: 24px 0 12px;
  font-size: 11px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--text-3);
}

.bg-family { margin-bottom: 18px; }
.bg-family-k {
  font-size: 11.5px; font-weight: 650; color: var(--text-3);
  margin-bottom: 8px; letter-spacing: .02em;
}
.bg-row {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 10px;
}
.bg-preset {
  display: flex; flex-direction: column; gap: 7px;
  padding: 0; border: 0; background: none; cursor: pointer;
  font-size: 11.5px; font-weight: 600; color: var(--text-3);
  text-align: left;
}
.bg-preview {
  display: block; height: 84px; border-radius: var(--r-md);
  /* No fill is declared here on purpose. The swatch tint arrives inline, per
     preset. A fallback set in this rule would quietly stand in whenever the
     inline one was missing, hiding the very failure being designed out. */
  background-size: cover;
  background-repeat: no-repeat;
  border: 1px solid var(--glass-line);
  box-shadow: var(--lift-1);
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease);
}

.bg-preset:hover .bg-preview { transform: translateY(-3px); box-shadow: var(--lift-2); }
.bg-preset.on { color: var(--text); }
.bg-preset.on .bg-preview { box-shadow: 0 0 0 2px var(--brand), var(--lift-2); }
.bg-name { padding-left: 2px; }

.bg-builder {
  display: grid; grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  gap: 16px; align-items: stretch;
}
.bg-custom-preview {
  min-height: 170px; border-radius: var(--r-2xl);
  background-color: var(--page);
  background-size: cover;
  background-repeat: no-repeat;
  border: 1px solid var(--glass-line);
  box-shadow: var(--lift-2), var(--inset-1);
}
.bg-controls { display: flex; flex-direction: column; gap: 12px; justify-content: center; min-width: 0; }
.bg-kind { align-self: flex-start; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.bg-kind::-webkit-scrollbar { display: none; }
.bg-kind .segmented-btn { padding: 8px 14px; font-size: 12.5px; white-space: nowrap; }

.bg-custom { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.bg-swatch-field { display: flex; align-items: center; gap: 9px; font-size: 12px; color: var(--text-3); font-weight: 650; }
.bg-swatch-field input[type="color"] {
  width: 46px; height: 36px; padding: 3px; cursor: pointer;
  border: 1px solid var(--glass-line); border-radius: 11px; background: var(--surface-2);
}
.bg-angle { flex: 1 1 160px; }
.bg-swatch-field input[type="range"] { flex: 1; min-width: 100px; accent-color: var(--brand); }

@media (max-width: 720px) {
  .bg-builder { grid-template-columns: 1fr; }
  .bg-custom-preview { min-height: 120px; }
}

/* ── Accent picker ─────────────────────────────────────────────────────────*/
.accent-row { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.accent-presets { display: flex; flex-wrap: wrap; gap: 9px; }
.accent-dot {
  width: 34px; height: 34px; padding: 3px; cursor: pointer;
  border: 0; border-radius: 50%; background: transparent;
  display: grid; place-items: center;
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease);
}
.accent-dot > span {
  display: block; width: 100%; height: 100%; border-radius: 50%;
  box-shadow: var(--lift-1), inset 0 1px 0 rgba(255,255,255,.3);
}
.accent-dot:hover { transform: translateY(-2px) scale(1.06); }
.accent-dot.on { box-shadow: 0 0 0 2px var(--text-3); }

/* ── Save the look ─────────────────────────────────────────────────────────*/
.appearance-save {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 20px; padding: 16px 18px;
  border-radius: var(--r-2xl);
  background: var(--surface-2);
  border: 1px solid var(--glass-line);
}
.appearance-save .grow { min-width: min(100%, 240px); }

/* A colour someone chose, shown rather than named. */
.act-swatch {
  display: inline-block; width: 13px; height: 13px;
  margin-left: 8px; vertical-align: -1px;
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.35), var(--lift-1);
}

/* A standing condition, not a notification: it stays until it is fixed. */
.schema-warn {
  margin-bottom: 18px;
  border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
  background: color-mix(in srgb, var(--amber) 8%, var(--surface));
}

/* ── Account menu ──────────────────────────────────────────────────────────
   The pill is two controls sharing one shape: the name navigates, the
   chevron opens a menu. They look like one object and behave like two,
   which is what makes the common action stay a single click. */
.head-account-wrap { position: relative; display: inline-flex; align-items: stretch; }
.head-account-wrap .head-account { border-radius: var(--r-pill) 0 0 var(--r-pill); padding-right: 10px; }
.head-account-caret {
  display: grid; place-items: center;
  width: 32px; padding: 0 4px 0 0; border: 0; cursor: pointer;
  border-radius: 0 var(--r-pill) var(--r-pill) 0;
  background: var(--surface);
  box-shadow: var(--lift-1), var(--inset-1);
  color: var(--text-2);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.head-account-caret svg { width: 14px; height: 14px; transition: transform var(--t-med) var(--ease-out); }
.head-account-caret:hover { background: var(--surface-3); color: var(--text); }
.head-account-caret[aria-expanded="true"] svg { transform: rotate(180deg); }
/* One continuous pill: the seam between the two halves is a hairline, not a
   gap, so it does not read as two buttons that happen to touch. */
.head-account-wrap::after {
  content: ""; position: absolute; top: 22%; bottom: 22%;
  left: calc(100% - 32px); width: 1px;
  background: var(--glass-line); pointer-events: none;
}

.account-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 80;
  min-width: 190px; padding: 6px;
  border-radius: var(--r-xl);
  background: var(--surface);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-line);
  box-shadow: var(--lift-3);
  animation: account-menu-in .16s var(--ease-out);
}
@keyframes account-menu-in { from { opacity: 0; transform: translateY(-4px); } }
.account-menu[hidden] { display: none; }
.account-menu-row {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 10px 12px; border: 0; background: none; cursor: pointer;
  border-radius: var(--r-md);
  color: var(--text-2); font-size: 14px; font-weight: 600; text-align: left;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.account-menu-row svg { width: 17px; height: 17px; flex: none; }
.account-menu-row:hover { background: var(--surface-2); color: var(--text); }
.account-menu-row.danger { color: var(--brand-2); }
.account-menu-row.danger:hover { background: var(--brand-soft); }

.head-connect { gap: 9px; padding-left: 5px; }
.head-connect-ico {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--grad-brand); color: #fff;
}
.head-connect-ico svg { width: 16px; height: 16px; }

/* The owls a member chose to show, on their card. Overlapped rather than
   spaced: four small squares in a row read as a list, a stack reads as a set. */
.member-featured { display: flex; justify-content: center; margin-top: 8px; }
.member-featured-owl {
  width: 34px; height: 34px; border-radius: 11px; overflow: hidden;
  border: 2px solid var(--surface);
  background: var(--surface-2);
  margin-left: -8px;
  box-shadow: var(--lift-1);
  transition: transform var(--t-fast) var(--ease-out);
}
.member-featured-owl:first-child { margin-left: 0; }
.member-card:hover .member-featured-owl { transform: translateY(-2px); }
.member-featured-owl img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; display: block; }

/* The version, stated quietly where a finished product states it. */
.version-line {
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--glass-line);
  font-family: var(--font-mono); font-size: 11px;
  color: var(--text-3); text-align: center;
}

/* ==========================================================================
   MOTION
   --------------------------------------------------------------------------
   The Hub painted everything instantly. Nothing was wrong with that, but it
   is the clearest remaining difference between "well drawn" and "expensive".

   Three rules this follows, because most interface motion fails by ignoring
   one of them:

   1. MOTION EXPLAINS, IT DOES NOT DECORATE. Every animation here says
      something: this arrived, this is loading, this responded to you. There
      is no motion whose only job is to be noticed.

   2. NOTHING BLOCKS. Every duration is under 400ms and nothing delays an
      interaction. An interface that makes you wait for its animation is
      slower, not richer.

   3. IT ENTERS ONCE. Content animates when it first appears, never on
      re-render. Cards that re-animate every time a filter changes turn a
      list into a slot machine.

   All of it is disabled wholesale under prefers-reduced-motion at the
   bottom of this block.
   ========================================================================== */

/* ── Entrance ──────────────────────────────────────────────────────────────
   A short rise and fade. 14px, not 40: a large travel reads as a slide, a
   small one reads as settling into place. */
@keyframes enter-up {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes enter-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Applied by JS to a container. Children stagger; the container does not
   animate itself, so nothing shifts layout while it runs. */
.stagger > * {
  animation: enter-up .42s var(--ease-out) both;
}
/* Eight steps of 45ms. Beyond that the delay is capped rather than growing,
   or the last card in a 50 item grid would arrive two seconds late. */
.stagger > *:nth-child(1)  { animation-delay: 0ms; }
.stagger > *:nth-child(2)  { animation-delay: 45ms; }
.stagger > *:nth-child(3)  { animation-delay: 90ms; }
.stagger > *:nth-child(4)  { animation-delay: 135ms; }
.stagger > *:nth-child(5)  { animation-delay: 180ms; }
.stagger > *:nth-child(6)  { animation-delay: 225ms; }
.stagger > *:nth-child(7)  { animation-delay: 270ms; }
.stagger > *:nth-child(n+8) { animation-delay: 315ms; }

/* A whole section arriving, for panels rather than grids. */
.enter { animation: enter-up .5s var(--ease-out) both; }
.enter-soft { animation: enter-fade .5s var(--ease) both; }

/* ── Response ──────────────────────────────────────────────────────────────
   Press states. A control that moves when you push it feels connected to the
   finger; one that does not feels like a picture of a control. */
.btn:active:not(:disabled),
.chip:active,
.ncard:active,
.member-card:active,
.accent-dot:active,
.bg-preset:active { transform: translateY(1px) scale(.985); }
.btn, .chip, .accent-dot, .bg-preset { transition: transform .12s var(--ease), box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease); }

/* ── Numbers ───────────────────────────────────────────────────────────────
   A figure that counts up is read; a figure that appears is skipped. Used
   only on the handful of headline numbers, never on a table. */
.tick { display: inline-block; font-variant-numeric: tabular-nums; }

/* ── Waiting ───────────────────────────────────────────────────────────────
   The skeleton already shimmers. This makes its replacement graceful rather
   than a jump cut. */
.skel { animation: theme-shimmer 1.3s linear infinite; }
.settled { animation: enter-fade .3s var(--ease) both; }

/* ── Attention ─────────────────────────────────────────────────────────────
   Reserved for one thing: a value that CHANGED while you were looking at it,
   such as a claimable balance arriving. It pulses twice and stops. */
@keyframes value-arrived {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  20%      { box-shadow: 0 0 0 4px var(--brand-soft); }
  60%      { box-shadow: 0 0 0 8px transparent; }
}
.value-arrived { animation: value-arrived 1.6s var(--ease) 2; }

/* ── Page transition ───────────────────────────────────────────────────────
   The Hub is multi-page, so the browser handles navigation. This softens the
   arrival without pretending to be a single page app. */
@media (prefers-reduced-motion: no-preference) {
  .app-main { animation: enter-fade .26s var(--ease) both; }
}

/* ── Off ───────────────────────────────────────────────────────────────────
   One block, everything. A person who has asked their system for less motion
   has asked once and should not have to ask each component. */
@media (prefers-reduced-motion: reduce) {
  .stagger > *, .enter, .enter-soft, .settled, .app-main,
  .value-arrived, .brand-wordmark::after, .pitch::before {
    animation: none !important;
  }
  .btn:active:not(:disabled), .chip:active, .ncard:active,
  .member-card:active, .accent-dot:active, .bg-preset:active { transform: none; }
}

/* ── Trait breakdown ───────────────────────────────────────────────────────*/
.trait-headline { margin-bottom: 16px; background: color-mix(in srgb, var(--brand) 9%, var(--surface)); }
.trait-headline-k { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--text-3); }
.trait-headline-v {
  font-family: var(--font-display, "Space Grotesk", sans-serif);
  font-size: clamp(22px, 3vw, 30px); font-weight: 700; letter-spacing: -.035em;
  margin: 4px 0 6px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.trait-headline-v .mono { font-size: .6em; color: var(--brand-2); }

.trait-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
.trait-group { padding: 18px; }
.trait-rows { display: flex; flex-direction: column; gap: 13px; }
.trait-stat { min-width: 0; }
.trait-stat-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.trait-stat-v { font-size: 13px; font-weight: 700; }
.trait-stat-n { font-size: 12.5px; font-weight: 650; }
.trait-stat-bar { height: 5px; border-radius: var(--r-pill); background: var(--surface-3); margin: 6px 0 4px; overflow: hidden; }
.trait-stat-bar > i { display: block; height: 100%; border-radius: inherit; background: var(--grad-brand); }
.trait-stat-note { font-size: 11px; }

/* ── Earnings sparkline ────────────────────────────────────────────────────
   Bars, not a line: a line implies a continuous quantity between points, and
   claims are discrete events on particular days. */
.spark { display: flex; align-items: flex-end; gap: 4px; height: 130px; margin-top: 6px; }
.spark-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 6px; }
.spark-bar {
  width: 100%; max-width: 30px; border-radius: 6px 6px 3px 3px;
  background: var(--grad-brand);
  box-shadow: 0 4px 14px -6px var(--brand);
  transition: filter var(--t-fast) var(--ease);
}
.spark-col:hover .spark-bar { filter: brightness(1.25); }
/* A month with no claims is information, so it is drawn rather than skipped. */
.spark-bar.empty { background: var(--surface-3); box-shadow: none; }
.spark-x { font-size: 10px; color: var(--text-3); font-weight: 650; }

/* ── Owl history ───────────────────────────────────────────────────────────*/
.owl-history { display: flex; flex-direction: column; gap: 6px; max-height: 480px; overflow-y: auto; }
.owl-history-row {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px; border-radius: var(--r-lg); cursor: pointer;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.owl-history-row:nth-child(odd) { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.owl-history-row:hover { background: var(--surface-2); transform: translateX(3px); }
.owl-history-art { width: 38px; height: 38px; border-radius: 11px; flex: none; image-rendering: pixelated; background: var(--surface-2); }
.owl-history-id { font-size: 13.5px; font-weight: 700; margin-right: 8px; }
.owl-history-kind { font-size: 12px; margin-left: 8px; }
.owl-history-when { font-size: 11.5px; flex: none; }

/* ── Standouts ─────────────────────────────────────────────────────────────
   The rare and legendary owls someone holds, as cards. Grouped by tier with
   the collection-wide count beside each, so "3 Legends" carries the weight
   of "3 of the 12 that exist". */
.standout-group + .standout-group { margin-top: 22px; }
.standout-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }

/* ── Staking rate ──────────────────────────────────────────────────────────
   The numbers that answer "what does this pay". The tile about YOUR owls is
   the one that matters, so it is the one that carries the accent. */
.rate-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.rate-tile {
  padding: 18px 20px; border-radius: var(--r-2xl);
  background: var(--surface); border: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: var(--lift-1);
}
.rate-k { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--text-3); }
.rate-v {
  font-family: var(--font-display, "Space Grotesk", sans-serif);
  font-size: clamp(24px, 3vw, 32px); font-weight: 700; letter-spacing: -.04em;
  margin: 5px 0 4px; line-height: 1.05;
}
.rate-v span { font-size: .42em; font-weight: 650; opacity: .6; letter-spacing: 0; }
.rate-note { font-size: 11.5px; color: var(--text-3); }
.rate-tile-you {
  background: linear-gradient(160deg, color-mix(in srgb, var(--brand) 20%, var(--surface)), var(--surface));
  border-color: color-mix(in srgb, var(--brand) 40%, transparent);
}
.rate-tile-you .rate-v { color: var(--brand-2); }
.rate-tile-warn { border-color: color-mix(in srgb, var(--amber) 38%, transparent); }
.rate-tile-warn .rate-v { color: var(--amber); }

/* ── Wallet deep links ─────────────────────────────────────────────────────
   The route that needs no SDK: open the Hub inside the wallet's own browser,
   where a normal provider is injected. */
.wallet-deeplinks { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--glass-line); }
.wallet-deeplinks-k {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-3); margin-bottom: 10px;
}
.wallet-deeplinks-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
.wallet-deeplinks-row .btn { justify-content: center; }
