/* ============================================================
   Swiftpoint Hub — the profile gallery (/profiles/hub).

   Split out of the home sheet when the home page became the page that
   explains the mouse and the tools, and the gallery moved behind its
   own URL. Tokens, the reset and the header are in the shared layers;
   only gallery layout belongs here.

   The profile card itself, the filter chips, the upload modal, the
   toasts and the notification bell are the shared components in
   css/ui.css.
   ============================================================ */

.wrap {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ============ Page head ============ */

.gal-head {
  padding: 44px 0 4px;
}
.gal-eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 10px;
}
.gal-head h1 {
  font-family: var(--font-display);
  font-size: clamp(26px, 4.2vw, 36px);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
  max-width: 20ch;
}
.gal-lede {
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--text-dim);
  max-width: 62ch;
  margin: 0 0 4px;
}
.gal-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin: 26px 0 0;
  padding: 0;
}
.gal-stats > div {
  padding: 14px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.gal-stats dt {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 6px;
}
.gal-stats dd {
  margin: 0;
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
}

/* ============ Filter bar ============ */

.sec-title {
  margin: 34px 0 20px;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 12px;
}
.sec-title::before {
  content: '';
  width: 22px; height: 4px;
  border-radius: 2px;
  background: var(--lime);
}

/* The one line that explains the card accent. The hue is derived from the
   game name and carries no other meaning, which is exactly the kind of
   thing a visitor stops to work out on their own if nobody says so. */
.gal-hint {
  margin: -6px 0 20px;
  max-width: 74ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-3);
}

/* One bar for both controls, and it stays with you.
   The grid is a long scroll on a page that exists to be scrolled,
   and a search field you have to scroll back up to reach is a search
   field people stop using. It sticks just under the header and
   carries a background of its own, because cards pass behind it. */
.gal-filters {
  position: sticky;
  top: var(--hdr-total-h);
  /* Below the header, not equal to it: at the same level this bar would
     win the paint order simply by coming later in the document. */
  z-index: calc(var(--z-hdr) - 1);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.gal-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 260px;
  min-width: 0;
}
.gal-search-ico {
  position: absolute;
  left: 16px;
  color: var(--text-3);
  pointer-events: none;
}
.gal-search input[type="text"] {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 11px 44px 11px 42px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.gal-search input::placeholder { color: var(--text-3); }
.gal-search input:focus {
  outline: none;
  border-color: var(--lime);
  box-shadow: 0 0 0 3px rgba(198, 245, 66, 0.12);
}
.gal-search-clear {
  position: absolute;
  right: 8px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  font-size: 18px;
  line-height: 1;
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.gal-search-clear:hover { color: var(--text); border-color: var(--line-strong); }
.gal-search-clear:focus-visible { outline: 2px solid var(--lime); outline-offset: 2px; }

.gal-sort {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
.gal-sort-k {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}
.gal-sort select {
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 10px 38px 10px 16px;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236c6c76' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 15px center;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.gal-sort select:hover { border-color: var(--line-strong); color: var(--text); }
.gal-sort select:focus { outline: none; border-color: var(--lime); }
.gal-sort select option { background: var(--surface-2); color: var(--text); }

/* The line between the filters and the grid. It is also the only place
   that says how much a search actually found — without it, a query that
   returned two cards looks exactly like a page that stopped working. */
.gal-count {
  margin: 16px 0 22px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* ============ Gallery grid ============ */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 18px;
  /* Stretch, not start: a card is stretched to the tallest in its row,
     so the grid is a rectangle instead of a staircase. The ragged bottom
     came from `align-items: start`, which let every card shrink to its
     own content — a profile with a description and three tags stood two
     fingers taller than one without. Inside the card, .card-body takes
     the slack and .card-foot stays on the baseline. */
  padding-bottom: 60px;
}

/* Profile card itself is the shared .card kit in css/ui.css */

.empty-state {
  grid-column: 1 / -1;
  text-align: center;
  padding: 70px 20px;
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
}
.empty-state h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
}
.empty-state p { margin: 8px 0 0; color: var(--text-3); }
.empty-actions { margin-top: 18px !important; }
.empty-actions .btn { text-decoration: none; }


/* ============ Responsive ============ */

@media (max-width: 640px) {
  .wrap { padding: 0 16px; }
  .gal-head { padding: 32px 0 4px; }
  .gal-stats { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .gal-stats > div { padding: 12px 12px; }
  .gal-stats dd { font-size: 21px; }
  .gal-stats dt { font-size: 9.5px; letter-spacing: 0.08em; }
  .gallery { grid-template-columns: 1fr; gap: 14px; }
  .gal-filters { gap: 8px; padding: 10px 0; }
  .gal-sort { flex: 1 1 100%; }
  .gal-sort select { flex: 1; }
  .modal { padding: 20px; }
}
