/* Shared palette lives in /tokens.css (dark-only, loaded by index.html before
   this file), including --chip-bg, which moved there when the Transfiguration
   Atlas started drawing the same chip. Only the app-specific tokens — the affix
   category colours — are declared here. */
:root {
  /* One hue family per category (utility is gold so it can never be confused
     with defensive blue). Steps chosen by maximizing the minimum pairwise
     OKLab distance — worst pair ≥15 ΔE normal vision, ≥7 under
     protan/deutan simulation, every colour ≥3:1 on --panel. Re-validate the
     full set if you retune any single colour: the floors are pairwise. */
  --cor: #d17374;
  --off: #985a00;
  --def: #3188f1;
  --res: #8c53af;
  --uti: #a09524;
  --mob: #277a4b;
  --skl: #22a79e;
}
/* A populated pool is often tall enough to need the browser's vertical
   scrollbar while the initial picker is not; ../shared/base.css keeps the bar
   present always so rendering a selection never nudges the centred page
   sideways. */
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font:
    16px/1.5 "Segoe UI",
    system-ui,
    sans-serif;
}
.wrap {
  max-width: 1680px;
  margin: 0 auto;
  padding: 0 20px 24px;
}
/* The box-sizing reset, the scrollbar gutter, the inherited control font and the
   boot-failure and no-script notices are apps/shared/base.css, linked before
   this file. Only this app's own rules live below. */
/* Page chrome — the top site rail, <header class="pagehead">, and the
   <footer class="pagefoot"> build stamp — is shared/chrome.css, linked in
   index.html right after tokens.css. Only this app's own rules live below. */

/* ---- affix category legend ----
   A colour key, nothing more: prisms aren't listed because a category isn't
   exclusive to one. It sits below the toolbar so the class row is the first
   thing under the title; a single wrapping row keeps it shallow enough that the
   cards it keys are still on screen at first paint. */
.legend {
  margin: 12px 0 14px;
  display: flex;
  align-items: baseline;
  gap: 8px 18px;
  flex-wrap: wrap;
}
.legend-title {
  margin: 0;
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  font-weight: 600;
}
.legend-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
}
.legend-list li {
  display: flex;
  align-items: center;
  gap: 7px;
}
/* --fs-base for the same reason .cbtn takes it (see shared/chrome.css): these
   were 13.5px and the scale rounded them down. The legend sits directly against
   the picker row, so the two have to round the same way. */
.legend-list .lname {
  font-size: var(--fs-base);
  color: var(--muted);
}

.toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--ground);
  padding: 12px 0 10px;
  border-bottom: 1px solid var(--edge);
  display: flex;
  flex-direction: column;
  gap: 9px;
}
/* .btnrow and .rowlabel are shared/chrome.css — every picker page draws the
   same labelled row. */
.quality-search-row {
  display: flex;
  align-items: center;
  gap: 9px 24px;
  flex-wrap: wrap;
}
.quality-search-row #searchrow {
  flex: 1 1 420px;
}
.searchbox {
  font: inherit;
  /* Peer of .cbtn in the same toolbar — same padding, same radius, so it takes
     the same step. It was 13.5px too. */
  font-size: var(--fs-base);
  padding: 5px 11px;
  border-radius: var(--radius-sm);
  flex: 1 1 220px;
  max-width: 340px;
  min-width: 0;
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--edge-soft);
}
.searchbox::placeholder {
  color: var(--faint);
}
.searchbox:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ---- affix and prism overview ---- */
.prism-cards {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px;
  margin-top: 18px;
}
/* .selection-prompt is in apps/shared/base.css: the Atlas shows the same box
   when its item is cleared, and two copies of a card-sized panel would be the
   .noscript notice's history repeating. */
@media (max-width: 900px) {
  .prism-cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (max-width: 560px) {
  .prism-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.pcard {
  background: var(--panel);
  border: 1px solid var(--edge-soft);
  border-radius: var(--radius-md);
  min-width: 0;
  padding: 12px 12px 11px;
}
.pcard.empty {
  opacity: 0.55;
}
.pcard-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 2px;
}
.pcard-head .pname {
  font-family: "Palatino Linotype", "Book Antiqua", Palatino, Georgia, serif;
  font-size: var(--fs-xl);
  line-height: 1.25;
  letter-spacing: 0.035em;
  color: var(--accent-ink);
  flex: 1;
}
.pcard ul.chips {
  margin-top: 10px;
  gap: 6px;
  align-content: flex-start;
}
.pcard .chip {
  width: 100%;
  padding: 4px 8px;
  font-size: var(--fs-base);
  line-height: 1.3;
}
.pcard .chip .affix-name {
  min-width: 0;
}
.pcard .chip .chance {
  flex: none;
  margin-left: auto;
  padding-left: 5px;
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  font-weight: 600;
}
.pcard .noaff {
  font-size: var(--fs-sm);
  color: var(--faint);
  font-style: italic;
}
/* Explains the .chance figures above the cards that carry them, so the
   affordance sits with the numbers instead of trailing a Quality button. */
.odds-note {
  margin: 18px 0 14px;
  max-width: 70ch;
}
.odds-note summary {
  display: list-item;
  width: fit-content;
  cursor: pointer;
  color: var(--muted);
  font-size: var(--fs-sm);
}
.odds-note summary:hover {
  color: var(--accent-ink);
}
.odds-note summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.odds-note p {
  margin: 6px 0 0;
  padding: 9px 11px;
  border: 1px solid var(--edge-soft);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--ink);
  font-size: var(--fs-sm);
  line-height: 1.45;
}

/* Use the game's inventory art as the visual anchor. */
.prism-mark {
  position: relative;
  display: inline-block;
  flex: none;
}

/* The icons are screenshot crops, so they carry a fixed, small pixel count
   (--iw is each asset's true width). Drawn at natural CSS size they get
   stretched by --dpr on a scaled display, which blurs them and makes them
   read larger than they do in-game. Divide by --dpr so one image pixel lands
   on one device pixel. Falls back to natural size if a browser can't match
   its own scaling below. */
:root {
  --dpr: 1;
}
@media (min-resolution: 1.25dppx) {
  :root {
    --dpr: 1.25;
  }
}
@media (min-resolution: 1.5dppx) {
  :root {
    --dpr: 1.5;
  }
}
@media (min-resolution: 1.75dppx) {
  :root {
    --dpr: 1.75;
  }
}
@media (min-resolution: 2dppx) {
  :root {
    --dpr: 2;
  }
}
@media (min-resolution: 2.25dppx) {
  :root {
    --dpr: 2.25;
  }
}
@media (min-resolution: 2.5dppx) {
  :root {
    --dpr: 2.5;
  }
}
@media (min-resolution: 3dppx) {
  :root {
    --dpr: 3;
  }
}
.prism-icon {
  --iw: 66;
  display: block;
  width: calc(var(--iw) * 1px / var(--dpr));
  height: auto;
}
.prism-icon[src$="tuning-prism.webp"] {
  --iw: 40;
}
/* Crops that keep the frame's left inner bevel are one column wider. Aggressive
   stays 66: its left edge was hand-picked, not derived from the bevel. */
.prism-icon[src$="prism-protectors.webp"],
.prism-icon[src$="prism-resourceful.webp"],
.prism-icon[src$="prism-pragmatic.webp"],
.prism-icon[src$="prism-chromatic.webp"],
.prism-icon[src$="prism-adepts.webp"] {
  --iw: 67;
}

/* ---- affix category dots ----
   One per runtime category; implicit/mythic never reach the page (the runtime
   dataset excludes them), so they get no dot here. */
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}
.dot-core {
  background: var(--cor);
}
.dot-offensive {
  background: var(--off);
}
.dot-defensive {
  background: var(--def);
}
.dot-resource {
  background: var(--res);
}
.dot-utility {
  background: var(--uti);
}
.dot-mobility {
  background: var(--mob);
}
.dot-skillranks {
  background: var(--skl);
}

/* ---- affix chips ---- */
ul.chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.chip {
  background: var(--chip-bg);
  border: 1px solid var(--edge-soft);
  border-radius: var(--radius-sm);
  padding: 3.5px 9px;
  font-size: var(--fs-base);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.chip .dot {
  width: 8px;
  height: 8px;
}
/* Clickable where the same stat can appear on more than one prism card. */
.chip[data-affix] {
  cursor: pointer;
}
.chip[data-affix]:hover {
  border-color: var(--accent);
}
.chip[data-affix]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
/* Two states, one emphasis. .hl is the picked stat, marked on every prism that
   can roll it; .search-hit marks stats matching the search box while every
   other chip stays visible in place. The border alone is too close to :hover
   to read across six columns at a glance, so the fill and inset border carry
   the state. Keep the text weight unchanged so marking a stat does not
   re-rasterize its small label and make it appear soft. */
.chip.hl,
.chip.search-hit {
  border-color: var(--accent);
  background: var(--panel2);
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* Hovering one chip marks every other copy of that stat. Deliberately weaker
   than .hl: this is a transient preview of the same relationship a click pins,
   and matching .hl's fill would make a pointer sweeping the cards look like it
   was picking them. The border alone is what :hover already gives the chip
   under the pointer, so the far copies read as its echo. */
.chip.hover-hl {
  border-color: var(--accent);
}
