/* NODES: a workbench in the game's own vernacular.
   The ground is the map's ocean, darkened, so the dimmed biome map sits in the
   page instead of in a black hole. FICSIT orange is reserved for actions.
   Bahnschrift is Windows' DIN, which most Satisfactory players already have;
   everyone else falls back to their system face. No webfonts: the page loads
   nothing but its own files. */
:root {
  color-scheme: dark;
  --ground: #0a1317;     /* map canvas and inputs */
  --bench: #101d23;      /* page */
  --panel: #152730;      /* sidebar */
  --line: #24404b;
  --line-strong: #35596a;
  --text: #dde6e9;
  --muted: #8aa1ab;
  --ficsit: #fa9549;
  --ficsit-ink: #1c0f04;
  --error: #ff7a6b;
  --display: Bahnschrift, "DIN Alternate", "DIN Condensed", "Barlow", system-ui, sans-serif;
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* Out of sight but still in the tab order, unlike [hidden]: the file inputs
   behind the drop zone and Import, which their labels stand in for. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
body { margin: 0; background: var(--bench); color: var(--text); }
a { color: var(--ficsit); text-underline-offset: 2px; }
:focus-visible { outline: 2px solid var(--ficsit); outline-offset: 2px; }
h1, h3, legend, summary, .sidebar header strong { font-family: var(--display); font-weight: 600; letter-spacing: .01em; }
code { font-size: .92em; }

/* Upload: the drop zone over a faint sight of the map it will change. */
.upload { position: relative; min-height: 100vh; display: grid; place-content: center; padding: 2rem 16px; isolation: isolate; }
.upload::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: url(biome-map.jpg) center / cover no-repeat;
  opacity: .14;
  mask-image: radial-gradient(closest-side, #000 40%, transparent);
}
.upload > * { max-width: 32rem; }
.upload h1 { font-size: 3.4rem; line-height: 1; margin: 0 0 .4rem; font-weight: 700; }
.upload > p { margin: 0 0 1.6rem; color: var(--muted); font-size: 1.1rem; }
/* The rolled expansion of NODES (web/acronyms.json), under the name. */
.upload > .tagline { margin: 0 0 .9rem; color: var(--ficsit); font-family: var(--display); font-size: 1.15rem; }
.sidebar header .tagline { color: var(--ficsit); font-family: var(--display); font-size: .85rem; }
.drop {
  display: block; padding: 3.2rem 1.2rem; text-align: center; cursor: pointer;
  background: color-mix(in srgb, var(--panel) 85%, transparent);
  border: 2px dashed var(--line-strong); border-radius: 10px;
  font-family: var(--display); font-size: 1.15rem;
}
.drop:hover, .drop.over { border-color: var(--ficsit); border-style: solid; }
.drop:has(:focus-visible) { outline: 2px solid var(--ficsit); outline-offset: 2px; }
.notes { color: var(--muted); padding-left: 1.1rem; margin: 1.2rem 0 0; }
.notes li + li { margin-top: .2rem; }

/* Bench: sidebar of settings, map filling the rest. */
/* --sidebar is set by the resize handle (web/app.ts); 24rem until then, wide enough
   that the longest settings line (Allow cross-form swaps) stays on one line. */
.bench { display: grid; grid-template-columns: var(--sidebar, 24rem) auto minmax(0, 1fr); height: 100vh; }
.resize { width: 6px; margin-left: -3px; margin-right: -3px; z-index: 1; cursor: col-resize; touch-action: none; }
.resize:hover, .resize.dragging, .resize:focus-visible { background: var(--ficsit); outline: none; }
.sidebar { display: flex; flex-direction: column; overflow: auto; background: var(--panel); border-right: 1px solid var(--line); }
.sidebar header { display: flex; flex-direction: column; gap: .1rem; padding: 1rem 1.1rem .9rem; border-bottom: 1px solid var(--line); }
.sidebar header strong { font-size: 1.5rem; line-height: 1.1; }
.save { display: flex; gap: .6rem; align-items: baseline; min-width: 0; color: var(--muted); font-size: .9rem; }
#save-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#settings { display: flex; flex-direction: column; flex: 1; padding: .4rem 1.1rem 0; }
.sidebar label { display: block; margin: .8rem 0; }
.sidebar fieldset { border: 0; border-top: 1px solid var(--line); margin: .8rem 0 0; padding: .4rem 0 0; }
.sidebar legend { padding: 0 .4rem 0 0; color: var(--muted); }
.sidebar fieldset label { margin: .4rem 0; }
output { float: right; font-variant-numeric: tabular-nums; color: var(--ficsit); font-family: var(--display); }

input[type=number], input[type=text], select {
  width: 100%; background: var(--ground); color: var(--text); font: inherit;
  border: 1px solid var(--line); border-radius: 4px; padding: .35rem .5rem;
  font-variant-numeric: tabular-nums; margin-top: .2rem;
}
input[type=number]:hover, input[type=text]:hover, select:hover { border-color: var(--line-strong); }
input[type=checkbox], input[type=range] { accent-color: var(--ficsit); }
input[type=checkbox] { margin: 0 .45rem 0 0; vertical-align: -2px; }
input[type=range] { width: 100%; margin: .4rem 0 .1rem; }
small { color: var(--muted); display: block; font-size: .82rem; }
.row { display: flex; gap: .4rem; align-items: center; }
.row input { margin-top: 0; }

button, .button {
  background: var(--line); color: var(--text); border: 1px solid transparent; border-radius: 4px;
  padding: .45rem .85rem; cursor: pointer; font: inherit; display: inline-block;
}
button:hover:not(:disabled), .button:hover { background: var(--line-strong); }
.button:has(:focus-visible) { outline: 2px solid var(--ficsit); outline-offset: 2px; }
button:disabled { opacity: .4; cursor: default; }
/* A disabled select looks just like a live one unless told otherwise; its label dims with it. */
select:disabled { opacity: .4; cursor: default; }
.map-bar label:has(:disabled) { color: var(--muted); }
button.link { background: none; padding: 0; color: var(--ficsit); text-decoration: underline; text-underline-offset: 2px; font-size: .85rem; }
#dice { padding: .35rem .6rem; line-height: 1.2; }

details#advanced { border-top: 1px solid var(--line); margin-top: .8rem; }
details#advanced > summary { cursor: pointer; padding: .7rem 0; color: var(--muted); }
details#advanced[open] > summary { color: var(--text); }
details#advanced section { margin: 0 0 1.2rem; }
details#advanced h3 { font-size: 1rem; margin: 0 0 .3rem; }

/* The one loud thing: the action plate, pinned to the bottom of the sidebar. */
.actions {
  position: sticky; bottom: 0; margin: auto -1.1rem 0; padding: .9rem 1.1rem 1.1rem;
  display: grid; gap: .45rem;
  background: linear-gradient(transparent, var(--panel) .9rem);
}
#generate {
  background: var(--ficsit); color: var(--ficsit-ink); border-radius: 6px;
  padding: .75rem; font-family: var(--display); font-size: 1.2rem; font-weight: 700;
  box-shadow: inset 0 -3px 0 #0003;
}
#generate:hover:not(:disabled) { background: #ffa862; }
#generate:active:not(:disabled) { box-shadow: inset 0 2px 0 #0003; }
#download { border-color: var(--line-strong); background: transparent; }
#download:not(:disabled) { border-color: var(--ficsit); color: var(--ficsit); }
#progress {
  width: 100%; height: .9rem; appearance: none; border: 1px solid var(--line-strong); border-radius: 3px;
  background: var(--ground); overflow: hidden;
}
#progress::-webkit-progress-bar { background: var(--ground); }
/* Hazard stripes: one rule per engine, since an unknown pseudo-element voids a shared rule. */
#progress::-webkit-progress-value { background: repeating-linear-gradient(-45deg, var(--ficsit) 0 8px, #1c1205 8px 16px); }
#progress::-moz-progress-bar { background: repeating-linear-gradient(-45deg, var(--ficsit) 0 8px, #1c1205 8px 16px); }

/* Results */
.results { display: flex; flex-direction: column; min-width: 0; padding: 1rem; gap: .7rem; overflow: auto; }
.map-bar { display: flex; flex-wrap: wrap; gap: .6rem 1.2rem; align-items: center; }
.map-bar select { width: auto; margin: 0 0 0 .3rem; }
.toggle { display: inline-flex; border: 1px solid var(--line-strong); border-radius: 6px; overflow: hidden; }
.toggle button { border-radius: 0; background: transparent; font-family: var(--display); padding: .4rem 1rem; }
.toggle button + button { border-left: 1px solid var(--line-strong); }
.toggle button[aria-pressed=true] { background: var(--ficsit); color: var(--ficsit-ink); }
.map-wrap { position: relative; flex: 1; min-height: 24rem; }
#map {
  position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 6px;
  background: var(--ground); box-shadow: 0 0 0 1px var(--line); cursor: grab; touch-action: none;
}
#map:active { cursor: grabbing; }
#map.picking { cursor: crosshair; box-shadow: 0 0 0 2px var(--ficsit); }
.tooltip {
  position: absolute; pointer-events: none; background: #050b0eeb; border: 1px solid var(--line-strong);
  padding: .25rem .55rem; border-radius: 4px; font-size: 12.5px; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.legend { display: flex; flex-wrap: wrap; gap: .25rem; list-style: none; padding: 0; margin: 0; }
.legend button { background: none; padding: .15rem .45rem; font-size: .9rem; font-variant-numeric: tabular-nums; border-radius: 99px; }
.legend button:hover { background: var(--line); }
.dot { display: inline-block; width: .75rem; height: .75rem; border-radius: 50%; margin-right: .35rem; vertical-align: -1px; box-shadow: 0 0 0 1px #000a; }
.legend .dim { opacity: .35; }
.results.is-stale .map-wrap, .results.is-stale .summary, .results.is-stale #report-box { opacity: .4; }
.stale { color: var(--ficsit); margin: 0; font-family: var(--display); }
.error { color: var(--error); white-space: pre-wrap; margin: 0; }
.summary { display: grid; grid-template-columns: max-content 1fr; gap: .25rem 1.2rem; margin: 0; font-variant-numeric: tabular-nums; }
.summary dt { color: var(--muted); }
.summary dd { margin: 0; }
#report-box > summary { cursor: pointer; color: var(--muted); }
pre { overflow: auto; font-size: 12px; background: var(--ground); border: 1px solid var(--line); border-radius: 6px; padding: .8rem; }

.mismatch { color: var(--error); }
/* Counts editor (web/counts.ts): a budget bar per budget, a row per resource. */
.budget { border: 1px solid var(--line); border-radius: 6px; padding: .6rem; margin: .5rem 0; background: #0a131766; }
/* The budget's totals sit on their own band, ruled off from the resource rows below. */
.budget-summary {
  margin: -.6rem -.6rem .2rem; padding: .6rem .6rem .4rem;
  background: var(--panel); border-bottom: 1px solid var(--line-strong); border-radius: 6px 6px 0 0;
}
.budget-head { font-size: .9rem; color: var(--muted); }
.counts-reset { margin-bottom: .2rem; }
.budget-head strong { color: var(--text); }
.budget-bar {
  display: flex; height: .9rem; margin: .45rem 0; border-radius: 3px; overflow: hidden;
  background: var(--ground); box-shadow: 0 0 0 1px var(--line);
}
.budget-bar .segment { flex: 0 1 0; min-width: 0; padding: 0; border: 0; border-radius: 0; }
.budget-bar .segment + .segment { box-shadow: inset 1px 0 0 #000a; }
.budget-bar .spare-seg { flex-basis: 0; background: repeating-linear-gradient(-45deg, var(--line-strong) 0 4px, transparent 4px 8px); }
.problems { list-style: none; padding: 0; margin: .2rem 0; font-size: .85rem; color: var(--error); }
.problems button { margin-left: .4rem; padding: .1rem .45rem; font-size: .8rem; }
.budget-row { margin-top: .8rem; }
.budget-row .row { gap: .45rem; }
.budget-row .total { width: 4.5rem; margin: 0 0 0 auto; }
.purity-track { position: relative; height: 1.1rem; border-radius: 3px; margin-top: .3rem; }
.purity-track .divider {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  background: none; appearance: none; pointer-events: none;
}
/* Only the thumbs take the pointer, so either divider can be grabbed. One rule per engine. */
.purity-track .divider::-webkit-slider-thumb {
  pointer-events: auto; appearance: none; width: 6px; height: 1.3rem; cursor: ew-resize;
  background: var(--text); border-radius: 2px; box-shadow: 0 0 0 1px #000;
}
.purity-track .divider::-moz-range-thumb {
  pointer-events: auto; width: 6px; height: 1.3rem; cursor: ew-resize;
  background: var(--text); border: 0; border-radius: 2px; box-shadow: 0 0 0 1px #000;
}
.purity-track .divider::-moz-range-track { background: none; }
.purity-nums { display: flex; gap: .5rem; margin-top: .3rem; font-size: .8rem; color: var(--muted); }
.sidebar .purity-nums label { display: flex; align-items: center; gap: .25rem; margin: 0; }
.purity-nums input { width: 3.2rem; margin: 0; padding: .15rem .3rem; }
.row-note { font-size: .85rem; }
.warn { color: var(--ficsit); }
.zone { border: 1px solid var(--line); border-radius: 6px; padding: .6rem; margin: .5rem 0; background: #0a131766; }
/* Requires / Excludes blocks, Add requirement, and Delete each get room to breathe. */
.zone > div { margin-top: .7rem; }
.zone > div > button { margin-top: .5rem; }
.zone > button { margin-top: .8rem; }
.zone-heading { margin-bottom: .3rem; color: var(--muted); }
.chips { display: flex; flex-wrap: wrap; gap: .25rem; }
.chips button { padding: .1rem .45rem; font-size: 12px; }
.chips button[aria-pressed=true] { background: var(--error); color: #1a0503; }

.credits { font-size: 11.5px; color: var(--muted); padding: .6rem 1rem; border-top: 1px solid var(--line); }

@media (max-width: 800px) {
  .bench { grid-template-columns: minmax(0, 1fr); height: auto; }
  .resize { display: none; }
  .sidebar { overflow: visible; border-right: 0; border-bottom: 1px solid var(--line); }
  .actions { position: static; background: none; }
  .map-wrap { min-height: 80vw; }
  .upload h1 { font-size: 2.6rem; }
}

/* ⓘ help buttons and the explanation popovers they open (web/help.ts). */
button.info {
  background: none; color: var(--muted); padding: 0 .15rem; margin: 0;
  font-size: .95em; line-height: 1; vertical-align: baseline; border-radius: 50%;
}
button.info:hover:not(:disabled) { color: var(--ficsit); background: none; }
.help {
  position: fixed; inset: auto; margin: 0;
  max-width: min(20rem, calc(100vw - 16px));
  padding: .6rem .75rem; border: 1px solid var(--line-strong); border-radius: 6px;
  background: var(--panel); color: var(--text);
  font: 400 13px/1.45 system-ui, sans-serif; letter-spacing: normal; text-transform: none;
  box-shadow: 0 6px 24px #0008;
}
