/* Quality Detective on the park guide map. Reading and the result sit on the water at the left; the checks, the path
   and the batch sit on the lobe. The path's geometry (node widths, heights) is shared with draw() in game.js. */
.brief h1 { margin-bottom: 14px; }
.brief p { margin: 0 0 10px; font-size: 17px; line-height: 1.45; }
.brief .chip { margin: 0 6px 4px 0; }
#door[hidden], #facts[hidden], #rules[hidden], .key[hidden] { display: none; }
.hint { margin: 0 0 8px; font-size: 14px; line-height: 1.45; max-width: 65ch; }
.build h2 { font-size: 19px; margin: 0 0 6px; }
.play:focus { outline: none; }
.side > *, .cols > * { min-width: 0; }

/* ---- checks (capsules) and your gates ---- */
.side { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 20px; align-items: start; }
#palette { display: flex; flex-wrap: wrap; gap: 8px; }
#palette button { /* name over a few words on what it checks, as in Refinery's block palette */
  display: grid; align-content: center; gap: 3px; text-align: left; min-height: 56px; padding: 7px 14px; cursor: pointer;
  color: var(--ink); background: var(--water); border: 2px solid var(--ink); border-radius: var(--radius-card);
  transition: transform var(--t) var(--bounce), background-color .2s;
}
#palette button:hover:enabled { transform: translateY(-2px); background: var(--panel-2); }
#palette button:active:enabled { transform: scale(.96); }
#palette button:disabled { border-style: dashed; color: var(--muted); cursor: not-allowed; }
#palette b { font: 700 14px/1 var(--mono); display: flex; align-items: center; gap: 6px; }
#palette small { font: 400 13px/1.3 var(--font); }
/* one drawn icon per check type */
.kico { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; vertical-align: -3px; }

#rules { margin: 0 0 10px; padding: 0 0 0 20px; font-size: 14px; line-height: 1.45; }
#checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
#checks li {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; min-height: 48px; padding: 6px 8px 6px 12px;
  background: var(--water); border: 2px solid var(--ink); border-radius: var(--radius-card);
}
#checks li.none { background: none; border-style: dashed; font-size: 14px; font-weight: 500; }
#checks b { font: 700 14px var(--mono); }
#checks label { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; font: 600 13px var(--font); color: var(--muted); }
#checks input, #checks select {
  min-height: 34px; min-width: 0; max-width: 100%; padding: 4px 6px;
  font: 13px var(--mono); color: var(--ink); background: var(--water); border: 2px solid var(--ink); border-radius: 10px;
}
#checks input[type=number] { width: 72px; }
#checks input[type=text] { width: 190px; }
#checks .acts { margin-left: auto; display: flex; gap: 4px; }
#checks .acts button { /* the arrows and the cross are drawn; their text stays for screen readers and tests */
  position: relative; width: 32px; height: 32px; font-size: 0; cursor: pointer; color: var(--ink); background: var(--water); border: 2px solid var(--ink); border-radius: 50%;
}
#checks .acts button::before { content: ''; position: absolute; inset: 6px; background: currentColor; mask: var(--i-down) center / contain no-repeat; }
#checks .acts [data-act="up"]::before { rotate: 180deg; }
#checks .acts [data-act="del"]::before { mask-image: var(--i-x); }
#checks .acts button:hover:enabled { background: var(--ink); color: var(--water); }
#checks li:only-child .acts button:disabled { display: none; } /* one gate: nothing to reorder */
#checks .acts button:disabled { border-style: dashed; color: var(--muted); border-color: var(--muted); cursor: not-allowed; }

/* ---- toolbar: the target at the left, Reset and Run at the right end ---- */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
#target { margin-right: auto; flex: 0 1 auto; min-width: 0; }
#target .star-row { flex: none; }
#why { font-size: 14px; font-weight: 600; text-align: right; }
#why:empty { display: none; }
#why::before, .flagwrap h2::before, .gate.warn::after { /* the "!" sign, drawn */
  content: ''; display: inline-block; vertical-align: -4px; width: 18px; height: 18px; margin-right: 6px; border-radius: 50%;
  background: var(--amber) var(--pic-bang) center / 12px no-repeat;
}
@media (min-width: 641px) { .toolbar { flex-wrap: nowrap; } .toolbar .btn { flex: none; } }
@media (max-width: 640px) { #why { flex-basis: 100%; text-align: left; } #reset { margin-left: auto; } }

/* ---- the path: Source → gates → Warehouse, one ink line across the lobe, a branch down to Quarantine ----
   Laid out in real px by draw(): the line runs at y=40, a gate that holds a check drops a branch to the quarantine
   box under the tallest gate. Records are numbered dots on the line. Coral marks only what was stopped or got in. */
.world { position: relative; height: calc(var(--qy) + 92px); --qy: 112px; --sx: 108px; --sw: 300px; } /* --qy: the quarantine's top edge, under the tallest gate */
.has-taps:not(.compact) { min-height: 232px; }
.has-flags:not(.compact) { height: calc(var(--qy) + 116px); } /* two bays share the width, so each gets more height */
.compact { height: calc(var(--qy) + 64px); }
.belt { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.belt path { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.source, .gate, .warehouse, .crate, .tap { background: var(--water); border: 2px solid var(--ink); }

.source {
  position: absolute; left: 0; top: 12px; width: 96px; height: 56px; z-index: 3; padding-left: 16px;
  display: grid; align-content: center; border-radius: var(--pill); font: 500 13px/1.25 var(--font);
}
.source b, .warehouse strong, .gate:not(.empty)::before { font: 800 17px/1.1 var(--display); letter-spacing: -.02em; }
.source small { font-size: inherit; }

/* a gate is a stop on the line; its left and width come from draw() */
.gate { position: absolute; top: 16px; z-index: 2; min-height: 48px; padding: 6px 10px 7px; border-radius: 16px; font: 600 12px/1.3 var(--font); pointer-events: none; }
.gate:not(.empty)::before { content: attr(data-name) / ''; display: block; }
.gate .head { display: flex; gap: 4px; font: 600 12px/1.3 var(--mono); overflow-wrap: anywhere; }
.gate:not(.empty) .count { min-height: 1.3em; } /* room for the count, so the scene keeps its height during a run */
.gate .kico { width: 13px; height: 13px; margin-top: 1px; }
/* an empty gate is the only cue for where gates go: dashed, with its label at full text contrast */
.gate.empty { display: grid; place-content: center; border-style: dashed; }
.gate.empty .head { font: 600 13px/1.2 var(--font); color: var(--muted); }
.gate.warn::after { position: absolute; right: -8px; top: -8px; margin: 0; }
.gate.hit { animation: hit .5s; }
.gate.pass { animation: ok .4s; }
.gate.flag { animation: flag .5s; }
@keyframes hit { 30% { background: var(--coral); transform: scale(1.06); } }
@keyframes ok { 40% { background: var(--panel-2); } }
@keyframes flag { 30% { background: var(--amber); color: var(--water); transform: scale(1.06); } }

/* records: numbered dots that travel the line behind the gates */
#cards { position: absolute; left: 0; top: 0; z-index: 1; }
.card {
  position: absolute; left: -11px; top: -11px; width: 22px; height: 22px; border-radius: 50%; display: grid; place-content: center;
  font: 700 11px/1 var(--mono); color: var(--water); background: var(--ink);
}
.card.caught, .card.fp { color: var(--ink); background: var(--coral); outline: 2px solid var(--ink); }
.card.fp { outline-style: dashed; } /* a good record that was stopped */
.card.flagged { color: var(--ink); background: var(--water); outline: 2px dashed var(--ink); } /* warned about, still travelling */

/* quarantine: a dashed bay under the line; what was stopped is listed in words */
.binwrap {
  position: absolute; left: var(--sx); top: var(--qy); bottom: 0; width: var(--sw); padding: 6px 12px; overflow-y: auto;
  border: 2px dashed var(--ink); border-radius: 16px; font: 500 13px/1.35 var(--font);
}
.binwrap h2 { margin: 0 0 2px; font: 800 14px/1.25 var(--display); letter-spacing: -.01em; }
#bin, #flags { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 2px 14px; }
:is(#bin, #flags) li { animation: pop var(--t) var(--bounce) backwards; }
:is(#bin, #flags) li b:first-child { font-family: var(--mono); }
@keyframes pop { from { transform: translateY(-14px) scale(.6); opacity: 0; } }
/* flagged records were let through: a solid bay beside the quarantine */
.has-flags .binwrap { width: calc(var(--sw) * .56); }
.has-flags .flagwrap { left: calc(var(--sx) + var(--sw) * .58); width: calc(var(--sw) * .42); border-style: solid; }
.flagwrap h2::before { width: 16px; height: 16px; background-size: 11px; vertical-align: -3px; }

/* the warehouse: where the line ends */
.warehouse { position: absolute; right: 0; top: 6px; width: 150px; z-index: 3; padding: 10px 14px 12px; border-radius: 26px; font: 500 13px/1.35 var(--font); }
.warehouse strong { display: block; margin-bottom: 4px; }
.warehouse.shake, .tap.shake { animation: shake .4s; }
@keyframes shake { 25% { transform: translateX(-5px); } 50% { transform: translateX(5px); } 75% { transform: translateX(-3px); } }
.trust .row { display: flex; justify-content: space-between; gap: 6px; }
.meter { --m: 100; height: 10px; margin-top: 6px; background: var(--water); border: 2px solid var(--ink); border-radius: var(--pill); overflow: hidden; }
.meter i { display: block; height: 100%; width: calc(var(--m) * 1%); background: var(--ink); transition: width var(--t); }
.meter[data-idle] i { width: 0; } /* empty until a run: a full bar would claim a result nobody has yet */
/* a bad record that arrived: one coral mark each, counted in words by "Bad rows in" */
#stains { display: flex; flex-wrap: wrap; gap: 3px; }
#stains i { width: 16px; height: 16px; margin-top: 6px; border-radius: 50%; background: var(--coral); border: 1.5px solid var(--ink); animation: pop var(--t) var(--bounce) backwards; }
.win .warehouse::after { /* three stars: the warehouse is ticked off */
  content: ''; position: absolute; right: -6px; top: -8px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent) var(--pic-tick) center / 14px no-repeat; border: 2px solid var(--ink); animation: pop var(--t) var(--bounce) backwards;
}

/* ---- levels 6+: the gate at the source, crates, other readers ---- */
.crate { /* a whole batch waiting under the source */
  position: absolute; left: 0; top: 78px; width: 96px; z-index: 3; padding: 3px 6px; opacity: 0;
  text-align: center; border-radius: var(--radius); font: 500 12px/1.3 var(--font);
}
.crate b { display: block; font: 700 12px/1.3 var(--mono); }
.crate.show { opacity: 1; animation: pop var(--t) var(--bounce) backwards; }
.crate.open { border-style: dashed; }
.crate.caught, .crate.fp { background: var(--coral); }
.crate.fp { border-style: dashed; }
.crate.drop { animation: cratedrop .4s ease-in forwards; }
@keyframes cratedrop { to { transform: translate(120px, 60px) scale(.5); opacity: 0; } }
#bin li.whole { font-weight: 700; }

/* other readers: stops on a branch that leaves the source before any of your gates */
.taps { position: absolute; left: 0; top: 68px; width: 108px; z-index: 3; padding-top: 8px; display: grid; gap: 6px; font: 500 12px/1.3 var(--font); }
.taps h2 { margin: 0 0 0 30px; font: 800 13px/1.25 var(--display); white-space: nowrap; }
.pipe { position: absolute; z-index: -1; left: 19px; top: 0; bottom: 20px; width: 3px; background: var(--ink); }
.pipe.flow { animation: flow .4s; }
.pipe.badflow { animation: badflow .4s; }
@keyframes flow { 40% { transform: scaleX(3); } }
@keyframes badflow { 40% { transform: scaleX(4); background: var(--coral); } }
.tap { display: grid; padding: 4px 12px; border-radius: 14px; transition: background-color .3s; }
.tap b { font-size: 13px; font-weight: 700; }
.tap i { font-style: normal; font-weight: 700; }
.tap.stained { background: var(--coral); } /* bad rows arrived here, and the count says so */

/* ---- compact path: too narrow for full labels (phones). Nodes drop to numbers, records keep theirs,
   and the key under the path names the gates and carries the counts. Row details are in the batch table. ---- */
.key { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 2px 14px; font: 13px/1.4 var(--mono); }
.key b { font-family: var(--font); font-weight: 700; }
.compact .source { top: 18px; width: 44px; height: 44px; padding: 0; place-content: center; font: 700 13px/1 var(--mono); }
.compact .source :is(b, small) { display: none; }
.compact .gate { top: 24px; height: 32px; min-height: 0; padding: 0; border-radius: 50%; display: grid; place-content: center; }
.compact .gate::before { content: attr(data-n) / ''; font: 700 13px/1 var(--mono); letter-spacing: 0; }
.compact .gate.empty::before { color: var(--muted); }
.compact .gate :is(.head, .count), .compact .trust .row, .compact .taps h2 { display: none; }
.compact .binwrap { padding: 4px 10px; }
.compact .binwrap h2 { font-size: 12px; }
.compact :is(#bin, #flags) { gap: 2px 8px; }
.compact :is(#bin, #flags) li { font-size: 0; }
.compact :is(#bin, #flags) li b:first-child { font-size: 12px; }
.compact .flagwrap h2 { font-size: 0; }
.compact .flagwrap h2::after { content: 'Flagged'; font-size: 12px; }
.compact .warehouse { top: 10px; width: 100px; padding: 8px 10px 10px; border-radius: 20px; }
.compact .warehouse strong { font-size: 13px; letter-spacing: 0; margin: 0; }
.compact.win .warehouse::after { top: auto; bottom: -12px; }
.compact .crate { top: 68px; width: 44px; padding: 2px; font-size: 0; }
.compact .crate b { font-size: 11px; }
.compact .taps { top: 62px; width: 44px; padding-top: 10px; gap: 8px; justify-items: center; font-size: 0; }
.compact .pipe { left: 20.5px; }
.compact .tap { width: 20px; height: 20px; padding: 0; border-radius: 50%; }
.compact .tap * { display: none; }

/* ---- the lake: the incoming batch, with each record's verdict after a run ---- */
#evidence { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); gap: 16px 28px; align-items: start; }
#extra h2 ~ h2 { margin-top: 16px; }
.scroll { overflow-x: auto; }
#cue { font-weight: 700; white-space: nowrap; }
table.data { width: 100%; }
table.data td { white-space: nowrap; }
/* the result is the last column and wraps, so the evidence columns keep their place after a run */
table.data td.status:not(:empty) { white-space: normal; min-width: 16ch; }
table.data.tight td.status:not(:empty) { white-space: nowrap; }
td.status.good { color: var(--good); }
td.status.bad { color: var(--ink); background: var(--coral); }
td.status.warn { color: var(--amber); }
/* the verdict as a drawn mark in the first column, so it shows on a phone without scrolling the table sideways */
#batch .mark { display: inline-block; width: 18px; }
:is(#batch .mark, .marks b).good { color: var(--good); }
:is(#batch .mark, .marks b).bad { color: var(--bad); }
:is(#batch .mark, .marks b).warn { color: var(--amber); }
:is(#batch .mark, .marks b):is(.good, .bad, .warn) { font-size: 0; }
:is(#batch .mark, .marks b):is(.good, .bad, .warn)::before { content: ''; display: inline-block; width: 13px; height: 13px; vertical-align: -2px; background: currentColor; mask: var(--i-tick) center / contain no-repeat; }
:is(#batch .mark, .marks b).bad::before { mask-image: var(--i-x); }
:is(#batch .mark, .marks b).warn::before { mask-image: var(--i-bang); }
.marks { margin: 10px 0 0; font-size: 13px; }

/* lookup table and lineage map */
table.lookup tr.match td { animation: matchrow .7s; }
table.lookup.nomatch { animation: nomatch .6s; }
@keyframes matchrow { 30% { background: var(--good); color: var(--water); } }
@keyframes nomatch { 30% { background: var(--coral); } }
.lin { display: flex; flex-wrap: wrap; gap: 12px 20px; align-items: center; }
svg.lineage { display: block; flex: 1 1 320px; max-width: 460px; height: auto; }
/* the level's three rules, read side by side with the map */
.legend { flex: 1 1 200px; margin: 0; display: grid; gap: 8px; font-size: 14px; line-height: 1.4; }
.legend div { display: grid; grid-template-columns: 104px 1fr; gap: 10px; align-items: baseline; }
.legend dt { padding: 3px 8px; font-size: 13px; font-weight: 700; text-align: center; border: 1.5px solid var(--ink); border-radius: var(--pill); }
.legend div:nth-child(1) dt { background: var(--coral); }
.legend div:nth-child(2) dt { border-style: dashed; }
.legend dd { margin: 0; }
/* the lineage map: columns are stops on the feed's line, each report a stop on a branch */
.lineage path { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.lineage circle { fill: var(--water); stroke: var(--ink); stroke-width: 3; transition: fill .3s; }
.lineage text { font: 600 14px var(--mono); fill: var(--ink); }
.lineage .rep text:first-of-type { font: 800 16px var(--display); letter-spacing: -.01em; }
.lineage text.n { font-size: 13px; font-weight: 400; fill: var(--muted); }
.lineage .unread circle { stroke: var(--muted); stroke-width: 2; stroke-dasharray: 4 3; }
.lineage .unread text { fill: var(--muted); }
.lineage .rep.ok circle { fill: var(--ink); }
.lineage .rep.notified circle { stroke-dasharray: 5 3; }
.lineage .rep:is(.broken, .lost) circle { fill: var(--coral); }
#impact { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 4px; font: 13px/1.4 var(--mono); }
#impact li::before { content: ''; display: inline-block; width: 13px; height: 13px; margin-right: 6px; vertical-align: -2px; background: currentColor; mask: var(--i-tick) center / contain no-repeat; }
#impact .ok { color: var(--good); }
#impact .notified { color: var(--amber); }
#impact .notified::before { mask-image: var(--i-bang); }
#impact :is(.broken, .lost) { color: var(--bad); }
#impact :is(.broken, .lost)::before { mask-image: var(--i-x); }

/* ---- result, on the water ---- */
#results p:not(.result-title, .result-stars) { font-size: 15px; }
#results[data-state="win"] .result-stars { animation: pop var(--t) var(--bounce) backwards; } /* only a win is celebrated */
#results .takeaway::before { content: 'Takeaway: '; font-weight: 700; }
#results .stats { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
#results .chip.good::before { content: ''; width: 12px; height: 12px; background: currentColor; mask: var(--i-tick) center / contain no-repeat; }
#results .chip.warn { border-style: dashed; }
#results .chip.warn::before { content: ''; width: 12px; height: 12px; background: currentColor; mask: var(--i-bang) center / contain no-repeat; }

/* ---- phones: one column, touch-sized controls ---- */
@media (max-width: 640px) {
  .side { grid-template-columns: minmax(0, 1fr); }
  #palette button, #checks input, #checks select { min-height: 44px; }
  #checks .acts button { width: 44px; height: 44px; }
  #checks .acts button::before { inset: 11px; }
  /* results on one line: wrapping cells made the rows grow mid-run and pushed the page about */
  table.data td.status:not(:empty) { white-space: nowrap; }
  table.data :is(th, td) { padding-inline: 6px; } /* a three-column batch and its result fit a phone before a run */
}
