:root {
  /* Compatibility aliases keep the calculator's descriptive local token
     names while sourcing the palette from /tokens.css like the other apps. */
  --bg: var(--ground);
  --border: var(--edge);
  --text: var(--ink);
  /* --good and --bad were declared here, and were the site's only definition of
     "this value is good" / "this one is not" — while the identical red was also
     hand-written into apps/shared/chrome.css and site/index.html as the Alpha
     pill's background. One meaning, three definitions. Both are in
     site/tokens.css now. The rarity colours below stay: those are game data
     rather than a status, and the test that pins them reads this file. */
  /* The game's own rarity colours, the same ones the loot filter paints its
     swatches with. A unique and a mythic unique are different rarities and
     the page colours them apart, which is also the only place it says which
     of the two an item is without opening a disclosure.

     These are derived values, not chosen ones: lib/rarity-colors.mjs reads them
     out of the snapshot's own arFontColorsExt table and apps/loot-filter/data.json
     carries the result. A stylesheet cannot import that, so they are transcribed
     here and tests/game-data.test.mjs pins the transcription — change the game's
     palette and this block fails by name rather than drifting quietly, which is
     the same arrangement 404.html's inline token copy already has. */
  --legendary: #ff8000;
  --unique: #dca779;
  --mythic: #dc9bf2;
}
body {
  min-height: 100vh;
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font:
    16px/1.5 "Segoe UI",
    system-ui,
    sans-serif;
}
/* The site rail, page header, and footer build stamp are shared/chrome.css,
   linked in index.html right after tokens.css. .pagehead h1 there already
   supplies this page's title typography (font, size, letter-spacing, margin);
   this app's body font is the same 16px/1.5 as prism-crafting's, so the
   heading's line-height matches it too without repeating it here. Only this
   app's extra focus-visible selectors live below. */
.pagehead h1 {
  /* Stated locally as well as in shared chrome so this calculator's title
     cannot be masked by a page-specific cascade. */
  font-family: Outfit, "Segoe UI", system-ui, sans-serif;
}
button:focus-visible,
input:focus-visible,
select:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.wrap {
  width: min(var(--page-width), 100%);
  margin: 0 auto;
  padding: 0 20px 28px;
}
/* This page is an alpha test version — flagged loudly rather than quietly, so
   nobody mistakes an in-progress number for a verified one.

   The pill itself is apps/shared/chrome.css, which every page that draws this
   marker loads; only what is different beside an <h1> is stated here. The full
   copy that used to live here is why the homepage's card drew the word "Alpha"
   as bare serif text: it was styled by the rail's rule or by this one, and the
   card matched neither. */
.alpha-tag {
  vertical-align: middle;
  margin-left: 0.5em;
  padding: 0.12em 0.55em;
  /* Relative, not a scale step, and deliberately: this pill sits beside the
     page <h1>, so it has to track a heading that is itself a clamp(). */
  font-size: 0.42em;
  line-height: 1.6;
}
/* The rail's own copy of this tag is sized in apps/shared/chrome.css: the rule
   above is relative to an <h1> (0.42em), which is meaningless in a 12px tab. */
.alpha-banner {
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid var(--bad);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: rgb(239 68 68 / 12%);
  color: #ffd9d9;
  font-size: var(--fs-base);
  line-height: 1.5;
}
.alpha-banner strong {
  color: #fff;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.icon-sprite {
  display: none;
}
/* .noscript is apps/shared/base.css, alongside .bootfail. */
.layout {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  width: 100%;
}
.top-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem);
  align-items: start;
  gap: 1.5rem;
}
.profile-loader {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.profile-loader h2,
.profile-loader p {
  margin: 0;
}
.profile-loader h2 {
  font-size: var(--fs-base);
}
.profile-loader div > p,
.profile-status {
  color: var(--muted);
  font-size: var(--fs-xs);
}
.profile-loader select {
  width: 100%;
}
.profile-actions {
  display: flex;
  gap: 0.5rem;
}
.profile-actions button {
  flex: 1;
}
/* .sr-only lives in ../shared/chrome.css: three pages needed it once the form
   labels were associated, and a fourth copy here is how the four localStorage
   guards drifted before apps/shared/safe-storage.js existed. */
#form {
  column-count: 3;
  column-gap: 1.5rem;
}
#form fieldset,
#form > .row {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}
@media (max-width: 1280px) {
  #form {
    column-count: 2;
  }
}
@media (max-width: 860px) {
  /* The rail matches this padding at the same width, from chrome.css — it folds
     into its mobile drawer on exactly this breakpoint. */
  .wrap {
    padding-right: 14px;
    padding-left: 14px;
  }
  #form {
    column-count: 1;
  }
  .top-grid {
    grid-template-columns: 1fr;
  }
}
fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  margin: 0 0 1rem;
  padding: 0.75rem 1rem 1rem;
}
/* A legend's own box floats over the fieldset's top border at whatever width
   its text needs, so a button positioned by the fieldset (or by absolute
   coordinates) drifts out of line with it and can overlap long titles.
   Stretching the legend to the full width and laying its own children out
   with flex keeps the button pinned to the same line as the title, flush
   with the right edge, on every fieldset regardless of title length. */
legend {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  font-size: var(--fs-xl);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: color-mix(in srgb, var(--accent) 68%, var(--text));
  text-shadow: 0 0 0.45rem color-mix(in srgb, currentColor 35%, transparent);
  padding: 0 0.35rem;
}
.group-reset {
  flex: none;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  text-shadow: none;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: var(--radius-md);
  padding: 0.2rem 0.55rem;
  font-size: var(--fs-xs);
  cursor: pointer;
}
.group-reset:hover {
  border-color: var(--bad);
  color: var(--bad);
}
.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0.4rem 0;
}
/* Same author-`display`-beats-UA-`[hidden]` gotcha as .note-body below. */
.row[hidden] {
  display: none;
}
.row label {
  flex: 1;
  font-size: var(--fs-base);
}
.row .hint {
  display: block;
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-top: 0.1rem;
}
.row input[type="number"],
.row input[type="text"],
.row select {
  width: 9rem;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-md);
  padding: 0.3rem 0.5rem;
  font-size: var(--fs-base);
  text-align: right;
}
.row input[type="checkbox"] {
  width: 1.1rem;
  height: 1.1rem;
}
.range-label {
  flex: 1;
  font-size: var(--fs-base);
}
.range-label .hint {
  display: block;
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-top: 0.1rem;
}
.range-inputs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  width: 14rem;
}
.row .range-inputs label {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.25rem;
  flex: none;
  font-size: var(--fs-xs);
}
.row .range-inputs input[type="number"] {
  width: 100%;
}
.slider-cell {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 9rem;
}
.slider-cell input[type="range"] {
  flex: 1;
  min-width: 0;
  accent-color: var(--accent);
}
.slider-cell output {
  width: 3.2rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: var(--fs-sm);
}
/* One block shape for every equippable power the page names — aspects and
   uniques share it. --item-color is the item's rarity, so the same rules
   paint a legendary aspect orange and a mythic unique purple without a
   second copy of them. */
.aspect {
  --item-color: var(--legendary);
  padding: 0.2rem 0;
  border-top: 1px dashed var(--border);
}
.aspect.rarity-unique {
  --item-color: var(--unique);
}
.aspect.rarity-mythic {
  --item-color: var(--mythic);
}
.aspect:first-child {
  padding-top: 0;
  border-top: none;
}
.aspect select {
  width: 12rem;
  text-align: left;
}
/* Aspects are legendary affixes, so they carry the rarity colour the rest
   of the repo uses for them rather than the page's generic accent. */
.aspect .slider-cell input[type="range"],
.aspect input[type="checkbox"] {
  accent-color: var(--item-color);
}
legend.legendary {
  color: var(--legendary);
}
legend.unique {
  color: var(--unique);
}
legend .header-blue {
  color: var(--accent);
}
legend .mythic {
  color: var(--mythic);
}
.required-note {
  margin: -0.1rem 0 0.5rem;
  color: var(--muted);
  font-size: var(--fs-xs);
}
.required-note span,
.required-mark {
  color: var(--bad);
  font-weight: 700;
}
/* Required stat inputs start unfilled on purpose (no prefilled value) so they
   don't read as an example build. Colour them red until the visitor enters
   their own number; :invalid clears once a value satisfies min/max/required. */
.row input[type="number"]:required:invalid {
  border-color: var(--bad);
  color: var(--bad);
}
.unique-add-row select {
  flex: 1;
  width: auto;
  text-align: left;
}
.unique-remove {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: var(--radius-md);
  padding: 0.2rem 0.55rem;
  font-size: var(--fs-xs);
  cursor: pointer;
}
.unique-remove:hover {
  border-color: #e06666;
  color: #e06666;
}
#uniqueEmptyNote:not(.showing) {
  display: none;
}
.fixed-value {
  width: 9rem;
  padding: 0.3rem 0;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: var(--fs-base);
  text-align: right;
}
.results {
  position: sticky;
  top: 1.5rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1rem 1.25rem;
}
.results h2 {
  font-size: var(--fs-lg);
  margin: 0 0 0.75rem;
}
.results table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
}
.results td {
  padding: 0.25rem 0;
  border-bottom: 1px dashed var(--border);
}
.results td:first-child {
  color: var(--muted);
}
.results td:last-child {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.results tr.total td {
  border-bottom: none;
  padding-top: 0.6rem;
  font-size: var(--fs-xl);
  color: var(--good);
  font-weight: 600;
}
.section-title {
  margin: 1rem 0 0.25rem;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.error {
  color: #e06666;
  font-size: var(--fs-base);
  margin-top: 0.5rem;
}
/* Set while a calculation is refused. The figures below are the last ones that
   resolved, so they stay readable for comparison but must not look current;
   .error is excluded because it is the line saying why they are not. */
.results.stale > *:not(.error) {
  opacity: 0.35;
}
.field-group {
  margin: 0.5rem 0 0.7rem;
}
.group-label {
  font-size: var(--fs-base);
  margin-bottom: 0.2rem;
}
.skill-toggle {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}
.skill-toggle label {
  flex: 1;
  cursor: pointer;
}
.skill-toggle input[type="checkbox"] {
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
}
.group-heading {
  margin: 0.55rem 0 0.15rem;
  padding-top: 0.3rem;
  border-top: 1px dashed var(--border);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.group-heading:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}
.field-group .row label {
  font-size: var(--fs-base);
}
.stat-key {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.45rem;
  margin: 0 0 0.65rem;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--bg) 62%, transparent);
}
.stat-key-title {
  margin-right: 0.15rem;
  color: var(--muted);
  font-size: var(--fs-2xs);
}
/* Every role has a named chip as well as a colour: this remains readable when
   colour is not available, while the left rail makes the same distinction easy
   to scan through a long column of otherwise similar number inputs. */
.stat-type {
  display: inline-flex;
  align-items: center;
  width: max-content;
  margin-left: 0.35rem;
  padding: 0.03rem 0.32rem;
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  color: var(--stat-role-color);
  font-size: var(--fs-3xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  line-height: 1.5;
  text-transform: uppercase;
  vertical-align: middle;
  white-space: nowrap;
}
.stat-key .stat-type {
  margin-left: 0;
}
.stat-role-additive {
  --stat-role-color: #78b9e6;
}
.stat-role-multiplier {
  --stat-role-color: #dc9bf2;
}
.stat-role-critical {
  --stat-role-color: #f1bf6c;
}
.stat-role-condition {
  --stat-role-color: #7fd18a;
}
.row.stat-role {
  padding-left: 0.45rem;
  border-left: 2px solid var(--stat-role-color);
}
.group-total {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
  margin-top: 0.2rem;
}
/* Where a value came from used to be a recoloured label, which said "green"
   without saying what green meant. It is a badge now: it names itself, the
   label reads like every other label, and the two colours stay on the badge
   as the confidence signal. */
.ocr-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.22rem;
  margin-left: 0.4rem;
  padding: 0 0.34rem;
  border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, currentColor 12%, transparent);
  font-size: var(--fs-3xs);
  font-weight: 600;
  letter-spacing: 0.07em;
  line-height: 1.6;
  white-space: nowrap;
  vertical-align: middle;
  cursor: help;
}
.ocr-badge.confirmed {
  color: var(--good);
}
.ocr-badge.tentative {
  color: var(--accent);
}
.ocr-badge-icon {
  width: 0.66rem;
  height: 0.66rem;
  flex: none;
}
.more-stats {
  margin-top: 0.4rem;
}
.more-stats summary {
  cursor: pointer;
  font-size: var(--fs-xs);
  color: var(--muted);
  padding: 0.2rem 0;
}
.more-stats summary:hover {
  color: var(--text);
}
.more-stats[open] summary {
  margin-bottom: 0.2rem;
}
.ocr-help {
  margin: 0 0 0.6rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.5;
}
.drop-zone {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  padding: 1rem;
  font-size: var(--fs-base);
  color: var(--muted);
}
.drop-zone.dragging {
  border-color: var(--accent);
  color: var(--text);
}
.ocr-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.55rem;
  font-size: var(--fs-xs);
  color: var(--muted);
}
.ocr-status {
  margin-top: 0.55rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  min-height: 1.1rem;
}
.ocr-status.failed {
  color: #e2706a;
}
.review {
  margin-top: 0.75rem;
}
.review table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.review th {
  text-align: left;
  font-weight: 500;
  color: var(--muted);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
  padding: 0.25rem 0.4rem;
}
.review td {
  border-bottom: 1px solid var(--border);
  padding: 0.3rem 0.4rem;
  vertical-align: top;
}
.review .raw {
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: var(--fs-xs);
  word-break: break-word;
}
.review tr.matched .target {
  color: var(--good);
}
.review tr.tentative .target {
  color: var(--accent);
}
.review tr.ignored td,
.review tr.unmatched .target {
  color: var(--muted);
}
.review input[type="number"] {
  width: 7rem;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-md);
  padding: 0.2rem 0.4rem;
  font-size: var(--fs-sm);
  text-align: right;
}
.review select {
  max-width: 22rem;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-md);
  padding: 0.2rem 0.3rem;
  font-size: var(--fs-xs);
}
.review .note {
  display: block;
  font-size: var(--fs-2xs);
  color: var(--muted);
  margin-top: 0.15rem;
}
#ocr-text {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-md);
  padding: 0.4rem 0.5rem;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: var(--fs-xs);
}
.review-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.7rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}
button {
  font: inherit;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-md);
  padding: 0.4rem 0.9rem;
  font-size: var(--fs-base);
  cursor: pointer;
}
button:hover {
  border-color: var(--accent);
}
/* A "?" that reveals its explanation in place rather than in a title
   tooltip. The provenance notes on this page are paragraphs, and a native
   tooltip truncates them, cannot be selected or copied, and never opens on
   touch — so every one of them is a real disclosure instead. */
.qmark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 1rem;
  padding: 0;
  margin-left: 0.3rem;
  border: none;
  border-radius: 50%;
  background: rgba(127, 127, 127, 0.25);
  color: var(--muted);
  font-family: inherit;
  font-size: var(--fs-2xs);
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
}
.qmark:hover,
.qmark[aria-expanded="true"] {
  background: var(--accent);
  color: var(--panel);
  border-color: transparent;
}
.note-body {
  display: block;
  margin: 0.4rem 0 0.2rem;
  padding-left: 0.6rem;
  border-left: 2px solid var(--border);
  font-size: var(--fs-xs);
  font-weight: 400;
  line-height: 1.55;
  color: var(--muted);
  /* Notes hang off small-caps labels as well as ordinary ones, and a
     paragraph must not inherit a heading's letter-spaced upper case. */
  text-transform: none;
  letter-spacing: normal;
}
/* An author `display` beats the UA sheet's `[hidden] { display: none }`, so
   without this every note renders open and the disclosures do nothing. */
.note-body[hidden] {
  display: none;
}
.note-body code {
  background: rgba(127, 127, 127, 0.15);
  padding: 0.05rem 0.3rem;
  border-radius: var(--radius-sm);
  font-size: 0.94em;
}
.note-body p {
  margin: 0 0 0.5rem;
}
.note-body p:last-child {
  margin-bottom: 0;
}

.tagline {
  max-width: 90rem;
  margin: 0.15rem 0 0.75rem;
  font-size: var(--fs-base);
  color: var(--muted);
}
.tagline code {
  background: rgba(127, 127, 127, 0.15);
  padding: 0.05rem 0.35rem;
  border-radius: var(--radius-sm);
  font-size: 0.82em;
}

.disclosure {
  max-width: 68rem;
  margin: 0 0 1rem;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.disclosure > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 1rem;
  font-size: var(--fs-base);
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}
.disclosure > summary::-webkit-details-marker {
  display: none;
}
.disclosure > summary::before {
  content: "▸";
  font-size: var(--fs-2xs);
}
.disclosure[open] > summary::before {
  content: "▾";
}
.disclosure > summary:hover {
  color: var(--text);
}
.disclosure-body {
  padding: 0 1rem 1rem;
  font-size: var(--fs-base);
  color: var(--muted);
  line-height: 1.55;
}
.disclosure-body code {
  background: rgba(127, 127, 127, 0.15);
  padding: 0.05rem 0.35rem;
  border-radius: var(--radius-sm);
  font-size: 0.82em;
}
.disclosure-body p {
  margin: 0 0 0.7rem;
}

.headline {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.headline .label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.headline .value {
  font-size: var(--fs-display);
  font-weight: 600;
  line-height: 1.15;
  color: var(--good);
  font-variant-numeric: tabular-nums;
}
.key-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.3rem 1.5rem;
  margin: 0.9rem 0 0.2rem;
}
.key-figures > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
/* Same author-`display`-beats-UA-`[hidden]` gotcha as .row[hidden] above. */
.key-figures > div[hidden] {
  display: none;
}
.key-figures .label {
  font-size: var(--fs-xs);
  color: var(--muted);
}
.key-figures .value {
  font-size: var(--fs-xl);
  font-variant-numeric: tabular-nums;
}

/* An aspect is one line until it is ticked. The verdict used to be a
   sentence under the name, which wrapped to three lines on the widest of
   them and made five aspects taller than the rest of the form; it is now
   a chip, and the sentence is the first thing its disclosure says. */
.aspect-head {
  gap: 0.5rem;
  margin: 0.2rem 0;
}
.aspect-head > label {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.1rem 0.4rem;
  color: var(--item-color);
}
.aspect-head > label > .note-body {
  flex-basis: 100%;
  color: var(--muted);
}
.aspect-verdict {
  font-size: var(--fs-3xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1.6;
  padding: 0 0.4rem;
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  background: none;
  white-space: nowrap;
}
.aspect-verdict.applies {
  color: var(--good);
}
.aspect-verdict.conditional {
  color: var(--accent);
}
.aspect-verdict.inapplicable {
  color: #e2706a;
}
/* Equipped and modelled, but contributing no damage term of its own — grey
   rather than red, because nothing is wrong with it. */
.aspect-verdict.indirect {
  color: var(--muted);
}
button.aspect-verdict {
  font-family: inherit;
  cursor: pointer;
}
button.aspect-verdict:hover,
button.aspect-verdict[aria-expanded="true"] {
  /* Not the generic button:hover accent — the chip's border is its own
     verdict colour and swapping it to amber would read as "conditional". */
  border-color: currentColor;
  background: color-mix(in srgb, currentColor 20%, transparent);
}
.aspect-roll {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.aspect-body {
  margin: 0 0 0.45rem;
  padding-left: 0.6rem;
  border-left: 2px solid var(--item-color);
}
/* A unique with no roll still unfolds — what it says is the whole point of
   ticking it — so the body has to read as prose, not as a stranded control. */
.aspect-body .body-note {
  margin: 0.3rem 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.aspect-body .row {
  margin: 0.25rem 0;
}

/* Over the Talisman's current Unique Charm slot count — visible caution, not a
   block: the page states the mismatch and lets the entered scenario stand, the
   same non-blocking treatment every other cross-field assumption on this page
   gets. */
#uniqueCharmSlotNote.over-cap {
  color: var(--accent);
  font-weight: 600;
}

/* Both sides of a pair of lines that cannot both be true of one hit. Same
   treatment and same reason as the Unique Charm note above: the page names the
   contradiction and leaves the entered scenario standing, because which side
   applies is the visitor's to say. Empty for as long as there is nothing to
   say, and taking no space while it is. */
#exclusiveStatNote {
  margin: 0.4rem 0 0;
  font-size: var(--fs-sm);
  color: var(--accent);
  font-weight: 600;
}
#exclusiveStatNote:empty {
  display: none;
}

/* An opt-in add-on rather than a section of the form: one line under the
   fieldsets until it is ticked, then the same left-ruled body an aspect
   unfolds. A fieldset would give it a panel and a heading, which is more
   weight than an optional scenario deserves. */
.opt-block {
  margin: 0 0 1rem;
}
.opt-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 0.15rem;
}
.opt-head > .note-body {
  flex-basis: 100%;
}
.opt-toggle {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: var(--fs-base);
  color: var(--muted);
  cursor: pointer;
}
.opt-toggle:hover {
  color: var(--text);
}
.opt-toggle input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
}
.opt-body {
  margin-top: 0.15rem;
  padding-left: 0.7rem;
  border-left: 2px solid var(--border);
}
.opt-body .row {
  margin: 0.25rem 0;
}
