/* ============================================================
   Grindveil — KUZNIA (forge.css)

   Towarzyszy js/forge.js. Wszystkie kolory pochodza z tokenow
   w style.css — zaden nowy hex poza tym, co jest barwa klejnotu
   albo rzadkosci, a te przychodza zmienna (--gc, klasy .r-*).

   Prefiks `fr-`. Stare klasy Kuzni (`sf-`, `anv-`, `fg-`) nie sa
   tu ruszane: zostaja w style.css, dopoki nie zniknie ostatnie
   miejsce, ktore ich uzywa.
   ============================================================ */

.fr {
  position: relative;
  min-height: 100%;
  padding: 12px 12px 24px;
  display: flex; flex-direction: column; gap: 16px;
}

/* Tlo siedzi na PANELU, nie w tresci.

   Bylo elementem wewnatrz `.fr`, ktory konczy sie tam, gdzie konczy sie
   tresc. Panel jest wyzszy, wiec ponizej wychodzilo stare tlo Kuzni ze
   style.css i ekran mial dwa rozne obrazy jeden pod drugim, z ostra
   kreska na styku. Na panelu nie ma czego uciac: on ZAWSZE ma pelna
   wysokosc, niezaleznie od tego, ile jest tresci.

   `!important` jest tu potrzebny, bo style.css nadaje tym samym
   identyfikatorom wlasne tlo, a jest wczytywany wczesniej. */
#panelSoulforge, #panelAnvil {
  position: relative;
  background: #0a0814 url('../img/forge/forge-bg.webp') center top / cover no-repeat fixed !important;
  min-height: 100%;
}
/* Przyciemnienie. Tlo ma byc tlem, a nie konkurencja dla tresci. */
#panelSoulforge::before, #panelAnvil::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(10,8,20,0.30) 0%, rgba(10,8,20,0.52) 55%, rgba(10,8,20,0.72) 100%);
}
/* Zar.

   Byl jednym kadrem (embers.webp) kafelkowanym w poziomie i przesuwanym
   na ukos. Kadr ma 640 px, wiec wzor wracal co 640 px i widac to bylo
   golym okiem: przez ekran szedl pasek, a nie unosil sie zar.

   Teraz to sa osobne iskry. Kazda ma wlasna sciezke, wlasny czas i wlasne
   opoznienie, wiec nic sie nie powtarza — a kosztuje tyle samo, bo caly
   ruch to `transform` i `opacity`, czyli rzeczy, ktore robi karta
   graficzna. Zadnej petli w JavaScripcie: warstwa powstaje RAZ przy
   wejsciu do Kuzni i przezywa przerysowania (patrz `shell()` w forge.js).

   Ograniczone do 28 iskier. Wiecej nie widac, a kazda to osobna warstwa
   do zlozenia przy kazdej klatce. */
.fr-embers {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden; pointer-events: none;
}
.fr-embers i {
  position: absolute;
  bottom: -12px;
  left: var(--x);
  width: var(--s); height: var(--s);
  border-radius: 50%;
  background: radial-gradient(circle, #FFF0CC 0%, #FFD79A 25%, #FFB25A 50%, #E2661C 75%, rgba(226,102,28,0) 100%);
  box-shadow: 0 0 6px 1px rgba(255,150,60,0.55);
  opacity: 0;
  animation: fr-ember-rise var(--d) linear var(--delay) infinite;
  will-change: transform, opacity;
}
/* Dryf w bok jest w polowie drogi, nie na koncu — iskra ma sie kolysac,
   a nie skrecac. */
@keyframes fr-ember-rise {
  0%   { transform: translate3d(0, 0, 0) scale(0.6); opacity: 0; }
  8%   { opacity: var(--o); }
  50%  { transform: translate3d(var(--drift), -50vh, 0) scale(1); opacity: var(--o); }
  85%  { opacity: calc(var(--o) * 0.35); }
  100% { transform: translate3d(0, -102vh, 0) scale(0.7); opacity: 0; }
}
/* Kto nie chce ruchu, ten go nie dostaje. */
@media (prefers-reduced-motion: reduce) {
  .fr-embers { display: none; }
}
.fr > * { position: relative; z-index: 1; }

/* ── EKRAN WEJSCIA ──────────────────────────────────────── */
.fr-hub {
  display: flex; flex-direction: column; align-items: center; gap: 18px;
  padding: 24px 0 8px;
}
.fr-title {
  font-family: var(--font-display);
  font-size: 30px; font-weight: 900; letter-spacing: 3px;
  color: var(--gold-soft); margin: 0;
  text-shadow: 0 2px 0 rgba(0,0,0,0.5), 0 0 22px var(--gold-glow);
}
.fr-lead {
  margin: 0; max-width: 460px; text-align: center;
  color: var(--text-dim); font-size: 13px; line-height: 1.6;
}
.fr-hubcards {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px; width: 100%; max-width: 680px;
}
.fr-hubcard {
  position: relative; overflow: hidden;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--surface-elevated), var(--bg-lighter));
  box-shadow: var(--shadow-card);
  padding: 0; cursor: pointer;
  min-height: 190px;
  display: flex; align-items: flex-end;
  transition: transform 0.16s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.fr-hubcard:hover { transform: translateY(-3px); border-color: var(--gold-deep); box-shadow: var(--shadow-card), var(--shadow-glow-gold); }
.fr-hubcard:active { transform: scale(0.985); }
.fr-hubcard-art {
  position: absolute; inset: 0;
  background-size: cover; background-position: center top;
  opacity: 0.9;
}
/* Emblemat zastepczy. Znika sam, gdy nad nim lezy warstwa z ilustracja —
   `~` dziala, bo .fr-hubcard-art jest w markupie PRZED nim. */
.fr-hubcard-emb {
  position: absolute; left: 0; right: 0; top: 0; bottom: 34%;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.fr-hubcard-emb img {
  width: 84px; height: 84px; object-fit: contain;
  opacity: 0.5; filter: drop-shadow(0 6px 18px rgba(0,0,0,0.6));
  transition: transform 0.25s ease, opacity 0.25s ease;
}
.fr-hubcard:hover .fr-hubcard-emb img { transform: scale(1.08) translateY(-3px); opacity: 0.75; }
.fr-hubcard-art ~ .fr-hubcard-emb { display: none; }

/* Poswiata pod napisem. Robi to, co w innych grach robi przyciemniony
   pasek: napis ma byc czytelny takze wtedy, gdy grafika pod nim jest
   jasna. Bez grafiki wyglada jak zwykly gradient karty. */
.fr-hubcard-glow {
  position: absolute; left: 0; right: 0; bottom: 0; height: 68%;
  background: linear-gradient(to top, rgba(10,5,24,0.95), rgba(10,5,24,0.0));
}
.fr-hubcard-body {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 3px;
  padding: 14px; width: 100%; text-align: left;
}
.fr-hubcard-name {
  font-family: var(--font-display);
  font-size: 20px; font-weight: 900; letter-spacing: 1.5px;
  color: var(--text-bright);
}
.fr-hubcard-sub { font-size: 11px; color: var(--text-dim); }
.fr-hubcard-flag {
  margin-top: 5px; align-self: flex-start;
  font-size: 10px; font-weight: 800; letter-spacing: 0.4px;
  padding: 3px 9px; border-radius: 999px;
  color: #0f2a18; background: var(--win);
}
.fr-hubcard-flag.quiet { color: var(--text-dim); background: rgba(255,255,255,0.07); }
.fr-hubcard.gems:hover  { box-shadow: var(--shadow-card), var(--shadow-glow-violet); border-color: var(--violet); }

/* Lup — „co z tego mam". Ten sam ksztalt w oknie wyniku i w paskach,
   zeby ta sama informacja wygladala wszedzie tak samo. */
.fr-lup { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: center; }
.fr-lup-poz { display: inline-flex; align-items: center; gap: 5px; }
.fr-lup-poz img { width: 20px; height: 20px; object-fit: contain; }
.fr-lup-poz b { font-size: 15px; font-weight: 900; color: var(--win); }
.fr-lup-poz i { font-style: normal; font-size: 11px; color: var(--text-dim); }
/* W oknie wyniku to jest glowna tresc, nie przypis. */
.fr-lup.duzo { gap: 18px; }
.fr-lup.duzo .fr-lup-poz img { width: 34px; height: 34px; }
.fr-lup.duzo .fr-lup-poz b { font-size: 24px; }
.fr-lup.duzo .fr-lup-poz i { font-size: 13px; color: var(--text); }

/* ── SAKIEWKA ───────────────────────────────────────────── */
.fr-purse {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px;
  padding: 10px; border-radius: var(--radius);
  border: 1px solid var(--border);
  background: rgba(10,5,24,0.55);
}
.fr-purse.compact { padding: 8px 10px; gap: 6px; }
.fr-coin {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(255,255,255,0.05);
  font-size: 14px; font-weight: 800; color: var(--text);
}
.fr-purse.compact .fr-coin { font-size: 13px; padding: 5px 10px; }
.fr-coin img { width: 20px; height: 20px; object-fit: contain; }

/* ── PASEK GORNY ────────────────────────────────────────── */
.fr-top { display: flex; align-items: center; gap: 10px; }
.fr-back {
  border: 1px solid var(--border-strong); background: rgba(255,255,255,0.05);
  color: var(--text); border-radius: 999px;
  padding: 7px 14px; font-size: 12px; font-weight: 800; cursor: pointer;
}
.fr-back:hover { background: rgba(255,255,255,0.1); }
.fr-top-title {
  font-family: var(--font-display);
  font-size: 20px; font-weight: 900; letter-spacing: 2px; color: var(--gold-soft);
}

/* ── SEKCJE ─────────────────────────────────────────────── */
.fr-sec {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: rgba(16,9,36,0.78);
  padding: 12px;
  box-shadow: var(--shadow-card);
}
.fr-sech {
  margin: 0 0 10px; font-family: var(--font-display);
  font-size: 13px; font-weight: 900; letter-spacing: 2px; text-transform: uppercase;
  color: var(--gold-deep);
}
.fr-sech.sm { font-size: 11px; }
.fr-sech i { font-style: normal; color: var(--text-dim); font-weight: 700; letter-spacing: 0; }
.fr-sech-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.fr-sech-row .fr-sech { margin: 0; }
.fr-sech-acts { display: flex; gap: 6px; flex-wrap: wrap; }
.fr-sech-acts.wide { margin-bottom: 10px; }
.fr-empty {
  padding: 16px 14px; text-align: center;
  color: var(--text-dim); font-size: 12px; line-height: 1.6;
}
.fr-note { font-size: 11px; color: var(--text-dim); line-height: 1.55; padding: 6px 2px; }
.quiet { color: var(--text-dim); }

.fr-chip {
  border: 1px solid var(--border); background: rgba(255,255,255,0.04);
  color: var(--text-dim); border-radius: 999px;
  padding: 5px 11px; font-size: 11px; font-weight: 800; cursor: pointer;
}
.fr-chip.on { color: #10061f; background: var(--gold-soft); border-color: var(--gold-soft); }

/* ── GNIAZDA ────────────────────────────────────────────── */
.fr-sockets {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px;
}
.fr-socket {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 104px; padding: 8px 4px;
  border: 2px solid var(--border); border-radius: var(--radius);
  background: rgba(0,0,0,0.45); cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.12s ease;
}
.fr-socket:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.fr-socket.filled { border-color: var(--gc, var(--border-strong)); box-shadow: 0 0 14px -2px var(--gc, transparent); }
.fr-socket.locked { border-style: dashed; opacity: 0.62; }
.fr-socket-ring { position: absolute; inset: 0; background-size: contain; background-position: center; background-repeat: no-repeat; opacity: 0.65; pointer-events: none; }
.fr-socket-gem, .fr-socket-empty, .fr-socket-lock { position: relative; z-index: 1; }
.fr-socket-gem img { display: block; filter: drop-shadow(0 0 8px var(--gc, transparent)); }
.fr-socket-empty { font-size: 24px; color: var(--text-dim); opacity: 0.5; line-height: 1; }
.fr-socket-lock img { width: 20px; height: 20px; opacity: 0.7; }
.fr-socket-lv {
  position: absolute; top: 4px; right: 6px; z-index: 2;
  font-size: 11px; font-weight: 900; color: var(--gold-soft);
}
.fr-socket-corr { position: absolute; top: 4px; left: 6px; z-index: 2; color: var(--violet); font-size: 11px; }
.fr-socket-bonus {
  position: relative; z-index: 1;
  font-size: 9.5px; font-weight: 800; text-align: center; line-height: 1.25;
  color: var(--text); word-break: break-word;
}
.fr-socket-bonus.quiet { font-weight: 600; }
.fr-bonuses {
  margin-top: 10px; padding: 9px 12px; border-radius: var(--radius);
  background: rgba(255,255,255,0.04); border: 1px solid var(--border);
  font-size: 12px; color: var(--text-dim); text-align: center;
}
.fr-bonuses b { color: var(--gold-soft); }

/* Klejnot wskakujacy w gniazdo. */
.fr-socket.fr-fit { animation: fr-fit 0.7s ease; }
@keyframes fr-fit {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.13); box-shadow: 0 0 28px 2px var(--gc, #fff); }
  100% { transform: scale(1); }
}

/* ── TYGIEL ─────────────────────────────────────────────── */
.fr-crucible {
  position: relative; overflow: hidden; border-radius: var(--radius);
  max-width: 720px; margin: 0 auto;
}
.fr-crucible-art {
  position: absolute; inset: 0; background-size: cover; background-position: center;
  opacity: 0.32; pointer-events: none;
}
.fr-crucible-empty { padding: 18px 12px; text-align: center; color: var(--text-dim); font-size: 13px; }
.fr-cru-stage {
  position: relative;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px;
  padding: 14px 8px;
}
.fr-cru-slot { display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center; }
.fr-cru-gem img { display: block; filter: drop-shadow(0 0 14px var(--gc, transparent)); }
.fr-cru-gem.next img { opacity: 0.92; animation: fr-breathe 2.4s ease-in-out infinite; }
@keyframes fr-breathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.06); } }
.fr-cru-name { font-size: 12px; font-weight: 800; color: var(--text); }
.fr-cru-lv { font-size: 11px; color: var(--text-dim); }
.fr-cru-lv.up { color: var(--gold-soft); font-weight: 800; }
.fr-cru-bonus { font-size: 11px; font-weight: 800; color: var(--text-dim); }
.fr-cru-bonus.up { color: var(--win); }
.fr-cru-mid { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 70px; }
.fr-cru-arrow { font-size: 20px; color: var(--gold-deep); }
.fr-cru-odds { font-family: var(--font-display); font-size: 22px; font-weight: 900; line-height: 1; }
.fr-cru-odds.good { color: var(--win); }
.fr-cru-odds.fair { color: var(--legendary); }
.fr-cru-odds.poor { color: var(--loss); }
.fr-cru-odds-l { font-size: 9px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--text-dim); }

.fr-cru-terms {
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
  padding: 0 8px 10px;
}
.fr-term {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: 999px;
  background: rgba(255,255,255,0.05); border: 1px solid var(--border);
  font-size: 11px; font-weight: 700; color: var(--text);
}
.fr-term img { width: 14px; height: 14px; }
.fr-term-mini img { width: 16px !important; height: 16px !important; }
.fr-term.warn { color: var(--legendary); border-color: rgba(255,179,64,0.35); }
.fr-term.danger { color: var(--loss); border-color: rgba(255,71,87,0.4); }

.fr-cru-scrolls { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 8px; padding: 0 8px 10px; }
.fr-scroll {
  display: flex; align-items: center; gap: 8px; text-align: left;
  padding: 8px 10px; border-radius: var(--radius);
  border: 1px solid var(--border); background: rgba(255,255,255,0.03);
  cursor: pointer; color: var(--text);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.fr-scroll img { width: 26px; height: 26px; object-fit: contain; }
.fr-scroll-t { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.fr-scroll-t b { font-size: 11.5px; font-weight: 800; }
.fr-scroll-t i { font-style: normal; font-size: 10px; color: var(--text-dim); }
.fr-scroll-n { font-size: 12px; font-weight: 900; color: var(--gold-soft); }
.fr-scroll.on { border-color: var(--gold-soft); background: rgba(255,212,106,0.12); box-shadow: var(--shadow-glow-gold); }
.fr-scroll.none { opacity: 0.42; cursor: default; }

.fr-cru-acts { display: flex; gap: 8px; padding: 0 8px 12px; }
.fr-cru-acts .gvk-btn { flex: 1; }
.fr-cru-acts .gvk-btn.sm { flex: 0 0 auto; }

/* Uderzenie, wygrana i przegrana. Trzy krotkie animacje na jednym
   elemencie — bez petli rysujacej, bo ten ekran stoi otwarty
   godzinami. */
.fr-crucible.fr-strike, .fr-bench.fr-strike { animation: fr-strike 0.6s cubic-bezier(.36,.07,.19,.97); }
@keyframes fr-strike {
  0%   { transform: translateY(0); }
  18%  { transform: translateY(-6px) rotate(-0.4deg); }
  34%  { transform: translateY(3px); filter: brightness(1.6); }
  46%  { transform: translateY(0); }
  100% { transform: translateY(0); }
}
.fr-crucible.fr-won, .fr-bench.fr-won { animation: fr-won 0.9s ease; }
@keyframes fr-won {
  0%   { box-shadow: inset 0 0 0 0 rgba(46,213,115,0); }
  25%  { box-shadow: inset 0 0 60px 0 rgba(46,213,115,0.45); }
  100% { box-shadow: inset 0 0 0 0 rgba(46,213,115,0); }
}
.fr-crucible.fr-lost, .fr-bench.fr-lost { animation: fr-lost 0.7s ease; }
@keyframes fr-lost {
  0%, 100% { transform: translateX(0); box-shadow: none; }
  15% { transform: translateX(-7px); box-shadow: inset 0 0 50px rgba(255,71,87,0.35); }
  35% { transform: translateX(6px); }
  55% { transform: translateX(-4px); }
  75% { transform: translateX(3px); }
}

/* Arkusz klatek. Klatki leza w jednym rzedzie, animacja przesuwa tlo
   krokami do konca arkusza. Element jest ozdoba i nie lapie klikniec. */
.fr-sheet {
  position: fixed;
  background-repeat: no-repeat; background-position: 0 0;
  pointer-events: none; z-index: 9000;
}
@keyframes fr-sheet-play {
  from { background-position: 0 0; }
  to   { background-position: var(--end) 0; }
}

/* Iskry. Dziesiec elementow, kazdy z wlasnym katem w --a. */
.fr-sparks { position: fixed; pointer-events: none; overflow: visible; z-index: 9000; }
.fr-sparks i {
  position: absolute; left: 50%; top: 50%;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold-soft);
  box-shadow: 0 0 10px 2px var(--gold-glow);
  transform: rotate(var(--a)) translateX(0);
  animation: fr-spark var(--d, 0.6s) ease-out forwards;
}
@keyframes fr-spark {
  from { transform: rotate(var(--a)) translateX(0) scale(1); opacity: 1; }
  to   { transform: rotate(var(--a)) translateX(120px) scale(0.2); opacity: 0; }
}

/* ── SKRZYNKA KLEJNOTOW ─────────────────────────────────── */
.fr-tray {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px;
}
.fr-gemcard {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 6px 9px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: rgba(0,0,0,0.4); cursor: pointer; color: var(--text);
  transition: transform 0.14s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.fr-gemcard:hover { transform: translateY(-2px); border-color: var(--gc, var(--border-strong)); }
.fr-gemcard.sel { border-color: var(--gold-soft); box-shadow: var(--shadow-glow-gold); }
.fr-gemcard.corr { border-color: rgba(191,95,255,0.5); }
.fr-gemcard.picked { border-color: var(--loss); background: rgba(255,71,87,0.1); }
.fr-gemcard-ico img { display: block; filter: drop-shadow(0 0 7px var(--gc, transparent)); }
.fr-gemcard-n { font-size: 12px; font-weight: 800; }
.fr-gemcard-lv { font-size: 10px; color: var(--text-dim); }
.fr-gemcard-b { font-size: 10.5px; font-weight: 800; color: var(--gold-soft); }
.fr-gemcard-x {
  position: absolute; top: 5px; right: 7px;
  font-size: 11px; font-weight: 900; color: var(--text-dim);
}
.fr-gemcard-pair { margin-top: 3px; font-size: 9px; letter-spacing: 0.3px; color: var(--win); }
.fr-gemcard-pick {
  position: absolute; top: 5px; left: 7px;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  background: var(--loss); color: #fff; font-size: 10px; font-weight: 900; line-height: 16px;
}

.fr-picktray {
  margin-top: 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 11px; border-radius: var(--radius);
  background: rgba(255,71,87,0.08); border: 1px solid rgba(255,71,87,0.28);
  font-size: 12px; color: var(--text);
}
.fr-picktray-t { flex: 1; }

/* Odnosnik do sklepu gry. Stoi pod torba klejnotow zamiast wlasnego
   straganu, ktory Kuznia miala do 31.08.2026. */
.fr-shoplink {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  flex-wrap: wrap; margin-top: 10px;
  padding: 9px 12px; border-radius: var(--radius);
  border: 1px dashed var(--border-strong); background: rgba(255,255,255,0.03);
  font-size: 12px; color: var(--text-dim);
}
.fr-shoplink .gvk-btn img { width: 16px; height: 16px; }

/* ── ZAOPATRZENIE ───────────────────────────────────────── */
.fr-drawer { border-color: var(--border-strong); }
.fr-supply-quick { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-bottom: 14px; }
.fr-buy {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: var(--radius);
  border: 1px solid var(--border); background: rgba(255,255,255,0.04);
  cursor: pointer; color: var(--text); text-align: left;
}
.fr-buy:hover { border-color: var(--gold-deep); }
.fr-buy > img { width: 28px; height: 28px; object-fit: contain; }
.fr-buy b { flex: 1; font-size: 11.5px; font-weight: 800; }
.fr-buy span { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 900; color: var(--gold-soft); }
.fr-buy span img { width: 14px; height: 14px; }

.fr-stall { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
.fr-stallcard {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 9px 6px; border-radius: var(--radius);
  border: 1px solid var(--border); background: rgba(0,0,0,0.4);
  cursor: pointer; color: var(--text);
}
.fr-stallcard:hover { border-color: var(--gold-deep); }
.fr-stallcard.sold { opacity: 0.4; cursor: default; }
.fr-stallcard-n { font-size: 10.5px; font-weight: 700; text-align: center; }
.fr-stallcard-p { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 900; color: var(--gold-soft); }
.fr-stallcard-p img { width: 13px; height: 13px; }
.fr-stallcard-p.sold { color: var(--text-dim); }

/* ── EKWIPUNEK ──────────────────────────────────────────── */
.fr-geargrid {
  display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 620px);
  gap: 14px; align-items: start; justify-content: center;
}
@media (max-width: 760px) { .fr-geargrid { grid-template-columns: minmax(0, 1fr); } }

/* Warsztat pokazuje sie dopiero z przedmiotem na nim, wiec przy pustym
   rzad "na sobie" zostaje sam. Bez tego siedzialby w waskiej kolumnie
   po lewej, z pustka obok. */
.fr-geargrid.solo { grid-template-columns: minmax(0, 1fr); }
/* Bez warsztatu obok, osiem slotow rozciagnietych na cztery kolumny
   wygladaloby jak rozlazly rzad kafli. W jednym rzedzie czyta sie jak
   postac. */
/* Bez warsztatu obok postac moze byc wieksza — jest sama na ekranie. */
@media (min-width: 761px) { .fr-geargrid.solo .fr-doll { max-width: 440px; } }


/* Sylwetka pod slotami. Grafika jest OZDOBA — bez niej zostaje sam uklad
   trzy na trzy, ktory i tak czyta sie jak postac, bo helm jest u gory,
   a buty na dole. */
/* Kadr postaci. Proporcja idzie za rysunkiem zbroi (640x900), zeby sylwetka
   wypelniala go w calosci, a nie plywala w srodku z marginesami. Wysokosc
   liczy sie sama z szerokosci — dzieki temu procentowe pozycje kafli trzymaja
   sie tych samych partii ciala na kazdym ekranie. */
.fr-doll {
  position: relative;
  width: 100%; max-width: 380px; margin: 0 auto;
  aspect-ratio: 640 / 900;
}
.fr-doll-art {
  position: absolute; inset: 0; z-index: 0;
  background-size: contain; background-position: center; background-repeat: no-repeat;
  opacity: 0.85; pointer-events: none;
}
/* Kafel siedzi SRODKIEM na podanym punkcie, stad przesuniecie o polowe
   wlasnego rozmiaru. */
.fr-doll .fr-wslot {
  position: absolute; z-index: 1;
  width: 82px; margin: 0;
  transform: translate(-50%, -50%);
}
.fr-doll .fr-wslot-ico { min-height: 54px; }

.fr-worn { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
.fr-wslot {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 3px; min-height: 68px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: rgba(6,3,14,0.78); cursor: default; color: var(--text-dim);
  backdrop-filter: blur(2px);
}
.fr-wslot.filled { cursor: pointer; color: var(--text); }
.fr-wslot.filled:hover { border-color: var(--border-strong); }
.fr-wslot.sel { border-color: var(--gold-soft); box-shadow: var(--shadow-glow-gold); }
.fr-wslot-ico { min-height: 40px; display: flex; align-items: center; justify-content: center; }
.fr-wslot-l { font-size: 9px; letter-spacing: 0.3px; text-transform: uppercase; }
.fr-wslot.r-uncommon  { border-color: rgba(94,216,122,0.45); }
.fr-wslot.r-rare      { border-color: rgba(79,172,254,0.45); }
.fr-wslot.r-epic      { border-color: rgba(191,95,255,0.45); }
.fr-wslot.r-legendary { border-color: rgba(255,179,64,0.5); }
.fr-wslot.r-mythic    { border-color: rgba(255,71,87,0.5); }
.fr-wslot.r-unique    { border-color: rgba(255,20,147,0.5); }

.fr-bench { position: relative; overflow: hidden; border-radius: var(--radius); }
.fr-bench-art { position: absolute; inset: 0; background-size: cover; background-position: center; opacity: 0.22; pointer-events: none; }
.fr-bench-card { position: relative; z-index: 1; }
.fr-bench-acts { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.fr-bench-acts .gvk-btn { justify-content: space-between; }
/* Skladniki kosztu trzymaja sie razem. Bez tego opakowania kazdy z nich
   byl osobnym dzieckiem przycisku z `space-between` i rozjezdzaly sie
   po calej jego szerokosci. */
.fr-costs { display: inline-flex; align-items: center; gap: 10px; flex-shrink: 0; }
.fr-cost {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 900; color: var(--gold-soft);
}
.fr-cost img { width: 14px; height: 14px; }
.fr-cost.short { color: var(--loss); }
.gvk-btn.primary .fr-cost { color: #2A1B05; }
.gvk-btn.primary .fr-cost.short { color: #7A1520; }
.gvk-btn.primary .fr-cost img { filter: drop-shadow(0 0 2px rgba(255,255,255,0.6)); }

/* ── PLECAK ─────────────────────────────────────────────── */
.fr-bag { display: grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 8px; }
.fr-bagcard {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 9px 6px; border-radius: var(--radius);
  border: 1px solid var(--border); background: rgba(0,0,0,0.4);
  cursor: pointer; color: var(--text);
  transition: transform 0.14s ease, border-color 0.15s ease;
}
.fr-bagcard:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.fr-bagcard.sel { border-color: var(--gold-soft); box-shadow: var(--shadow-glow-gold); }
.fr-bagcard.picked { border-color: var(--loss); background: rgba(255,71,87,0.1); }
/* Slabsze od noszonego przygaszamy, zamiast oznaczac napisem: to jest
   informacja dla oka przy przewijaniu, nie zdanie do przeczytania. */
.fr-bagcard.worse { opacity: 0.62; }
.fr-bagcard.worse:hover { opacity: 1; }
.fr-bagcard-ico { min-height: 40px; display: flex; align-items: center; justify-content: center; }
.fr-bagcard-n { font-size: 11px; font-weight: 800; text-align: center; line-height: 1.25; }
.fr-bagcard-l { font-size: 9.5px; color: var(--text-dim); }
.fr-bagcard-tick { position: absolute; top: 5px; right: 7px; color: var(--loss); font-size: 12px; font-weight: 900; }
.fr-bagcard.r-uncommon  { border-color: rgba(94,216,122,0.4); }
.fr-bagcard.r-rare      { border-color: rgba(79,172,254,0.4); }
.fr-bagcard.r-epic      { border-color: rgba(191,95,255,0.4); }
.fr-bagcard.r-legendary { border-color: rgba(255,179,64,0.45); }
.fr-bagcard.r-mythic    { border-color: rgba(255,71,87,0.45); }
.fr-bagcard.r-unique    { border-color: rgba(255,20,147,0.45); }

/* ── ODLEWNIA I WYMIANA ─────────────────────────────────── */
.fr-castslots { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.fr-castrows { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.fr-castrow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 12px; border-radius: var(--radius);
  border: 1px solid var(--border); background: rgba(0,0,0,0.4);
  cursor: pointer; color: var(--text);
}
.fr-castrow:hover { border-color: var(--border-strong); }
.fr-castrow.on { border-color: var(--gold-soft); box-shadow: var(--shadow-glow-gold); }
.fr-castrow-n { font-size: 12.5px; font-weight: 900; letter-spacing: 0.4px; }
.fr-castrow.r-uncommon  .fr-castrow-n { color: var(--uncommon); }
.fr-castrow.r-rare      .fr-castrow-n { color: var(--rare); }
.fr-castrow.r-epic      .fr-castrow-n { color: var(--epic); }
.fr-castrow.r-legendary .fr-castrow-n { color: var(--legendary); }
.fr-castrow.r-mythic    .fr-castrow-n { color: var(--mythic); }
.fr-castrow-c { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.fr-melt { display: flex; flex-direction: column; gap: 7px; }
.fr-meltrow {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; border-radius: var(--radius);
  border: 1px solid var(--border); background: rgba(0,0,0,0.4);
  font-size: 12px; color: var(--text);
}
.fr-meltside { display: inline-flex; align-items: center; gap: 5px; font-weight: 700; }
.fr-meltside img { width: 18px; height: 18px; }
.fr-meltarrow { color: var(--gold-deep); }
.fr-meltn { flex: 1; text-align: right; font-size: 11px; color: var(--text-dim); }
.fr-meltacts { display: flex; gap: 6px; }

/* ── OKNO PRZEMIANY ─────────────────────────────────────────
   Wynik akcji dzieje sie na obiekcie, nie obok niego. Trzy fazy sa
   trzema klasami na tym samym oknie: .praca, .udane, .stracone.

   Cala rzecz stoi na `transform`, `opacity` i `filter` — bez grafik
   dziala w calosci, arkusze (iskry, pekniecie) tylko ja podbijaja. */
.fr-akt {
  position: fixed; inset: 0; z-index: 9500;
  display: flex; align-items: center; justify-content: center;
  animation: fr-akt-in 0.22s ease;
}
.fr-akt.znika { animation: fr-akt-out 0.26s ease forwards; }
@keyframes fr-akt-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes fr-akt-out { to { opacity: 0; } }

.fr-akt-tlo {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, rgba(10,6,20,0.72) 0%, rgba(6,3,14,0.93) 70%);
  backdrop-filter: blur(2px);
}
.fr-akt-scena {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 24px 32px; min-width: 360px; max-width: 440px; text-align: center;
}

/* Aura pod obiektem. W fazie pracy narasta i pulsuje — to jest ten
   moment, w ktorym „cos sie dzieje", zanim wiadomo co. */
.fr-akt-aura {
  position: absolute; top: 50%; left: 50%;
  width: 200px; height: 200px; margin: -130px 0 0 -100px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--gc, #FFB25A) 0%, rgba(0,0,0,0) 68%);
  opacity: 0; pointer-events: none;
}
.fr-akt.praca .fr-akt-aura { animation: fr-akt-aura 1.1s ease-in-out infinite; }
@keyframes fr-akt-aura {
  0%, 100% { opacity: 0.16; transform: scale(0.85); }
  50%      { opacity: 0.42; transform: scale(1.06); }
}

/* Pierscien run pod obiektem. Osiem klatek w jednym rzedzie, przesuwanych
   krokami w kolko przez caly czas pracy. Gasnie razem z faza — po wyniku
   nie ma juz na co czekac. */
.fr-akt-runy {
  position: absolute; top: 50%; left: 50%;
  width: 320px; height: 320px; margin: -92px 0 0 -160px;
  background-repeat: no-repeat;
  background-size: 2560px 320px;
  opacity: 0; pointer-events: none; z-index: 1;
  transition: opacity 0.3s ease;
}
.fr-akt.praca .fr-akt-runy {
  opacity: 0.85;
  animation: fr-akt-runy 1.4s steps(8) infinite;
}
@keyframes fr-akt-runy {
  from { background-position: 0 0; }
  to   { background-position: -2560px 0; }
}

/* Blysk przemiany. Jeden kadr bieli, ktory rozchodzi sie i gasnie. */
.fr-akt-blysk {
  position: absolute; top: 50%; left: 50%;
  width: 40px; height: 40px; margin: -50px 0 0 -20px;
  border-radius: 50%; background: #fff;
  opacity: 0; pointer-events: none;
}
.fr-akt.udane .fr-akt-blysk,
.fr-akt.stracone .fr-akt-blysk { animation: fr-akt-blysk 0.45s ease-out forwards; }
@keyframes fr-akt-blysk {
  0%   { opacity: 0.95; transform: scale(0.4); }
  100% { opacity: 0;    transform: scale(9); }
}

.fr-akt-obiekt {
  position: relative; z-index: 2;
  width: 136px; height: 136px;
  display: flex; align-items: center; justify-content: center;
}
.fr-akt-obiekt img { display: block; max-width: 100%; max-height: 100%; }

/* Faza pracy: obiekt oddycha i stopniowo bieleje. Rozjasnienie jest
   zapowiedzia — do momentu odpowiedzi serwera nie wiadomo jeszcze, czy
   skonczy sie przemiana, czy rozpadem. */
.fr-akt.praca .fr-akt-obiekt { animation: fr-akt-praca 1.1s ease-in-out infinite; }
@keyframes fr-akt-praca {
  0%, 100% { transform: scale(1);    filter: brightness(1)   drop-shadow(0 0 6px var(--gc, #FFB25A)); }
  50%      { transform: scale(1.07); filter: brightness(1.6) drop-shadow(0 0 22px var(--gc, #FFB25A)); }
}
/* Udane: obiekt strzela w gore i wraca juz jako nowy. */
.fr-akt.udane .fr-akt-obiekt { animation: fr-akt-udane 0.75s cubic-bezier(.2,.9,.3,1.2) forwards; }
@keyframes fr-akt-udane {
  0%   { transform: scale(1.1);  filter: brightness(3) drop-shadow(0 0 30px #fff); }
  35%  { transform: scale(0.82); filter: brightness(2.2); }
  100% { transform: scale(1);    filter: brightness(1.15) drop-shadow(0 0 16px var(--gc, #FFB25A)); }
}
/* Skazenie. Klejnot ani nie rosnie, ani nie ginie — ciemnieje i dostaje
   fioletowa obwodke. Ruch jest wolniejszy i cezszy niz przy ulepszeniu:
   to nie jest sukces, tylko uklad. */
.fr-akt.skazone .fr-akt-obiekt { animation: fr-akt-skazenie 1.1s ease forwards; }
@keyframes fr-akt-skazenie {
  0%   { transform: scale(1);    filter: brightness(1.4) drop-shadow(0 0 10px var(--gc, #fff)); }
  30%  { transform: scale(0.92); filter: brightness(0.35) saturate(0.4) drop-shadow(0 0 26px #7A2ECC); }
  55%  { transform: scale(1.05); filter: brightness(0.5)  saturate(0.7) drop-shadow(0 0 34px #BF5FFF); }
  100% { transform: scale(1);    filter: brightness(0.85) saturate(1.3) drop-shadow(0 0 18px #BF5FFF); }
}
.fr-akt.skazone .fr-akt-blysk { background: #BF5FFF; }
.fr-akt.skazone .fr-akt-pod { color: #d9b8ff; }

/* Oczyszczenie — ta sama droga w druga strone. */
.fr-akt.oczyszczone .fr-akt-obiekt { animation: fr-akt-oczyszczenie 1s ease forwards; }
@keyframes fr-akt-oczyszczenie {
  0%   { filter: brightness(0.6) saturate(1.4) drop-shadow(0 0 20px #BF5FFF); }
  45%  { filter: brightness(2.4) saturate(0.2) drop-shadow(0 0 30px #fff); transform: scale(1.06); }
  100% { filter: brightness(1)   saturate(1)   drop-shadow(0 0 14px var(--gc, #fff)); transform: scale(1); }
}
.fr-akt.oczyszczone .fr-akt-pod { color: var(--win); }

/* Stracone: drgniecie i zniknicie. Odlamki leca osobno. */
.fr-akt.stracone .fr-akt-obiekt { animation: fr-akt-drgnij 0.4s ease forwards; }
@keyframes fr-akt-drgnij {
  0%   { transform: translateX(0)    scale(1.08); filter: brightness(2.6); }
  20%  { transform: translateX(-9px) scale(1.02); }
  40%  { transform: translateX(8px); }
  60%  { transform: translateX(-5px); }
  80%  { transform: translateX(3px); }
  100% { transform: translateX(0)    scale(1);    filter: brightness(1); }
}
/* Kawalki SA tym obiektem, wiec oryginal musi zgasnac dokladnie w chwili,
   gdy one ruszaja. Kazda zwloka pokazuje jedno i drugie na raz. */
.fr-akt-obiekt.pekl { opacity: 0; transition: none; }

/* Odlamki. Osiem kawalkow rozbiegajacych sie z punktu, kazdy z wlasnym
   katem, zasiegiem i obrotem — bez tego wygladaja jak rozstrzelona
   gwiazdka, a nie jak cos, co peklo. */
/* Kawalki rozbitej grafiki. Kazdy startuje DOKLADNIE tam, gdzie lezal
   w obrazku (--sx, --sy), i leci od srodka na zewnatrz (--dx, --dy),
   opadajac po drodze (--spadek). Razem czyta sie jak rozpadniecie tej
   konkretnej rzeczy, a nie jak wybuch obok niej. */
.fr-akt-kawalek {
  position: absolute; top: 50%; left: 50%; z-index: 3;
  margin: -68px 0 0 0;
  background-repeat: no-repeat;
  transform: translate(var(--sx), var(--sy));
  animation: fr-akt-kawalek 1.05s cubic-bezier(.18,.62,.38,1) forwards;
  pointer-events: none;
  filter: drop-shadow(0 0 6px rgba(0,0,0,0.6));
}
@keyframes fr-akt-kawalek {
  0%   { transform: translate(var(--sx), var(--sy)) rotate(0deg); opacity: 1; }
  15%  { opacity: 1; }
  100% { transform: translate(calc(var(--sx) + var(--dx)), calc(var(--sy) + var(--dy) + var(--spadek)))
                    rotate(var(--rot)) scale(0.85);
         opacity: 0; }
}

.fr-akt-odlamek {
  position: absolute; top: 50%; left: 50%; z-index: 3;
  width: var(--sz); height: var(--sz); margin: -68px 0 0 calc(var(--sz) / -2);
  background: var(--gc, #d8d8e8);
  box-shadow: 0 0 10px 1px var(--gc, #d8d8e8);
  clip-path: polygon(50% 0%, 100% 38%, 78% 100%, 18% 88%, 0% 34%);
  animation: fr-akt-odlamek 1.15s cubic-bezier(.15,.6,.35,1) forwards;
  opacity: 0; pointer-events: none;
}
/* Dwa ruchy naraz: rozbiegniecie na boki (obrot + przesuniecie) i opadanie
   (osobny `translateY` na koncu). Bez opadania odlamki wygladaja, jakby
   leialy w prozni. */
@keyframes fr-akt-odlamek {
  0%   { transform: rotate(var(--a)) translateX(0) rotate(0deg) translateY(0);
         opacity: var(--op, 1); }
  60%  { opacity: var(--op, 1); }
  100% { transform: rotate(var(--a)) translateX(var(--r)) rotate(var(--rot)) translateY(var(--spadek));
         opacity: 0; }
}

/* Bylo -> jest. Cztery kolumny o stalych proporcjach, zeby liczby staly
   jedna pod druga niezaleznie od dlugosci nazwy statystyki. */
.fr-akt-tabela {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 1fr auto auto auto;
  gap: 2px 10px; align-items: center;
  margin-top: 10px; padding: 10px 14px;
  border-radius: var(--radius);
  background: rgba(0,0,0,0.45); border: 1px solid var(--border);
  font-size: 12px; width: 100%;
}
.fr-akt-wiersz { display: contents; }
.fr-akt-nazwa { color: var(--text-dim); text-align: left; }
.fr-akt-stara { color: var(--text-dim); font-weight: 700; font-variant-numeric: tabular-nums; }
.fr-akt-strzalka { color: var(--gold-deep); }
.fr-akt-nowa { font-weight: 900; font-variant-numeric: tabular-nums; }
.fr-akt-nowa.lepiej { color: var(--win); }
.fr-akt-nowa.gorzej { color: var(--loss); }
.fr-akt-nowa.rowno  { color: var(--text); }

.fr-akt-akcje {
  position: relative; z-index: 2;
  display: flex; gap: 8px; margin-top: 12px;
}
.fr-akt-akcje .gvk-btn { flex: 1; justify-content: center; gap: 8px; white-space: nowrap; padding: 11px 12px; }

.fr-akt-tytul {
  position: relative; z-index: 2;
  font-family: var(--font-display); font-size: 19px; font-weight: 900;
  color: var(--text-bright); text-shadow: 0 2px 8px rgba(0,0,0,0.8);
}
.fr-akt-pod {
  position: relative; z-index: 2;
  font-size: 12px; color: var(--text-dim);
}
.fr-akt.udane .fr-akt-pod { color: var(--gold-soft); font-weight: 800; }
.fr-akt.stracone .fr-akt-pod { color: var(--loss); font-weight: 800; }
.fr-akt-nota {
  position: relative; z-index: 2;
  min-height: 18px; margin-top: 4px;
  font-size: 13px; font-weight: 900; color: var(--win);
}
.fr-akt.stracone .fr-akt-nota { color: var(--text-dim); }

@media (prefers-reduced-motion: reduce) {
  .fr-akt-aura, .fr-akt-blysk, .fr-akt-odlamek { display: none; }
  .fr-akt .fr-akt-obiekt { animation: none !important; }
}

/* ── OKNA ───────────────────────────────────────────────── */
.fr-modal { text-align: center; max-width: 360px; margin: 0 auto; }
.fr-modal h3 { font-family: var(--font-display); font-size: 17px; font-weight: 900; color: var(--gold-soft); margin: 0 0 8px; }
.fr-modal p { font-size: 12px; line-height: 1.6; color: var(--text-dim); margin: 0 0 12px; }
.fr-modal-gem { margin-bottom: 8px; }
.fr-modal-gem img { display: inline-block; }
.fr-modal-cost {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  padding: 7px 14px; border-radius: 999px; margin-bottom: 12px;
  background: rgba(255,212,106,0.12); border: 1px solid rgba(200,168,78,0.35);
  font-size: 14px; font-weight: 900; color: var(--gold-soft);
}
.fr-modal-cost img { width: 18px; height: 18px; }
.fr-menu { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.fr-menu .gvk-btn { justify-content: space-between; }

/* ── TELEFON ────────────────────────────────────────────── */
@media (max-width: 560px) {
  .fr { padding: 8px 8px 20px; gap: 12px; }
  .fr-hubcards { grid-template-columns: minmax(0, 1fr); }
  .fr-hubcard { min-height: 150px; }
  .fr-title { font-size: 24px; }
  /* Szesc gniazd w jednym rzedzie daje 48 px na gniazdo — za malo,
     zeby zmiescic bonus. Dwa rzedy po trzy. */
  .fr-purse.compact { padding: 6px 7px; gap: 4px; }
  .fr-purse.compact .fr-coin { font-size: 12px; padding: 4px 8px; gap: 4px; }
  .fr-purse.compact .fr-coin img { width: 17px; height: 17px; }
  .fr-sockets { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fr-cru-stage { grid-template-columns: 1fr auto 1fr; gap: 4px; padding: 12px 2px; }
  .fr-cru-scrolls { grid-template-columns: minmax(0, 1fr); }
  .fr-cru-acts { flex-wrap: wrap; }
  .fr-worn { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .fr-tray, .fr-bag, .fr-stall { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
}
