/* Dunlight wiki — additions on top of the base theme.
   Everything here reuses the base design tokens so light and dark stay in sync. */

/* Palette sampled from the game's own icon: a lit torch over night blue.
   Each value below is a colour the icon actually uses. */
:root {
  /* Surface tokens the base stylesheet scopes to .pm-editor, which this theme
     does not use. Defined here so they apply across the whole page. */
  --pm-border: #00000030;
  --pm-border-subtle: #0000001a;
  --pm-bg-raised: #00000010;
  --pm-bg-inset: #00000014;
  --pm-bg-subtle: #0000000c;
  --pm-separator: #00000018;
  --pm-hover-bg: #00000012;
  --pm-page-bg: #f7f5f2;

  --dl-flame:      #ff3600;  /* dominant flame orange */
  --dl-flame-mid:  #ff6900;  /* mid flame */
  --dl-flame-core: #ffec6e;  /* bright core */
  --dl-ember:      #ff1200;  /* deep ember red */
  --dl-gold:       #c9ac60;  /* torch fitting */
  --dl-wood:       #6e4a26;  /* torch handle */
  --dl-night:      #161d2c;  /* icon background */
  --dl-night-deep: #10151f;
  --dl-night-soft: #1e273c;

  /* Rarity colours, warmed to sit with the flame palette. */
  --dl-common: #9aa3b2;
  --dl-uncommon: #5fbf6a;
  --dl-rare: #4a9eff;
  --dl-epic: #b56cf0;
  --dl-legendary: var(--dl-flame-core);

  /* Override the base theme's borrowed accent with the game's own. */
  --kb-brand: var(--dl-flame);
  --kb-light-bg: #f7f5f2;
  --kb-dark-bg: var(--dl-night);
  --kb-sidebar-bg: #efece7;
  --kb-light-text: #171d28;
  --kb-dark-text: #dfe4ee;
  --kb-brand-text: #d84a12;
}

html.dark {
  --pm-border: #ffffff2e;
  --pm-border-subtle: #ffffff1a;
  --pm-bg-raised: #ffffff0e;
  --pm-bg-inset: #ffffff14;
  --pm-bg-subtle: #ffffff0a;
  --pm-separator: #ffffff1c;
  --pm-hover-bg: #ffffff14;
  --pm-page-bg: var(--dl-night);

  --kb-sidebar-bg: var(--dl-night-deep);
  --kb-brand-text: var(--dl-flame-mid);
  --pm-page-bg: var(--dl-night);
}

/* ------------------------------------------------------ header chrome */
.kb-brand {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0.55rem;
  text-decoration: none;
}

.kb-brand-mark {
  width: 1.15rem;
  height: 1.15rem;
  flex: none;
  border-radius: 0.3rem;
  object-fit: contain;
  /* Pixel art: keep the edges crisp instead of smoothing them. */
  image-rendering: pixelated;
}

.kb-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  color: inherit;
  cursor: pointer;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 0.45rem;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.kb-icon-btn:hover { background: var(--pm-hover-bg); border-color: var(--pm-border-subtle); }
.kb-icon-btn:focus-visible,
.kb-search-btn:focus-visible,
.kb-lang-item:focus-visible {
  outline: 2px solid var(--kb-brand);
  outline-offset: 2px;
}

/* One icon per scheme, so the button always shows the action, not the state. */
.kb-icon-moon { display: none; }
html.dark .kb-icon-sun { display: none; }
html.dark .kb-icon-moon { display: inline; }

/* ------------------------------------------------------ language menu */
.kb-lang { position: relative; }

.kb-lang-menu {
  position: absolute;
  top: calc(100% + 0.35rem);
  right: 0;
  z-index: 60;
  min-width: 9rem;
  padding: 0.25rem;
  background: var(--pm-page-bg);
  border: 1px solid var(--pm-border);
  border-radius: 0.55rem;
  box-shadow: 0 8px 24px #0000002e;
}

.kb-lang-menu[hidden] { display: none; }

.kb-lang-item {
  display: block;
  padding: 0.4rem 0.6rem;
  font-size: 0.85em;
  color: inherit;
  text-decoration: none;
  border-radius: 0.35rem;
}

.kb-lang-item:hover { background: var(--pm-hover-bg); }
.kb-lang-item.active { color: var(--kb-brand-text); font-weight: var(--pm-weight-semibold); }

/* --------------------------------------------------------- search bits */
/* The base rule sets `display: flex` unconditionally, which outranks the
   `hidden` attribute's low-specificity `display: none`. Without `!important`
   the overlay stays on screen permanently, blurring the page and trapping
   the user. */
.kb-search-overlay[hidden] { display: none !important; }
body.kb-search-open { overflow: hidden; }

.kb-search-result { display: flex; flex-direction: column; gap: 0.15rem; }
.kb-search-title { font-weight: var(--pm-weight-medium); }

.kb-search-excerpt {
  font-size: 0.8em;
  line-height: var(--pm-leading-snug);
  color: var(--pm-text-muted, inherit);
  opacity: 0.7;
}

/* -------------------------------------------------- page foot and nav */
.kb-toc-title {
  margin: 0 0 0.5rem;
  font-size: 0.72em;
  font-weight: var(--pm-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.6;
}

.kb-page-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  align-items: center;
  justify-content: space-between;
  margin-top: 3rem;
  padding-top: 1rem;
  border-top: 1px solid var(--pm-separator);
}

.kb-edit-link {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.85em;
  color: inherit;
  text-decoration: none;
  opacity: 0.7;
}

.kb-edit-link:hover { color: var(--kb-brand-text); opacity: 1; }

.kb-copyright { margin: 0; font-size: 0.78em; opacity: 0.55; }

.kb-pagenav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin: 1.5rem 0 2rem;
}

.kb-pagenav-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.7rem 0.9rem;
  color: inherit;
  text-decoration: none;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.6rem;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.kb-pagenav-item:hover { background: var(--pm-hover-bg); border-color: var(--kb-brand); }
.kb-pagenav-item.next { text-align: right; }
.kb-pagenav-dir { font-size: 0.78em; opacity: 0.55; }
.kb-pagenav-title { font-weight: var(--pm-weight-medium); }

/* ------------------------------------------------------------ widgets */
.dl-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin: 1.25rem 0 0.6rem;
}

.dl-input,
.dl-select {
  padding: 0.45rem 0.65rem;
  font: inherit;
  font-size: 0.85em;
  color: inherit;
  background: var(--pm-bg-inset);
  border: 1px solid var(--pm-border);
  border-radius: 0.45rem;
}

.dl-input { flex: 1 1 15rem; min-width: 0; }
.dl-input-num { flex: 0 0 auto; width: 100%; }

.dl-input:focus-visible,
.dl-select:focus-visible,
.dl-btn:focus-visible,
.dl-chip:focus-visible,
.dl-sortable:focus-visible,
.dl-owned-chip:focus-visible {
  outline: 2px solid var(--kb-brand);
  outline-offset: 2px;
}

.dl-btn,
.dl-chip {
  padding: 0.45rem 0.85rem;
  font: inherit;
  font-size: 0.82em;
  font-weight: var(--pm-weight-medium);
  color: inherit;
  cursor: pointer;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border);
  border-radius: 2rem;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.dl-btn:hover,
.dl-chip:hover { background: var(--pm-hover-bg); border-color: var(--kb-brand); }

.dl-chip.is-active {
  color: #1c1917;
  background: var(--kb-brand);
  border-color: var(--kb-brand);
}

.dl-btn-danger { color: #ef4444; border-color: #ef444455; }
.dl-btn-danger:hover { color: #fff; background: #ef4444; border-color: #ef4444; }

.dl-hidden { display: none; }

.dl-count,
.dl-note {
  margin: 0.3rem 0;
  font-size: 0.8em;
  opacity: 0.65;
}

.dl-note-bad { color: #ef4444; opacity: 1; }
.dl-loading { font-size: 0.85em; opacity: 0.6; }
.dl-empty { padding: 2rem; text-align: center; opacity: 0.6; }

/* -------------------------------------------------------------- table */
.dl-tablewrap {
  margin: 0.5rem 0 1.5rem;
  overflow-x: auto;
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.6rem;
}

.dl-table {
  width: 100%;
  font-size: 0.85em;
  border-collapse: collapse;
}

.dl-table th,
.dl-table td {
  padding: 0.55rem 0.7rem;
  text-align: left;
  border-bottom: 1px solid var(--pm-separator);
}

.dl-table tbody tr:last-child td { border-bottom: 0; }

.dl-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  font-size: 0.92em;
  font-weight: var(--pm-weight-semibold);
  white-space: nowrap;
  background: var(--pm-bg-raised);
  backdrop-filter: blur(8px);
}

.dl-sortable { cursor: pointer; user-select: none; }
.dl-sortable:hover { color: var(--kb-brand-text); }
.dl-sortable.is-sorted { color: var(--kb-brand-text); }

.dl-row:hover { background: var(--pm-hover-bg); }

.dl-num {
  font-family: var(--font-mono);
  font-size: 0.95em;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.dl-th-own, .dl-td-own { width: 1.5rem; text-align: center; }
.dl-td-own input { accent-color: var(--kb-brand); cursor: pointer; }
.dl-skill { min-width: 19rem; }

.dl-skilltext {
  margin-top: 0.15rem;
  font-size: 0.88em;
  line-height: var(--pm-leading-snug);
  opacity: 0.65;
}

/* ------------------------------------------------------------- badges */
.dl-badge {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  font-size: 0.78em;
  font-weight: var(--pm-weight-semibold);
  white-space: nowrap;
  border-radius: 2rem;
  border: 1px solid currentColor;
}

.dl-badge.dl-common { color: var(--dl-common); }
.dl-badge.dl-uncommon { color: var(--dl-uncommon); }
.dl-badge.dl-rare { color: var(--dl-rare); }
.dl-badge.dl-epic { color: var(--dl-epic); }
.dl-badge.dl-legendary { color: var(--dl-legendary); }

/* Monster tiers, rising with how dangerous the encounter is. */
.dl-badge.dl-monster-normal { color: var(--dl-common); }
.dl-badge.dl-monster-elite { color: var(--dl-rare); }
.dl-badge.dl-monster-boss { color: var(--dl-legendary); }
.dl-badge.dl-monster-summon { color: var(--dl-uncommon); }
.dl-badge.dl-monster-other { color: var(--dl-uncommon); }

/* The monster card's tier stripe is defined after .dl-itemcard, whose border
   shorthand would otherwise reset it. */

/* --------------------------------------------------------- calculator */
.dl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.7rem;
  margin: 1rem 0;
}

.dl-field { display: flex; flex-direction: column; gap: 0.25rem; }

.dl-field-label {
  font-size: 0.78em;
  font-weight: var(--pm-weight-medium);
  opacity: 0.7;
}

.dl-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 0.6rem;
  margin: 1rem 0;
}

.dl-stat {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.65rem 0.8rem;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.6rem;
}

.dl-stat.is-primary {
  background: color-mix(in srgb, var(--kb-brand) 8%, transparent);
  border-color: color-mix(in srgb, var(--kb-brand) 45%, transparent);
}

.dl-stat-label {
  font-size: 0.72em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.6;
}

.dl-stat-value {
  font-family: var(--font-mono);
  font-size: 1.15em;
  font-weight: var(--pm-weight-semibold);
  font-variant-numeric: tabular-nums;
}

.dl-stat.is-primary .dl-stat-value { color: var(--kb-brand-text); }

/* ------------------------------------------------------------ tracker */
.dl-summary { margin: 1.25rem 0; }

.dl-summary-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.45rem;
}

.dl-pct {
  font-family: var(--font-mono);
  font-weight: var(--pm-weight-bold);
  color: var(--kb-brand-text);
}

.dl-bar {
  height: 0.45rem;
  overflow: hidden;
  background: var(--pm-bg-inset);
  border-radius: 2rem;
}

.dl-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--kb-brand), #fbbf24);
  border-radius: 2rem;
  transition: width 0.3s ease;
}

.dl-collection-group { margin: 1.5rem 0; }

.dl-collection-group h3 {
  margin: 0 0 0.55rem;
  font-size: 0.95em;
  opacity: 0.75;
}

.dl-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.dl-owned-chip {
  padding: 0.32rem 0.7rem;
  font: inherit;
  font-size: 0.82em;
  font-weight: var(--pm-weight-medium);
  color: inherit;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--pm-border);
  border-radius: 2rem;
  opacity: 0.45;
  transition: opacity 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}

.dl-owned-chip:hover { opacity: 0.8; }

.dl-owned-chip.is-owned {
  color: #1c1917;
  border-color: transparent;
  opacity: 1;
}

.dl-owned-chip.is-owned.dl-common { background: var(--dl-common); }
.dl-owned-chip.is-owned.dl-uncommon { background: var(--dl-uncommon); }
.dl-owned-chip.is-owned.dl-rare { background: var(--dl-rare); }
.dl-owned-chip.is-owned.dl-epic { background: var(--dl-epic); }
.dl-owned-chip.is-owned.dl-legendary { background: var(--dl-legendary); }

/* ------------------------------------------------------- home cards */
.dl-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.8rem;
  margin: 1.5rem 0;
}

.dl-card {
  display: block;
  padding: 1rem 1.1rem;
  color: inherit;
  text-decoration: none;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.7rem;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
}

.dl-card:hover {
  background: var(--pm-hover-bg);
  border-color: var(--kb-brand);
  transform: translateY(-2px);
}

.dl-card-text { font-size: 0.88em; line-height: var(--pm-leading-snug); opacity: 0.72; }

@media (max-width: 44em) {
  .dl-skill { min-width: 13rem; }
  .dl-input { flex-basis: 100%; }
  .kb-pagenav { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------- admonitions */
/* The base theme has no admonition styling, and the wiki relies on them
   to flag unconfirmed data and caveats. */
.admonition,
details.admonition {
  margin: 1.25rem 0;
  padding: 0.85rem 1rem;
  font-size: 0.92em;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-left: 3px solid var(--kb-brand);
  border-radius: 0.5rem;
}

.admonition > :first-child { margin-top: 0; }
.admonition > :last-child { margin-bottom: 0; }

.admonition-title {
  margin: 0 0 0.4rem;
  font-weight: var(--pm-weight-semibold);
  color: var(--kb-brand-text);
}

.admonition.note,
.admonition.info { border-left-color: #60a5fa; }
.admonition.note > .admonition-title,
.admonition.info > .admonition-title { color: #60a5fa; }

.admonition.tip { border-left-color: #4ade80; }
.admonition.tip > .admonition-title { color: #4ade80; }

.admonition.warning { border-left-color: #fbbf24; }
.admonition.warning > .admonition-title { color: #fbbf24; }

.admonition.danger,
.admonition.failure { border-left-color: #ef4444; }
.admonition.danger > .admonition-title,
.admonition.failure > .admonition-title { color: #ef4444; }

/* Markdown tables authored directly in pages (equipment, treasures, shrines). */
.kb-content table:not(.dl-table) {
  display: block;
  width: 100%;
  margin: 1.25rem 0;
  overflow-x: auto;
  font-size: 0.88em;
  border-collapse: collapse;
}

.kb-content table:not(.dl-table) th,
.kb-content table:not(.dl-table) td {
  padding: 0.5rem 0.7rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--pm-separator);
}

.kb-content table:not(.dl-table) th {
  font-weight: var(--pm-weight-semibold);
  white-space: nowrap;
  background: var(--pm-bg-raised);
}

.kb-content table:not(.dl-table) tr:hover td { background: var(--pm-hover-bg); }

/* -------------------------------------------------------------- sprites */
/* Game artwork is pixel art: scaling must not smooth it. */
.dl-sprite {
  image-rendering: pixelated;
  flex: none;
  vertical-align: middle;
  object-fit: contain;
}

.dl-sprite-hero {
  width: 2rem;
  height: 2rem;
  margin-right: 0.5rem;
}

.dl-table thead th.dl-sortable {
  white-space: nowrap;
}

/* Trait reference table and hero galleries. */
.dl-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
  gap: 0.6rem;
  margin: 1.25rem 0;
}

.dl-gallery-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 0.6rem 0.4rem;
  font-size: 0.78em;
  text-align: center;
  color: inherit;
  text-decoration: none;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.55rem;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.dl-gallery-item:hover {
  border-color: var(--kb-brand);
  transform: translateY(-2px);
}

.dl-gallery-item img {
  width: 3rem;
  height: 3rem;
  image-rendering: pixelated;
  object-fit: contain;
}

.dl-sprite-item {
  width: 1.5rem;
  height: 1.5rem;
  margin-right: 0.35rem;
}

.dl-gallery-blank {
  width: 3rem;
  height: 3rem;
  background: var(--pm-bg-inset);
  border-radius: 0.35rem;
}

.dl-gallery-item span:not(.dl-gallery-blank) {
  line-height: 1.25;
  word-break: break-word;
}

/* ---------------------------------------------------------- game cards */
/* Panels modelled on the in-game hero screen: portrait and identity on top,
   a stat grid across star levels, then the skill text per level. */

.dl-herocard {
  margin: 1.25rem 0;
  overflow: hidden;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-left: 3px solid var(--dl-common);
  border-radius: 0.7rem;
}

.dl-rarity-common    { border-left-color: var(--dl-common); }
.dl-rarity-uncommon  { border-left-color: var(--dl-uncommon); }
.dl-rarity-rare      { border-left-color: var(--dl-rare); }
.dl-rarity-epic      { border-left-color: var(--dl-epic); }
.dl-rarity-legendary { border-left-color: var(--dl-legendary); }

.dl-card-title { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }

.dl-card-name {
  font-size: 1.05em;
  font-weight: var(--pm-weight-bold);
  line-height: 1.2;
}

.dl-card-meta { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }
.dl-card-trait { font-size: 0.82em; opacity: 0.75; }

/* --- top band: portrait, Max Mana, quality --- */
.dl-card-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 0.85rem;
  background: var(--pm-bg-raised);
  border-bottom: 1px solid var(--pm-separator);
}

.dl-card-quality {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.dl-card-quality-slot { display: none; }

.dl-card-top {
  display: grid;
  grid-template-columns: auto minmax(8rem, 1fr);
  gap: 0.7rem;
  /* The cell beside the portrait matches its height rather than floating in
     the middle of it, so the two read as one row. */
  align-items: stretch;
  padding: 0.8rem;
}

/* Its contents stay centred within that taller box. */
.dl-card-top .dl-stat-cell { justify-content: center; }

.dl-card-art {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  background: radial-gradient(circle at 50% 40%,
              color-mix(in srgb, var(--kb-brand) 12%, transparent),
              var(--pm-bg-inset) 75%);
  border: 1px solid var(--pm-border);
  border-radius: 0.6rem;
}

.dl-card-portrait {
  width: 7rem;
  height: 7rem;
  image-rendering: pixelated;
  object-fit: contain;
}

.dl-quality-label {
  font-size: 0.66em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.55;
}

/* --- star stepper --- */
.dl-starbar { display: inline-flex; gap: 0.4rem; align-items: center; }

.dl-starstep {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  font-size: 1rem;
  line-height: 1;
  color: inherit;
  cursor: pointer;
  background: var(--pm-bg-inset);
  border: 1px solid var(--pm-border);
  border-radius: 0.35rem;
  transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}

.dl-starstep:hover:not(:disabled) {
  background: var(--pm-hover-bg);
  border-color: var(--kb-brand);
}

.dl-starstep:disabled { opacity: 0.25; cursor: default; }
.dl-starstep:focus-visible { outline: 2px solid var(--kb-brand); outline-offset: 2px; }

.dl-starcurrent {
  display: inline-flex;
  gap: 1px;
  align-items: center;
  justify-content: center;
  min-width: 4.5rem;
}

.dl-starshow { display: inline-flex; gap: 1px; }
.dl-starshow[hidden] { display: none; }

.dl-star {
  width: 0.95rem;
  height: 0.95rem;
  image-rendering: pixelated;
  object-fit: contain;
}

/* Ranks 1-2 are silver in game; 3-4 turn gold. */
.dl-star-silver {
  filter: brightness(0) saturate(100%) invert(85%) sepia(6%) saturate(180%)
          hue-rotate(185deg) brightness(96%) contrast(90%);
}

.dl-star-gold {
  filter: brightness(0) saturate(100%) invert(72%) sepia(64%) saturate(1100%)
          hue-rotate(1deg) brightness(96%) contrast(94%);
}

.dl-starpanel[hidden] { display: none; }

/* --- stat grid --- */
.dl-statgrid { padding: 0 0.6rem 0.5rem; }

.dl-statrow {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.35rem;
}

.dl-statrow + .dl-statrow { margin-top: 0.35rem; }

.dl-stat-cell {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  align-items: center;
  padding: 0.55rem 0.35rem;
  text-align: center;
  background: var(--pm-bg-inset);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.45rem;
}

.dl-stat-mana {
  background: color-mix(in srgb, var(--kb-brand) 10%, var(--pm-bg-inset));
  border-color: color-mix(in srgb, var(--kb-brand) 35%, transparent);
}

.dl-stat-head {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  align-items: center;
  font-size: 0.68em;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0.7;
}

.dl-stat-num {
  font-family: var(--font-mono);
  font-size: 1em;
  font-weight: var(--pm-weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--kb-brand-text);
}

/* --- trait and skill, each with its description --- */
.dl-card-foot {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  padding: 0.15rem 0.6rem 0.5rem;
}

.dl-foot-item {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.6rem;
  background: var(--pm-bg-inset);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.45rem;
}

.dl-foot-label {
  font-size: 0.64em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.5;
}

.dl-foot-value {
  display: flex;
  gap: 0.45rem;
  align-items: center;
  font-size: 0.9em;
  font-weight: var(--pm-weight-semibold);
}

.dl-foot-desc {
  margin: 0;
  font-size: 0.8em;
  line-height: var(--pm-leading-snug);
  white-space: pre-line;
  opacity: 0.8;
}

/* Values the game highlights: those items, traits or star level can change. */
.dl-val {
  font-weight: var(--pm-weight-semibold);
  color: var(--dl-flame-core);
}

html:not(.dark) .dl-val { color: #b45309; }

.dl-card-note {
  margin: 0;
  padding: 0 0.7rem 0.7rem;
  font-size: 0.72em;
  font-style: italic;
  opacity: 0.5;
}

@media (max-width: 46em) {
  .dl-card-top { grid-template-columns: 1fr; justify-items: center; }
  .dl-card-foot { grid-template-columns: 1fr; }
  .dl-card-head { justify-content: center; }
}

/* --- tile grid (gems, generic galleries) --- */
.dl-cardgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.65rem;
  margin: 1.5rem 0;
}

.dl-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 0.85rem 0.6rem;
  text-align: center;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.6rem;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.dl-tile:hover { border-color: var(--kb-brand); transform: translateY(-2px); }

.dl-tile-art {
  width: 3rem;
  height: 3rem;
  image-rendering: pixelated;
  object-fit: contain;
}

.dl-tile-name { font-size: 0.85em; font-weight: var(--pm-weight-semibold); }
.dl-tile-desc { font-size: 0.75em; opacity: 0.65; }

.dl-sprite-shrine { width: 1.75rem; height: 1.75rem; margin-right: 0.35rem; }

@media (max-width: 40em) {
  .dl-statrow { grid-template-columns: minmax(5rem, 1.2fr) repeat(4, 1fr); }
  .dl-statlabel { font-size: 0.75em; }
  .dl-stat-cell { font-size: 0.75em; }
}

/* ------------------------------------------------------ icon contrast */
/* Stat icons ship pure white; the game renders them gold, so the same tint is
   applied here in both themes. Skill icons are already coloured artwork and
   are left untouched. */
.dl-sprite-stat {
  width: 1.15rem;
  height: 1.15rem;
  filter: brightness(0) saturate(100%) invert(72%) sepia(64%) saturate(1100%)
          hue-rotate(1deg) brightness(96%) contrast(94%);
  opacity: 0.95;
}



/* ---------------------------------------------------- trait medallion */
/* The game frames trait icons in a round badge; matching that reads as the
   same UI element rather than a loose sprite. */
.dl-sprite-trait {
  padding: 0.15rem;
  background: radial-gradient(circle at 50% 35%,
              color-mix(in srgb, var(--kb-brand) 30%, transparent),
              var(--pm-bg-raised) 70%);
  border: 1px solid color-mix(in srgb, var(--kb-brand) 45%, transparent);
  border-radius: 50%;
  box-sizing: content-box;
}

.dl-foot-value .dl-sprite-trait,
.dl-foot-value .dl-sprite-skill {
  width: 2rem;
  height: 2rem;
  flex: none;
  /* Sprites are not square; contain keeps their aspect inside the circle. */
  object-fit: contain;
}

/* Skill icons get the same round frame as traits, matching the game's UI. */
.dl-sprite-skill {
  padding: 0.15rem;
  background: radial-gradient(circle at 50% 35%,
              color-mix(in srgb, var(--dl-flame-core) 22%, transparent),
              var(--pm-bg-raised) 70%);
  border: 1px solid color-mix(in srgb, var(--dl-flame-core) 40%, transparent);
  border-radius: 50%;
  box-sizing: content-box;
}

/* ------------------------------------------------- chrome corrections */
/* The brand link inherited the default anchor colour, reading as a stray
   hyperlink rather than the site's identity. */
.kb-brand,
.kb-brand:hover { color: var(--md-default-fg-color, inherit); text-decoration: none; }

.kb-brand-name {
  font-weight: var(--pm-weight-bold);
  color: var(--kb-brand-text);
  /* The tabs beside it compete for the same row; without this the name wraps
     onto a second line and pushes the header out of shape. */
  white-space: nowrap;
}

/* Heading permalinks: present for deep links, but muted until hovered. */
.kb-content .headerlink {
  margin-left: 0.35rem;
  color: inherit;
  text-decoration: none;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.kb-content h1:hover .headerlink,
.kb-content h2:hover .headerlink,
.kb-content h3:hover .headerlink,
.kb-content .headerlink:focus-visible { opacity: 0.45; }

/* The hero heading exists so the page's table of contents lists it and the
   scrollspy can anchor on it; the name is shown by the card itself. */
.dl-card-heading {
  margin: 0;
  padding: 0;
  font-size: 0;
  line-height: 0;
  /* Offset the anchor so a jump does not hide the card under the header. */
  scroll-margin-top: 5rem;
}

/* Deeper TOC levels indent, so hero entries read as belonging to the section. */
.kb-toc-item[data-level="3"] { padding-left: 0.75rem; }
.kb-toc-item[data-level="4"] { padding-left: 1.5rem; }

/* ------------------------------------------------------ sticky chrome */
/* Sidebar and contents list run from below the chrome to the bottom of the
   viewport, scrolling their own overflow rather than being clipped. */
/* The base stylesheet hides the contents list below 1200px and the sidebar
   below 768px; `display` is set only above those widths so those rules, which
   load earlier, are not overridden. */
@media (min-width: 1201px) {
  .kb-toc { display: flex; }
}

.kb-toc-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  min-height: 0;
}

/* Anchors must clear the header and tab bar when jumped to. */
.dl-card-heading,
.kb-content :is(h1, h2, h3, h4)[id] {
  scroll-margin-top: calc(var(--kb-sticky-offset, 6.75rem) + 1rem);
}

/* -------------------------------------------------- contents rail */
/* A vertical rule runs down the nested entries; the segment beside the
   current one lights up, so position within the page is visible at a glance. */
.kb-toc-item[data-level="2"],
.kb-toc-item[data-level="3"],
.kb-toc-item[data-level="4"] {
  position: relative;
}

.kb-toc-item[data-level="2"]::before,
.kb-toc-item[data-level="3"]::before,
.kb-toc-item[data-level="4"]::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--pm-border-subtle);
  border-radius: 1px;
  transition: background 0.15s ease;
}

.kb-toc-item[data-level="3"]::before { left: 0.75rem; }
.kb-toc-item[data-level="4"]::before { left: 1.5rem; }

/* The active entry's segment takes the brand colour. */
.kb-toc-item:has(> .kb-toc-link.active)::before {
  background: var(--kb-brand);
}

.kb-toc-link.active { font-weight: var(--pm-weight-semibold); }

/* Nested entries clear the rule. */
.kb-toc-item[data-level="3"] > .kb-toc-link { padding-left: 1.5rem; }
.kb-toc-item[data-level="4"] > .kb-toc-link { padding-left: 2.25rem; }

/* --------------------------------------------------------- topbar tabs */
.kb-topbar-tab {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
}

.kb-tab-icon {
  width: 1rem;
  height: 1rem;
  image-rendering: pixelated;
  object-fit: contain;
  opacity: 0.65;
  transition: opacity 0.15s ease;
}

.kb-topbar-tab:hover .kb-tab-icon,
.kb-topbar-tab.active .kb-tab-icon { opacity: 1; }

/* ------------------------------------------------------------ tooltips */
.dl-tooltip {
  position: absolute;
  z-index: 300;
  max-width: 20rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.55rem 0.7rem;
  pointer-events: none;
  background: var(--pm-page-bg);
  border: 1px solid var(--kb-brand);
  border-radius: 0.45rem;
  box-shadow: 0 6px 20px #00000055;
}

.dl-tooltip[hidden] { display: none; }

.dl-tooltip-title {
  font-size: 0.8rem;
  font-weight: var(--pm-weight-bold);
  color: var(--kb-brand-text);
}

.dl-tooltip-body {
  font-size: 0.76rem;
  line-height: var(--pm-leading-snug);
  opacity: 0.85;
}

[data-tip-title] { cursor: help; }

/* --------------------------------------------------------- item cards */
.dl-itemcard {
  margin: 1rem 0 1.5rem;
  overflow: hidden;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.7rem;
}

/* Monster cards are hero cards with four stats instead of six, souls where
   the hero shows Max Mana, and a tier stripe instead of a rarity one. */
.dl-monstercard {
  margin: 1.25rem 0;
  overflow: hidden;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-left: 3px solid var(--pm-border-subtle);
  border-radius: 0.7rem;
}

.dl-monstercard.dl-monster-normal { border-left-color: var(--dl-common); }
.dl-monstercard.dl-monster-elite { border-left-color: var(--dl-rare); }
.dl-monstercard.dl-monster-boss { border-left-color: var(--dl-legendary); }
.dl-monstercard.dl-monster-summon { border-left-color: var(--dl-uncommon); }

/* Four stats share the row a hero splits into three. */
.dl-statrow-four {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.35rem;
}

@media (max-width: 60em) {
  .dl-statrow-four { grid-template-columns: repeat(2, 1fr); }
}

.dl-card-tags { display: flex; gap: 0.3rem; flex-wrap: wrap; }

.dl-tag {
  padding: 0.1rem 0.45rem;
  font-size: 0.66em;
  font-weight: var(--pm-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--kb-brand-text);
  border: 1px solid color-mix(in srgb, var(--kb-brand) 45%, transparent);
  border-radius: 2rem;
}

.dl-item-body {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  padding: 0.8rem;
  align-items: start;
}

.dl-item-main { min-width: 0; }

/* Item sprites are around 23px; scaling them far beyond that dilutes the
   pixel art, so the frame stays close to their native size. */
.dl-item-body .dl-card-art { padding: 0.5rem; }
.dl-item-body .dl-card-portrait { width: 2.9rem; height: 2.9rem; }
.dl-item-body .dl-statgrid { padding: 0 0 0.5rem; }
.dl-item-body .dl-card-foot { padding: 0; grid-template-columns: 1fr; }

/* Grants vary in number, so the row flows instead of forcing three columns. */
.dl-statrow-auto {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
}

/* A card with a single stat would stretch that one cell across the whole
   card; the cells keep their width and sit together instead. */
.dl-statrow-auto:has(> :only-child) {
  grid-template-columns: minmax(8rem, 14rem);
  justify-content: start;
}

/* --------------------------------------------------------- tier stepper */
.dl-tierbtn {
  padding: 0.25rem 0.6rem;
  font: inherit;
  font-size: 0.72em;
  font-weight: var(--pm-weight-medium);
  color: inherit;
  cursor: pointer;
  background: var(--pm-bg-inset);
  border: 1px solid var(--pm-border);
  border-radius: 0.35rem;
  opacity: 0.5;
  transition: opacity 0.15s ease, border-color 0.15s ease;
}

.dl-tierbtn:hover { opacity: 0.85; }

.dl-tierbtn.is-active {
  opacity: 1;
  border-color: var(--kb-brand);
  color: var(--kb-brand-text);
}

.dl-tierbtn:focus-visible { outline: 2px solid var(--kb-brand); outline-offset: 2px; }
.dl-tierpanel[hidden] { display: none; }

@media (max-width: 40em) {
  .dl-item-body { grid-template-columns: 1fr; justify-items: center; }
  .dl-item-main { width: 100%; }
}

/* Hero chips on the traits page: each links to that hero's card. */
.dl-hero-chip {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  padding: 0.25rem 0.55rem 0.25rem 0.3rem;
  font-size: 0.78em;
  color: inherit;
  text-decoration: none;
  background: var(--pm-bg-raised);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 2rem;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.dl-hero-chip:hover {
  border-color: var(--kb-brand);
  background: var(--pm-hover-bg);
}

.dl-chip-art {
  width: 1.4rem;
  height: 1.4rem;
  image-rendering: pixelated;
  object-fit: contain;
}

.dl-gem-name {
  margin: 0.4rem 0 0;
  font-size: 0.78em;
  text-align: center;
  opacity: 0.6;
}

.dl-itemcard .dl-chips { gap: 0.3rem; }

/* ------------------------------------------------ unified header bar */
/* Section tabs share the header rather than occupying a second bar, and the
   sidebar runs the full height beside them. */
.kb-header {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  /* Above the tab bar below it: the language menu opens downwards from here,
     and a header stacked under that bar has its menu clipped by it. */
  z-index: 50;
}

.kb-header-left {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  min-width: 0;
  flex: 1;
}

.kb-tabs {
  display: flex;
  gap: 0.15rem;
  align-items: center;
  /* Fills its own bar. Between the point the tabs stop fitting and the point
     the menu button takes over, the bar scrolls rather than clipping. */
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.kb-tabs::-webkit-scrollbar { display: none; }

/* The tab bar: its own row under the header, so the tabs keep their icons at
   every width the bar is shown and never compete with the search box. */
.kb-topbar {
  position: sticky;
  top: var(--kb-header-h, 3.75rem);
  z-index: 40;
  display: flex;
  align-items: center;
  padding: 0 2rem;
  background: var(--kb-sidebar-bg);
  border-bottom: 1px solid var(--pm-border-subtle);
}

.kb-topbar .kb-topbar-tab {
  padding: 0.5rem 0.7rem;
  font-size: 0.82rem;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.kb-topbar .kb-topbar-tab:hover { color: var(--kb-brand-text); }

.kb-topbar .kb-topbar-tab.active {
  color: var(--kb-brand-text);
  border-bottom-color: var(--kb-brand);
}

/* With the row to themselves the tabs only tighten, never drop their icons. */
@media (max-width: 900px) {
  .kb-topbar { padding: 0 1rem; }
  .kb-topbar .kb-topbar-tab { padding: 0.5rem 0.5rem; font-size: 0.78rem; }
}

/* Both bars stack, so anything sticky below them clears the pair. */
.kb-sidebar {
  top: var(--kb-sticky-offset, 6.75rem);
  height: calc(100vh - var(--kb-sticky-offset, 6.75rem));
  overflow-y: auto;
  overscroll-behavior: contain;
}

.kb-toc {
  top: var(--kb-sticky-offset, 6.75rem);
  max-height: calc(100vh - var(--kb-sticky-offset, 6.75rem));
  overflow: hidden;
  flex-direction: column;
}

.dl-card-heading,
.kb-content :is(h1, h2, h3, h4)[id] {
  scroll-margin-top: calc(var(--kb-sticky-offset, 6.75rem) + 1rem);
}

/* On a row of their own the tabs survive far narrower screens; only below
   this does the menu button take over and open the same map in full. */
.kb-mobile-nav { display: none; }

@media (max-width: 700px) {
  .kb-topbar { display: none; }

  /* The base theme only reveals the button at 768px, which would leave a
     range with the tabs gone and nothing in their place. */
  .kb-mobile-nav-btn { display: flex; align-items: center; }

  .kb-mobile-nav {
    position: fixed;
    top: var(--kb-header-h, 3.75rem);
    left: 0;
    z-index: 60;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    width: min(19rem, 82vw);
    height: calc(100vh - var(--kb-header-h, 3.75rem));
    padding: 0.9rem 0.75rem 2rem;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* A theme token, not a fixed colour: a dark fallback here rendered
       grey-on-black over the light theme. This is the sidebar in another
       shape, so it takes the sidebar's background. */
    background: var(--kb-sidebar-bg);
    border-right: 1px solid var(--pm-border-subtle);
    transform: translateX(-100%);
    transition: transform 0.2s ease;
  }

  body.kb-mobile-open .kb-mobile-nav { transform: translateX(0); }

  body.kb-mobile-open .kb-mobile-nav-backdrop {
    position: fixed;
    inset: var(--kb-header-h, 3.75rem) 0 0;
    z-index: 55;
    display: block;
    background: rgba(0, 0, 0, 0.5);
  }

  /* The panel scrolls on its own, so the page behind it must not. */
  body.kb-mobile-open { overflow: hidden; }

  .kb-mobile-group {
    padding: 0.85rem 0.55rem 0.3rem;
    font-size: 0.66rem;
    font-weight: var(--pm-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 0.45;
  }

  .kb-mobile-link {
    padding: 0.55rem 0.6rem;
    font-size: 0.9rem;
    color: inherit;
    text-decoration: none;
    border-radius: 0.4rem;
  }

  .kb-mobile-link:hover { background: var(--pm-hover-bg); }

  .kb-mobile-link.active {
    color: var(--kb-brand-text);
    background: color-mix(in srgb, var(--kb-brand) 12%, transparent);
  }
}

.dl-tiercurrent {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 5.5rem;
  font-size: 0.78rem;
  font-weight: var(--pm-weight-semibold);
  color: var(--kb-brand-text);
}

.dl-tiername[hidden] { display: none; }
.dl-tierbar { display: inline-flex; gap: 0.4rem; align-items: center; }

/* An item's unique effect is what distinguishes it; the stat bonuses beside
   it are already shown as cells. */
.dl-foot-unique {
  background: color-mix(in srgb, var(--kb-brand) 8%, var(--pm-bg-inset));
  border-color: color-mix(in srgb, var(--kb-brand) 35%, transparent);
}

.dl-foot-unique .dl-foot-label { color: var(--kb-brand-text); opacity: 0.9; }

/* A caveat on the effect rather than part of it. The game greys this text
   out, so it stays quieter than the field it qualifies and spans the footer
   when that footer has two columns. */
.dl-foot-limit {
  grid-column: 1 / -1;
  background: transparent;
  border-style: dashed;
}

.dl-foot-limit .dl-foot-desc { font-style: italic; opacity: 0.6; }

.dl-tag-unique {
  color: var(--dl-flame-core);
  border-color: color-mix(in srgb, var(--dl-flame-core) 50%, transparent);
}

.dl-uncertain {
  color: #fbbf24;
  font-style: italic;
  opacity: 0.8;
}

/* An item's trait requirement sits under its artwork, shown the way the
   traits page shows it, rather than as a tag in the header. */
.dl-card-side {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: center;
}

.dl-item-trait {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  align-items: center;
  font-size: 0.72em;
  font-weight: var(--pm-weight-semibold);
  color: var(--kb-brand-text);
  text-align: center;
  max-width: 5rem;
}

/* ------------------------------------------------------ achievements */
/* Levels the reader ticks off, with their rewards adding up below. */
.dl-ach {
  margin: 0 0 0.9rem;
  background: var(--pm-bg-subtle);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.6rem;
  overflow: hidden;
}

.dl-ach-head {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 0.75rem;
  font-size: 0.88rem;
  font-weight: var(--pm-weight-semibold);
  background: var(--pm-bg-inset);
  border-bottom: 1px solid var(--pm-border-subtle);
}

.dl-ach-title {
  display: flex;
  gap: 0.45rem;
  align-items: center;
  min-width: 0;
}

/* Takes or gives up every level of its achievement at once. */
.dl-ach-all {
  display: flex;
  flex: none;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.68rem;
  font-weight: var(--pm-weight-normal);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  opacity: 0.65;
}

.dl-ach-all:hover { opacity: 1; }

/* The header and the rows share one grid so their columns line up. */
.dl-ach > :is(.dl-ach-cols, .dl-ach-row) {
  display: grid;
  grid-template-columns: 1.6rem 5.5rem 1fr 4rem;
  gap: 0.6rem;
  align-items: center;
  padding: 0.4rem 0.75rem;
}

.dl-ach-cols {
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.5;
}

.dl-ach-row {
  font-size: 0.84rem;
  cursor: pointer;
  border-top: 1px solid var(--pm-border-subtle);
}

.dl-ach-row:hover { background: var(--pm-hover-bg); }

/* The native checkbox is replaced by a drawn box: the browser default cannot
   be styled to match the rest of the page. The input stays in the markup and
   keeps focus and keyboard behaviour; only its painting is taken over. */
.dl-ach-tick {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.dl-ach-box {
  position: relative;
  display: inline-block;
  flex: none;
  width: 1.05rem;
  height: 1.05rem;
  background: var(--pm-bg-raised);
  border: 1px solid var(--pm-border);
  border-radius: 0.3rem;
  transition: background 0.15s ease, border-color 0.15s ease;
}

/* The tick itself: two strokes rotated into a check. */
.dl-ach-box::after {
  position: absolute;
  top: 0.08rem;
  left: 0.32rem;
  width: 0.28rem;
  height: 0.58rem;
  content: "";
  border: solid #fff;
  border-width: 0 2px 2px 0;
  opacity: 0;
  transform: rotate(45deg) scale(0.7);
  transition: opacity 0.12s ease, transform 0.12s ease;
}

.dl-ach-tick:checked + .dl-ach-box {
  background: var(--kb-brand);
  border-color: var(--kb-brand);
}

.dl-ach-tick:checked + .dl-ach-box::after {
  opacity: 1;
  transform: rotate(45deg) scale(1);
}

/* Some levels done, not all: a dash rather than a tick. */
.dl-ach-tick:indeterminate + .dl-ach-box {
  background: var(--kb-brand);
  border-color: var(--kb-brand);
}

.dl-ach-tick:indeterminate + .dl-ach-box::after {
  top: 0.42rem;
  left: 0.2rem;
  width: 0.55rem;
  height: 0;
  opacity: 1;
  border-width: 0 0 2px;
  transform: none;
}

.dl-ach-tick:focus-visible + .dl-ach-box {
  outline: 2px solid var(--kb-brand);
  outline-offset: 2px;
}

.dl-ach-row:hover .dl-ach-tick:not(:checked) + .dl-ach-box {
  border-color: var(--kb-brand);
}
.dl-ach-goal { font-variant-numeric: tabular-nums; opacity: 0.8; }
.dl-ach-reward { color: var(--dl-flame-core); font-weight: var(--pm-weight-semibold); }
html:not(.dark) .dl-ach-reward { color: #b45309; }
.dl-ach-elixir { font-variant-numeric: tabular-nums; text-align: right; opacity: 0.6; }

/* A ticked row recedes: what is left to earn is what the reader is reading. */
.dl-ach-row:has(.dl-ach-tick:checked) { opacity: 0.55; }

/* The running total follows the reader down the list. */
.dl-ach-total {
  position: sticky;
  bottom: 0;
  margin-top: 1rem;
  padding: 0.7rem 0.85rem;
  background: var(--kb-sidebar-bg);
  border: 1px solid var(--pm-border);
  border-radius: 0.6rem;
}

.dl-ach-total-head {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.6;
}

.dl-ach-clear {
  padding: 0.2rem 0.5rem;
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.3rem;
}

.dl-ach-clear:hover { background: var(--pm-hover-bg); }

.dl-ach-sums {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.dl-ach-sum {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.4rem 0.6rem;
  background: var(--pm-bg-inset);
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.4rem;
}

.dl-ach-sum-stat {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.55;
}

.dl-ach-sum-value {
  font-size: 0.92rem;
  font-weight: var(--pm-weight-semibold);
  color: var(--dl-flame-core);
  font-variant-numeric: tabular-nums;
}

html:not(.dark) .dl-ach-sum-value { color: #b45309; }
.dl-ach-empty { font-size: 0.82rem; opacity: 0.55; }

@media (max-width: 40em) {
  .dl-ach > :is(.dl-ach-cols, .dl-ach-row) {
    grid-template-columns: 1.4rem 4.5rem 1fr 3rem;
    gap: 0.4rem;
    font-size: 0.78rem;
  }
}

/* The goal still to reach, named in the heading and moved along as levels
   are ticked off. */
.dl-ach-next {
  color: var(--dl-flame-core);
  font-variant-numeric: tabular-nums;
}

html:not(.dark) .dl-ach-next { color: #b45309; }

/* Nothing left to reach: the figure is the achievement's last goal. */
.dl-ach-next.dl-ach-done { color: inherit; opacity: 0.55; }

/* The reward follows the pattern of the achievements checked in game, but
   this one has not been seen on screen. */
.dl-ach-unconfirmed {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  margin-left: 0.4rem;
  font-size: 0.68rem;
  font-weight: var(--pm-weight-semibold);
  color: #b45309;
  cursor: help;
  background: color-mix(in srgb, #b45309 12%, transparent);
  border-radius: 50%;
}

.dark .dl-ach-unconfirmed { color: #fbbf24; background: color-mix(in srgb, #fbbf24 14%, transparent); }

/* The three modifier shapes are read off differently by the game, so the
   total keeps them apart on sight as well as in the arithmetic. */
.dl-ach-sum-flat { border-left: 2px solid var(--dl-uncommon); }
.dl-ach-sum-pct { border-left: 2px solid var(--dl-rare); }
.dl-ach-sum-mult { border-left: 2px solid var(--dl-epic); }
.dl-ach-sum-elixir { border-left: 2px solid var(--dl-gold); }

/* Under each trait's levels: what the whole trait costs, and what of that is
   still to pay. Per trait rather than per page, since research is bought one
   trait at a time. */
.dl-res-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  align-items: center;
  justify-content: flex-end;
  padding: 0.55rem 0.75rem;
  background: var(--pm-bg-inset);
  border-top: 1px solid var(--pm-border-subtle);
}

.dl-res-foot-item { display: flex; gap: 0.45rem; align-items: center; }

/* The reset stands alone: research needs no page-wide total, but a selection
   still has to be clearable in one go. */
.dl-res-reset { display: flex; justify-content: flex-end; margin: 1.25rem 0; }

.dl-res-foot-label {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.55;
}

.dl-res-foot .dl-res-price {
  font-size: 0.9rem;
  font-weight: var(--pm-weight-semibold);
  font-variant-numeric: tabular-nums;
}

.dl-res-foot-left .dl-res-price { color: var(--kb-brand-text); }

/* Nothing left to pay for this trait. */
.dl-res-foot-left.dl-res-done .dl-res-price { color: inherit; opacity: 0.45; }

/* ------------------------------------------------- content links & tables */
/* Neither had a style of their own, so links fell back to the browser's blue
   and tables to its bare borders -- both at odds with the rest of the page. */
.kb-content a:not(.headerlink):not(.dl-chip):not(.dl-card-link) {
  color: var(--kb-brand-text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease;
}

.kb-content a:not(.headerlink):not(.dl-chip):not(.dl-card-link):hover {
  border-bottom-color: currentcolor;
}

.kb-content table {
  width: 100%;
  margin: 1.25rem 0;
  font-size: 0.9em;
  border-collapse: collapse;
  border: 1px solid var(--pm-border-subtle);
  border-radius: 0.6rem;
  /* Rounded corners need the overflow clipped, which a table only honours
     when it is not collapsing its own borders into the cells. */
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
}

.kb-content thead th {
  padding: 0.6rem 0.8rem;
  font-size: 0.82em;
  font-weight: var(--pm-weight-semibold);
  text-align: left;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--pm-bg-inset);
  border-bottom: 1px solid var(--pm-border-subtle);
  opacity: 0.75;
}

.kb-content tbody td {
  padding: 0.6rem 0.8rem;
  vertical-align: top;
  border-top: 1px solid var(--pm-border-subtle);
}

.kb-content tbody tr:first-child td { border-top: 0; }
.kb-content tbody tr:hover { background: var(--pm-hover-bg); }

/* A table wider than the page scrolls inside itself rather than pushing the
   whole page sideways. */
.kb-content .md-typeset__table,
.kb-content table { display: table; }

/* Research reuses the achievement list; only its heading differs, carrying
   the trait's icon and what its upgrade raises. */
.dl-res-raises {
  font-size: 0.7rem;
  font-weight: var(--pm-weight-normal);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.5;
}

.dl-res .dl-ach-goal { text-align: center; }

/* Research costs name two currencies, so the last column takes the room the
   achievement list gives to a bare elixir figure. */
.dl-res > :is(.dl-ach-cols, .dl-ach-row) {
  grid-template-columns: 1.6rem 3.5rem 1fr 9rem;
}

.dl-res .dl-ach-elixir {
  display: flex;
  gap: 0.3rem;
  align-items: center;
  justify-content: flex-end;
  white-space: nowrap;
}

/* Each currency shows its own icon; the two are alternatives, so the word
   between them says so rather than a separator that reads as "and". */
.dl-res-price { display: inline-flex; gap: 0.25rem; align-items: center; }
.dl-res-coin { width: 1.15rem; height: 1.15rem; flex: none; }
.dl-res-or { font-size: 0.72em; opacity: 0.5; }

/* The trait shown as a hero card shows it, above its upgrade levels. */
.dl-res-trait {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.7rem 0.75rem;
  border-bottom: 1px solid var(--pm-border-subtle);
}

.dl-res-trait .dl-foot-value { font-weight: var(--pm-weight-semibold); }
.dl-res-trait .dl-foot-desc { margin: 0; }

/* A figure the reader's research has raised above its base. */
.dl-res-raised {
  padding: 0 0.2rem;
  border-radius: 0.2rem;
  background: color-mix(in srgb, var(--kb-brand) 16%, transparent);
}

@media (max-width: 40em) {
  .dl-res > :is(.dl-ach-cols, .dl-ach-row) {
    grid-template-columns: 1.4rem 2.5rem 1fr 7rem;
  }
}
