:root {
  /* Native widgets (the date-picker popout, scrollbars) follow the theme;
     without this the dark theme gets a light-UA calendar popout rendered
     black-on-dark-grey. */
  color-scheme: light;
  --bg: #ffffff;
  --fg: #1a1a1a;
  --muted: #5f6368;
  --border: #d7dae0;
  --panel: #f7f8fa;
  --accent: #2f6f4f;
  --accent-fg: #ffffff;
  --warning: #8a5a00;
  --warning-bg: #fff4e0;
  --error: #b3261e;
  --error-bg: #fdecea;
  --row-selected: #e4f2ea;
  --row-cheapest-border: #2f6f4f;
  --row-fastest-border: #2f5fbf;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg: #16181c;
    --fg: #e8e8e8;
    --muted: #9aa0a6;
    --border: #33363b;
    --panel: #1f2226;
    --accent: #4caf7d;
    --accent-fg: #0c130f;
    --warning: #e0b03a;
    --warning-bg: #3a2f10;
    --error: #ef6a62;
    --error-bg: #3a1917;
    --row-selected: #1d2b23;
    --row-cheapest-border: #4caf7d;
    --row-fastest-border: #6ea8ff;
  }
}

* {
  box-sizing: border-box;
}

body {
  font-family: -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--fg);
  margin: 0;
  padding: 1.5rem;
  line-height: 1.45;
}

header {
  max-width: 60rem;
  margin: 0 auto 1.5rem;
  /* Keeps the tagline clear of the fixed settings cog on narrow viewports,
     where the header spans the full width. */
  padding-right: 2.5rem;
}

h1 {
  margin: 0 0 0.25rem;
  font-size: 1.6rem;
}

.tagline {
  color: var(--muted);
  font-size: 0.9rem;
}

/* The status box and the debug-only CLI-command button share a fixed bar
   pinned to the bottom-right; the button sits just to the left of the status. */
#bottom-bar {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.status {
  max-width: min(22rem, calc(100vw - 2rem));
  padding: 0.35rem 0.7rem;
  border-radius: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--border);
  font-size: 0.85rem;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}

#debug-command-btn {
  flex: none;
  padding: 0.3rem 0.5rem;
  border-radius: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.8rem;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}

#debug-command-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* The CLI-command popup, floating above the bottom bar. */
#debug-popup {
  position: fixed;
  right: 1rem;
  bottom: 3.75rem;
  z-index: 101;
  width: min(34rem, calc(100vw - 2rem));
  padding: 0.6rem;
  border-radius: 0.5rem;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
}

#debug-popup[hidden] {
  display: none;
}

.debug-popup-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  margin-bottom: 0.4rem;
}

#debug-popup-close {
  border: none;
  background: none;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.2rem;
}

#debug-popup-close:hover {
  color: var(--error);
}

#debug-command-text {
  width: 100%;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.78rem;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
  resize: vertical;
}

.debug-popup-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.4rem;
}

.debug-popup-actions .pane-hint {
  margin: 0;
}

/* The settings cog, pinned top-right the way #bottom-bar is pinned
   bottom-right, and its popover hanging below it. Both pages include the same
   markup (templates/solverapp/_settings.html). */
#settings-btn {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 100;
  padding: 0.25rem 0.5rem;
  border-radius: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1.2;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}

#settings-btn:hover,
#settings-btn[aria-expanded="true"] {
  color: var(--accent);
  border-color: var(--accent);
}

/* A tall panel: the head and the Cancel/Save actions stay put while the panes
   scroll between them, so Save is always reachable however much is expanded. */
#settings-popover {
  position: fixed;
  top: 3.5rem;
  right: 1rem;
  z-index: 101;
  display: flex;
  flex-direction: column;
  /* Wide enough for two field columns (see .pane-body) on a desktop window, and
     never wider than the viewport on a phone. */
  width: min(52rem, calc(100vw - 2rem));
  max-height: calc(100vh - 4.5rem);
  padding: 0.6rem;
  border-radius: 0.5rem;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
}

/* `display: flex` above would otherwise beat the attribute. */
#settings-popover[hidden] {
  display: none;
}

#settings-popover:focus {
  outline: none;
}

.settings-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  margin-bottom: 0.4rem;
}

#settings-close {
  border: none;
  background: none;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.2rem;
}

#settings-close:hover {
  color: var(--error);
}

.settings-body {
  overflow-y: auto;
  /* Room for the panes' own focus rings and the scrollbar. */
  padding: 0.1rem 0.4rem 0.1rem 0.1rem;
}

.settings-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}

.settings-actions .pane-hint {
  margin: 0;
  margin-right: auto;
}

/* Save is the primary action of the only modal-ish surface in the app. */
.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
}

.btn-primary:hover {
  filter: brightness(1.1);
}

.status-pending {
  color: var(--muted);
}

.status-ok {
  color: var(--accent);
  border-color: var(--accent);
}

.status-error {
  color: var(--error);
  background: var(--error-bg);
  border-color: var(--error);
}

main {
  max-width: 60rem;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

/* Collapsible panes: the game-state paste boxes, each controls group, and
   the report's craft breakdown all share this box + summary-heading look. */
details.pane {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 1rem;
}

details.pane > summary {
  cursor: pointer;
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  user-select: none;
}

details.pane[open] > summary {
  margin-bottom: 0.75rem;
}

/* The Goal pane's summary describes the configured goal -- but only while
   collapsed; open, the fields themselves say it. */
.summary-detail {
  text-transform: none;
  letter-spacing: normal;
}

details[open] > summary .summary-detail {
  display: none;
}

/* Explanatory blurb at the top of a pane (e.g. Trading values' unit note). */
.pane-hint {
  margin: 0 0 0.75rem;
  font-size: 0.8rem;
  color: var(--muted);
}

/* The two paste boxes sit side by side while each still gets a readable ~18rem,
   and stack below that -- keyed to the popover's width, not the viewport's. */
.paste-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: 1rem;
}

/* The settings popover's own pane stack: one full-width pane per row. The panes
   come from _settings.html in display order, so no explicit ordering is needed
   (the page itself now holds only the Goal pane). */
.settings-panes {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Inside a pane, the field rows flow into as many columns as fit. The track
   minimum is the widest row that must not wrap: an 11rem label, the 0.5rem gap
   and a 10rem date field (Registered on / Updated on) -- give it less and those
   controls drop under their label. Two of those fit the popover at its full
   52rem; a squeezed one (narrow window / phone) falls back to a single column
   with no media query.
   The grid is the pane's own `.pane-body` wrapper, not the <details> itself:
   a <details>' non-summary children are rendered inside a ::details-content box,
   so gridding the <details> only lays out summary + that one box, leaving the
   rows stacked inside it. */
.settings-panes .pane-body {
  display: grid;
  /* min(…, 100%) so the single column of a popover narrower than one track
     shrinks to fit instead of overflowing it. */
  grid-template-columns: repeat(auto-fit, minmax(min(21.5rem, 100%), 1fr));
  align-content: start;
  column-gap: 0.9rem;
}

/* The generated wrappers are grouping-only: dissolving them lets their field
   rows sit in the pane's grid instead of stacking inside one cell. */
.settings-panes .config-fields,
.settings-panes .config-section {
  display: contents;
}

/* Everything that reads across the whole pane rather than as one field: the
   blurb, the labelled textareas, the sub-section headings, and the blocks that
   are grids of their own (paste boxes, pet levels, material list). Direct
   children only, so a nested grid's own cells are left alone. */
.settings-panes .pane-body > .pane-hint,
.settings-panes .pane-body > .field,
.settings-panes .pane-body > .paste-fields,
.settings-panes .pane-body > .material-trading-toolbar,
.settings-panes .pane-body > .material-trading-list,
/* Rows carrying more than one control after their label, which need the whole
   width: the three calendar radios, and the spread lo:hi pair (whose
   label-gutter indent already eats 11.5rem before its two inputs). */
.settings-panes .pane-body > .field-row.wide,
/* These two sit under a display: contents wrapper, so they are grid items of the
   pane body without being its DOM children. */
.settings-panes .config-section h4,
.settings-panes .pet-grid {
  grid-column: 1 / -1;
}

/* display: contents drops the wrapper's own margin, so the heading carries the
   gap between building sub-sections itself. */
.settings-panes .config-section h4 {
  margin-top: 0.9rem;
}

.field {
  margin-bottom: 0.75rem;
}

.field label {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 0.25rem;
}

.field textarea {
  width: 100%;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.8rem;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
  resize: vertical;
}

.field-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}

.field-row label {
  flex: 0 0 11rem;
  font-size: 0.85rem;
  color: var(--muted);
}

.field-row label.inline {
  flex: none;
  color: var(--fg);
}

.field-row input[type="text"],
.field-row input[type="number"],
.field-row input[type="date"],
.field-row select {
  flex: 1 1 8rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
  min-width: 0;
}

.field-row input.narrow {
  flex: 0 0 6rem;
}

/* The spread Range row has two narrow inputs (lo, hi) after its label. When the
   row is too narrow to fit both, we want "hi" to wrap directly under "lo" (in the
   control column) rather than under the "Range" label. Indent the row's content
   box to the control column and pull the label back into that gutter with a
   negative margin, so a wrapped input starts under lo instead of at the label. */
#spread-range-row {
  padding-left: 11.5rem;
}
#spread-range-row label {
  margin-left: -11.5rem;
}

/* Tri-state config bool selects ("Default (off)" / On / Off) need room for the
   longest label but shouldn't stretch full width like a plain field-row select. */
.field-row select.narrow {
  flex: 0 0 9rem;
}

/* Date config fields (storehouse "Updated on", farmhouse "Registered on") need
   room for the full dd/mm/yyyy plus the picker button. */
.field-row input.date-field {
  flex: 0 0 10rem;
}

/* Config bool checkboxes sit left-aligned in the control column, not stretched
   like the text/number/select controls. */
.field-row input[type="checkbox"] {
  flex: none;
  width: 1rem;
  height: 1rem;
  margin: 0;
  margin-right: auto;
}

/* Generated preference panels (Exploring effectiveness / Farming / Pets /
   Buildings): the Buildings pane groups its controls under <h4> sub-sections. */
.config-section + .config-section {
  margin-top: 0.9rem;
}

.config-section h4 {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.2rem;
}

/* Pet levels: a compact grid rather than 28 full-width rows. A name + level box
   needs ~12rem, so this is three columns across the open popover and one on a
   phone -- where the old fixed two columns were cramped. */
.pet-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
  gap: 0.35rem 0.9rem;
  margin-top: 0.5rem;
}

.field-compact {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.field-compact label {
  flex: 1 1 auto;
  font-size: 0.8rem;
  color: var(--muted);
  min-width: 0;
}

.field-compact input {
  flex: 0 0 4rem;
  padding: 0.3rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
  min-width: 0;
}

/* Material trading pane: a filter/buttons toolbar over a scrollable list of
   one checkbox + price + guide-range row per tradeable material. */
.material-trading-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0.5rem 0;
}

.material-trading-toolbar #material-trading-filter {
  flex: 1 1 8rem;
  min-width: 0;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
}

.material-trading-buttons {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.material-trading-list {
  max-height: 22rem;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  padding: 0.25rem 0.5rem;
}

.material-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.15rem 0;
}

.material-check {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  font-size: 0.85rem;
  cursor: pointer;
}

.material-check .material-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.material-row input.material-price {
  flex: 0 0 4rem;
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
  min-width: 0;
}

.material-bounds {
  flex: 0 0 3.5rem;
  text-align: right;
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Per-parameter [?] help icon, sitting just after a control's label; on
   hover/focus it shows the shared floating .help-tooltip (positioned in JS). */
.help-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  margin-left: 0.3rem;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1;
  cursor: help;
  vertical-align: middle;
}

.help-icon:hover,
.help-icon:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  outline: none;
}

.help-tooltip {
  position: fixed;
  z-index: 200;
  max-width: min(20rem, calc(100vw - 1rem));
  padding: 0.45rem 0.6rem;
  border-radius: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--fg);
  font-size: 0.8rem;
  line-height: 1.35;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  pointer-events: none;
}

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

/* The impact graph's floating hover overlay (wireGraphHover), on top of the
   SVG's own no-JS :hover baseline (report._svg_plot's inline <style>) --
   same singleton-div/fixed-position pattern as .help-tooltip above, just
   cursor-anchored instead of icon-anchored. */
.graph-tooltip {
  position: fixed;
  z-index: 200;
  max-width: min(16rem, calc(100vw - 1rem));
  padding: 0.45rem 0.6rem;
  border-radius: 0.4rem;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--fg);
  font-size: 0.8rem;
  line-height: 1.35;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  pointer-events: none;
}

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

.graph-tooltip-plan {
  font-weight: 700;
  margin-bottom: 0.15rem;
}

.graph-tooltip-time {
  font-weight: 600;
  margin-bottom: 0.15rem;
}

/* The start date always displays a date, but until the user picks one it
   shows today muted, placeholder-style -- the value is not sent (the solver
   defaults to today server-side). */
.field-row input.implicit-date {
  color: var(--muted);
}

/* Make gated inputs (pumpkin-juice cap, calendar start date) visibly inert. */
.field-row input:disabled,
.field-row select:disabled {
  background: var(--panel);
  color: var(--muted);
  border-style: dashed;
  opacity: 0.6;
  cursor: not-allowed;
}

/* Mastery/Item goal lists: one row per goal (item picker + amount + delete),
   built dynamically by app.js's renderGoalRows/createGoalRow. */
.goal-rows {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

.goal-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.goal-row input[type="text"] {
  flex: 1 1 8rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--fg);
  min-width: 0;
}

.goal-row input.narrow {
  flex: 0 0 6rem;
}

.btn-delete {
  flex: none;
  width: 1.8rem;
  height: 1.8rem;
  line-height: 1;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
  font-size: 1rem;
}

.btn-delete:hover {
  color: var(--error);
  border-color: var(--error);
}

.btn-add {
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  background: var(--panel);
  color: var(--accent);
  font-size: 0.85rem;
  cursor: pointer;
}

.btn-add:hover {
  border-color: var(--accent);
}

#results {
  max-width: 60rem;
  margin: 2rem auto 0;
}

#results h2 {
  font-size: 1.1rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.25rem;
}

/* Wraps the "Selected plan" h2 with the expand/collapse-all buttons; the row
   itself carries the border-bottom/padding #results h2 normally would, so
   the h2 inside doesn't double it up. */
.plan-heading-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.25rem;
}

/* #results h2's specificity (ID + element) beats a plain ".plan-heading-row
   > h2" class rule, so the override needs the #results prefix too, or the h2's
   own border-bottom (sized to its fit-content flex-item width, not the row's
   full width) still shows as a short underline under just the text. */
#results .plan-heading-row > h2 {
  border-bottom: none;
  padding-bottom: 0;
}

.plan-group-controls {
  display: flex;
  gap: 0.4rem;
  flex: none;
}

/* The report markdown nests h3/h4 under the pane's h2 (MarkdownDoc's
   heading_shift); unstyled they'd keep browser defaults, where h3 (1.17em)
   outsizes the 1.1rem h2 above and inverts the hierarchy. */
#results h3 {
  font-size: 0.95rem;
}

#results h4 {
  font-size: 0.85rem;
}

/* Each plan section (Fishing, Farming, Surplus, ...) collapses on its own
   (collapsePlanGroups in app.js wraps report.markdown_plan's h3-delimited
   groups into these); summary takes over #results h3's sizing since the
   original heading is gone. They wear the same boxed card + uppercase muted
   summary as details.pane (e.g. the "Required crafts" panel below). */
.plan-group {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 1rem;
  margin: 0 0 0.75rem;
}

.plan-group > summary {
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}

.plan-group > summary .summary-detail {
  text-transform: none;
  letter-spacing: normal;
  color: var(--muted);
}

.plan-group[open] > summary {
  margin-bottom: 0.75rem;
}

/* The critical path is pinned open as a static panel: drop the disclosure
   triangle and make the summary non-clickable so it can't be collapsed. */
.plan-group-static > summary {
  list-style: none;
  cursor: default;
  pointer-events: none;
}

.plan-group-static > summary::-webkit-details-marker {
  display: none;
}

/* The Goal report section is wrapped into a <details> by collapseGoalSection;
   its <summary> stands in for the original <h2>Goal</h2>, so it carries the
   same size/underline #results h2 has. */
.goal-group {
  margin: 0 0 1rem;
}

.goal-group > summary {
  font-size: 1.1rem;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.25rem;
}

.goal-group > summary .summary-detail {
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--muted);
}

.report-section table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  margin: 0.5rem 0 1rem;
}

.report-section th,
.report-section td {
  text-align: left;
  padding: 0.4rem 0.5rem;
  border-bottom: 1px solid var(--border);
}

.report-section th {
  color: var(--muted);
  font-weight: 600;
}

/* The impact graph (--graph's web counterpart, a self-contained inline SVG
   from report._svg_plot -- see the "graph" SectionedReporter section). The
   container scrolls rather than squashing the SVG's own fixed viewBox on a
   narrow viewport; the SVG's own <style> handles its .pt:hover state. */
#graph-section:not(:empty) {
  margin: 0.5rem 0 1rem;
  overflow-x: auto;
}

#graph-section svg {
  max-width: 100%;
  height: auto;
  display: block;
}

#frontier-section table tbody tr.clickable {
  cursor: pointer;
}

#frontier-section table tbody tr.clickable:hover {
  background: var(--panel);
}

#frontier-section table tbody tr.selected {
  background: var(--row-selected);
  font-weight: 600;
}

/* Left-edge bars flag the fastest and cheapest plans (independent of which row
   is selected). A row that is both takes the cheapest bar (this rule comes
   last); the coloured note tags below still show both facts. */
#frontier-section table tbody tr.fastest td:first-child {
  border-left: 3px solid var(--row-fastest-border);
}

#frontier-section table tbody tr.cheapest td:first-child {
  border-left: 3px solid var(--row-cheapest-border);
}

/* The matching "[fastest]" / "[cheapest]" words in the Notes column, tinted to
   reinforce the left-edge bars (wrapped in spans by wireFrontierRows). */
.tag-fastest {
  color: var(--row-fastest-border);
  font-weight: 600;
}

.tag-cheapest {
  color: var(--row-cheapest-border);
  font-weight: 600;
}

/* The crafts pane's summary already says "Required crafts": the markdown's
   own leading heading would just repeat it. */
#crafts-details {
  margin-top: 1.5rem;
}

#crafts-section > h3:first-child {
  display: none;
}

/* A Goal row with no known source at all (report.UNREACHABLE_GOAL_MARK, "✗",
   flagged client-side by markUnreachableGoalRows). Reuses the error palette,
   already tuned for contrast in both themes. */
#solution-section table tbody tr.unreachable-goal {
  background: var(--error-bg);
  color: var(--error);
}

.note {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
}

.warning {
  background: var(--warning-bg);
  color: var(--warning);
  border: 1px solid var(--warning);
  border-radius: 0.35rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
}

/* --- Cross-page navigation + the seeded-goal banner ----------------------- */

/* The link between the two pages, sitting above each page's <h1>. */
.page-nav {
  font-size: 0.85rem;
  margin-bottom: 0.35rem;
}

.page-nav a {
  color: var(--muted);
  text-decoration: none;
}

/* Pages carry more than one cross-link now, so they need space between them --
   the markup's single space alone reads as one run-on link. */
.page-nav a + a {
  margin-left: 1rem;
}

.page-nav a:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* Shown on the solver page only when it was opened from a mastery-costs row
   ("/?mastery=Item:TIER"), naming the goal it was seeded with. */
.seeded-banner {
  background: var(--row-selected);
  border: 1px solid var(--accent);
  border-radius: 0.35rem;
  padding: 0.5rem 0.75rem;
  margin: 0 0 0.75rem;
  font-size: 0.85rem;
}

/* --- Mastery-costs page --------------------------------------------------- */

/* Per-column sort button, sitting just after its header label (sizing borrowed
   from .help-icon, so the two read as the same family of inline affordances).
   The arrow glyph -- neutral, up or down -- is set by masteries.js for this
   page's table and by timeline.js for the timeline page's two; only the active
   column's button takes the accent. */
.sort-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  margin-left: 0.25rem;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 0.25rem;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.6rem;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
}

.sort-btn:hover,
.sort-btn:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  outline: none;
}

.sort-btn.active {
  color: var(--accent);
  border-color: var(--accent);
  font-weight: 600;
}

/* Sort + self-source controls, side by side above the table (the page has no
   preference panes, so these sit loose rather than inside a details.pane). */
.mastery-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 2rem;
}

.mastery-controls .field-row {
  margin: 0;
}

/* Right-aligned numeric columns (Time, Cost) -- the mastery-costs table is
   built in JS, so it tags its own cells rather than relying on the markdown
   tables' column alignment. */
.report-section th.num,
.report-section td.num {
  text-align: right;
  white-space: nowrap;
}

#mastery-costs-section table tbody tr.clickable {
  cursor: pointer;
}

#mastery-costs-section table tbody tr.clickable:hover {
  background: var(--panel);
}

#unmasterable-list,
#limited-list {
  margin: 0;
  padding-left: 1.2rem;
  font-size: 0.85rem;
}

#unmasterable-list li,
#limited-list li {
  margin-bottom: 0.2rem;
}

/* --- Mastery history + timeline ------------------------------------------- */

/* The "Save dated snapshot" row under the mastery paste box, and the summary of
   what is stored beside it. Not a .pane-hint: it sits inline in a flex row, so
   it carries no bottom margin of its own. */
.snapshot-row {
  margin: 0.5rem 0 0;
}

#snapshot-status {
  font-size: 0.8rem;
  color: var(--muted);
}

/* An error here (an unreadable paste, a browser that won't store) is worth
   colouring, but it is a hint beside a button -- no box, unlike .status-error. */
#snapshot-status.status-error {
  color: var(--error);
  background: none;
}

/* The timeline's progress chart: an inline SVG built client-side by
   timeline.js's chartSvg, sized exactly like the solver page's impact graph
   (the container scrolls rather than squashing the fixed viewBox). */
.timeline-chart {
  margin: 0.5rem 0 1rem;
  overflow-x: auto;
}

.timeline-chart svg {
  max-width: 100%;
  height: auto;
  display: block;
}

#timeline-index table tbody tr.clickable {
  cursor: pointer;
}

#timeline-index table tbody tr.clickable:hover {
  background: var(--panel);
}

/* Two quiet per-row links, styled alike: the mastery-costs table's "timeline"
   link, and the timeline index's next-goal link ("→ GM"). Both sit beside an
   item name without competing with it, and are marked out on hover -- the
   row's own click still goes to that row's own destination. */
.timeline-link,
.solver-link {
  font-size: 0.75rem;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}

.timeline-link:hover,
.solver-link:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* The tier name beside its token in the timeline table ("GM (Grandmaster)"). */
.muted-inline {
  color: var(--muted);
}

/* A checkbox and its own label sitting inline in a filter row -- unlike
   `.field-row label`, which is the row's 11rem label gutter. */
.field-row label.check {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.85rem;
  color: var(--fg);
}

/* The filter row's controls grow to fill the pane otherwise, which leaves an
   item-name box the width of the page. */
#material-input,
#zone-select {
  max-width: 18rem;
  flex: 1 1 12rem;
}

/* The chosen "made from" materials, one removable chip each, with Clear all
   riding along at the end of the same wrapping row. */
.material-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.5rem;
}

.material-chips[hidden] {
  display: none;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  padding: 0.15rem 0.3rem 0.15rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 1rem;
  background: var(--panel);
  font-size: 0.8rem;
}

/* The shared .btn-delete is a 1.8rem bordered square -- inside a pill that
   makes a box within a box, taller than the pill has room for. Here it is just
   the glyph, sized to the text it sits beside. */
.chip .btn-delete {
  width: 1.1rem;
  height: 1.1rem;
  border: none;
  border-radius: 50%;
  background: none;
  font-size: 0.85rem;
}

.chip .btn-delete:hover {
  background: var(--bg);
  color: var(--error);
}
