/* Marketplace whitelabel creator hub — themed to match marketplace.tyga.games.

   Faithful port of WeSell's Steam/games storefront chrome, retargeted at a
   CREATOR roster. The page background is the operator BRAND colour
   (--hub-primary, cherry red for tyga.games); the accent underline / active
   states use --hub-accent (bright blue for tyga.games). Both are injected
   per-marketplace from the operator theme in marketplace-hub.ejs. The top nav
   (.mp-navbar) and footer (.mp-footer) are the dark games chrome, styled inline
   in the view exactly as WeSell renders them. */

.hub-body {
  margin: 0;
  font-family: 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  /* Operator brand background (cherry red for tyga.games) */
  background: var(--hub-primary, #d2042d);
  color: #f3d9dd;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Content surfaces are theme-aware so BOTH a light (white/red) and a dark
   (black/red) hub read correctly. LIGHT is the default here; a dark tenant
   (body.hub-dark, driven by theme.darkMode) overrides the vars below. The hero
   sits on its own brand gradient and keeps white text in both modes. */
.hub-body {
  --card: #ffffff;
  --card-hover: #f6f6f7;
  --card-border: rgba(0, 0, 0, .10);
  --hub-fg: #1a1a1a;
  --hub-fg-muted: rgba(0, 0, 0, .62);
  --hub-surface: #ffffff;
  --hub-surface-border: rgba(0, 0, 0, .10);
  --hub-primary-dark: color-mix(in srgb, var(--hub-primary, #d2042d) 76%, #000);
}
.hub-body.hub-dark {
  --card: rgba(255, 255, 255, .14);
  --card-hover: rgba(255, 255, 255, .24);
  --card-border: rgba(255, 255, 255, .08);
  --hub-fg: #ffffff;
  --hub-fg-muted: rgba(255, 255, 255, .78);
  --hub-surface: var(--card-bg, #16202d);
  --hub-surface-border: var(--border-color, #2a475e);
}

/* ---- Red browse sub-nav (Steam-style, under the dark top nav) ---- */
.hub-subnav {
  background: var(--hub-primary-dark, #a3021f);
  border-bottom: 1px solid rgba(0, 0, 0, .55);
  position: sticky;
  top: 68px;
  z-index: 1010;
}
/* Width = play.tyga.games (wesell) Bootstrap .container-xl: 1200px box, 15px gutters.
   The sub-nav and every tab's .hub-wrap share it, so all edges line up across both sites. */
.hub-subnav-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 15px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}
.hub-subnav-link {
  color: #f0c9cf;
  text-decoration: none;
  font-size: 13px;
  padding: 12px 14px;
  text-transform: uppercase;
  letter-spacing: .03em;
  transition: color .15s, box-shadow .15s;
}
.hub-subnav-link:hover { color: #fff; text-decoration: none; }
.hub-subnav-link.active { color: #fff; box-shadow: inset 0 -3px 0 var(--hub-accent, #66c0f4); }
.hub-subnav-link.ms-auto { margin-left: auto; }

/* Phones: ONE row that scrolls, never a second row of chrome. Measured on QA
   2026-10-21: the five tabs at 13px with 14px side padding need ~470px, so at 360-393
   they wrapped and nav chrome ate 157px before any content (113px at >=768). Shrinking
   the type enough to fit five tabs into 360px would make them unreadable, so the row
   keeps a legible size and scrolls instead — every tab stays reachable and the document
   stops overflowing. BUG-2026-1018-0004; the "Become a Reviewer" third row the bug also
   reported is already gone (see subnav.ejs, 2026-10-20). */
@media (max-width: 767px) {
  .hub-subnav-inner {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 0 10px;
  }
  .hub-subnav-inner::-webkit-scrollbar { display: none; }
  .hub-subnav-link { flex: 0 0 auto; padding: 11px 11px; font-size: 12.5px; }
  /* margin-left:auto inside a scroller parks the tab past the scroll edge */
  .hub-subnav-link.ms-auto { margin-left: 0; }
}

/* ---- Content container ---- */
/* width:100% is load-bearing, not decoration. .hub-body is a column flex container
   (:18) and .hub-wrap is one of its items, so `margin: 0 auto` on the CROSS axis
   cancels the default stretch — the auto margins absorb the free space and the item
   shrink-to-fits its own max-content. Most tabs hid it because their content is
   intrinsically wide; /live did not, because a grid of auto-fill minmax(230px,1fr)
   has a max-content width of ONE column. Measured on QA 1.0.242 at a 1440 viewport:
   .hub-wrap 294px while its sibling .hub-subnav-inner, same max-width, sat at 1200. */
.hub-wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 28px 15px 48px; }
/* Platform pages served as hub tabs (leaderboard .lb-wrap, jams .jm-wrap) carry their
   own narrower wrappers; on a hub they take the same width as every other tab.
   Two classes so this beats the page's own inline/page CSS. */
.lb-wrap.hub-page-wrap, .jm-wrap.hub-page-wrap { max-width: 1200px; padding: 28px 15px 48px; }

/* ---- Hero (dark contained featured banner, like the games carousel) ---- */
.hub-hero {
  position: relative;
  border-radius: 6px;
  overflow: hidden;
  background-size: cover;
  background-position: center;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .4);
  padding: 96px 28px 28px;
  margin-bottom: 40px;
}
/* On-brand gradient hero (no uploaded/placeholder banner image) */
.hub-hero-brand {
  background-image:
    linear-gradient(180deg, rgba(0, 0, 0, .30), rgba(0, 0, 0, .78)),
    linear-gradient(135deg,
      var(--hub-primary, #d2042d) 0%,
      var(--hub-primary-dark, #a3021f) 55%,
      var(--hub-accent, #66c0f4) 165%);
}
.hub-hero-compact { padding: 40px 28px 32px; margin-bottom: 28px; }
/* Banner art (services/hubArt.js → --hub-art, a CDN url). The image carries the
   scene; the left-to-right fade keeps the eyebrow/title/sub readable over it.
   Two classes so it beats .hub-hero-brand's gradient. */
.hub-hero.hub-art {
  background-image:
    linear-gradient(90deg, rgba(0, 0, 0, .82) 0%, rgba(0, 0, 0, .55) 45%, rgba(0, 0, 0, .12) 100%),
    var(--hub-art);
  background-size: cover;
  background-position: center right;
}
/* Page heads that were bare text (leaderboard, jams) become a banner card too. */
.hub-art-head {
  border-radius: 6px; overflow: hidden;
  padding: 36px 28px 30px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .4);
  background-image:
    linear-gradient(90deg, rgba(0, 0, 0, .82) 0%, rgba(0, 0, 0, .55) 45%, rgba(0, 0, 0, .12) 100%),
    var(--hub-art);
  background-size: cover;
  background-position: center right;
}
/* The leaderboard head is centred, so it gets an even veil instead of a fade. */
.lb-head.hub-art-head {
  background-image: linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, .6)), var(--hub-art);
  background-position: center;
}
.hub-art-head .lb-title, .hub-art-head .jm-title { color: #fff; }
.hub-art-head .lb-sub, .hub-art-head .jm-sub { color: rgba(255, 255, 255, .82); }
.hub-hero-inner { max-width: 720px; }
.hub-eyebrow {
  display: inline-block; text-transform: uppercase; letter-spacing: .14em;
  font-size: .72rem; font-weight: 700; color: var(--hub-accent, #66c0f4); margin-bottom: 12px;
}
.hub-title {
  font-size: clamp(1.8rem, 4.5vw, 3rem); font-weight: 700; line-height: 1.06;
  margin: 0 0 14px; letter-spacing: -.01em; color: #fff;
}
.hub-sub { font-size: 1.05rem; color: rgba(255, 255, 255, .82); max-width: 60ch; margin: 0 0 18px; }
.hub-stats { display: flex; gap: 22px; font-size: .95rem; color: rgba(255, 255, 255, .78); }
.hub-stats strong { color: #fff; }
.hub-live-count strong { color: #ff5a5c; }

/* ---- Section heading (left accent bar, Steam-style) ---- */
.hub-section { margin-bottom: 40px; }
.hub-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.hub-section-head h2 {
  color: var(--hub-fg); font-weight: 500; font-size: 18px; margin: 0;
  text-transform: uppercase; letter-spacing: .04em;
  border-left: 3px solid var(--hub-accent, #66c0f4); padding-left: 10px;
}
.hub-empty { color: var(--hub-fg-muted); font-size: 1rem; }

/* ---- Grid + creator cards (translucent white over the red brand) ---- */
.hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}

/* Community board — Pinterest-style masonry: as many ~240px columns as fit the
   page width. Cards keep their natural height (varying bios) and pack without row
   gaps. Every hub tab shares the .hub-wrap width (1200px, aligned with the nav) —
   no tab gets its own. */

#community.hub-section .hub-grid {
  display: block;
  columns: 240px;
  column-gap: 18px;
}
#community.hub-section .hub-grid > .hub-card {
  width: 100%;
  display: inline-block;
  margin: 0 0 18px;
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}

/* ---- Community search toolbar (sticky under the subnav) ---- */
.hub-community-toolbar {
  /* Sticks just below the red sub-nav (navbar 68px + subnav ~46px) */
  position: sticky; top: 110px; z-index: 40;
  display: flex; align-items: center; gap: 14px;
  padding: 12px 0; margin-bottom: 6px;
  /* Match the ACTUAL page background: bootstrap paints body from --body-bg
     (!important), which dark tenants override via chrome-head; fall back to
     the hub brand color. */
  background: var(--body-bg, var(--hub-primary, #d2042d));
}
.hub-search {
  position: relative; flex: 1; max-width: 520px;
}
.hub-search-icon {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--hub-fg-muted); font-size: .85rem; pointer-events: none;
}
.hub-search-input {
  width: 100%; padding: 11px 40px 11px 38px;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: 999px;
  color: var(--hub-fg); font-size: .92rem;
  outline: none; transition: border-color .15s ease, box-shadow .15s ease;
  -webkit-appearance: none; appearance: none;
}
.hub-search-input::placeholder { color: var(--hub-fg-muted); }
.hub-search-input:focus {
  border-color: var(--hub-primary, #d2042d);
  box-shadow: 0 0 0 3px rgba(210, 4, 45, .15);
}
.hub-search-input::-webkit-search-cancel-button { display: none; }
.hub-search-clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; line-height: 1; border: 0; border-radius: 50%;
  background: transparent; color: var(--hub-fg-muted);
  font-size: 1.15rem; cursor: pointer;
}
.hub-search-clear:hover { color: var(--hub-fg); background: var(--card-hover); }
.hub-search-count {
  font-size: .85rem; color: var(--hub-fg-muted); white-space: nowrap;
}

/* ---- Infinite-scroll sentinel + spinner ---- */
.hub-scroll-sentinel {
  display: flex; justify-content: center; padding: 22px 0 8px; min-height: 20px;
}
.hub-scroll-spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid var(--card-border);
  border-top-color: var(--hub-primary, #d2042d);
  animation: hubSpin .7s linear infinite;
}
@keyframes hubSpin { to { transform: rotate(360deg); } }
.hub-card {
  display: block; text-decoration: none; color: inherit;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: 8px; overflow: hidden;
  transition: transform .16s ease, background .16s ease, box-shadow .16s ease;
}
.hub-card:hover {
  transform: translateY(-3px);
  background: var(--card-hover);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .38);
  color: inherit; text-decoration: none;
}
.hub-card-cover {
  height: 118px; background-size: cover; background-position: center;
  background-color: rgba(0, 0, 0, .25); position: relative;
}
/* No real cover uploaded (default '/img/default-cover.jpg' placeholder) → on-brand
   gradient instead of the "Hello!" stock banner. */
.hub-card-cover-brand {
  background-image: linear-gradient(135deg,
    var(--hub-primary, #d2042d) 0%,
    var(--hub-primary-dark, #a3021f) 60%,
    var(--hub-accent, #66c0f4) 160%);
}
/* Card cover art (Jam Champions): a light bottom shade so the award pill reads. */
.hub-card-cover.hub-art-card {
  background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 45%, rgba(0, 0, 0, .5) 100%), var(--hub-art);
  background-size: cover;
  background-position: center;
}
.hub-card-live {
  position: absolute; top: 10px; left: 10px;
  background: #ff4d4f; color: #fff; font-size: .68rem; font-weight: 800;
  padding: 4px 9px; border-radius: 3px; letter-spacing: .04em;
}
/* position+z-index lifts the body (avatar) above the cover, whose position:relative
   would otherwise paint over the avatar's overlapping top half. */
.hub-card-body { display: flex; align-items: center; gap: 12px; padding: 0 14px; margin-top: -26px; position: relative; z-index: 1; }
.hub-card-avatar {
  width: 54px; height: 54px; border-radius: 50%; object-fit: cover;
  border: 3px solid #fff; background: var(--hub-primary-dark, #a3021f);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
}
.hub-card-meta { display: flex; flex-direction: column; min-width: 0; padding-top: 24px; }
.hub-card-name { font-weight: 700; font-size: .96rem; color: var(--hub-fg); display: flex; align-items: center; gap: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hub-card-verified { color: var(--hub-accent, #66c0f4); font-size: .82rem; }
.hub-card-username { font-size: .82rem; color: var(--hub-fg-muted); }
.hub-card-bio { padding: 10px 14px 16px; margin: 0; font-size: .85rem; color: var(--hub-fg-muted); line-height: 1.5; }

/* ---- Live Now — stream cards, not roster cards ----------------------------
   A live stream is a SESSION, so the card is shaped like Twitch's and YouTube's
   rather than like the creator cards above it: a 16:9 thumbnail carrying the
   session's own state (live, who is watching, how long it has been running),
   then the stream TITLE as the headline with the channel underneath. The roster
   card says it the other way round — big name, title as grey afterthought — which
   reads as "here is a person" when the question on this tab is "what is on".
   No category/game line: models/Stream.js has no such field and inventing one is
   not a layout decision. */
.live-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 26px 20px;
}
.live-card { display: block; text-decoration: none; color: inherit; }
.live-card:hover { text-decoration: none; color: inherit; }
.live-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 5px;
  background-size: cover; background-position: center;
  background-color: rgba(0, 0, 0, .35);
  transition: transform .12s ease, box-shadow .12s ease;
}
/* Thumbnail with no uploaded art falls back to the hub gradient, same as the
   roster cards, so a missing image never shows an empty grey box. */
.live-thumb-brand {
  background-image: linear-gradient(135deg,
    var(--hub-primary, #d2042d) 0%,
    var(--hub-primary-dark, #a3021f) 60%,
    var(--hub-accent, #66c0f4) 170%);
}
/* Twitch's hover: the thumbnail lifts off an accent-coloured block behind it. */
.live-card:hover .live-thumb {
  transform: translate(-5px, -5px);
  box-shadow: 5px 5px 0 var(--hub-accent, #66c0f4);
}
.live-chip {
  position: absolute;
  font-size: .72rem; font-weight: 700; line-height: 1;
  padding: 4px 7px; border-radius: 3px;
  background: rgba(0, 0, 0, .72); color: #fff;
}
.live-chip-live {
  top: 8px; left: 8px;
  background: #e91916;
  font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
}
.live-chip-viewers { bottom: 8px; left: 8px; }
.live-chip-uptime { bottom: 8px; right: 8px; font-variant-numeric: tabular-nums; }
/* "Subscribers" — this viewer cannot watch, so the card goes to the creator's profile
   instead of the player (BUG-2026-1016-0046). Accent, not red: it is a price tag, not a
   warning, and it sits beside the red LIVE chip which must stay the loudest thing. */
.live-chip-locked {
  top: 8px; right: 8px;
  background: var(--hub-accent, #66c0f4); color: #06121c;
  letter-spacing: .04em; text-transform: uppercase;
}
.live-meta { display: flex; align-items: flex-start; gap: 10px; margin-top: 11px; }
.live-avatar {
  width: 40px; height: 40px; flex: none;
  border-radius: 50%; object-fit: cover;
  background: var(--hub-primary-dark, #a3021f);
}
.live-text { min-width: 0; }
.live-title {
  margin: 0 0 2px;
  font-size: .95rem; font-weight: 700; color: var(--hub-fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color .12s ease;
}
.live-card:hover .live-title { color: var(--hub-accent, #66c0f4); }
.live-channel {
  display: block;
  font-size: .85rem; color: var(--hub-fg-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

@media (max-width: 640px) {
  .live-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px 14px; }
  .hub-hero { padding: 64px 20px 22px; }
  .hub-wrap, .lb-wrap.hub-page-wrap, .jm-wrap.hub-page-wrap { padding: 20px 15px 40px; }
  .hub-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
  #community.hub-section .hub-grid { columns: 1; }
  .hub-community-toolbar { flex-wrap: wrap; gap: 8px; }
  .hub-search { max-width: none; flex-basis: 100%; }
}

@media (min-width: 641px) and (max-width: 1024px) {
  #community.hub-section .hub-grid { columns: 2; column-gap: 14px; }
}

/* ===== Content-first hub: theme the shared feed/sidebar to hub vars ===== */
.hub-body .front-cols { align-items: flex-start; }
.hub-body .cs-card,
.hub-body .feed-sort-tab {
  background: var(--hub-surface);
  border-color: var(--hub-surface-border);
}
.hub-body .feed-sort-tab { color: var(--hub-fg-muted); }
.hub-body .feed-sort-tab:hover { color: var(--hub-fg); border-color: var(--primary, #d2042d); }
.hub-body .feed-sort-tab.active {
  background: var(--primary, #d2042d);
  border-color: var(--primary, #d2042d);
  color: #fff;
}
.hub-body .cs-card-head h6 { color: var(--hub-fg); }
.hub-body .cs-card-head h6 .las { color: var(--accent, #66c0f4); font-size: 16px; }
.hub-body .cs-card-link { color: var(--accent, #66c0f4); }
.hub-body .cs-row-name { color: var(--hub-fg); }
.hub-body .cs-about-text { font-size: 13.5px; color: var(--hub-fg-muted); line-height: 1.55; margin: 0 0 10px; }
.hub-body .cs-about-stats { display: flex; gap: 16px; font-size: 13px; color: var(--hub-fg-muted); }
.hub-body .cs-about-stats strong { color: var(--hub-fg); }

/* Post boxes — surface adapts to light/dark hub */
.hub-body .post-box {
  background: var(--hub-surface);
  border: 1px solid var(--hub-surface-border);
  border-radius: 10px;
  margin-bottom: 14px;
}
