/* Cascade layers, in order: a later layer wins whatever the specificity.
   Every part sits in pages, in file order, so specificity and order
   decide there as in one flat file. overrides holds the few rules that
   must beat any page rule (the phone's chip folds, end of chip-folds.css),
   so they need no repeated classes. base and components stay empty: a
   shared part moved there would lose to every page rule, also where it
   wins by specificity today (the header's buttons against the plain
   button rule). An unlayered rule would beat every layer, so every rule
   sits in one. */
@layer base, components, pages, overrides;

@layer pages {
:root {
  /* One terminal language for the chrome (header, nav, panels)
     and the CRT screens inside it. Black to deep navy grounds; phosphor for
     what's live or chosen; muted mint for labels and figures; amber for
     ISK; a red kept for losses and warnings. */
  color-scheme: dark;
  accent-color: #00ff88;
  --black: #000000;
  --navy: #050a1d;
  --phosphor: #00ff88;
  --mint: #7dffb2;
  --amber: #ffb000;
  --red: #ff5c5c;
  /* JetBrains Mono everywhere: a UI mono readable at 10-12px, its figures
     all one width, so a column of numbers lines up digit for digit. */
  --mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;

  /* Chrome: panels and sheets on navy, framed in dim phosphor. */
  --panel-bg: #030817;
  --panel-bg-2: #07102a;
  --panel-border: rgba(0, 255, 136, 0.22);
  /* Under the brand mark's planet and its ring's knockout (index.html). */
  --header-bg: #01030b;

  /* Screens and what's in them. Contrast on --input-bg (#040b1a, the
     cards and fields; the screens are darker still): */
  --screen-bg: #01040c;
  --input-bg: #040b1a;
  --text: var(--phosphor);          /* 14.7:1 — headings, chosen, live */
  --text-bright: #d9ffe9;           /* 18:1 — names, field values */
  --mint-dim: #5bc08a;              /* 8.8:1 — table headers, field names */
  /* Secondary text: sub-lines, notes, explainers. 6.5:1. */
  --text-dim: #46a673;
  /* Small secondary text on phones (card labels, sub-lines): --text-dim is
     too faint at 11px on a phone in daylight, so phones get this one,
     8.8:1 — never below --text-dim. */
  --text-label: #5bc08a;
  --accent: var(--mint);            /* links and secondary actions */
  --line: rgba(125, 255, 178, 0.14);      /* rules and frames */
  --row-line: rgba(125, 255, 178, 0.08);  /* between a table's rows */
  /* A control's edge: 3.8:1 on navy, over WCAG's 3:1 for telling a field
     or a button from its ground. */
  --edge: #2e7a52;

  /* The five trade hubs' swatches (hud.js hubBarHtml, .hub-bar below):
     apart from the palette's meanings (phosphor, amber, red) and from each
     other, each 7:1 or more on navy. The Forge in Caldari blue, Domain in
     Amarr gold, Sinq Laison in Gallente teal, Heimatar in Minmatar rust,
     Metropolis in violet — both hubs of the Minmatar would have been rust. */
  --hub-forge: #4da3ff;
  --hub-domain: #f5d76e;
  --hub-sinq: #3fe0d0;
  --hub-heimatar: #ff7a59;
  --hub-metropolis: #c08cff;

  /* The scale the sheets space and size by: spacing steps (margin, padding,
     gap), the type sizes of controls and tables, and the phosphor at the four
     alphas it is used at most. A value off the scale snaps to the nearest
     step, a tie to the tighter. --chrome-gap is the space above a page's
     panel, --row-pad a table row's vertical padding (the density knob). */
  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 6px;
  --sp-4: 8px;
  --sp-5: 10px;
  --sp-6: 12px;
  --sp-7: 16px;
  --fs-xs: 10.5px;
  --fs-sm: 11px;
  --fs-md: 12px;
  --fs-lg: 13px;
  --phos-a10: rgba(0, 255, 136, 0.1);
  --phos-a20: rgba(0, 255, 136, 0.2);
  --phos-a35: rgba(0, 255, 136, 0.35);
  --phos-a60: rgba(0, 255, 136, 0.6);
  --chrome-gap: 12px;
  --row-pad: var(--sp-3);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* A column of at least the window's height, main taking what is left: a short
   page keeps its footer at the foot, and the footer's own bottom padding (the
   phone's bar) is always part of the page's length, so it can be scrolled
   clear. dvh is the visible height on a phone whose address bar comes and
   goes; vh is the fallback. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  position: relative;
  /* Black at the top to deep navy, under a faint HUD grid: calm behind the
     panels. Intentional: no starfield or corner glows, which fight the
     tables for attention. */
  background:
    linear-gradient(90deg, rgba(125, 255, 178, 0.022) 1px, transparent 1px) 0 0 / 48px 48px,
    linear-gradient(rgba(125, 255, 178, 0.022) 1px, transparent 1px) 0 0 / 48px 48px,
    linear-gradient(180deg, var(--black) 0, #020616 480px, var(--navy) 100%);
  background-color: var(--navy);
}

.status-leds { position: absolute; top: 12px; right: 32px; display: flex; gap: var(--sp-3); }
.led { width: 5px; height: 5px; border-radius: 50%; }
.led-green { background: var(--phosphor); box-shadow: 0 0 6px 1px rgba(0, 255, 136, 0.8); animation: led-pulse 3.1s ease-in-out infinite; }
.led-amber { background: var(--amber); box-shadow: 0 0 5px 1px rgba(255, 176, 0, 0.6); }
.led-off { background: #1a2a3a; }
@keyframes led-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }

header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-6) 28px;
  padding: var(--sp-7) 32px;
  position: relative;
  /* Higher than <main> and .site-nav (both z-index <= 30): header and main
     both create their own stacking context via position:relative, and at
     equal z-index later DOM siblings paint on top — so main's tables would
     bury the Trade settings dropdown (z-index:50, but scoped inside
     header's own stacking context) however high its own z-index. */
  z-index: 60;
  border-bottom: 1px solid var(--panel-border);
  /* A planet's horizon rising at the bottom right, lit green along its rim:
     its top always 20px above the header's bottom edge, however tall the
     header wraps. Backgrounds only, since the header can't clip — the Trade
     settings panel hangs out of it. */
  background:
    radial-gradient(circle at 88% calc(100% + 960px), transparent 979px, rgba(0, 255, 136, 0.65) 980px, rgba(0, 255, 136, 0.16) 983px, rgba(0, 255, 136, 0.04) 995px, transparent 1030px),
    radial-gradient(circle at 88% calc(100% + 960px), #030a1f 980px, transparent 981px),
    radial-gradient(ellipse 560px 90px at 88% 100%, rgba(0, 255, 136, 0.09), transparent 70%),
    linear-gradient(180deg, var(--black) 0%, var(--header-bg) 100%);
  box-shadow: 0 1px 0 rgba(0, 255, 136, 0.06), 0 6px 18px rgba(0, 0, 0, 0.6);
}

.header-title {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  min-width: 0;
}

.brand-mark {
  flex: none;
  width: 46px;
  height: 46px;
  color: var(--phosphor);
  filter: drop-shadow(0 0 4px var(--phos-a60));
}

.brand-mark-fill { fill: var(--header-bg); }
.brand-mark-knockout { stroke: var(--header-bg); }

header h1 {
  margin: 0;
}

/* Widely tracked caps; the negative right margin takes back the tracking
   after the last letter, so it doesn't push the tagline off centre. */
.wordmark {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: 0.32em;
  margin-right: -0.32em;
  line-height: 1;
  color: var(--text-bright);
  text-shadow: 0 0 12px rgba(0, 255, 136, 0.55), 0 0 2px rgba(0, 255, 136, 0.8);
}

.subtitle {
  margin: var(--sp-3) 0 0;
  color: var(--mint-dim);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* The kicker and its blinking block cursor, on a screen wide enough to
   hold it beside the brand and the tools, never on a phone: on a narrower
   one it wraps the tools onto a second header row. */
.header-kicker { display: none; }

@media (min-width: 1420px) {
  .header-kicker {
    display: block;
    margin: 0;
    padding-left: var(--sp-7);
    border-left: 1px solid var(--line);
    color: var(--mint);
    font-size: var(--fs-md);
    letter-spacing: 0.06em;
  }

  .header-kicker::before { content: "> "; color: var(--phosphor); }

  .header-kicker::after {
    content: "";
    display: inline-block;
    width: 0.6em;
    height: 1.1em;
    margin-left: var(--sp-2);
    vertical-align: -0.22em;
    background: var(--phosphor);
    box-shadow: 0 0 8px rgba(0, 255, 136, 0.7);
    animation: cursor-blink 1.1s steps(1) infinite;
  }
}

@keyframes cursor-blink { 50% { opacity: 0; } }

.header-tools {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  margin-left: auto;
}

/* The order sync's age, with a status light: phosphor while fresh, amber
   when stale (settings.js initDataAge). */
.data-age { font-size: var(--fs-sm); letter-spacing: 0.03em; color: var(--mint-dim); }

/* A phone shows the short form (phone.css); the full line is the tip. */
.data-age-short { display: none; }

.data-age:not(:empty)::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: var(--sp-4);
  vertical-align: 1px;
  border-radius: 50%;
  background: var(--phosphor);
  box-shadow: 0 0 6px rgba(0, 255, 136, 0.8);
}

.data-age-stale { color: var(--amber); }
.data-age-stale:not(:empty)::before { background: var(--amber); box-shadow: 0 0 6px rgba(255, 176, 0, 0.7); }

.settings-widget { position: relative; }

.settings-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  background: rgba(0, 255, 136, 0.04);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--mint);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: var(--sp-4) var(--sp-6);
}

.settings-btn:hover, .settings-btn[aria-expanded="true"] {
  border-color: var(--phosphor);
  background: rgba(0, 255, 136, 0.08);
  color: var(--phosphor);
  box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);
}

.settings-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 50;
  width: 440px;
  max-width: calc(100vw - 32px);
  background: var(--panel-bg);
  border: 1px solid var(--phos-a35);
  border-radius: 2px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.75), 0 0 24px rgba(0, 255, 136, 0.08);
  padding: var(--sp-6) var(--sp-7);
  color: var(--mint);
  font-size: var(--fs-md);
}

.settings-panel.hidden { display: none; }

/* Phone-only (see the 768px block): the panel's Done row and the backdrop
   behind it. A desktop closes the panel by clicking anywhere outside it. */
.settings-panel-head, .settings-backdrop { display: none; }

.settings-presets { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-6); }

.settings-label, .settings-grid label {
  color: var(--mint-dim);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.settings-chip {
  background: transparent;
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--mint);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: var(--sp-2) var(--sp-5);
}

.settings-chip:hover { border-color: var(--phosphor); color: var(--phosphor); background: rgba(0, 255, 136, 0.08); }

.settings-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-5) var(--sp-6);
}

.settings-grid label { display: flex; flex-direction: column; gap: var(--sp-2); }

.settings-grid select, .settings-grid input {
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: inherit;
  font-size: var(--fs-md);
  letter-spacing: 0;
  text-transform: none;
  padding: var(--sp-3) var(--sp-4);
}

.settings-grid select:focus, .settings-grid input:focus {
  outline: none;
  border-color: var(--phosphor);
  box-shadow: 0 0 8px rgba(0, 255, 136, 0.3);
}

.settings-summary { margin: var(--sp-6) 0 0; color: var(--text-dim); line-height: 1.5; }
.settings-summary strong { color: var(--phosphor); }

main {
  flex: 1 0 auto;
  width: min(1680px, 98vw);
  margin: 0 auto;
  padding: var(--chrome-gap) var(--sp-7) 60px;
  position: relative;
  z-index: 2;
}

}
@layer pages {
/* A panel: a thin, dim phosphor frame around its CRT screen, with a
   brighter tick at each corner. The screen fills it; its header bar
   (.section-header) runs across the top. */
.search-section, .opportunities-section {
  scroll-margin-top: 60px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 2px;
  padding: 0;
  margin-bottom: 28px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55), 0 0 32px rgba(0, 255, 136, 0.035);
  position: relative;
}

.search-section::after, .opportunities-section::after {
  --tick: rgba(0, 255, 136, 0.75);
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 3;
  pointer-events: none;
  background:
    linear-gradient(var(--tick), var(--tick)) left top / 12px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) left top / 1px 12px no-repeat,
    linear-gradient(var(--tick), var(--tick)) right top / 12px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) right top / 1px 12px no-repeat,
    linear-gradient(var(--tick), var(--tick)) left bottom / 12px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) left bottom / 1px 12px no-repeat,
    linear-gradient(var(--tick), var(--tick)) right bottom / 12px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) right bottom / 1px 12px no-repeat;
}

.module-page { display: none; }
.module-page.page-active { display: block; }

/* --pad-y / --pad-x: the screen's padding, which its header bar reaches
   across with negative margins (.section-header). */
.screen {
  --pad-y: 18px;
  --pad-x: 20px;
  background:
    radial-gradient(ellipse 120% 70% at 50% 0%, rgba(0, 255, 136, 0.035), transparent 60%),
    var(--screen-bg);
  padding: var(--pad-y) var(--pad-x);
  font-family: var(--mono);
  color: var(--text);
  position: relative;
  overflow: hidden;
}

.screen::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,0.18) 0px, rgba(0,0,0,0.18) 1px, transparent 1px, transparent 3px);
  pointer-events: none;
}

.screen > .crt-sweep {
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  overflow: hidden;
  mix-blend-mode: screen;
  animation: crt-flicker 6.3s infinite;
}

.crt-sweep::before {
  content: "";
  position: absolute; inset: 0;
  background-image: repeating-linear-gradient(90deg, rgba(255,40,60,0.05) 0px, rgba(255,40,60,0.05) 1px, rgba(40,255,90,0.04) 1px, rgba(40,255,90,0.04) 2px, rgba(40,140,255,0.05) 2px, rgba(40,140,255,0.05) 3px, transparent 3px, transparent 4px);
}

.crt-sweep::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: -50%;
  height: 200%;
  background-image: linear-gradient(180deg, transparent 0%, rgba(255,255,255,0.08) 8%, transparent 16%, transparent 100%);
  background-repeat: repeat-y;
  background-size: 100% 50%;
  animation: crt-sweep-t 14s linear infinite;
  will-change: transform;
}

@keyframes crt-sweep-t {
  0% { transform: translateY(0%); }
  100% { transform: translateY(50%); }
}

@keyframes crt-flicker {
  0%, 92%, 100% { opacity: 0.9; }
  92.5% { opacity: 0.65; }
  93% { opacity: 0.9; }
  95% { opacity: 0.7; }
  95.5% { opacity: 0.9; }
}

.screen > * { position: relative; }

.screen a { color: var(--accent); text-underline-offset: 2px; }
.screen a:hover { color: var(--phosphor); }

/* A terminal prompt before the search box. */
.search-input-wrap { position: relative; }

.search-input-wrap::before {
  content: ">";
  position: absolute;
  left: 13px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  color: var(--phosphor);
  font-weight: 700;
  text-shadow: 0 0 6px var(--phos-a60);
  pointer-events: none;
}

/* The search screen's .screen has overflow:hidden (it clips the CRT scanline
   sweep to its own box), which also clips the search-results dropdown at
   the screen's current height: invisible on a first search, before
   #item-detail has grown the box tall enough to fit it. The
   dropdown is the only thing in this screen that needs to render past its
   own box, so this is scoped to the search page rather than turned on
   everywhere (removing overflow:hidden site-wide would let the sweep
   overlay bleed outside its box on every other screen too). */
#item-search .screen { overflow: visible; }

#search {
  width: 100%;
  padding: var(--sp-6) var(--sp-6) var(--sp-6) 32px;
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: 14px;
}

#search::placeholder, .filter-search::placeholder, .controls input::placeholder { color: var(--text-dim); }

#search:focus, .controls input:focus, .controls select:focus, .filter-search:focus, .section-header :where(input, select):focus {
  outline: none;
  border-color: var(--phosphor);
  box-shadow: 0 0 0 1px var(--phos-a20), 0 0 10px rgba(0, 255, 136, 0.3);
}

/* The "/" key hint, a keycap at the box's right end: "/" on any page comes
   here (itemsearch.js). Gone while the box has the focus, and on a touch
   screen or a phone, with no key to press (the phone block too: a narrow
   desktop window gets the phone's page). */
.search-kbd {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  min-width: 22px;
  padding: var(--sp-1) var(--sp-3);
  background: rgba(0, 255, 136, 0.05);
  border: 1px solid var(--edge);
  border-radius: 2px;
  box-shadow: inset 0 -1px 0 rgba(0, 255, 136, 0.25);
  color: var(--mint);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  pointer-events: none;
}

#search:focus + .search-kbd { display: none; }

@media (hover: none) {
  .search-kbd { display: none; }
}

.search-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--input-bg);
  border: 1px solid var(--phos-a35);
  border-radius: 2px;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.6);
  margin-top: var(--sp-2);
  max-height: 240px;
  overflow-y: auto;
  z-index: 10;
}

.search-results:empty { display: none; }

.search-result-item {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-6);
  min-height: 38px;
  cursor: pointer;
  font-size: var(--fs-lg);
  color: var(--text-bright);
  border-bottom: 1px solid var(--row-line);
}

.search-result-item .type-icon { margin: 0; flex: none; }

.search-result-item:hover, .search-result-item.active { background: rgba(0, 255, 136, 0.08); box-shadow: inset 2px 0 0 var(--phosphor); }

.item-detail {
  margin-top: var(--sp-6);
  background: var(--input-bg);
  border: 1px solid var(--line);
  border-radius: 2px;
  /* Narrower at the sides than it's tall: every pixel goes to the order
     tables' columns. */
  padding: var(--sp-6) var(--sp-5);
}

.item-detail.hidden { display: none; }

/* The item's name, after its icon (itemsearch.js showName). */
.item-detail h3 {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  margin-top: 0;
  color: var(--text-bright);
  font-size: 17px;
  letter-spacing: 0.02em;
  text-shadow: 0 0 8px var(--phos-a35);
}

.item-detail h3 .type-icon-lg { width: 40px; height: 40px; margin: 0; flex: none; }

.item-detail table { width: 100%; }

}
@layer pages {
/* Item search (itemsearch.js). The strip comparing the five regions: one
   cell each, in a row. A desktop wraps it on the rare item whose prices
   are too long to fit (a mouse wheel doesn't scroll sideways); a phone or
   a tablet scrolls it sideways instead, like the nav (the blocks below).
   With no scrollbar, an edge with more cells beyond it fades (fade-left /
   fade-right, set as it scrolls), as the phone tab bar's do; a strip that
   fits isn't faded at all. A cell is a button: it picks the region the
   tables show. The cells' 8px sides and narrow gaps are what fit most
   items' six cells on one 1440px row; any wider, a module's or a drone's
   leaves The Forge alone on a second one. */
.item-ticker {
  display: flex;
  flex-wrap: wrap;
  /* 5px, and the 10px beside a region's name below: any wider and the six
     cells don't fit a 1366px laptop's row. */
  gap: var(--sp-2);
  overflow-x: auto;
  scrollbar-width: none;
  margin-bottom: var(--sp-6);
}

.item-ticker::-webkit-scrollbar { display: none; }

.item-ticker.fade-right {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
}

.item-ticker.fade-left {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px);
  mask-image: linear-gradient(90deg, transparent 0, #000 28px);
}

.item-ticker.fade-left.fade-right {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}

/* position: the containing block of its visually-hidden "(cheapest)": one
   outside the strip's scroller escapes its clipping, and a cell scrolled
   out of a phone's view would widen the whole page to reach it. The cell
   keeps its 11px text and 8px sides (the strip's fit, above). */
.ticker-cell {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  padding: var(--sp-3) var(--sp-4);
  background: rgba(0, 255, 136, 0.02);
  border-color: var(--line);
  border-radius: 2px;
  color: var(--text-bright);
  font-size: var(--fs-sm);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  text-align: left;
  white-space: nowrap;
}

.ticker-cell:hover { border-color: var(--mint-dim); color: var(--text-bright); }

/* The global market (PLEX) has no strip legend, hub filter or region note
   to show; its cell is a box, not a button: nothing to pick. */
.ticker-legend[hidden], .item-filters .control-check[hidden], #item-global-note[hidden] { display: none; }
.ticker-global { border: 1px solid var(--line); cursor: default; }
.ticker-global:hover { border-color: var(--line); }

.ticker-cell.active {
  border-color: var(--phosphor);
  background: var(--phos-a10);
  box-shadow: 0 0 8px rgba(0, 255, 136, 0.3), inset 0 0 8px rgba(0, 255, 136, 0.08);
}

/* A touch screen keeps :hover on the last cell tapped, so a region tapped
   again to clear it would go on looking picked, beside All regions, which
   is. Only the picked cell looks picked there. */
@media (hover: none) {
  .ticker-cell:not(.active):hover { background: rgba(0, 255, 136, 0.02); border-color: var(--line); color: var(--text-bright); }
}

/* The strip's tips for a touch screen, where a cell's tap picks its
   region instead of showing them (a .last-sync tip, app.js). */
.ticker-legend { display: none; }

@media (hover: none) {
  /* Its words padded to a finger's 32px, so a tap finds them. */
  .ticker-legend { display: block; margin: -8px 0 var(--sp-2); }
  .ticker-legend > span { display: inline-block; padding: 9px 0; }
}

.ticker-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-5); align-self: stretch; }

.ticker-region {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--mint);
}

.ticker-k {
  display: inline-block;
  min-width: 3.4em;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

.ticker-hub, .ticker-sub { font-size: var(--fs-xs); color: var(--text-dim); }

/* The cheapest sell and the highest buy of the five. */
.ticker-best-sell, .ticker-best-buy { font-weight: 700; padding: 0 var(--sp-1); border-radius: 2px; }
.ticker-best-sell { background: rgba(0, 255, 136, 0.18); color: var(--phosphor); text-shadow: 0 0 5px rgba(0, 255, 136, 0.5); }
.ticker-best-buy { background: rgba(255, 176, 0, 0.16); color: var(--amber); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.item-filters { margin-bottom: var(--sp-2); }

/* The LP store's fifteen columns overflow their pane below 1600px, the
   pinned "+ Notebook" hiding the columns under it. There every cell has 3px a
   side, 4px less than elsewhere, the item's icon moved in with them
   (td.has-icon), and the "ISK" after Value's and ISK cost's figures may go
   under them rather than set those columns' widths. 1440px is the width
   that fits every page of every Show; narrower, some pages still overflow.
   The cost is height: rows a line taller. A phone's cards keep their own
   padding. */
@media (min-width: 769px) and (max-width: 1599px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #lp-table :is(td, .th-sort-btn, th.order-col) { padding-left: var(--sp-1); padding-right: var(--sp-1); }
  #lp-table td.has-icon { padding-left: 30px; }
  #lp-table td.has-icon > .type-icon { left: 3px; }
  #lp-table td:is([data-label="Value"], [data-label="ISK cost"]) { white-space: normal; }
  /* Station trading grew a Turnover/day column; the same tighter cells keep
     its table inside the pane down to 1366px. */
  #station-table :is(td, .th-sort-btn, th.order-col) { padding-left: var(--sp-1); padding-right: var(--sp-1); }
  #station-table td.has-icon { padding-left: 30px; }
  #station-table td.has-icon > .type-icon { left: 3px; }
}

/* Item search's "Observed at the hubs" (itemsearch.js renderFlow): our own
   snapshots' flow, secondary to everything above it — under the order
   tables, ruled off from them, its heading not the tables' own style. One
   row per region, each side's three windows ruled off as a group; a
   figure's second and third lines (≈ estimate, time watched) are notes. */
.item-flow { margin-top: 28px; padding-top: var(--sp-6); border-top: 1px dashed var(--line); }

.item-flow-title {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-md);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--mint);
}

.item-flow-table th { padding: var(--sp-3) var(--sp-4); text-align: right; vertical-align: bottom; }
.item-flow-table th:first-child { text-align: left; }
.item-flow-table th.flow-group { text-align: center; border-bottom: 1px solid var(--line); }
.item-flow-table td { padding: var(--sp-3) var(--sp-4); vertical-align: top; }
.item-flow-table .flow-start { border-left: 1px solid var(--line); }

.item-flow-table td.flow-region {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-bright);
  white-space: nowrap;
}

/* "–up to" in the label colour (brighter than --text-dim), kept whole when
   a narrow column puts it on a line of its own (a phone's card may break
   it before the number: see the phone block). */
.flow-upto { white-space: nowrap; color: var(--text-label); }

/* A phone card's line naming the side above its three windows; a desktop
   has the table's group headers. */
.item-flow-table .flow-side-head { display: none; }

/* A touch screen's tip (initTapTips, app.js) opens on a tap on the words
   that have one: each figure's, ~14px tall, padded out to a finger's
   32px — the negative margins keep the lines and the figure in place.
   Across too: a lone "0" or "—" (most of a quiet item's cells) is a
   7px-wide target. At least 40px: 8px before the figure (into the column
   gap, or the card's edge) and the rest after it — or, in a right-aligned
   cell, before it. Nothing reaches past the cell's right edge, so no row
   or card gets wider. */
@media (hover: none) {
  .item-flow-table td span[title] {
    display: inline-block;
    min-width: 40px;
    padding: 9px 0 9px var(--sp-4);
    margin: -9px 0 -9px -8px;
  }
}

/* "Also:" under the item's name (itemsearch.js showAlso): links to where else
   the site uses the item, only those that apply. The links' hit areas grow
   by padding the lines take back, so the line keeps its height. */
.item-also {
  margin: calc(-1 * var(--sp-3)) 0 var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-label);
}
.item-also[hidden] { display: none; }
.item-also a {
  display: inline-block;
  padding: 9px 3px;
  margin: -9px 0;
  color: var(--phosphor);
}
.item-also a:hover, .item-also a:focus-visible { text-decoration: underline; }

/* The decision strip under the item's name (itemsearch.js renderPaths): up to
   three paths, one line each: the path, its figure and the page that takes it
   on. The figure wraps under the name on a narrow screen; the link's hit area
   grows by padding the line takes back. */
.item-paths {
  display: grid;
  gap: var(--sp-2);
  margin: calc(-1 * var(--sp-3)) 0 var(--sp-3);
  font-size: var(--fs-sm);
}
.item-paths[hidden] { display: none; }
.item-path {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--sp-4);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--edge);
}
.item-path-k {
  flex: 0 0 5.5em;
  color: var(--phosphor);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--fs-xs);
}
.item-path-fig { flex: 1 1 12em; min-width: 0; overflow-wrap: anywhere; }
.item-path > a {
  display: inline-block;
  padding: 9px 3px;
  margin: -9px 0;
  color: var(--phosphor);
  white-space: nowrap;
}
.item-path > a:hover, .item-path > a:focus-visible { text-decoration: underline; }
.item-paths:not([hidden]) + .item-also { margin-top: 0; }
@media (pointer: coarse) {
  .item-path > a { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; margin: 0; }
  .item-path { align-items: center; }
}

/* A system or region in the search box (itemsearch.js placeRow): its name,
   and its links to the Route planner, the War room and Outposts. The row
   itself does nothing, so a tap lands on a link. */
.search-result-place {
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--sp-1) var(--sp-5);
  cursor: default;
}
.srp-name { display: inline-flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.srp-links { display: flex; flex-wrap: wrap; gap: 0 var(--sp-5); font-size: var(--fs-sm); }
.srp-link {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: var(--phosphor);
}
.srp-link:hover, .srp-link:focus-visible { text-decoration: underline; }

/* Before an item is open (itemsearch.js renderHome): the items opened on this
   device and one line of today, each a link, under the search box. */
.item-home { display: flex; flex-direction: column; gap: var(--sp-4); margin: var(--sp-6) 0 var(--sp-4); }
.item-home[hidden], .item-home-row[hidden] { display: none; }
.item-home-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-6); margin: 0; font-size: var(--fs-md); color: var(--text-label); }
.item-home-label { flex: 0 0 auto; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-dim); }
.item-home-links { display: flex; flex: 1 1 0; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-7); min-width: 12em; }
.item-home-item { color: var(--text-bright); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .item-home-row { flex-direction: column; align-items: stretch; gap: 0; }
  .item-home-links { flex-basis: auto; }
}

}
@layer pages {
/* A screen's header bar, "TITLE // context": the title in
   phosphor, its context in muted mint, across the top of the screen
   (reaching its edges through the screen's padding, --pad-x/--pad-y),
   and a meta slot at the right end — the order sync's time, set by
   settings.js showSectionMeta. The page's controls follow on a row of
   their own. */
.section-header {
  position: relative;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-6);
  margin: calc(-1 * var(--pad-y)) calc(-1 * var(--pad-x)) var(--sp-6);
  padding: 0 var(--pad-x);
}

.section-header h2 {
  flex: 1 1 100%;
  margin: 0 calc(-1 * var(--pad-x));
  padding: var(--sp-4) var(--pad-x);
  background: linear-gradient(90deg, var(--phos-a10), rgba(0, 255, 136, 0.03) 55%, transparent);
  border-bottom: 1px solid var(--panel-border);
  font-size: var(--fs-lg);
  font-weight: 700;
  line-height: 1.35;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--phosphor);
  text-shadow: 0 0 6px rgba(0, 255, 136, 0.45);
}

/* Room for the stale stamp at the right end of the bar, only while it shows. */
.section-header:has(> .section-meta:not([hidden])) h2 { padding-right: 170px; }

.section-header h2::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 0.95em;
  margin-right: var(--sp-5);
  vertical-align: -0.1em;
  background: var(--phosphor);
  box-shadow: 0 0 6px rgba(0, 255, 136, 0.7);
}

.section-context {
  color: var(--mint-dim);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-shadow: none;
}

/* The slashes are decoration: a screen reader says the title and its
   context, not "slash slash". */
.section-context::before { content: "// "; content: "// " / ""; color: var(--text-dim); }

.section-meta {
  position: absolute;
  top: 0;
  right: var(--pad-x);
  height: 34px;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mint-dim);
  white-space: nowrap;
}

.section-meta::after {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--phosphor);
  box-shadow: 0 0 6px rgba(0, 255, 136, 0.8);
  animation: led-pulse 3.1s ease-in-out infinite;
}

.section-meta[hidden] { display: none; }

.section-meta-stale { color: var(--amber); }
.section-meta-stale::after { background: var(--amber); box-shadow: 0 0 6px rgba(255, 176, 0, 0.7); animation: none; }

.section-header > .controls { flex: 1 1 100%; }

/* The title bar (pageHead in core.js): the title on one line, its full words
   in the tooltip, and the page's tools at the right end — its links, the
   stale stamp and "How it works", which opens the explainer. The bar carries
   the title's backdrop; the title inside it only its type. */
.section-header > .head-bar {
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  min-width: 0;
  margin: 0 calc(-1 * var(--pad-x));
  padding: 0 var(--pad-x);
  background: linear-gradient(90deg, var(--phos-a10), rgba(0, 255, 136, 0.03) 55%, transparent);
  border-bottom: 1px solid var(--panel-border);
}
.section-header .head-bar > h2 {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: var(--sp-4) 0;
  background: none;
  border: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.head-tools { display: flex; flex: 0 0 auto; align-items: center; gap: var(--sp-5); font-size: var(--fs-xs); }
.head-tools:empty { display: none; }
.head-link { display: inline-flex; align-items: center; min-height: 28px; white-space: nowrap; }
/* Page links beyond the first (core.js pageHead): inline on a desktop, behind
   a "Links" button on a phone (phone.css). */
.head-links { display: contents; }
.head-links-btn { display: none; }
.head-tools > .section-meta { position: static; height: auto; }

/* "How it works": a small labelled button on a desktop, a "?" on a phone. */
.head-help {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 26px;
  padding: var(--sp-1) var(--sp-4);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  color: var(--mint-dim);
  border-color: var(--edge);
  background: transparent;
}
.head-help:hover, .head-help[aria-expanded="true"] { color: var(--phosphor); border-color: var(--phosphor); }
.head-help-mark { font-weight: 700; color: var(--phosphor); }

/* The explainer takes no row of its own: closed, the title bar's button is
   its way in; open, it shows where the page has it. */
.module-page details.explainer.head-explained:not([open]) { display: none; }

.controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-5) var(--sp-6);
  font-size: var(--fs-xs);
  color: var(--mint-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.controls input, .controls select {
  width: 70px;
  padding: var(--sp-3) var(--sp-4);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: var(--fs-md);
  letter-spacing: 0;
  text-transform: none;
}

.controls select { width: auto; }

/* A field in a page head outside a .controls row (a head that folds itself,
   data-filters-fold on .section-header: Outposts' Other region, the Wormhole
   atlas' Find) wears the same skin. :where keeps it below the .controls
   rules, which also size their fields. */
.section-header :where(input:not([type="checkbox"]):not([type="radio"]), select) {
  padding: var(--sp-3) var(--sp-4);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: var(--fs-md);
  letter-spacing: 0;
  text-transform: none;
}
.section-header :where(input)::placeholder { color: var(--mint-dim); opacity: 1; }

.controls-group { display: inline-flex; align-items: center; gap: var(--sp-3); }

.hub-multiselect {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-5);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  padding: var(--sp-3) var(--sp-4);
}

.hub-check {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-sm);
  font-weight: normal;
  color: var(--text-bright);
  cursor: pointer;
}

/* Outlined terminal buttons: uppercase and tracked, lit phosphor under the
   pointer. */
button {
  padding: var(--sp-3) var(--sp-6);
  background: rgba(0, 255, 136, 0.02);
  color: var(--mint);
  border: 1px solid var(--edge);
  border-radius: 2px;
  font-weight: 700;
  cursor: pointer;
  font-size: var(--fs-sm);
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

button:hover { background: rgba(0, 255, 136, 0.08); border-color: var(--phosphor); color: var(--phosphor); }

button:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }

/* A page's main action: outlined too, with a phosphor glow. */
.btn-primary {
  background: var(--phos-a10);
  color: var(--phosphor);
  border: 1px solid var(--phosphor);
  box-shadow: 0 0 10px var(--phos-a35), inset 0 0 8px rgba(0, 255, 136, 0.12);
  text-shadow: 0 0 6px var(--phos-a60);
}

.btn-primary:hover { background: rgba(0, 255, 136, 0.18); box-shadow: 0 0 16px rgba(0, 255, 136, 0.5), inset 0 0 8px rgba(0, 255, 136, 0.18); }

/* overflow-wrap: a zero-row status prints the filters as id lists with no
   space in them ("exclude_market=[1612,1659,...]"). With Default's market
   groups that one word is wider than a phone's line: cut off at the edge,
   and with the filter sheet open (.screen's overflow visible) it would
   widen the page past Done and the tab bar. It breaks inside a word only
   where a line would overflow. */
.last-sync {
  color: var(--text-dim);
  font-size: var(--fs-md);
  line-height: 1.55;
  margin-bottom: var(--sp-6);
  font-family: var(--mono);
  overflow-wrap: anywhere;
}

.last-sync::before { content: "> "; color: var(--phosphor); opacity: 0.8; }

/* A status line with nothing to say yet would print its lone "> " prompt, and
   one a page hides is out of the layout. !important: a phone clamps the notes
   above the results with a display of its own (chip-folds.css), which would
   otherwise bring both back as empty lines. */
.last-sync:empty, .last-sync[hidden] { display: none !important; }

.last-sync strong { color: var(--mint); }

/* A page's status block (pageStatus, core.js): the status line, a warning
   with an action after it, and at the line's end the notes' toggle and the
   table's pager. The notes open under the line. */
.page-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-6);
  margin-bottom: var(--sp-4);
}
.page-status > .last-sync { flex: 1 1 24em; min-width: 0; margin: 0; }
.page-status > .page-warn { flex: 0 1 auto; color: var(--amber); }
.page-status > .page-warn::before { content: "! "; color: var(--amber); }
.page-status > .status-tools { order: 1; display: none; align-items: center; gap: var(--sp-4); margin-left: auto; }
.page-status > .status-tools:has(.notes-toggle:not([hidden]), .pagination:not(:empty, [hidden])) { display: flex; }
.page-status > .page-note { order: 2; flex: 1 1 100%; display: none; }
.page-status.notes-open > .page-note { display: block; }
/* A table's title on its status line: the title, then the count beside it. */
.page-status > .status-title { flex: 0 0 auto; margin: 0; }
.page-status:has(> .status-title) { margin-top: var(--sp-7); }

.notes-toggle {
  padding: var(--sp-1) var(--sp-5);
  font-size: var(--fs-xs);
  color: var(--mint-dim);
  background: transparent;
}
.notes-toggle::after { content: " ▾"; }
.notes-open .notes-toggle::after { content: " ▴"; }
.notes-toggle[hidden] { display: none; }
.notes-toggle.notes-warn { color: var(--amber); border-color: var(--amber); }

/* A one-line strip under a page's title for a state the whole page is in (the
   Capsuleer demo): a tag, a short text that says the rest in its tip (a
   hover title; a tap on a touch screen, initTapTips), and an optional link at
   the end. On a narrow screen the text wraps and the link drops to its own
   line rather than squeeze the text. */
.page-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--sp-5);
  margin: var(--sp-3) 0;
  padding: var(--sp-1) var(--sp-5);
  border: 1px solid var(--edge);
  border-left-width: 4px;
  font-size: var(--fs-md);
  line-height: 1.5;
  color: var(--text-bright);
}

.page-banner p { margin: 0; }

.page-banner-text { flex: 1 1 16em; min-width: 0; }

.page-banner-info { color: var(--text-dim); }

.page-banner-demo { border-color: var(--amber); background: rgba(255, 176, 0, 0.07); }

.page-banner a { display: inline-block; padding: var(--sp-2) 0; color: var(--amber); text-decoration: underline; }

/* A Cargo manifest that a phone folds away: always open here, with no
   summary, so a desktop shows it exactly as a plain block. On a phone
   (768px block) the summary shows and it starts closed (syncPhoneFolds in
   app.js). A page's explainer (.explainer) folds on every screen (it is
   one or two screens of text between the controls and the results), so
   its summary, "▸ How this works", shows here too.
   The summary's look lives here once; the phone block only turns it on. */
.page-jump { display: none; }
.phone-fold > summary {
  display: none;
  cursor: pointer;
  list-style: none;
  padding: var(--sp-5) 0;
  margin-bottom: var(--sp-2);
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.phone-fold > summary::-webkit-details-marker { display: none; }
.phone-fold > summary::before { content: "▸ "; color: var(--phosphor); }
.phone-fold[open] > summary::before { content: "▾ "; }
.phone-fold.explainer > summary { display: block; }
.phone-fold.explainer:not([open]) { margin-bottom: var(--sp-3); }

/* A table is as tall as its rows and the page scrolls it: no pane with a
   scroll of its own to fight the wheel, since the rows are paged (pagination.js
   rowsPerPage) to a height the page can hold. Only a table wider than the
   screen scrolls, sideways, inside its box. A phone's tables are cards
   (phone block). */
.table-scroll {
  /* What the table sits on, for the cells that have to be opaque (the pinned
     "+ Notebook", below): the screen, or Item search's lighter box. */
  --table-bg: var(--screen-bg);
  overflow-x: auto;
  scrollbar-color: var(--edge) transparent;
  scrollbar-width: thin;
  /* Keeps the stuck cells' z-indexes (below) inside the box, under the
     screen's CRT sweep like the rest of the table. */
  isolation: isolate;
}

.item-detail .table-scroll { --table-bg: var(--input-bg); }

.table-scroll::-webkit-scrollbar { width: 8px; height: 8px; }
.table-scroll::-webkit-scrollbar-thumb { background: var(--edge); border-radius: 0; }
.table-scroll::-webkit-scrollbar-track, .table-scroll::-webkit-scrollbar-corner { background: transparent; }

}
@layer pages {
/* --- HUD tables ---
   EVE's own market window as the model: dense rows (~29px) on hairline
   separators with a barely-there zebra, small uppercase muted-mint headers
   over a phosphor rule, a hover band with a phosphor edge, and figures
   that read by colour — ISK amber, a profit phosphor, a loss red (hud.js
   marks it), everything else mint; a name near-white after its item's
   icon. "+ Notebook" sticks to the right edge of a table wider than the screen
   (see "Wide tables", below). */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
  line-height: 1.4;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

th, td {
  padding: var(--row-pad) var(--sp-3);
  text-align: left;
  border-bottom: 1px solid var(--row-line);
}

th {
  color: var(--mint-dim);
  font-weight: 600;
  text-transform: uppercase;
  font-size: var(--fs-xs);
  line-height: 1.3;
  letter-spacing: 0.09em;
  vertical-align: bottom;
  background: rgba(0, 255, 136, 0.035);
  border-bottom: 1px solid rgba(0, 255, 136, 0.55);
  padding: var(--row-pad) var(--sp-3);
}

/* A sortable header's button carries the padding (sortable.js), so the
   whole cell is its target. */
th:has(> .th-sort-btn) { padding: 0; }

td { color: var(--mint); }

tbody tr:nth-child(even) { background: rgba(125, 255, 178, 0.022); }

/* Sits the filter widget and a table's bulk "add to order book" buttons
   (Fill industry slots / Add diverse selection) on the same row instead of
   stacking them — they're both "narrow down or bulk-act on what's below",
   just via different mechanisms. Wraps on narrow screens rather than
   squeezing. */
.filter-and-bulk-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-5);
  margin-bottom: var(--sp-5);
}

.bulk-add-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}

/* Numbers read by magnitude, not by where their leftmost digit starts — with
   everything left-aligned, 33,000 and 33,000,000 line up on their first "3"
   and look deceptively similar at a glance, especially re-sorting a column
   between ascending/descending. Right-align table data by default (the
   ones digit anchors in the same place every row, so length itself becomes
   a visual cue) and left-align back the handful of columns that hold text,
   not numbers: the row's own identifying first column, plus named
   location/status/free-text columns across the various tables.
   The default DOESN'T apply to header cells — .th-sort-btn keeps its own
   left-aligned text-align so the sort arrow stays where a header naturally
   reads it. */
.table-scroll td { text-align: right; }

.table-scroll td:first-child,
.table-scroll td[data-label="Sell at"],
.table-scroll td[data-label="Location"],
.table-scroll td[data-label="Region"],
.table-scroll td[data-label="Inputs"],
.table-scroll td[data-label="Outputs (per batch)"],
.table-scroll td[data-label="NPC facility"],
.table-scroll td[data-label="Station"],
.table-scroll td[data-label="System"],
.table-scroll td[data-label="LP store"],
.table-scroll td[data-label="Required items"],
.table-scroll td[data-label="Buy at (region)"],
.table-scroll td[data-label="Sell at (region)"],
.table-scroll td[data-label="Type"],
.table-scroll td.order-cell {
  text-align: left;
}

/* Dense rows: a figure's own line never wraps ("8,616,310.03 ISK" split
   before its ISK, one word a line, makes a Production row seven or eight
   lines tall), while the notes under it do, in the column's width — and
   so do the columns of words listed above (names, stations, lists), which
   have nowhere else to go. */
.table-scroll td { white-space: nowrap; }

.table-scroll td:first-child,
.table-scroll td:is([data-label="Sell at"], [data-label="Location"],
  [data-label="Region"], [data-label="Inputs"], [data-label="Outputs (per batch)"], [data-label="NPC facility"], [data-label="Station"],
  [data-label="LP store"], [data-label="Required items"], [data-label="Buy at (region)"], [data-label="Sell at (region)"], [data-label="Type"]),
.table-scroll td :is(.filter-count, .cell-note, .flag-warn, .flag-bad, .flag-yes) {
  white-space: normal;
}

/* The notes under a figure a size down from it. */
.table-scroll td :is(.filter-count, .cell-note) { font-size: var(--fs-xs); }

/* The row's name, near-white: the identity the rest of the row is about. */
td:is([data-label="Item"], [data-label="Product"]),
td:first-child:is([data-label="Route"], [data-label="System"]) {
  color: var(--text-bright);
}

/* ISK, by column: prices, costs and values in amber. Their sub-lines keep
   their own colours (.filter-count, .cell-note). */
td:is(
  [data-label="Price"], [data-label="Value"], [data-label="Buy price"], [data-label="Sell price"], [data-label="Spread"],
  [data-label="Listing price"], [data-label="Material cost"], [data-label="Input cost"], [data-label="BPC cost"],
  [data-label="Best bid"], [data-label="Best ask"], [data-label="Median trade"], [data-label="Typical price"],
  [data-label="Haul"], [data-label="Haul cost"], [data-label="Capital"], [data-label="Reprocess value"],
  [data-label="ISK cost"], [data-label="Required items"], [data-label="Cost/unit"], [data-label="Sell/unit"],
  [data-label="Sell-now floor"]
) {
  color: var(--amber);
}

/* What a row makes, in phosphor — red instead when it's a loss (is-neg,
   below). */
td:is(
  [data-label="Net profit (after haul)"], [data-label="Outbound"], [data-label="Return"], [data-label="Net per trip"],
  [data-label="Net"], [data-label="Net ISK"], [data-label="Profit"], [data-label="Profit/run"], [data-label="Profit/day (capped)"],
  [data-label="Profit/unit"], [data-label="ISK/day (capped)"], [data-label="Profit after haul"], [data-label="Total profit"],
  [data-label="ISK/LP"]
) {
  color: var(--phosphor);
}

td.spread-pct { color: var(--phosphor); text-shadow: 0 0 5px rgba(0, 255, 136, 0.45); font-weight: 700; }

td.score-value { color: var(--phosphor); text-shadow: 0 0 6px rgba(0, 255, 136, 0.5); font-weight: 700; }

td.col-active { color: var(--phosphor); background: rgba(0, 255, 136, 0.05); font-weight: 700; }

/* A cell leading with a negative figure (hud.js): a loss, a negative
   margin — red whatever its column. */
td.is-neg { color: var(--red); text-shadow: none; }

.cell-note {
  display: inline-block;
  max-width: 340px;
  font-size: var(--fs-sm);
  color: var(--text-dim);
  line-height: 1.4;
}

/* "route ›" beside a trip or a place (routeAction in core.js). Its hit area is
   grown by padding the layout takes back, so a row keeps its height. */
.route-link {
  display: inline-block;
  padding: 9px 5px;
  margin: -9px -2px -9px 2px;
  font-size: var(--fs-xs);
  font-weight: 400;
  white-space: nowrap;
}
.route-link:hover, .route-link:focus-visible { text-decoration: underline; }
/* A row of links in a list or a tip ("route ›  War room ›  Fit lab ›"):
   each link keeps its own box, not the table cell's negative margins, and
   is a finger's 32 px tall on a phone (phone.css). */
.link-row .route-link { margin: 0 var(--sp-1) 0 0; padding: 9px 4px; }

/* An item's or a place's name that opens Item search or the Route planner
   (itemLink, placeLink in core.js): the name's own colour and weight, a
   faint dotted line under it, the link colour on hover. On a phone its hit
   area grows by padding an inline box adds without moving the line. */
.item-link, .place-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted rgba(0, 255, 136, 0.35);
}
.item-link:hover, .item-link:focus-visible, .place-link:hover, .place-link:focus-visible { color: var(--phosphor); border-bottom-style: solid; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .item-link, .place-link { padding: var(--sp-5) 0; }
}

.sec { font-weight: 700; }
.sec-high { color: var(--phosphor); }
.sec-low { color: var(--amber); }
.sec-null { color: var(--red); }
.sec-wormhole { color: #b98cff; }

.flag-yes { color: var(--phosphor); font-weight: 700; text-shadow: 0 0 4px rgba(0, 255, 136, 0.5); }
.flag-warn { color: var(--amber); }
.flag-bad { color: var(--red); }

th.order-col { width: 1%; white-space: nowrap; }

.order-add-btn {
  padding: var(--sp-1) var(--sp-4);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  color: var(--mint);
  border-color: var(--edge);
  white-space: nowrap;
}

.order-add-btn:hover { background: var(--phos-a10); border-color: var(--phosphor); color: var(--phosphor); box-shadow: 0 0 8px rgba(0, 255, 136, 0.3); }
.order-add-btn:disabled { opacity: 0.7; cursor: default; }

/* A desktop table's "+ Notebook" is a 28 px "+" (its words stay its
   accessible name and tooltip); "✓" while it says Added. A phone's card has
   the room for the words. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  td.order-cell .nb-add {
    min-width: 28px;
    padding: var(--sp-1) 0;
    font-size: 0;
    letter-spacing: 0;
  }
  td.order-cell .nb-add::before { content: "+"; font-size: 16px; line-height: 1; }
  td.order-cell .nb-add.is-added::before { content: "✓"; font-size: 13px; }
}

/* A row's details (makeTable details, pagination.js): "▸" before the row's
   first words opens a row under it with the figures and links the cells
   leave out. */
.row-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-right: var(--sp-3);
  padding: 0;
  vertical-align: middle;
  font-size: var(--fs-xs);
  color: var(--mint-dim);
  border-color: var(--edge);
  background: transparent;
}
.row-more::before { content: "▸"; }
.row-more[aria-expanded="true"]::before { content: "▾"; color: var(--phosphor); }
.row-more:hover { color: var(--phosphor); border-color: var(--phosphor); }
/* Second lines (.cell-sub, with the line break before it) show once the row
   is open (pagination.js toggleRow); a closed row is its figures alone. */
tr:not(.row-open) .cell-sub, tr:not(.row-open) br.cell-sub-br { display: none; }
tr.row-open > td { background: color-mix(in srgb, var(--phosphor) 3%, transparent); }
tbody tr:has(.row-more) { cursor: pointer; }
tr.row-details > td { padding: var(--sp-4) var(--sp-6) var(--sp-5); background: rgba(0, 255, 136, 0.03); }
.row-details-body { font-size: var(--fs-sm); line-height: 1.5; color: var(--text-label); white-space: normal; }
.row-details-body ul { margin: var(--sp-2) 0 0; padding-left: var(--sp-6); columns: 2 220px; }
.row-details-body li { break-inside: avoid; }
.row-details-body .row-details-links { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); margin-top: var(--sp-3); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .row-more { width: 32px; height: 32px; }
  tr.row-details > td::before { display: none; }
  .row-details-body .row-details-links a { display: inline-flex; align-items: center; min-height: 32px; }
}

/* Hub colour bars (hud.js hubBarHtml): a thin swatch before a hub's name,
   the same colour for a hub wherever a table names it. */
.hub-bar {
  display: inline-block;
  width: 3px;
  height: 1.05em;
  margin-right: var(--sp-3);
  vertical-align: -0.18em;
  border-radius: 1px;
  background: var(--hub, var(--mint-dim));
  box-shadow: 0 0 5px var(--hub, transparent);
}

.hub-forge { --hub: var(--hub-forge); }
.hub-domain { --hub: var(--hub-domain); }
.hub-sinq { --hub: var(--hub-sinq); }
.hub-heimatar { --hub: var(--hub-heimatar); }
.hub-metropolis { --hub: var(--hub-metropolis); }

.hub-name { white-space: nowrap; }

/* A hub named as a tag (hud.js hubTagHtml): one size and colour wherever a
   page shows one. */
.hub-tag { font-size: var(--fs-xs); color: var(--text-label); }
.hub-tag .hub-bar { margin-right: var(--sp-2); }

/* Item icons (hud.js typeIconHtml), as EVE's market window shows them: a
   fixed box, so nothing moves when the image arrives, or when it never
   does (.type-icon-missing keeps the box, empty). */
.type-icon {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-right: var(--sp-4);
  vertical-align: middle;
  object-fit: contain;
  background: #000;
  border: 1px solid var(--line);
  border-radius: 2px;
}

.type-icon-missing { visibility: hidden; }

/* In a name cell the icon hangs in the cell's own left padding, centred on
   the cell's height, so a name's second line (a note under it) starts
   where its first does and a one-line name in a tall row keeps its icon
   beside it. */
td.has-icon { position: relative; padding-left: 34px; }
td.has-icon > .type-icon { position: absolute; left: 7px; top: 50%; margin: 0; transform: translateY(-50%); }

/* The row a table shows when it has none (setupPagination, pagination.js):
   one dim line, its why in the status line above. A phone's card has no
   label for it. */
.table-empty td { padding: var(--sp-5) var(--sp-4); color: var(--text-dim); text-align: left; white-space: normal; }
.table-empty td::before { content: none; display: none; }

}
@layer pages {
/* The line above a table that says a link narrowed it (core.js
   linkFilterBanner): the words, the name in bold and a clear button. The
   button is a 32px square tap target on a phone as on a desktop. */
.link-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin: var(--sp-2) 0;
  font-size: var(--fs-sm);
  color: var(--text-bright);
}
.link-filter-text { flex: 1 1 0; min-width: 0; overflow-wrap: anywhere; }
.link-filter-text strong { color: var(--text); font-weight: 600; }
.link-filter-clear {
  flex: none;
  min-width: 32px;
  min-height: 32px;
  padding: 0 var(--sp-4);
  line-height: 1;
  font-size: var(--fs-lg);
}
}
@layer pages {
/* --- Today's best page: a curated top 20 --- */

.picks-panel {
  margin: var(--sp-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

/* Today's best builds its Hub / Max capital row without .controls
   (picks.js); it takes their look here, or a phone shows small white
   native fields. */
.picks-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-5);
  font-size: var(--fs-xs);
  color: var(--mint-dim);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.picks-panel .last-sync { margin: 0; }

.picks-head input, .picks-head select {
  padding: var(--sp-3) var(--sp-4);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: var(--fs-md);
  letter-spacing: 0;
  text-transform: none;
}

.picks-head input { width: 140px; }

.picks-head input:focus, .picks-head select:focus {
  outline: none;
  border-color: var(--phosphor);
  box-shadow: 0 0 0 1px var(--phos-a20), 0 0 10px rgba(0, 255, 136, 0.3);
}

/* The picks table: activity, hub, risk, the pick, score and profit each in a
   column of their own, so a badge sits in its column whatever the text beside
   it runs to. */
#picks-table td { vertical-align: top; }
/* Words wrap in the pick's column, which takes what the others leave; the
   badge and the tags stay at the left of theirs. */
#picks-table td.pick-main { white-space: normal; text-align: left; width: 100%; min-width: 320px; }
#picks-table td.pick-cell { text-align: left; }
.pick-name { font-weight: 700; font-size: 13.5px; color: var(--text-bright); }
.pick-name .type-icon { margin-right: var(--sp-3); vertical-align: -5px; }
.pick-hub { font-size: var(--fs-sm); color: var(--mint-dim); white-space: nowrap; }
.pick-why { font-size: var(--fs-sm); color: var(--text-dim); margin-top: var(--sp-1); line-height: 1.45; }
/* The detail line is one line until the row is opened (the button beside the
   name); the flags, which warn, stay in view. */
#picks-table tr:not(.pick-open) .pick-why { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; }
.pick-flags { margin-top: var(--sp-1); font-size: var(--fs-sm); }
.pick-more { margin-left: var(--sp-3); padding: 0 var(--sp-3); min-height: 28px; min-width: 28px; background: none; border: 1px solid var(--edge); color: var(--mint-dim); border-radius: 2px; cursor: pointer; line-height: 1; }
.pick-open .pick-more { transform: rotate(180deg); }
.explainer-more { margin-top: var(--sp-3); }
.explainer-more > summary { cursor: pointer; color: var(--mint-dim); }
.hotkey-chip.pick-none { opacity: 0.55; }
.pick-risk-left { margin-left: var(--sp-2); text-transform: none; letter-spacing: 0; }
.pick-value { min-width: 12em; }
.pick-value strong { font-size: 13.5px; }

/* The phone query (PHONE_MEDIA_QUERY in pagination.js — keep them the same). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  #picks-table td.pick-main { min-width: 0; }
  .pick-value { min-width: 0; text-align: left; white-space: normal; overflow-wrap: anywhere; }
  .pick-why { overflow-wrap: anywhere; color: var(--text-label); }
  #picks-table tr:not(.pick-open) .pick-why { -webkit-line-clamp: 2; }
  .pick-more { min-height: 32px; min-width: 32px; }
  .pick-value .filter-count, .pick-value .flag-warn { font-size: var(--fs-md); }
  .pick-value .filter-count { color: var(--text-label); }
}

}
@layer pages {
/* --- Order book page --- */

.order-list { display: flex; flex-direction: column; gap: var(--sp-6); }

.order-card {
  background: var(--input-bg);
  border: 1px solid var(--line);
  border-left: 2px solid rgba(0, 255, 136, 0.55);
  border-radius: 2px;
  padding: var(--sp-6) var(--sp-6);
}

.order-card.order-done { opacity: 0.55; }
.order-card.order-done .order-title { text-decoration: line-through; }

.order-card-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-5);
  margin-bottom: var(--sp-4);
}

.order-check { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; }
.order-check input { accent-color: var(--phosphor); }

.order-print-check { display: none; }

.order-module-tag {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--mint-dim);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 1px var(--sp-3);
}

.order-title { font-weight: 700; color: var(--text-bright); flex: 1 1 auto; min-width: 120px; }
.order-title .type-icon, .order-toggle-title .type-icon { margin-right: var(--sp-4); vertical-align: -5px; }

.order-qty { display: inline-flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--mint-dim); }
.order-qty input { width: 56px; padding: var(--sp-1) var(--sp-3); background: var(--screen-bg); border: 1px solid var(--edge); color: var(--text-bright); border-radius: 2px; font-family: var(--mono); }

/* A phone's Qty, in the opened line instead of its compact row (phone
   block); a desktop and a printout keep the one in the card's head. */
.order-qty-detail { display: none; }

.order-remove {
  background: none;
  border: 1px solid var(--edge);
  color: var(--mint-dim);
  border-radius: 2px;
  width: 22px;
  height: 22px;
  line-height: 1;
  padding: 0;
  font-size: var(--fs-md);
  letter-spacing: 0;
}

.order-remove:hover { color: var(--red); border-color: var(--red); background: rgba(255, 92, 92, 0.08); }

.order-undo { padding: var(--sp-1) var(--sp-5); margin-left: var(--sp-2); color: var(--phosphor); border-color: var(--phosphor); }

/* A phone's compact row (see the phone block): its title and first field,
   opening the line. A desktop shows the title and every field. */
.order-toggle { display: none; }

#orderbook-list:focus { outline: none; }

/* Lines added together (a Cargo trip, a Fill industry slots batch...) under
   one header that folds, ticks and removes them all (renderOrderBook). */
.order-group {
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: var(--sp-4) var(--sp-6);
  background: rgba(0, 255, 136, 0.025);
}

.order-group-head { display: flex; align-items: center; gap: var(--sp-5); }

.order-group-toggle {
  flex: 1 1 auto;
  min-width: 0;
  display: block;
  padding: var(--sp-2) 0;
  border: none;
  background: none;
  color: var(--text-bright);
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-lg);
}

.order-group-toggle:hover { background: none; color: var(--phosphor); }
.order-group-toggle::before { content: "▸ "; color: var(--phosphor); }
.order-group-toggle[aria-expanded="true"]::before { content: "▾ "; }
.order-group-count { margin-left: var(--sp-5); font-size: var(--fs-sm); font-weight: 400; color: var(--text-dim); white-space: nowrap; }

.order-group-body { display: none; flex-direction: column; gap: var(--sp-6); margin-top: var(--sp-4); }
.order-group-open > .order-group-body { display: flex; }
.order-group.order-done > .order-group-head { opacity: 0.55; }

/* Order book: "Removed … — Undo" at the foot of the screen, wherever the
   list is scrolled to (orderbook.js). */
.undo-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: max-content;
  max-width: min(520px, calc(100vw - 32px));
  background: var(--panel-bg);
  border: 1px solid rgba(0, 255, 136, 0.5);
  border-radius: 2px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.7), 0 0 16px rgba(0, 255, 136, 0.15);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-6);
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: var(--fs-md);
}

.undo-toast.hidden { display: none; }

.undo-toast-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow-wrap: anywhere;
}

.undo-toast-undo { color: var(--phosphor); border-color: var(--phosphor); }
/* A glyph wide (30px), 8px from Undo: at least a fingertip. */
.undo-toast-close { border: none; padding: var(--sp-4) var(--sp-5); min-width: 40px; color: var(--mint-dim); background: none; }

/* 230px columns: narrower, a station's name or a price with its units
   wraps to four or five lines beside its label. */
.order-fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--sp-2) var(--sp-7);
  margin: 0 0 var(--sp-4);
}

.order-fields > div { display: flex; justify-content: space-between; gap: var(--sp-4); font-size: var(--fs-md); border-bottom: 1px solid var(--row-line); padding: var(--sp-1) 0; }
.order-fields dt { color: var(--text-dim); margin: 0; }
.order-fields dd { margin: 0; text-align: right; color: var(--mint); }

.order-notes {
  width: 100%;
  min-height: 34px;
  padding: var(--sp-3) var(--sp-4);
  background: var(--screen-bg);
  border: 1px solid var(--edge);
  color: var(--text-bright);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: var(--fs-md);
  resize: vertical;
}

.order-notes::placeholder { color: var(--text-dim); }

.controls input[type="text"] { width: 190px; }
.controls input.input-isk { width: 120px; }
.controls input[type="checkbox"] { width: auto; padding: 0; accent-color: var(--phosphor); }
.control-check { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; }

/* --- Notebook: tasks --- */

/* A task's kind, on its card. */
.order-kind { flex: 0 0 auto; color: var(--mint); }
.order-card[data-kind="buy"] .order-kind { color: var(--phosphor); border-color: rgba(0, 255, 136, 0.5); }
.order-card[data-kind="sell"] .order-kind { color: var(--amber); border-color: rgba(255, 176, 0, 0.5); }
.order-card[data-kind="haul"] .order-kind { color: var(--hub-forge); border-color: rgba(77, 163, 255, 0.5); }
.order-card[data-kind="build"] .order-kind, .order-card[data-kind="react"] .order-kind { color: var(--hub-metropolis); border-color: rgba(192, 140, 255, 0.5); }
.order-card[data-kind="lp"] .order-kind { color: var(--hub-sinq); border-color: rgba(63, 224, 208, 0.5); }

/* Units, price and ISK in the card's head; a phone's compact row says the
   same under the title. */
.order-task-sum { flex: 0 1 auto; color: var(--mint); font-size: var(--fs-md); white-space: nowrap; }
.order-card-head > .order-title { flex: 1 1 160px; }

.order-from { margin: 0 0 var(--sp-4); font-size: var(--fs-md); color: var(--text-dim); }
.order-src { color: var(--accent); }

/* Chips for a task's kind and for the grouping. */
.notebook-kinds, .notebook-views { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: 0 0 var(--sp-4); }

.notebook-chip {
  min-height: 32px;
  padding: var(--sp-2) var(--sp-5);
  background: transparent;
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--mint);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.notebook-chip:hover { border-color: var(--phosphor); color: var(--phosphor); }
.notebook-chip-on { border-color: var(--phosphor); color: var(--phosphor); background: var(--phos-a10); }

/* A task's own fields: place, where it goes next, units, ISK. */
.notebook-task-edit { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3) var(--sp-6); margin: 0 0 var(--sp-4); }
.notebook-task-edit .notebook-kinds { flex: 0 0 auto; margin: 0; }
.notebook-edits { display: flex; flex: 1 1 420px; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); min-width: 0; }

.notebook-edit {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  flex: 0 1 110px;
  min-width: 0;
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mint-dim);
}

.notebook-edit-wide { flex: 1 1 200px; }

.notebook-edit input {
  width: 100%;
  min-width: 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--screen-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: var(--fs-md);
  letter-spacing: 0;
  text-transform: none;
}

/* The hand-written task. */
.notebook-add { margin: 0 0 var(--sp-5); }
.notebook-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-4) var(--sp-6); padding: var(--sp-4) 0; }
.notebook-form .notebook-kinds { flex: 1 1 100%; margin: 0; }
.notebook-form button[type="submit"] { min-height: 32px; }

/* A group's ISK totals, beside its count. */
.order-group-sum { margin-left: var(--sp-5); font-size: var(--fs-sm); font-weight: 400; color: var(--mint); }
.order-group-copy { min-height: 32px; padding: var(--sp-2) var(--sp-5); font-size: var(--fs-sm); }

/* The route. */
#notebook-route:empty { display: none; }
.notebook-route { margin: 0 0 var(--sp-6); border: 1px solid var(--line); border-radius: 2px; padding: var(--sp-2) var(--sp-6) var(--sp-4); background: rgba(0, 255, 136, 0.025); }
.notebook-route > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--text-bright); font-weight: 700; }
.notebook-route > summary .notebook-trip { margin-left: auto; padding: var(--sp-4) 0 var(--sp-4) var(--sp-6); font-size: var(--fs-md); font-weight: 400; white-space: nowrap; }
.notebook-route-title { margin: var(--sp-4) 0 var(--sp-2); font-size: var(--fs-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.notebook-stops { margin: 0; padding: 0; list-style: none; counter-reset: stop; }
.notebook-stops li { counter-increment: stop; padding: var(--sp-1) 0; font-size: var(--fs-md); }
.notebook-stop::before { content: counter(stop) ". "; color: var(--text-dim); }
.notebook-leg { display: block; padding-left: var(--sp-7); font-size: var(--fs-sm); color: var(--amber); }
.notebook-leg::before { content: "↓ "; }
.notebook-stop { color: var(--text-bright); overflow-wrap: anywhere; margin-right: var(--sp-5); }
.notebook-stop-meta { color: var(--text-dim); font-size: var(--fs-sm); }

/* The item's link beside the way back: a phone's only one (its title is the
   card's toggle); a desktop links the title itself. */
.order-item-link { margin-left: var(--sp-5); }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .order-item-link { display: none; }
}

}
@layer pages {
/* A wrapper of secondary inputs inside a page head's Options fold
   (chipfold.js): no box of its own, so its fields sit in the row as if
   unwrapped, and fold with the rest. */
.controls-more { display: contents; }

.th-sort-btn {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--sp-3) var(--sp-3);
  margin: 0;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
  user-select: none;
  position: relative;
}

.th-sort-btn:hover { color: var(--mint); background: rgba(0, 255, 136, 0.05); }

.th-sort-btn:focus-visible {
  outline: 1px solid var(--phosphor);
  outline-offset: -2px;
}

.th-sort-btn::after {
  content: "↕";
  margin-left: var(--sp-2);
  opacity: 0.4;
  font-size: var(--fs-xs);
}

/* Sort control for phones, where <thead> is hidden (see the 768px media
   query) — never shown alongside the real headers. */
.controls.mobile-sort { display: none; }

/* The column the table is sorted by: its header lit, a solid arrow, and a
   phosphor bar under it. */
.th-sort-btn.sort-asc, .th-sort-btn.sort-desc { color: var(--phosphor); text-shadow: 0 0 6px rgba(0, 255, 136, 0.45); }
.th-sort-btn.sort-asc::after { content: "▲"; opacity: 1; font-size: 8px; vertical-align: 1px; }
.th-sort-btn.sort-desc::after { content: "▼"; opacity: 1; font-size: 8px; vertical-align: 1px; }
th[aria-sort="ascending"], th[aria-sort="descending"] { background: rgba(0, 255, 136, 0.09); box-shadow: inset 0 -2px 0 var(--phosphor); }

.sort-order {
  display: inline-block;
  background: var(--phosphor);
  color: var(--black);
  border-radius: 2px;
  font-size: 9px;
  font-weight: 800;
  width: 13px;
  height: 13px;
  line-height: 13px;
  text-align: center;
  margin-left: var(--sp-1);
  vertical-align: middle;
  text-shadow: none;
}

/* The hover band and its phosphor left edge. A mouse only: a touch screen
   keeps :hover on the last card tapped. */
@media (hover: hover) {
  tbody tr:hover { background: rgba(0, 255, 136, 0.07); }
  tbody tr:hover > td:first-child { box-shadow: inset 2px 0 0 var(--phosphor); }
}

tbody tr:last-child td { border-bottom: none; }

/* Wide tables (.table-scroll, above): "+ Notebook" (Arbitrage's routes:
   Actions) stays at the right edge while the columns scroll sideways; a wide
   table (Production at 1440px, the LP store at 1280) would otherwise have it
   past the edge, a scroll away. It is opaque — what the table sits on
   (--table-bg) under the row's own tint: zebra, hover, a sorted column's
   header — so nothing scrolled under it shows through. A stuck cell leaves
   its collapsed border behind with the table, so the header's phosphor rule
   is drawn by the cell itself, on the border's own pixel row: the border
   stays, transparent, so the rows keep their place. Stacked: the pinned
   cells over the rows, the header over both, and their shared corner over
   all. A phone's cards pin nothing (phone block). */
.table-scroll thead th {
  position: sticky;
  z-index: 2;
  background: linear-gradient(rgba(0, 255, 136, 0.035), rgba(0, 255, 136, 0.035)), var(--table-bg);
  border-bottom-color: transparent;
}

.table-scroll thead th::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: rgba(0, 255, 136, 0.55);
  pointer-events: none;
}

.table-scroll thead th:is([aria-sort="ascending"], [aria-sort="descending"]) {
  background: linear-gradient(rgba(0, 255, 136, 0.09), rgba(0, 255, 136, 0.09)), var(--table-bg);
}

.table-scroll td.order-cell {
  position: sticky;
  right: 0;
  z-index: 1;
  background: var(--table-bg);
}

.table-scroll tbody tr:nth-child(even) td.order-cell {
  background: linear-gradient(rgba(125, 255, 178, 0.022), rgba(125, 255, 178, 0.022)), var(--table-bg);
}

@media (hover: hover) {
  .table-scroll tbody tr:hover td.order-cell {
    background: linear-gradient(rgba(0, 255, 136, 0.07), rgba(0, 255, 136, 0.07)), var(--table-bg);
  }
}

.table-scroll thead th.order-col {
  right: 0;
  z-index: 3;
}

/* The pinned column's edge — a rule down its left, and a faint shadow over
   the columns passing under it — only while the table is wider than its
   pane, so a table that fits shows no edge. The pane's sideways scroll
   drives it (scroll(nearest inline)): with nothing to scroll that way the
   timeline is inactive and the edge isn't drawn. A browser without scroll
   timelines runs it as a 0s animation instead, whose end state stays: the
   edge, always. */
.table-scroll td.order-cell,
.table-scroll thead th.order-col {
  animation: pinned-edge linear both;
  animation-timeline: scroll(nearest inline);
}

@keyframes pinned-edge {
  from, to { box-shadow: inset 1px 0 0 var(--line), -8px 0 8px -6px rgba(0, 0, 0, 0.9); }
}

/* Item search's Observed at the hubs: at most five rows, one per hub region.
   Its header keeps its own borders: a group's rule under its three windows
   (.flow-group) is a dimmer one. */
.item-flow-table thead th { position: static; border-bottom-color: rgba(0, 255, 136, 0.55); }
.item-flow-table thead th::after { content: none; }

.hotkey-panel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}

/* The presets row (filters.js) is laid out like Category's: its label in
   the same column, its chips beside. Its last chip opens the filter sheet
   (.filter-icon-btn): "Filter" with the funnel while a preset is lit, lit
   itself as "Custom" with the badge when none is. The sheet hangs from the
   row, not the chip (.filter-dropdown). */
.hotkey-presets { position: relative; }
.hotkey-presets > .hotkey-chip-list { flex: 1 1 auto; align-items: center; }

.hotkey-group {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-5);
}

.hotkey-group-label {
  flex-shrink: 0;
  min-width: 68px;
  padding-top: var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--mint-dim);
  white-space: nowrap;
}

.hotkey-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* Segmented tabs: outlined boxes, the chosen one lit and filled. */
.hotkey-chip {
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--mint-dim);
  border-color: var(--edge);
  background: transparent;
}

.hotkey-chip:hover { color: var(--mint); border-color: var(--mint-dim); background: rgba(0, 255, 136, 0.05); }

.hotkey-chip.active {
  color: var(--phosphor);
  border-color: var(--phosphor);
  background: rgba(0, 255, 136, 0.13);
  box-shadow: 0 0 8px rgba(0, 255, 136, 0.3), inset 0 0 6px rgba(0, 255, 136, 0.12);
  text-shadow: 0 0 6px rgba(0, 255, 136, 0.55);
}

/* Cargo's Trip row (All / Round trip / One-way) sits in the header between
   the title and the page's controls, full width, so the choice of trip comes
   before the settings that belong to it. */
.section-header > .cargo-trip { flex: 1 1 100%; margin: var(--sp-1) 0 0; }
.route-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

.route-cell { min-width: 0; }

/* Static: the dropdown is placed against the presets row. */
.filter-widget {
  display: inline-block;
  margin-bottom: 0;
}

/* A chip like the presets beside it; the funnel at the text's size keeps
   it their height, so the row's label lines up as Category's does. */
.hotkey-chip.filter-icon-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
}

.filter-icon-btn svg { width: 12px; height: 12px; flex-shrink: 0; }

.filter-count-badge {
  background: var(--phosphor);
  color: var(--black);
  border-radius: 2px;
  padding: 0 var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0;
  box-shadow: 0 0 6px rgba(0, 255, 136, 0.5);
}

/* Empty on a preset: the badge counts changes from the nearest one. */
.filter-count-badge:empty { display: none; }

/* Hangs from the presets row's left edge (.hotkey-presets), under the
   chips: its opener sits mid-row, after the presets, and a 420px sheet
   anchored to the chip would run past one screen edge or the other. Tall
   content (the Expert category tree) scrolls inside it rather than running
   off. */
.filter-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: auto;
  z-index: 20;
  width: 420px;
  max-width: 90vw;
  max-height: min(70vh, 600px);
  overflow-y: auto;
  background: var(--panel-bg);
  border: 1px solid var(--phos-a35);
  border-radius: 2px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.7), 0 0 20px rgba(0, 255, 136, 0.08);
  padding: var(--sp-6) var(--sp-6);
}

.filter-dropdown.hidden { display: none; }

/* Phone-only, like the Trade settings panel's (768px block). */
.filter-sheet-head, .filter-backdrop { display: none; }

/* A page with few or no rows (Cargo before Calculate, Production after a
   too-tight filter — exactly when you'd open Filter to loosen it) has a
   screen shorter than the dropdown, and .screen's overflow:hidden would cut
   its bottom off. While a dropdown is open its screen stops clipping: the CRT
   overlays (.screen::before, .crt-sweep) are inset:0 and clip themselves,
   so nothing else changes. */
.screen:has(.filter-dropdown:not(.hidden)) { overflow: visible; }

.filter-section + .filter-section {
  margin-top: var(--sp-6);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}

.filter-advanced {
  margin-top: var(--sp-6);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}

.filter-advanced summary {
  cursor: pointer;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--mint);
  list-style: none;
}

.filter-advanced summary::-webkit-details-marker { display: none; }

.filter-advanced summary::before { content: "▸ "; color: var(--phosphor); }

.filter-advanced[open] summary::before { content: "▾ "; }

.filter-advanced-badge {
  background: var(--amber);
  color: var(--black);
  border-radius: 2px;
  padding: 0 var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 800;
  margin-left: var(--sp-1);
}

.filter-advanced-badge:empty { display: none; }

.filter-advanced .filter-section:first-of-type {
  margin-top: var(--sp-6);
}

.filter-section-title {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--mint-dim);
  margin-bottom: var(--sp-4);
}

.filter-section-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
}

.filter-select-links {
  display: flex;
  gap: var(--sp-5);
  flex-shrink: 0;
}

.filter-link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  font-family: var(--mono);
}

.filter-link-btn:hover { background: none; color: var(--phosphor); }

/* "Reset filters": a chip at the head of the filter sheet. Greyed out
   while every filter is at its default, so it also tells you whether
   anything is changed. */
.hotkey-chip.filter-reset-chip:disabled { opacity: 0.35; cursor: default; }
.hotkey-chip.filter-reset-chip:disabled:hover { color: var(--mint-dim); border-color: var(--edge); background: transparent; }
.filter-reset-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
  margin-bottom: var(--sp-5);
}

.filter-search {
  width: 100%;
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-5);
  background: var(--screen-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-size: var(--fs-md);
  font-family: var(--mono);
}

.filter-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: 160px;
  overflow-y: auto;
}

.filter-tree {
  max-height: 280px;
  overflow-y: auto;
}

.filter-item {
  display: inline-block;
  font-size: var(--fs-md);
  color: var(--mint);
  padding: var(--sp-1) 0;
}

/* A box a Category, Tech or Rig size chip keeps in (filters.js
   syncBoxes): unticked, and it can't be ticked until that chip is off. */
.filter-item:has(input:disabled) { opacity: 0.45; cursor: default; }

.filter-count { color: var(--text-dim); }

/* "Preset: Default." / "Custom: 1 change from Everything." at the sheet's head
   — what the Custom chip's badge counts from, where a touch screen can
   read it. */
.filter-status { color: var(--mint); }

.tree-node { padding: 1px 0; }

.tree-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.tree-toggle {
  cursor: pointer;
  color: var(--mint-dim);
  font-size: var(--fs-xs);
  width: 12px;
  display: inline-block;
  user-select: none;
}

.tree-toggle-spacer { width: 16px; display: inline-block; }

.tree-children.hidden { display: none; }

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
  margin-top: var(--sp-6);
}

.pagination:empty { display: none; }

/* The pager above a table (pagination.js): the top of a page of rows, which
   a jump from the pager below comes back to clear of the sticky nav (a
   phone's is at the bottom). */
.pagination-top {
  margin: 0 0 var(--sp-5);
  scroll-margin-top: calc(var(--nav-height, 56px) + 8px);
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .pagination-top { scroll-margin-top: 8px; }
}

/* The same pager at the end of a status line (.page-status): arrows and the
   page, no row of its own. */
.pagination-inline { margin: 0; gap: var(--sp-3); }
.pagination-inline[hidden] { display: none; }
.pagination-inline .page-btn { min-width: 28px; padding: var(--sp-1) var(--sp-4); }

.page-btn {
  background: transparent;
  color: var(--mint);
  border: 1px solid var(--edge);
  padding: var(--sp-3) var(--sp-6);
  font-size: var(--fs-sm);
  font-weight: 600;
}

.page-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.page-btn:disabled:hover { background: transparent; border-color: var(--edge); color: var(--mint); }

.page-btn:not(:disabled):hover { background: rgba(0, 255, 136, 0.08); }

.page-info {
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mint-dim);
  font-family: var(--mono);
}

/* A touch screen can't hover, so a tap on a result's tooltip-only detail
   (a Snipes station, an LP store's other corporations, Cargo's Capital
   breakdown...) or on a control's name (Max jumps, Market share %...)
   shows its title here instead (initTapTips in app.js). The dotted
   underline says which parts have one. */

@media (hover: none) {
  .module-page tbody [title], .ob-fields [title], .ob-spread [title], #orderbook-slots-summary [title], .hotkey-group-label[title],
  .last-sync [title], .settings-summary [title], .page-banner[title] .page-banner-text,
  .controls label[title]:not(.control-check), .controls .controls-group[title], .picks-head label[title], .settings-grid label[title] {
    text-decoration: underline dotted;
    text-underline-offset: 3px;
  }

  /* Not flex boxes: as flex items their hub names, or the Trade settings
     field's value, would take the words' underline too. */
  .controls .controls-group[title], .settings-grid label[title] { display: block; }
  .settings-grid label[title] > select, .settings-grid label[title] > input { display: inline-block; width: 100%; margin-top: var(--sp-2); }

  /* A page control's field that wraps under its name (Build system,
     Reaction system, Value at, Min. total profit, Max capital per pick)
     touches the words' line, and a tap on the words goes to the field —
     Chrome's touch adjustment prefers a field within a finger's reach, up
     to 16px from where it lands — so the keyboard comes up and no tip. This
     empty box, 24px tall from the top of the words' line, holds that line
     open to ~11px under the words, out of that reach. Beside its field the
     line is taller already (36px): no change there, unlike a margin on the
     field, which would add 10px to every such row. The same holds for "Sell
     at" (a thumb on the words would tick the first hub and reload the list)
     and every titled Trade settings field. */
  .controls label[title]:not(.control-check)::before, .picks-head label[title]::before,
  .controls .controls-group[title]::before, .settings-grid label[title]::before {
    content: "";
    display: inline-block;
    height: 24px;
    vertical-align: top;
  }

  /* The same tip for a control whose tap already does something — a
     checkbox's label, a chip, a bulk button: an "i" beside it (added by
     initTapTips in app.js). The two are wrapped as one: a line break
     between them would leave the "i" at the start of the next line, beside
     some other control. A chip too long for the line with its "i" wraps its own
     words instead. */
  .info-pair {
    display: inline-flex;
    align-items: center;
    flex-wrap: nowrap;
    min-width: 0;
    max-width: 100%;
  }

  /* A chip row's label with its "i" keeps its width beside the chips. */
  .hotkey-group > .info-pair { flex: 0 0 auto; }

}

/* The info tip's trigger (InfoTip, app.js): a small round "i" beside the
   control it explains. Its own words are in data-tip, or in the control's
   title for the ones a touch screen adds. A mouse's is the glyph's size; a
   finger's is 32 by 36 px, the glyph centred in it. */
.info-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 18px;
  height: 14px;
  min-height: 0;
  margin: 0 0 0 var(--sp-2);
  padding: 0;
  border: none;
  background: none;
  vertical-align: middle;
  cursor: help;
  letter-spacing: 0;
}
.info-tip::before {
  content: "i";
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border: 1px solid var(--mint-dim);
  border-radius: 50%;
  color: var(--mint);
  font: italic 700 10px/1 Georgia, "Times New Roman", serif;
  text-transform: none;
}
.info-tip:hover, .info-tip[aria-expanded="true"] { background: none; }
.info-tip:hover::before, .info-tip[aria-expanded="true"]::before { border-color: var(--phosphor); color: var(--phosphor); }

/* A sideways row's label that carries a tip takes the room it needs, not
   the phone's fixed 68 px label column (hub-chips.css), which the "i" would
   overrun; a wrapping row's label wraps its words instead. */
[data-fold="scroll"] > :is(.hotkey-group-label, .hub-picker-label):has(> .info-tip) { flex-basis: auto; }

@media (pointer: coarse) {
  .info-tip { width: 32px; height: auto; min-height: 36px; margin: 0; }
  .info-tip::before { width: 20px; height: 20px; font-size: var(--fs-lg); }
  /* In a chip row's label (Hub, Cheapest for...) the finger's box overlaps
     the label's padding rather than making its line taller. */
  .hotkey-group-label > .info-tip, .hub-picker-label > .info-tip { min-height: 32px; margin: calc(-1 * var(--sp-4)) 0; }
}

/* The info tip itself (InfoTip, app.js), above everything, the Trade
   settings sheet included: its labels have tips too, and it sits in the
   header's stacking context (z-index 60). A phone's spans the screen; a
   desktop's width is set where it opens. */
.tap-tip {
  position: fixed;
  left: 16px;
  right: 16px;
  z-index: 65;
  background: var(--panel-bg);
  border: 1px solid rgba(0, 255, 136, 0.55);
  border-radius: 2px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.7), 0 0 14px rgba(0, 255, 136, 0.12);
  padding: var(--sp-5) var(--sp-6);
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.45;
  white-space: pre-line;
  overflow-wrap: anywhere;
  /* A chip row's label tip cut short to stay clear of its row (app.js)
     scrolls, without taking the page with it. */
  overflow-y: auto;
  overscroll-behavior: contain;
}

.tap-tip.hidden { display: none; }
/* A card (markup a page built from its own data: an LP offer's breakdown,
   an agent group's stations) wraps its own lines. */
.tap-tip.tap-tip-card { white-space: normal; }

}
@layer pages {
/* Item search's region strip on a tablet too: wrapped, it takes two or
   three rows. Not with a mouse (a narrow desktop window, a small laptop):
   its wheel scrolls the page, not the strip, so the cells past the edge
   would be out of its reach. That keeps the wrap. */
@media (min-width: 769px) and (max-width: 1100px) and (pointer: coarse) {
  .item-ticker { flex-wrap: nowrap; }
}

}
@layer pages {
/* The phone query (PHONE_MEDIA_QUERY in pagination.js — keep them the same). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  main { width: 100%; padding: 20px var(--sp-7) calc(72px + env(safe-area-inset-bottom, 0px)); }

  /* The brand on one line of the header (no tagline); the tools (the sync
     age in its short form, Trade settings) are one line under it. */
  header { padding: var(--sp-4) var(--sp-7); gap: var(--sp-4); }

  .brand-mark { width: 32px; height: 32px; }
  .header-title { gap: var(--sp-5); }
  .wordmark { font-size: 18px; letter-spacing: 0.16em; margin-right: -0.16em; white-space: nowrap; }
  .subtitle { display: none; }
  .data-age-full { display: none; }
  .data-age-short { display: inline; }

  .header-tools {
    flex: 1 1 100%;
    margin-left: 0;
    flex-wrap: wrap;
    gap: var(--sp-4) var(--sp-6);
  }

  /* Trade settings: a sheet from just under its button (settings.js sets
     --settings-top when it opens, since the header's height varies with how
     the data-age line wraps) down to the tab bar; a fixed top would cover
     the button itself, or hide it on a narrow phone. At least ~280px tall
     even when that means covering the button (landscape): the Done row and
     the backdrop close it either way. */
  .settings-panel {
    position: fixed;
    left: 16px;
    right: 16px;
    top: max(8px, min(var(--settings-top, 120px), calc(100vh - 344px - env(safe-area-inset-bottom, 0px))));
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-height: none;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-top: 0;
  }

  .settings-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 -16px var(--sp-4);
    padding: var(--sp-4) var(--sp-7);
    background: var(--panel-bg-2);
    border-bottom: 1px solid var(--panel-border);
  }

  /* Takes the tap that closes the panel, so it can't also land on a tab or
     a "+ Notebook" underneath. A listener on the backdrop itself (cursor:
     pointer too) is what iOS Safari reliably fires a click for — a tap on
     plain page text doesn't reach a document-level listener there. */
  .settings-panel:not(.hidden) + .settings-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 45;
    background: rgba(0, 0, 0, 0.55);
    cursor: pointer;
    touch-action: none;
  }

  .settings-grid { grid-template-columns: minmax(0, 1fr); }

  .settings-chip, .settings-done { min-height: 40px; padding: var(--sp-4) var(--sp-6); }

  .settings-grid select, .settings-grid input { min-height: 40px; }

  .status-leds { top: 12px; right: 16px; }

  /* Nested frames (section panel, CRT screen, card), each padded as on a
     desktop, would leave a card little room for its label and value. The
     panel's frame has no padding of its own; the screen and the card keep
     theirs slim. */
  .search-section, .opportunities-section { margin-bottom: var(--sp-7); }

  .screen { --pad-y: 14px; --pad-x: 10px; }

  .item-detail { padding: 0; border: 0; background: none; }

  /* Item search: the region strip scrolls sideways (see above). */
  .item-ticker { flex-wrap: nowrap; }

  /* Observed at the hubs: a card per region, its name at the top, then per
     side a line naming it over its three windows abreast. One cell a row,
     a card would be ~400px tall and the five ~2,000px. A window's label sits
     over its figure, not beside it: a third of a 360px card has no room for
     both on one line. */
  .item-flow { margin-top: 20px; }
  .item-flow-table tbody tr { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--sp-5); }
  .item-flow-table td { grid-column: 1 / -1; padding: var(--sp-3) 0; }
  .item-flow-table .flow-start { border-left: none; }
  .item-flow-table td.flow-region { text-align: left; border-bottom: none; padding: var(--sp-1) 0 var(--sp-2); }
  .item-flow-table .flow-side-head {
    display: block;
    padding: var(--sp-4) 0 0;
    border-top: 1px solid var(--row-line);
    border-bottom: none;
    text-align: left;
    color: var(--text-label);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }
  .item-flow-table td.flow-win { grid-column: auto; text-align: left; border-bottom: none; }
  .item-flow-table td.flow-win::before { float: none; display: block; max-width: none; margin: 0 0 var(--sp-1); }
  /* Kept whole, "–up to 234.3M" is ~100px: wider than a third of a 360px
     card (82px), so it would run into the next window's figures. Here it may put
     its number on a line of its own ("–up to" stays together). */
  .item-flow-table .flow-upto { white-space: normal; }
  .item-flow-table td[data-label="CCP last day / 7-day avg"] { border-top: 1px solid var(--row-line); }

  /* The title bar's type is smaller; the sync time is the phone header's,
     so the bar has no stamp. */
  .section-header h2, .section-header:has(> .section-meta:not([hidden])) h2 { font-size: var(--fs-md); letter-spacing: 0.1em; padding-right: var(--pad-x); }
  .section-meta { display: none; }
  /* The page name alone: the "// ..." context after it would be cut off with an ellipsis. */
  .section-header h2 .section-context { display: none; }
  .head-help { min-width: 44px; min-height: 44px; margin: -0.4em 0; justify-content: center; padding: 0; }
  .head-help-text { display: none; }
  .head-link { min-height: 32px; }
  /* Several page links: one "Links" button, the links under it. */
  .head-tools { position: relative; }
  .head-links-btn { display: inline-flex; align-items: center; gap: var(--sp-3); min-height: 32px; padding: 0 var(--sp-5); font-size: var(--fs-xs); letter-spacing: 0.08em; color: var(--mint-dim); border-color: var(--edge); background: transparent; }
  .head-links-btn::after { content: "▾"; color: var(--mint-dim); }
  .links-open > .head-links-btn { color: var(--phosphor); border-color: var(--phosphor); }
  .head-links { display: none; }
  .links-open > .head-links { position: absolute; top: 100%; right: 0; z-index: 5; display: flex; flex-direction: column; min-width: 10em; padding: var(--sp-3); background: var(--panel-bg); border: 1px solid var(--edge); }
  .links-open > .head-links > a { display: flex; align-items: center; min-height: 36px; padding: 0 var(--sp-5); white-space: nowrap; }

  /* No "/" key to press (see .search-kbd). */
  .search-kbd { display: none; }

  /* iOS Safari zooms the page in when a field under 16px gets focus, and
     leaves it zoomed. */
  #search, .controls input, .controls select, .picks-head input, .picks-head select,
  .settings-grid input, .settings-grid select, .filter-search, .order-qty input, .order-notes {
    font-size: 16px;
  }

  .controls input:not([type="checkbox"]), .controls select, .picks-head input, .picks-head select { min-height: 36px; }
  .section-header :where(input:not([type="checkbox"]):not([type="radio"]), select) { min-height: 36px; font-size: 16px; }
  .link-row .route-link { display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--sp-3); }

  .controls input { width: 84px; }
  .controls input.input-isk { width: 140px; }

  /* A 16px select sizes itself to its longest option — LP's Store,
     "Society of Conscious Thought", is 307px — and the controls row can't
     shrink below it: on a narrow phone it runs past the screen, whose
     overflow:hidden cuts off the select's arrow and the Sell-at box's
     border. Held to the row, a select truncates its own text instead. */
  .section-header > .controls { min-width: 0; max-width: 100%; }
  .controls label, .controls .controls-group, .controls select { max-width: 100%; }

  /* "Sell at:" and its hub box: the box goes under the words when they
     don't fit side by side, rather than squeezing them to a word a line —
     and, not flex items, the hub names don't take the words' dotted
     underline (the tap tip's mark, @media (hover: none)). */
  .controls .controls-group { display: block; }

  /* Build system, Reaction system, System: a row of their own. At the
     desktop's fixed 190px the 16px hint would be cut in half. */
  .controls label:has(> input[type="text"]) { flex-basis: 100%; }
  .controls input[type="text"] { width: 100%; }

  /* Small secondary text in --text-label, like the card labels: brighter
     than --text-dim, for 10-12px on a phone. */
  .controls, .picks-head, .last-sync, .page-info, .filter-section-title, .order-fields dt, .order-qty,
  .order-module-tag, .hotkey-group-label, .hotkey-chip:not(.active),
  .ticker-hub, .ticker-sub, .ticker-k {
    color: var(--text-label);
  }

  .order-module-tag, .hotkey-group-label, .filter-section-title, .filter-advanced-badge { font-size: var(--fs-sm); }


  /* Touch targets: 36-40px instead of the 22-28px that suits a mouse. */
  button { min-height: 36px; }

  .order-add-btn { padding: var(--sp-4) var(--sp-6); font-size: var(--fs-sm); }

  .hotkey-chip { padding: var(--sp-4) var(--sp-6); font-size: var(--fs-sm); }

  .hotkey-chip-list { gap: var(--sp-4); }

  .hotkey-group-label { padding-top: 11px; }

  /* A label with a tip (Preset, Tech, Rig size) is a tap target: as tall as
     the chips beside it, not its 25px of text. */
  .hotkey-group-label[title] { min-height: 36px; }

  .control-check, .hub-check { min-height: 36px; }

  .controls input[type="checkbox"], .hub-check input, .order-check input, .filter-item input { width: 20px; height: 20px; }

  .hub-multiselect { gap: var(--sp-2) var(--sp-6); }

  .route-actions { justify-content: flex-end; gap: var(--sp-4); }

  /* Order book: the ✕ removes the line at once, so here it's bigger and at
     the far end of the row, away from Qty. */
  .order-remove { width: 40px; height: 40px; margin-left: auto; font-size: 14px; }

  .order-qty input { width: 72px; min-height: 36px; }

  .order-check { min-height: 36px; }

  /* Otherwise field names wrap to one word a line ("BPC / to / buy") beside
     a long station name. */
  .order-fields dt { flex: 0 0 auto; max-width: 45%; }

  table {
    display: block;
    border: none;
    background: none;
  }

  table thead { display: none; }

  table tbody { display: block; }

  /* A row is a HUD card: a thin frame with a phosphor edge down its left,
     like the panels. */
  table tbody tr,
  table tbody tr:nth-child(even) {
    display: block;
    background: var(--input-bg);
    border: 1px solid var(--line);
    border-left: 2px solid rgba(0, 255, 136, 0.55);
    border-radius: 2px;
    padding: var(--sp-2) var(--sp-6) var(--sp-3);
    margin-bottom: var(--sp-4);
  }

  table tbody tr:last-child { margin-bottom: 0; }

  /* Each cell is a label (floated left) and its content flowing to the
     right of it, right-aligned. Intentional: not a flex cell, which makes
     every piece of content — the value, the <br>, each sub-line <span> —
     its own column side by side (a <br> can't break a flex row), so a
     cell's second line ("per unit × units − haul", "bids down to …", a
     pickup note) would sit beside the value, squeezed to a word a line, and
     run off the card. As plain inline text the <br> works: the sub-lines
     stack under the value. */
  table td {
    display: block;
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--row-line);
    text-align: right;
    overflow-wrap: anywhere;
  }

  /* A card's value wraps within the card: the desktop's one-line figures
     (above) would run off a phone. */
  .table-scroll td { white-space: normal; }

  table td:last-child { border-bottom: none; }

  table td::before {
    content: attr(data-label);
    float: left;
    max-width: 50%;
    margin-right: var(--sp-6);
    color: var(--text-label);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    text-align: left;
    overflow-wrap: normal;
  }

  table td:not([data-label])::before { content: none; }

  table td::after { content: ""; display: block; clear: both; }

  /* The card's title: its item (after the item's icon) or its route, as a
     heading over the card's figures, with no "Item" label beside it to say
     what the name already does. */
  table td:first-child:is([data-label="Item"], [data-label="Product"], [data-label="Route"]) {
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-4);
    text-align: left;
    font-size: 13.5px;
    font-weight: 700;
    border-bottom-color: rgba(0, 255, 136, 0.22);
  }

  table td:first-child:is([data-label="Item"], [data-label="Product"], [data-label="Route"])::before { content: none; }

  table td:first-child:is([data-label="Item"], [data-label="Product"], [data-label="Route"]) .filter-count,
  table td:first-child:is([data-label="Item"], [data-label="Product"], [data-label="Route"]) .flag-warn { font-size: var(--fs-sm); font-weight: 400; }

  td.has-icon { padding-left: 36px; }
  td.has-icon > .type-icon { left: 0; width: 26px; height: 26px; }

  /* inline-block can't be narrower than its longest number, so a note
     would push its cell wider than the card. */
  .cell-note { display: inline; max-width: none; }

  table td .filter-count, table td .cell-note { color: var(--text-label); }

  /* "+ Notebook" stays at the right edge, under the thumb. */
  .table-scroll td.order-cell { text-align: right; }

  /* "+ Notebook" in its card, not pinned to a scrolling table's edge (see
     .table-scroll and "Wide tables" above). */
  .table-scroll { isolation: auto; }
  .table-scroll td.order-cell,
  .table-scroll tbody tr:nth-child(even) td.order-cell,
  .table-scroll tbody tr:hover td.order-cell { position: static; background: none; box-shadow: none; animation: none; }

  /* On a phone the Filter chip can land anywhere in its wrapped row, so
     anchoring to it would push the dropdown off one side of the screen or
     the other. It becomes a sheet pinned above the bottom tab bar instead,
     full width inside the 16px gutters. Only the sheet scrolls: its lists
     scrolling inside it as well would trap a swipe in a 160px box. It ends
     below the page header while that's on screen (--header-bottom,
     filters.js), which would otherwise hide its Done row. */
  .filter-dropdown {
    position: fixed;
    top: auto;
    left: 16px;
    right: 16px;
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-width: none;
    max-height: min(70vh, calc(100vh - 72px - env(safe-area-inset-bottom, 0px) - var(--header-bottom, 0px)));
    overscroll-behavior: contain;
    padding-top: 0;
  }

  .filter-dropdown .filter-list, .filter-dropdown .filter-tree { max-height: none; overflow: visible; }

  .filter-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 -14px var(--sp-5);
    padding: var(--sp-4) var(--sp-6);
    background: var(--panel-bg-2);
    border-bottom: 1px solid var(--panel-border);
  }

  .filter-sheet-head .filter-section-title { margin: 0; }

  /* Same job as the Trade settings backdrop: swallows the closing tap. It
     sits under main's own content only — the tab bar above it still
     switches pages (closing the sheet on the way). */
  .filter-dropdown:not(.hidden) + .filter-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 19;
    background: rgba(0, 0, 0, 0.55);
    cursor: pointer;
    touch-action: none;
  }

  .filter-item { display: block; padding: var(--sp-3) 0; }

  .tree-toggle { display: inline-flex; align-items: center; justify-content: center; width: 28px; min-height: 36px; font-size: var(--fs-md); }

  .tree-toggle-spacer { width: 32px; }

  .filter-link-btn { min-height: 32px; }

  /* A finger-sized target at the sheet's foot, not bare 11px text. */
  .filter-advanced summary { padding: var(--sp-6) 0; font-size: var(--fs-sm); }

  /* Phone-only sort control (sortable.js), standing in for the hidden
     column headers: "Sort by" and a strip of chips, a column each. The
     strip is one line that scrolls sideways inside itself — min-width: 0
     holds it to the row, so the page never scrolls sideways — and, with no
     scrollbar, the edge with more chips beyond it fades, as Item search's
     strip does. The lit chip's ▲ or ▼ is the direction. */
  .controls.mobile-sort { display: flex; flex-wrap: wrap; align-items: center; margin-bottom: var(--sp-5); gap: var(--sp-4); }
  .mobile-sort-label { flex: 0 0 auto; white-space: nowrap; }
  .mobile-sort-chips {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-wrap: nowrap;
    gap: var(--sp-3);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .mobile-sort-chips::-webkit-scrollbar { display: none; }
  .mobile-sort-chips.fade-right {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
  }
  .mobile-sort-chips.fade-left {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px);
    mask-image: linear-gradient(90deg, transparent 0, #000 28px);
  }
  .mobile-sort-chips.fade-left.fade-right {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
  }
  .mobile-sort-chip { flex: 0 0 auto; white-space: nowrap; }
  .mobile-sort-arrow:not(:empty) { margin-left: var(--sp-2); font-size: 10px; }
  .mobile-sort .filter-count { text-transform: none; }
  .mobile-sort .filter-count:empty { display: none; }
  .mobile-col-guide { flex-basis: 100%; text-transform: none; letter-spacing: 0; }
  .mobile-col-guide summary { cursor: pointer; color: var(--accent); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.08em; padding: var(--sp-5) 0; }
  .mobile-col-guide dl { margin: var(--sp-4) 0 0; font-size: var(--fs-md); }
  .mobile-col-guide dt { color: var(--text-bright); font-weight: 700; margin-top: var(--sp-4); }
  .mobile-col-guide dd { margin: var(--sp-1) 0 0; color: var(--text-label); line-height: 1.45; }

  .filter-item input { vertical-align: middle; margin: 0 var(--sp-4) 0 0; }

  .phone-fold > summary { display: block; }

  /* Jump links on a long page. */
  .page-jump { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-4); margin: 0 0 var(--sp-5); }
  .page-jump button { min-height: 32px; padding: 0 var(--sp-5); font: inherit; font-size: var(--fs-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); background: transparent; border: 1px solid var(--edge); border-radius: 0; cursor: pointer; }
  #optimize:has(#optimize-plan[hidden]) .page-jump [data-jump="optimize-plan"],
  #optimize:has(#optimize-chart[hidden]) .page-jump [data-jump="optimize-chart"] { display: none; }
}

/* Order book on a phone (the phone query, on screen only: a printout lists
   every line in full). Each line is one compact row — tick, title with its
   first field and tag, ✕ — that opens to its fields, Qty and notes: a full
   card is ~376px, one line a screen, so a Cargo trip would run to dozens of
   screens. The undo toast sits just above the tab bar. */
@media screen and (max-width: 768px), screen and (pointer: coarse) and (max-height: 500px) {
  .order-list, .order-group-body { gap: var(--sp-3); }

  .order-card { padding: var(--sp-2) var(--sp-4); }

  .order-card-head { flex-wrap: nowrap; gap: var(--sp-3); margin-bottom: 0; }
  .order-card-head > .order-check, .order-card-head > .order-remove { flex: 0 0 auto; }
  .order-card-head > .order-check, .order-group-head > .order-check { min-width: 36px; justify-content: center; }

  /* Qty moves into the opened line (.order-qty-detail); the folded row
     names it only when it's more than 1 (orderCardHtml). Beside the tick
     and ✕ its box would leave the title too little room: names wrap to 3-5
     lines, and the Quantity is cut to its first digit. */
  .order-card-head > .order-title, .order-card-head > .order-qty, .order-card-head > .order-kind, .order-card-head > .order-task-sum, .order-check .order-module-tag { display: none; }

  .order-toggle {
    display: block;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 44px;
    padding: var(--sp-2) 0;
    border: none;
    background: none;
    color: var(--text-bright);
    text-align: left;
    text-transform: none;
    letter-spacing: 0;
    font-size: var(--fs-lg);
    font-weight: 400;
    line-height: 1.3;
  }

  .order-toggle:hover { background: none; color: var(--text-bright); }
  .order-toggle-title { display: block; font-weight: 700; overflow-wrap: anywhere; }
  .order-done .order-toggle-title { text-decoration: line-through; }

  /* Wraps rather than ends in "…": cut to one line, the value is the part
     that goes ("Quantity: 4…"). */
  .order-peek {
    display: block;
    margin-top: var(--sp-1);
    color: var(--text-label);
    font-size: var(--fs-sm);
    overflow-wrap: anywhere;
  }

  .order-peek::before { content: "▸ "; color: var(--phosphor); }
  .order-toggle[aria-expanded="true"] .order-peek::before { content: "▾ "; }
  .order-peek .order-module-tag { display: inline-block; padding: 0 var(--sp-2); margin-left: var(--sp-1); white-space: nowrap; }

  .order-card:not(.order-open) .order-detail { display: none; }
  .order-detail { padding: var(--sp-2) 0 var(--sp-3); }

  .order-qty-detail { display: flex; margin: 0 0 var(--sp-4); }
  .order-card-head > .order-remove { width: 36px; }

  .order-group { padding: var(--sp-1) var(--sp-3) var(--sp-3); }

  /* A batch inside a batch (a trip's out and back holds): a rule down its
     left instead of a second framed box, whose border and padding would
     take another 14px off every line's row. */
  .order-group .order-group { padding: 0 0 var(--sp-1) var(--sp-3); border-width: 0 0 0 2px; border-color: var(--phos-a35); border-radius: 0; background: none; }
  .order-group-head { gap: var(--sp-3); }
  .order-group-head > .order-check, .order-group-head > .order-remove { flex: 0 0 auto; }
  .order-group-toggle { min-height: 44px; }
  .order-group-count, .order-group-sum { display: block; margin: var(--sp-1) 0 0; color: var(--text-label); }
  .order-group-head > .order-group-copy { flex: 0 0 auto; min-height: 40px; }
  .notebook-chip { min-height: 36px; }
  .notebook-edit { flex: 1 1 130px; }
  .notebook-edit input { min-height: 36px; font-size: 16px; }

  .undo-toast {
    left: 16px;
    right: 16px;
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    transform: none;
    width: auto;
    max-width: none;
  }
}

/* The presets row on a phone held upright (filters.js). Beside the 68px
   label column its chips take three lines. Here the label is the row's
   first item and the chips (10px sides, not 12px) flow on after it: two
   lines on a phone, "Custom" with a two-digit badge included. Held
   sideways, the column has room. */
@media (max-width: 768px) {
  .hotkey-presets { flex-wrap: wrap; gap: var(--sp-4); }
  .hotkey-presets > .hotkey-group-label { min-width: 0; }
  .hotkey-presets > .hotkey-chip-list { display: contents; }
  /* The presets and the Filter/Custom chip only: the filter sheet,
     Suggested chips and Reset included, sits inside this row too. */
  .hotkey-presets .hotkey-chip[data-preset] { padding-left: var(--sp-5); padding-right: var(--sp-5); }
  /* The Tech row (filters.js) the same way: at 12px sides its four chips
     don't fit beside the label column on a narrow phone, and Faction wraps
     onto a line of its own. */
  .hotkey-chip[data-tech] { padding-left: var(--sp-5); padding-right: var(--sp-5); }
}

}
@layer pages {
/* The site menu (shell.html .site-nav, nav.js). A page is a link and a
   category a button that opens its pages as a small menu: a dropdown under
   the bar on a desktop, a sheet above the bottom bar on a phone. Line icons
   from the sprite at the top of the page, drawn in the text colour, so the
   phosphor of a hover, the current page and a focus lights them too.
   Three layouts: icon and name (1300px and up), icons alone with the name
   sliding out under the icon on hover and focus (769-1299px), and a bottom
   bar of icon over name (the phone query, PHONE_MEDIA_QUERY in
   pagination.js — keep them the same). */
.nav-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.site-nav {
  position: sticky;
  top: 0;
  z-index: 30;
  background: linear-gradient(180deg, #02061a 0%, #010410 100%);
  border-bottom: 1px solid var(--panel-border);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.35);
  padding: 0 32px;
}

.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 52px;
}

.nav-item { position: relative; display: flex; }

/* Capsuleer sits at the right end. */
.nav-item-end { margin-left: auto; }

/* A bar control: a link or a category button, one look. */
.site-nav .nav-top {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  height: 40px;
  margin: 0;
  padding: 0 var(--sp-6);
  background: none;
  border: 0;
  border-radius: 3px;
  color: var(--mint-dim);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease, text-shadow 0.15s ease;
}

.site-nav .nav-top:hover,
.site-nav .nav-cat.open > .nav-top {
  color: var(--mint);
  background: rgba(0, 255, 136, 0.07);
  text-shadow: 0 0 8px var(--phos-a35);
}

.site-nav .nav-top[aria-current],
.site-nav .nav-cat.is-current > .nav-top {
  color: var(--phosphor);
  text-shadow: 0 0 8px var(--phos-a60);
}

/* The current page's bar under its control. */
.site-nav .nav-top::after {
  content: "";
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 0;
  height: 2px;
  border-radius: 1px;
  background: var(--phosphor);
  box-shadow: 0 0 8px rgba(0, 255, 136, 0.8);
  transform: scaleX(0);
  transition: transform 0.2s ease;
}

.site-nav .nav-top[aria-current]::after,
.site-nav .nav-cat.is-current > .nav-top::after { transform: scaleX(1); }

.site-nav .nav-top:focus-visible,
.site-nav .nav-menu a:focus-visible {
  outline: 2px solid var(--phosphor);
  outline-offset: -2px;
  box-shadow: 0 0 10px rgba(0, 255, 136, 0.4);
}

.site-nav .ic {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: filter 0.15s ease;
}

.site-nav .nav-top:hover .ic,
.site-nav .nav-top[aria-current] .ic,
.site-nav .nav-cat.open > .nav-top .ic,
.site-nav .nav-cat.is-current > .nav-top .ic,
.site-nav .nav-menu a:hover .ic,
.site-nav .nav-menu a[aria-current] .ic { filter: drop-shadow(0 0 3px rgba(0, 255, 136, 0.65)); }

.site-nav .nav-caret {
  width: 12px;
  height: 12px;
  flex: none;
  margin-left: -2px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.7;
  transition: transform 0.2s ease;
}

.site-nav .nav-cat.open > .nav-trigger .nav-caret { transform: rotate(180deg); }

.nav-short { display: none; }

/* The Notebook's count, on the Search button too. */
.nav-badge {
  position: absolute;
  top: 3px;
  left: 25px;
  min-width: 15px;
  height: 15px;
  padding: 0 var(--sp-2);
  border-radius: 8px;
  background: var(--phosphor);
  color: var(--black);
  font-size: 9.5px;
  font-weight: 800;
  line-height: 15px;
  letter-spacing: 0;
  text-align: center;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  text-shadow: none;
  box-shadow: 0 0 6px var(--phos-a60);
}

.nav-badge[hidden] { display: none; }

.order-count-badge {
  display: inline-block;
  margin-left: auto;
  min-width: 3ch;
  padding: 0 var(--sp-2);
  text-align: center;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  background: var(--phosphor);
  color: var(--black);
  border-radius: 2px;
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0;
  text-shadow: none;
  box-shadow: 0 0 6px var(--phos-a60);
}

.order-count-badge.hidden { visibility: hidden; }

/* A category's menu: hidden (and out of the tab order) until it opens, then
   it fades and settles under its button with a faint phosphor glow. */
.nav-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 5;
  min-width: 236px;
  max-width: calc(100vw - 16px);
  padding: var(--sp-4) var(--sp-3) var(--sp-3);
  max-height: var(--menu-room, calc(100vh - 90px));
  overflow-y: auto;
  background: linear-gradient(180deg, #04112b 0%, #020819 100%);
  border: 1px solid rgba(0, 255, 136, 0.32);
  border-radius: 6px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(0, 255, 136, 0.05), 0 0 26px rgba(0, 255, 136, 0.13);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-3px);
  transform-origin: top left;
  transition: opacity 0.1s ease, transform 0.1s ease, visibility 0s linear 0.1s;
}

.nav-item-end .nav-menu { left: auto; right: 0; transform-origin: top right; }

.site-nav .nav-cat.open > .nav-menu {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.07s ease-out, transform 0.07s ease-out, visibility 0s;
}

.nav-menu-title {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-5);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.nav-menu-title::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, rgba(0, 255, 136, 0.3), transparent); }

.nav-menu ul { list-style: none; margin: 0; padding: 0; }

/* A labelled run of pages inside a menu: the label names the group and is not a
   control. */
.nav-group + .nav-group,
.nav-menu > ul + .nav-group { margin-top: var(--sp-3); }

.nav-group-title {
  margin: var(--sp-2) 0 var(--sp-1);
  padding: 0 var(--sp-5);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mint-dim);
  opacity: 0.75;
}

.site-nav .nav-menu a {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  min-height: 36px;
  padding: 0 var(--sp-5);
  border-radius: 4px;
  color: var(--mint-dim);
  font-size: var(--fs-md);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.12s ease, background-color 0.12s ease;
}

.site-nav .nav-menu a:hover { color: var(--mint); background: rgba(0, 255, 136, 0.08); }

.site-nav .nav-menu a[aria-current] {
  color: var(--phosphor);
  background: rgba(0, 255, 136, 0.07);
  text-shadow: 0 0 8px rgba(0, 255, 136, 0.5);
  box-shadow: inset 2px 0 0 var(--phosphor);
}

.nav-backdrop { display: none; }

/* 769-1299px: icons alone. The name is the label slid out under the icon
   by a hover or a keyboard focus; the control keeps it as its aria-label.
   Not for a phone held sideways, which gets the bottom bar. */
@media (min-width: 769px) and (max-width: 1299px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .site-nav { padding: 0 var(--sp-7); }

  .site-nav .nav-top { gap: var(--sp-1); padding: 0 var(--sp-5); }

  .site-nav .nav-label {
    --tip-x: -50%;
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    z-index: 6;
    padding: var(--sp-2) 9px;
    background: #020819;
    border: 1px solid var(--phos-a35);
    border-radius: 4px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.6), 0 0 14px rgba(0, 255, 136, 0.15);
    color: var(--mint);
    font-size: var(--fs-xs);
    letter-spacing: 0.08em;
    text-shadow: none;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translate(var(--tip-x), -5px);
    transition: opacity 0.14s ease, transform 0.14s ease, visibility 0s linear 0.14s;
  }

  .site-nav .nav-list > .nav-item:first-child .nav-label { --tip-x: 0; left: 0; }
  .site-nav .nav-list > .nav-item:last-child .nav-label { --tip-x: 0; left: auto; right: 0; }

  .site-nav .nav-top:hover .nav-label,
  .site-nav .nav-top:focus-visible .nav-label {
    opacity: 1;
    visibility: visible;
    transform: translate(var(--tip-x), 0);
    transition-delay: 0s;
  }

  /* An open menu names itself. */
  .site-nav .nav-cat.open > .nav-top .nav-label { opacity: 0; visibility: hidden; }
}

/* The phone: a bar along the bottom, icon over name; a category opens its
   pages as a sheet of tiles above it, over a dimmed page. */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .site-nav {
    --tab-bar: 55px;
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    padding: 0 var(--sp-2) env(safe-area-inset-bottom, 0px);
    background: #01040f;
    border-bottom: 0;
    border-top: 1px solid var(--phos-a35);
    box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.6), 0 -1px 10px rgba(0, 255, 136, 0.08);
  }

  .nav-list { gap: 0; min-height: 0; align-items: stretch; }
  .nav-item { flex: 1 1 auto; min-width: 32px; }
  .nav-item-end { margin-left: 0; }

  .site-nav .nav-top {
    width: 100%;
    height: 54px;
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-1);
    padding: var(--sp-2) 0;
    border-radius: 0;
    font-size: 9.5px;
    letter-spacing: 0;
  }

  .site-nav .nav-top::after { top: 0; bottom: auto; left: 22%; right: 22%; }
  .site-nav .nav-caret { display: none; }
  .nav-full { display: none; }
  .nav-short { display: inline; }
  .nav-badge { left: calc(50% + 3px); top: 5px; }

  .nav-backdrop {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: calc(var(--tab-bar) + env(safe-area-inset-bottom, 0px));
    z-index: -1;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.18s ease, visibility 0s linear 0.18s;
  }

  .site-nav.has-open .nav-backdrop { opacity: 1; visibility: visible; transition-delay: 0s; }
  /* An open sheet lies over the site header (z-index 60) too: a tall sheet
     on a short screen would otherwise slide its top rows under it. */
  .site-nav.has-open { z-index: 70; }

  .nav-menu,
  .nav-item-end .nav-menu {
    position: fixed;
    top: auto;
    left: 8px;
    right: 8px;
    bottom: calc(var(--tab-bar) + env(safe-area-inset-bottom, 0px) + 8px);
    min-width: 0;
    max-width: none;
    max-height: calc(100vh - var(--tab-bar) - env(safe-area-inset-bottom, 0px) - 24px);
    max-height: calc(100dvh - var(--tab-bar) - env(safe-area-inset-bottom, 0px) - 24px);
    overflow-y: auto;
    padding: var(--sp-5);
    border-radius: 10px;
    transform: translateY(14px) scale(0.98);
    transform-origin: bottom center;
  }

  .nav-menu-title { padding: 0 var(--sp-1); margin-bottom: var(--sp-4); }
  .nav-group + .nav-group,
  .nav-menu > ul + .nav-group { margin-top: var(--sp-5); }
  .nav-group-title { margin: 0 0 var(--sp-3); padding: 0 var(--sp-1); }

  .nav-menu ul { display: grid; grid-template-columns: repeat(auto-fill, minmax(98px, 1fr)); gap: var(--sp-3); }

  .site-nav .nav-menu a {
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-3);
    min-height: 64px;
    padding: var(--sp-4) var(--sp-2);
    border: 1px solid rgba(0, 255, 136, 0.14);
    background: rgba(0, 255, 136, 0.025);
    font-size: var(--fs-xs);
    letter-spacing: 0.03em;
    text-align: center;
    white-space: normal;
  }

  .site-nav .nav-menu a[aria-current] { border-color: rgba(0, 255, 136, 0.55); box-shadow: 0 0 10px var(--phos-a20); }

  .order-count-badge { margin-left: 0; font-size: var(--fs-sm); }
}

/* Eight controls share a narrow bar (32 px at the least): the names are set a
   little smaller so the longest (Capsuleer, Industry, Hauling)
   stay apart. */
@media (max-width: 400px) {
  .site-nav .nav-top { font-size: 8.5px; }
}

/* A phone held sideways has the width and not the height: the header is one
   row (the brand, the sync age, Trade settings), the Flash ticker is one slim
   line (flashbar.css) and the tab bar is 44 px, so the page gets the screen. */
@media (pointer: coarse) and (max-height: 500px) {
  header { flex-wrap: nowrap; padding: var(--sp-1) var(--sp-7); gap: 0 var(--sp-6); }
  .brand-mark { width: 22px; height: 22px; }
  .wordmark { font-size: 17px; }
  header .header-tools { flex: 0 0 auto; margin-left: auto; flex-wrap: nowrap; gap: var(--sp-6); }
  header .header-tools .data-age { flex: 0 1 auto; }
  .settings-btn { min-height: 30px; }
  main { padding-top: var(--sp-5); }
  /* The one-row header has no corner for the lights: they sat on Trade settings. */
  .status-leds { display: none; }
  .site-nav { --tab-bar: 45px; }
  .site-nav .nav-top { height: 44px; }
  main { padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }
}

@media (prefers-reduced-motion: reduce) {
  .site-nav,
  .site-nav * ,
  .site-nav *::before,
  .site-nav *::after { transition: none !important; animation: none !important; }
}

/* Out of sight until the keyboard reaches it (nav.js). */
.skip-link {
  position: fixed;
  top: var(--sp-4);
  left: var(--sp-4);
  z-index: 70;
  transform: translateY(-200%);
}
.skip-link:focus-visible { transform: none; background: var(--panel-bg); }

}
@layer pages {
/* --- Hub chips (hud.js initHubChips) ---
   Every hub or region picker is a row of hotkey chips, each hub's with its
   colour bar. The select or checkboxes behind a row stay in the page as its
   source of truth and are never shown — !important, since .hub-multiselect
   and a titled Trade settings field's select (the tap tips, below) set a
   display of their own. */
.hub-chips-source { display: none !important; }

.hub-picker { align-items: flex-start; }
/* Level with the text of a chip beside it. */
.hub-picker-label { padding-top: var(--sp-3); white-space: nowrap; }
.hub-picker .hub-chips, .hub-picker .select-chips { min-width: 0; }

.hub-chip { display: inline-flex; align-items: center; white-space: nowrap; }
.hub-chip .hub-bar { margin-right: var(--sp-3); }
.hub-chip-short { display: none; }

/* Any other one-of-a-few choice as chips (hud.js initSelectChips: Build
   systems' Cheapest for and Security), laid out as a hub picker is — its
   name, then its chips — with a phone's shorter word where the option has one
   (.chip-short, below). An option hidden from code hides its chip: the
   display here would override the hidden attribute. */
.select-chip { display: inline-flex; align-items: center; white-space: nowrap; }
.select-chip[hidden] { display: none; }
/* A titled chip's "i" (a touch screen's .info-pair) goes with it. */
.info-pair:has(> .select-chip[hidden]) { display: none; }
.chip-short { display: none; }

/* The hub the other side of a pair has (Arbitrage, Cargo): not a choice
   (nor a select chip's disabled option). */
.hotkey-chip.hub-chip:disabled,
.hotkey-chip.hub-chip:disabled:hover,
.hotkey-chip.select-chip:disabled,
.hotkey-chip.select-chip:disabled:hover {
  opacity: 0.35;
  cursor: not-allowed;
  color: var(--mint-dim);
  border-color: var(--edge);
  background: transparent;
}

/* Build systems' Region: the regions that aren't a hub's, in one dropdown
   after the chips, lit like a chip while one of them is picked. */
/* The dropdown wears a chip's skin (hotkey-chip, controls.css), not the
   browser's field, its arrow drawn from the text colour; shared by Outposts,
   Agents, Battle reports, Fight calendar, Build systems and Optimize's More…. */
select.hub-other,
.controls select.hub-other,
.section-header select.hub-other {
  appearance: none;
  min-height: 32px;
  padding: var(--sp-2) calc(var(--sp-7) + var(--sp-5)) var(--sp-2) var(--sp-5);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mint-dim);
  background-color: transparent;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) 52%, calc(100% - 11px) 52%;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
  border: 1px solid var(--edge);
  border-radius: 2px;
  cursor: pointer;
}
select.hub-other:hover { color: var(--mint); border-color: var(--mint-dim); background-color: var(--phos-a10); }
select.hub-other:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }
select.hub-other option, select.hub-other optgroup { text-transform: none; letter-spacing: 0; color: var(--text-bright); background: var(--input-bg); }
/* "More": a chip row's rest (chipRow, LP store's Store list), opened in place. */
.hotkey-chip.chip-more { color: var(--mint-dim); border-style: dashed; }
.hotkey-chip.chip-more::after { content: " ▾"; }
.hotkey-chip.chip-more[aria-expanded="true"]::after { content: " ▴"; }
.controls select.hub-other.active {
  color: var(--phosphor);
  border-color: var(--phosphor);
  box-shadow: 0 0 8px rgba(0, 255, 136, 0.3);
}

/* Trade settings' Home hub: its name, then its chips across both columns. */
.settings-grid .settings-hub { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--sp-3); }

/* Trade settings' Build system across both columns: its name, the field and
   Clear on one line, then what it resolves to. */
.settings-grid .settings-build { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.settings-build-row { display: flex; align-items: stretch; gap: var(--sp-4); min-width: 0; }
.settings-build-row input { flex: 1 1 auto; min-width: 0; }
.settings-build-row .settings-chip { flex: 0 0 auto; min-height: 32px; }
.settings-chip:disabled { opacity: 0.45; cursor: default; }
.settings-build-info { margin: 0; color: var(--text-dim); line-height: 1.5; overflow-wrap: anywhere; }
.settings-build-info strong { color: var(--phosphor); }

/* A touch screen underlines a titled control's name for its tap tip: here
   the name alone, not the chips — as flex items they'd take the underline too
   — and without the spacer that holds a wrapped field away from the name
   (the name has a column of its own on a phone, below). */
@media (hover: none) {
  .controls .controls-group.hub-picker[title] { display: inline-flex; text-decoration: none; }
  .controls .controls-group.hub-picker[title]::before { content: none; }
  .controls .controls-group.hub-picker[title] > .hub-picker-label,
  .picks-head .controls-group.hub-picker[title] > .hub-picker-label { text-decoration: underline dotted; text-underline-offset: 3px; }
}

/* A phone: each hub by its hub system (Jita, Amarr, ...) and a blank choice
   by its short word (Auto, Any, All, None), which keeps six chips to two
   rows, where the full names take three or four. The row is laid out
   like a .hotkey-group: its name in a column of its own, the chips wrapping
   beside it, a picker to a line. The column is .hotkey-group-label's 68px,
   so a picker lines up with the chip rows under it (Today's best's
   Activity). "Start hub:" wraps in it rather than end 10px from the first
   chip, where a tap on the name for its tip could land on a chip instead
   (Chrome's touch adjustment, see the tap tips above). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .hub-chip-long, .chip-long { display: none; }
  .hub-chip-short, .chip-short { display: inline; }
  /* 10px sides, as the Tech chips have: at 12, Build systems' Cheapest for
     takes three lines on a narrow phone and Security two; like this two and
     one. */
  .hotkey-chip.select-chip { padding-left: var(--sp-5); padding-right: var(--sp-5); }

  .controls .controls-group.hub-picker, .controls .controls-group.hub-picker[title], .picks-head .hub-picker {
    display: flex;
    flex-basis: 100%;
    gap: var(--sp-5);
  }

  .hub-picker-label { flex: 0 0 68px; padding-top: 11px; white-space: normal; }
  /* A field's 16px, under which iOS zooms in on focus. */
  select.hub-other, .controls select.hub-other, .section-header select.hub-other { min-height: 36px; font-size: 16px; }
}

}
@layer pages {
/* --- LP store's Store chips (tools/lp.js initStoreChips) ---
   A row of hotkey chips above the Store select, one per store family or
   store most LP comes from; the select stays the source of truth. Hidden
   until the stores have loaded: a .hotkey-group's display would override
   the hidden attribute. Each chip's full name is the title of the words
   inside it (a titled chip would get an "i" beside it on a touch screen),
   so the words fill the chip: its padding is theirs, and a hover anywhere
   on the chip shows the name. */
.section-header > .lp-store-chips { flex: 1 1 100%; }
.lp-store-chips[hidden] { display: none; }
.hotkey-chip.lp-store-chip { display: inline-flex; padding: 0; }
/* The full Store list, behind More at the chips' end. */
.lp-store-other { display: none; align-items: center; }
.lp-store-more-open .lp-store-other { display: inline-flex; }
.lp-store-chip > span { display: flex; align-items: center; padding: var(--sp-2) var(--sp-5); }

/* A phone: ten of the 17 chips (lp.js STORE_CHIPS says which), which keeps
   the row to three lines upright. */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .lp-store-chip > span { padding: var(--sp-4) var(--sp-6); }
  .lp-store-chips:not(.lp-store-more-open) .lp-store-chip.lp-store-chip-extra { display: none; }
}

/* A phone held upright: the label is the row's first item and the chips
   flow on after it, 10px sides, as the presets row does — beside the 68px
   label column the ten take four lines; this way three. */
@media (max-width: 768px) {
  .lp-store-chips { flex-wrap: wrap; gap: var(--sp-4); }
  .lp-store-chips > .hotkey-group-label { min-width: 0; }
  .lp-store-chips > .hotkey-chip-list { display: contents; }
  .lp-store-chip > span { padding-left: var(--sp-5); padding-right: var(--sp-5); }
}

/* --- LP store's unvalued rows, verdicts and breakdown card (tools/lp.js) ---
   The Unvalued rows chips sit on a row of their own, as the Store chips do.
   A row's reason is amber under its name; its verdict sentence under vs LP
   value takes the colour of the case (red a loss before LP, amber a pay
   below the store's LP value, green above it, none at it). Class chains
   beat the phone's grey sub-lines (table td .filter-count). */
.section-header > .lp-unvalued { flex: 1 1 100%; }
.table-scroll td .not-valued { font-size: var(--fs-xs); }
.table-scroll td .lp-verdict { display: block; }
#lp-table td[data-label="vs LP value"] { white-space: normal; }
.controls input#lp-daily-lp { width: 96px; }
.table-scroll td .lp-verdict-loss, .table-scroll td .lp-verdict-costs { color: var(--red); }
.table-scroll td .lp-verdict-below { color: var(--amber); }
.table-scroll td .lp-verdict-above { color: var(--phosphor); }

/* The two figures that open the card: dotted like the other tapped parts. */
.lp-card-trigger { cursor: help; border-bottom: 1px dotted var(--text-dim); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .lp-card-trigger { display: inline-block; min-height: 32px; line-height: 32px; }
}

/* The card's rows of label and figure; the card is the info tip's
   (InfoTip, app.js). */
.lp-card-row { display: flex; justify-content: space-between; gap: var(--sp-6); padding: var(--sp-1) 0; }
.lp-card-row > span:last-child { text-align: right; white-space: nowrap; }
.lp-card-row.lp-card-sum { border-top: 1px solid var(--row-line); margin-top: var(--sp-1); padding-top: var(--sp-2); color: var(--phosphor); font-weight: 700; }
.lp-card-note { color: var(--text-label); font-size: var(--fs-sm); padding: 1px 0 var(--sp-2); }

}
@layer pages {
/* --- Agents (tools/agents.js) ---
   Two tables on one screen, each under a title in the voice of the table
   headers. */
.agents-table-title {
  margin: var(--sp-7) 0 var(--sp-1);
  color: var(--mint-dim);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* A family's name and its best offers' item names wrap in a column wide
   enough for a few words a line, not one, and narrow enough that the last
   columns stay inside the pane beside ISK/day. */
#agents-families-table td[data-label="Store family"] { min-width: 160px; white-space: normal; }
#agents-families-table td:is([data-label="Best item"], [data-label="Best profit"]) { min-width: 135px; }
#agents-families-table td[data-label="Divisions"] { white-space: normal; min-width: 100px; max-width: 110px; }
/* Below 1440px the family's name and its best offers give up some more
   width for the same; a row grows a line where a name wraps once more. A
   narrower pane scrolls the table inside it, never the page. */
@media (min-width: 769px) and (max-width: 1439px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #agents-families-table td[data-label="Store family"] { min-width: 140px; }
  #agents-families-table td:is([data-label="Best item"], [data-label="Best profit"]) { min-width: 110px; }
}

/* A lookup's line above its tables, and its By faction fold under the
   Agents table, its summary in the tables' title look. */
.agents-lookup-banner { margin: var(--sp-5) 0 0; padding-left: var(--sp-4); border-left: 2px solid var(--amber); color: var(--amber); font-size: var(--fs-md); line-height: 1.55; }
#agents-list-table td[data-label="Faction"] { text-align: left; white-space: normal; }
.agents-lookup-banner[hidden], .agents-factions-fold[hidden], #agents .controls-group[hidden] { display: none; }
.agents-factions-fold > summary { cursor: pointer; }
#agents-factions-table td[data-label="Faction"] { min-width: 160px; white-space: normal; }
#agents-factions-table td[data-label="Divisions"] { white-space: normal; min-width: 100px; max-width: 110px; }

/* A phone's family card: the five level counts on one line (Levels), not
   five lines; the sort strip still sorts by each. */
:is(#agents-families-table, #agents-factions-table) td.agents-levels { display: none; }
/* Robust ISK/day, the tables' default sort: no room for a column beside
   ISK/day on a desktop, where the ISK/day tip states it; a phone's card has
   it on a line, and its sort strip a chip. */
:is(#agents-families-table, #agents-list-table) .agents-robust { display: none; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  :is(#agents-families-table, #agents-factions-table) td.agents-level { display: none; }
  :is(#agents-families-table, #agents-factions-table) td.agents-levels { display: block; }
  :is(#agents-families-table, #agents-list-table) td.agents-robust { display: block; }
  :is(#agents-families-table, #agents-factions-table) td[data-label="Divisions"] { max-width: none; }
  /* A family's name is a tap target, 32px tall and at least as wide, where
     its line stays. */
  .agents-store-link { display: inline-block; min-width: 32px; padding: var(--sp-4) 0; margin: -8px 0; }
}

/* A family's "+N stations" under its station count: a link-like button,
   and its list in the tap tip's panel (agents.js), a line a station, the
   system's name first. */
.agents-stations-more {
  padding: 0;
  border: none;
  background: none;
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.agents-stations-more:hover, .agents-stations-more[aria-expanded="true"] { background: none; color: var(--phosphor); }
.agents-stations-head { margin-bottom: var(--sp-2); color: var(--mint-dim); }
.agents-stations-line { padding: 1px 0; }
.agents-stations-system { font-weight: 700; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .agents-stations-line { padding: var(--sp-1) 0; }
}

/* A phone held upright: Region's chips and its list flow on after its
   name across the whole row, 10px sides, as the LP store's Store chips do. */
@media (max-width: 768px) {
  .controls .controls-group.hub-picker.agents-region-picker { flex-wrap: wrap; gap: var(--sp-4); }
  .agents-region-picker > .hub-picker-label { flex: 0 0 auto; }
  .agents-region-picker > .hub-chips { display: contents; }
  .agents-region-picker .hub-chip { padding-left: var(--sp-5); padding-right: var(--sp-5); }
}

/* LP per day: five short fields, L1 to L5, then Reset and the note that
   the figures are assumptions, wrapping as a row of chips does. Each field
   holds "1,000,000" on a desktop and "100,000" at a phone's 16px, two to a
   line on a narrow phone, not a line each as the other text fields are. */
.agents-lp-day-fields { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-6); min-width: 0; }
.agents-lp-day-fields label { display: inline-flex; align-items: center; gap: var(--sp-2); white-space: nowrap; }
.controls .agents-lp-day-fields input[type="text"] { width: 76px; }
.agents-lp-day-note { white-space: normal; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .controls .agents-lp-day-fields label:has(> input[type="text"]) { flex-basis: auto; }
  .controls .agents-lp-day-fields input[type="text"] { width: 86px; padding-left: var(--sp-3); padding-right: var(--sp-3); }
  .agents-lp-day-fields { gap: var(--sp-4) var(--sp-5); }
}

}
@layer pages {
/* --- Cargo: Sell at destination and Suggested routes (cargo.js) ---
   The basis chips are a row under the header, as Arbitrage's View is. The
   route whose details are open stays lit in the list — the hover band and
   its phosphor edge, kept (and its pinned Details cell with it) — and its
   plan opens under the list, under a rule, a heading naming the route and
   the way back up. Both ends of that jump clear the sticky nav (a phone's
   is at the bottom). */
.cargo-basis { margin: 0 0 var(--sp-5); }

/* Free hold: a wider field than a number's 70px, for its placeholder. While
   an override is on the field and the line under the header turn amber, and
   a Reset a thumb can hit shows beside the field. */
.controls input#cargo-hold-m3 { width: 140px; }
.cargo-override-on { border-left: 2px solid var(--amber); padding-left: var(--sp-4); }
.cargo-override-badge {
  display: inline-block;
  margin-right: var(--sp-3);
  padding: 1px var(--sp-3);
  border: 1px solid var(--amber);
  border-radius: 2px;
  color: var(--amber);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.controls input.cargo-hold-on { border-color: var(--amber); }
.cargo-override-reset { min-height: 32px; min-width: 56px; padding: var(--sp-2) var(--sp-6); }
.cargo-override-reset[hidden] { display: none; }

#cargo-routes-table tbody tr.is-open { background: var(--phos-a10); }
#cargo-routes-table tbody tr.is-open > td:first-child { box-shadow: inset 2px 0 0 var(--phosphor); }
#cargo-routes-table tbody tr.is-open td.order-cell {
  background: linear-gradient(var(--phos-a10), var(--phos-a10)), var(--table-bg);
}
#cargo-routes-table tbody tr.is-open button[data-cargo-route] { color: var(--phosphor); border-color: var(--phosphor); }

#cargo-routes-status, #cargo-route-detail { scroll-margin-top: calc(var(--nav-height, 56px) + 8px); }
#cargo-route-detail:not(:empty) { margin-top: var(--sp-7); padding-top: var(--sp-6); border-top: 1px solid var(--phos-a35); }

.cargo-detail-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-7);
  margin-bottom: var(--sp-5);
}

.cargo-detail-title {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text-bright);
}

.cargo-detail-title .section-context { font-size: var(--fs-sm); }

.cargo-back-btn {
  padding: 0;
  border: none;
  background: none;
  color: var(--accent);
  font-size: var(--fs-sm);
  letter-spacing: 0.04em;
  text-transform: none;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.cargo-back-btn:hover { background: none; color: var(--phosphor); }

/* The heading takes focus when Details opens it (tabindex -1): no ring
   round a heading the viewer didn't tab to. Why nothing was added (the
   order book full, cargoAddToOrder) takes no room under the Add buttons
   until there's something to say. */
.cargo-detail-title:focus:not(:focus-visible) { outline: none; }
.cargo-add-note:empty { display: none; }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* "Sell at destination" beside the chips would leave them a chip a line:
     where both don't fit beside it, they go under it, on one line (held
     sideways they still fit beside it). */
  .cargo-basis { flex-wrap: wrap; row-gap: 0; }
  .controls input#cargo-hold-m3 { width: 160px; }
  .cargo-override-reset { min-height: 36px; }

  #cargo-routes-status, #cargo-route-detail { scroll-margin-top: 8px; }

  /* The lit route is a card: its whole frame lit instead of a band. */
  #cargo-routes-table tbody tr.is-open {
    background: var(--input-bg);
    border-color: var(--phosphor);
    box-shadow: 0 0 8px rgba(0, 255, 136, 0.3);
  }
  #cargo-routes-table tbody tr.is-open > td:first-child { box-shadow: none; }
  #cargo-routes-table tbody tr.is-open td.order-cell { background: none; }

  .cargo-back-btn { min-height: 36px; }
}

}
@layer pages {
/* --- Build systems: job mode, risk and hub columns (build-systems.js) ---
   What building somewhere saves (vs hub) in the phosphor of a gain, not
   the HUD's red of a leading minus. Jumps to hubs is five hub bars, each
   with its jumps: numbers only in a desktop's row, where the names would
   make it the widest column, and the names too on a phone's card, on a
   line of its own under the label: "Jita 4 Amarr 11 …", the bars parting
   them, tighter and a size down, so it's one line on a phone's card even
   with every hub two digits away. Each hub stays whole: on a narrower screen
   the five wrap, never scroll sideways. The row buttons that pass a job
   between Production and here ("Build where?", "Use on Production") are
   "+ Notebook"'s kind. On a touch screen neither they nor a hub's figure get the
   dotted "tap for a tip" underline: a button's tap does the button's job, and
   the card already names the hub.
   A desktop row's hub names and every " · " between hubs are hidden in
   place, a clipped 1px inline-block, not display: none, so they're still
   in the text a screen reader reads or a copy takes: "Jita 4 · Amarr 11 ·
   …". Not .visually-hidden's position: absolute, which puts each on a line
   of its own in that text. */
.build-saves { color: var(--phosphor); }

/* A route's ⚠ (risk.js) and a hotspot's stay on the figure's line: wrapped
   in their narrow columns, as notes are, they would make a one-line row of
   this table four lines tall. Route risk in words: "⚠ Uedama
   1,056/day" whole; with several hotspots, in red, "⚠ 2 hotspots ·" and
   "worst Uedama 1,056/day" each whole, a line each where the column is
   narrow. "12 via lowsec" in Jumps from hub stays whole too; the lowsec
   systems under it wrap. */
#build-systems td:is([data-label="Kills/day"], [data-label="Route risk"]) .flag-warn { white-space: nowrap; }
.build-risk-part { white-space: nowrap; }
#build-systems td[data-label="Jumps from hub"] .flag-warn { white-space: nowrap; }
/* Its "fewest lowsec/null:" and "3 in 37 j" break between, not inside. */
#build-systems .build-via-part { white-space: nowrap; }
/* NPC facility's "Factory ×2 + Lab": each part whole, a line each where
   the column is narrow, the "+" starting the second (the lit name inside
   a part too: a .flag-yes in a table cell may wrap). */
#build-systems .build-facility,
#build-systems .build-facility .flag-yes { white-space: nowrap; }

/* A job's costs in the amber of every ISK cost (Haul already is), and the
   haul's "in · out" line kept whole under it. */
#build-job-table td:is([data-label="Job cost"], [data-label="Total"]) { color: var(--amber); }
#build-job-table td[data-label="Haul"] .filter-count { white-space: nowrap; }

.build-hub { white-space: nowrap; }
.build-hub + .build-hub { margin-left: var(--sp-2); }
.build-hub .hub-bar { margin-right: var(--sp-2); }
.build-hub-name, .build-hub-sep {
  display: inline-block;
  width: 1px;
  height: 1px;
  margin-right: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: pre;
}
/* Two digits' room each, so a desktop's rows line their five bars up. */
.build-hub-jumps { display: inline-block; min-width: 2ch; text-align: left; }

/* The station under a system's name (buildStationsHtml): a note three lines
   deep at most for most names. Left to the table, the System column
   shrinks to the system's name and the station runs six lines down it;
   180px holds an average name in three. "+N more" stays whole. A phone's
   card has the width, and there the note is inline (the phone block) and
   min-width does nothing. */
#build-systems .build-station { min-width: 180px; }
.build-more { white-space: nowrap; }

/* Cheapest for (build-systems.js): the chain presets, then the activity
   chips, each a chip list of its own, wrapping as one, a wider gap between
   the two. Distance (#build-hub-mode) shows only while two or more Near
   hubs are lit: a hub picker's display would override the hidden
   attribute. Several activities' own fees go under Effective %'s
   combined one, a line each in a desktop's narrow column (on a phone's
   card, one line with " · " between them, each part whole with its " · "
   before it, where a narrow card wraps it), the first system at an
   activity's lowest fee (◆) in the phosphor of a lit chip. The summed
   jumps' "= Jita 4" and "+ Amarr 9" keep each part whole. */
#build-systems .build-activity-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-6); min-width: 0; }
#build-hub-mode[hidden] { display: none; }
#build-systems .build-each { display: block; }
#build-systems .build-each-part { display: block; white-space: nowrap; }
#build-systems .build-each-sep { display: none; }
#build-systems .build-sum-part { white-space: nowrap; }
#build-systems .build-best { color: var(--phosphor); }

/* The hub strip (build-systems.js renderStrip): Item search's
   ticker cells — .ticker-cell and its lines, the green and amber marks —
   six of them, All regions and the five hubs, in a row that wraps. A phone
   scrolls them sideways as one row, as Item search's strip, the edge with
   more cells fading under an arrow: as a grid of two a row they took 350 px
   above the table. The
   labels (Hub, Best, Median, Saves) get the room of the longest, so the
   figures line up. All regions in job mode taps to nothing (a job always
   hauls from a hub), and is dimmed to say so, since a touch screen shows
   neither the cursor nor the hover. The Include-all box is greyed out
   where it can change nothing. */
.build-strip { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-6); }
/* 5em: the key column keeps one width in every cell, so the figures line
   up. */
.build-strip .ticker-k { min-width: 5em; }
.build-strip .ticker-cell[aria-disabled="true"] { cursor: default; opacity: 0.6; }
.build-strip .ticker-cell[aria-disabled="true"]:hover { border-color: var(--line); color: var(--text-bright); }
#build-systems .control-check:has(input:disabled) { opacity: 0.5; cursor: default; }
/* The Include box keeps its size beside a label that wraps to two lines
   ("Include systems without both an NPC Factory and Laboratory"): as a
   flex item it would shrink to make room. */
#build-systems .control-check input { flex-shrink: 0; }

/* The strip is the Near hub picker, "Near hub:" before it
   as a hub picker's name: the controls' last row, the whole width, the
   cells wrapping beside the name where they don't fit. Always shown: with
   no figures yet, or after a failed load, its cells are drawn bare
   (build-systems.js). The cells keep their own type: .controls' small
   capitals stop at a .ticker-cell. */
#build-systems .build-near-hub { flex: 1 1 100%; }
#build-systems .build-near-hub > .build-strip { flex: 1 1 0; min-width: 0; margin-bottom: 0; }

/* The region line's words carry its tip (build-systems.js renderStrip):
   on a touch screen, padded to a finger's 32px as the legend's are — but
   left inline: as an inline-block, a line that wraps would take the whole
   width and push the .last-sync's "> " onto a line of its own. An inline
   box's padding widens what a tap finds without moving a line. */
@media (hover: none) {
  #build-region-line > span { padding: var(--sp-4) 0; }
}

/* Production's "Build where?" in a desktop row: "Where?" over "+ Notebook",
   no wider than it. Beside it, as "Build where?", it would more than
   double the pinned Order column, so Product and BPC cost wrap, rows grow,
   and at 1440px Margin % goes under the pinned column. A phone's card
   keeps "Build where?" beside "+ Notebook", where it fits. */
.build-where-btn { display: block; margin-bottom: var(--sp-1); }
.build-where-long { display: none; }
/* The product's name keeps a readable column (its notes wrap under it),
   not the least the figures beside it leave. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  :is(#production-table, #reactions-table) :is(th, td):first-child { min-width: 210px; }
}

@media (hover: none) {
  .module-page tbody button.build-where-btn[title], .module-page tbody button.build-use-btn[title],
  .module-page tbody .build-hub[title] { text-decoration: none; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  #build-systems td:is([data-label="Kills/day"], [data-label="Route risk"]) .flag-warn,
  #build-job-table td[data-label="Haul"] .filter-count { white-space: normal; }
  .build-hub-name { display: inline; width: auto; height: auto; margin-right: 0; overflow: visible; clip-path: none; white-space: inherit; }
  .build-hubs { font-size: var(--fs-xs); }
  .build-hub + .build-hub { margin-left: var(--sp-2); }
  .build-hub .hub-bar { margin-right: var(--sp-1); }
  .build-hub-jumps { display: inline; min-width: 0; }
  table td[data-label="Jumps to hubs"]::before { float: none; display: block; max-width: none; margin: 0 0 var(--sp-2); }
  .build-where-btn { display: inline-block; margin-bottom: 0; }
  .build-where-long { display: inline; }
  .build-where-short { display: none; }
  /* The strip as one sideways row (see above), each cell as wide as its
     words. */
  .build-strip { display: flex; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; touch-action: pan-x pan-y; overscroll-behavior-x: contain; }
  .build-strip::-webkit-scrollbar { display: none; }
  .build-strip .ticker-cell { flex: 0 0 auto; min-width: 10.5em; }
  /* Cheapest for's presets and activity chips 8px apart when they wrap,
     as a phone's chip rows are; the presets' and Distance's chips at 10px
     sides, as the activity chips beside them have. Several activities'
     own fees run inline on the card, wrapping a whole part at a time (see
     above). */
  #build-systems .build-activity-chips { gap: var(--sp-4) var(--sp-6); }
  #build-systems .build-each-part, #build-systems .build-each-sep { display: inline; }
  #build-systems .controls .hotkey-chip[data-preset] { padding-left: var(--sp-5); padding-right: var(--sp-5); }
  /* "Near hub:" over the grid, not in the hub pickers' 68px column beside
     it: there a cell is too narrow for "The Forge" and its count on one
     line. */
  #build-systems .controls .build-near-hub { position: relative; flex-direction: column; gap: var(--sp-3); }
  #build-systems .build-near-hub > .hub-picker-label { flex: 0 0 auto; padding-top: 0; }
  #build-systems .build-near-hub > .build-strip { flex: 0 0 auto; align-self: stretch; }
}


/* Someone who has asked for less motion gets a still screen: no sweep or
   flicker, no blinking cursor, no pulsing lights. */
@media (prefers-reduced-motion: reduce) {
  .screen > .crt-sweep, .crt-sweep::after, .led-green, .section-meta::after, .header-kicker::after { animation: none; }
  html { scroll-behavior: auto; }
}


/* The index table shows the columns of the activities lit (data-cols). */
#build-table:not([data-cols~="manufacturing"]) .idx-manufacturing,
#build-table:not([data-cols~="reaction"]) .idx-reaction,
#build-table:not([data-cols~="invention"]) .idx-invention,
#build-table:not([data-cols~="copying"]) .idx-copying,
#build-table:not([data-cols~="research_te"]) .idx-research_te,
#build-table:not([data-cols~="research_me"]) .idx-research_me { display: none; }

}
@layer pages {
/* --- Print: only the order book, as a plain paper list --- */
@media print {
  body * { visibility: hidden; }
  #orderbook, #orderbook *, #orderbook-list, #orderbook-list * { visibility: visible; }
  #orderbook { position: absolute; top: 0; left: 0; width: 100%; background: #fff !important; border: none; box-shadow: none; }
  #orderbook::after { content: none; }

  body { background: #fff; }

  #orderbook .screen, #orderbook .screen::before, #orderbook .crt-sweep { background: none; box-shadow: none; }
  #orderbook .section-header .controls, #orderbook .last-sync { display: none; }

  #orderbook h2, #orderbook .section-context, #orderbook .section-context::before { color: #000; text-shadow: none; background: none; }
  #orderbook h2 { border: none; }
  #orderbook h2::before, #orderbook .section-meta { display: none; }
  .order-fields > div { border-color: #ccc; }
  .order-notes::placeholder { color: #999; }

  .order-card {
    background: #fff;
    border: 1px solid #999;
    color: #000;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .order-title, .order-module-tag, .order-fields dt, .order-fields dd { color: #000; }
  .order-check, .order-remove, .type-icon { display: none; }

  /* Every batch printed open, its header a plain heading. */
  #orderbook .order-group-body { display: flex; }
  #orderbook .order-group { border: none; padding: 0; background: none; }
  #orderbook .order-group-toggle { color: #000; font-weight: 700; }
  #orderbook .order-group-toggle::before { content: none; }
  #orderbook .order-group-count { color: #000; }
  .order-print-check { display: inline; font-size: 15px; }
  .order-qty { color: #000; }
  .order-qty input { border: none; color: #000; width: auto; padding: 0; background: none; }
  .order-notes { border: none; background: none; color: #000; resize: none; }

  /* The editing controls stay on the screen; the printout says the task in words. */
  .notebook-kinds, .notebook-edits, .notebook-views, .notebook-add, .order-group-copy { display: none; }
  .order-kind, .order-task-sum, .order-group-sum, .order-from, .order-src, .notebook-route, .notebook-route * { color: #000; }
  .notebook-route { border-color: #999; background: none; }
}

}
@layer pages {
/* --- Optimize (tools/optimize.js) ---
   The order line's own cells (where it sells, its listing and where its
   materials are bought) ride in each row unseen, on a desktop and on a
   phone's card alike. */
:is(#optimize-table, #optimize-plan-table) td.optimize-order-only { display: none; }

/* A family's best by Profit/key unit, and the line above each family when
   the table is grouped. */
.optimize-star { color: var(--amber); }
#optimize-table tr.optimize-family-start td { border-top: 1px solid var(--phos-a35); }
#optimize-table tbody tr.optimize-family-start:first-child td { border-top: none; }

/* The rig's name wraps in a column wide enough for a few words a line;
   every figure column stays one line, so all sixteen fit the pane at 1366. */
#optimize-table td[data-label="Product"] { min-width: 170px; }
@media (min-width: 769px) and (max-width: 1439px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #optimize-table td[data-label="Product"] { min-width: 140px; }
}
#optimize-table td:not(.has-icon) { padding-left: var(--sp-3); }
#optimize-table td { padding-right: var(--sp-3); }

/* Key units / week: its field, then the preset chips, wrapping as a chip
   row does. */
.optimize-units { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-4); min-width: 0; }
.controls .optimize-units input[type="text"] { width: 96px; }
/* Several lit keys: a field each, its material's name before it; the one a
   preset chip fills outlined. */
.optimize-unit-fields { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-6); min-width: 0; }
.controls .optimize-unit-field { display: inline-flex; align-items: center; gap: var(--sp-3); min-width: 0; text-transform: none; letter-spacing: 0; }
.optimize-unit-name { color: var(--text-dim); max-width: 13em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.optimize-unit-field.active input { border-color: var(--phosphor); }
/* "Buy: Rens", "Sell: Jita" under a figure: the word, the bar and the name
   on one line, where a table's notes otherwise wrap. On a desktop the
   Plan's Key column is words, read from the left like the rig's name. */
.optimize-hub-line, .table-scroll td .optimize-hub-line { white-space: nowrap; }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #optimize-plan-table td[data-label="Key"] { text-align: left; white-space: normal; }
}
.optimize-borrowed { white-space: normal; text-transform: none; letter-spacing: 0; }
#optimize-view-note { align-self: center; text-transform: none; letter-spacing: 0; }
/* The rows a line doesn't use (T2 modules: Tech and Blueprint ME; Rigs:
   Invention skills), and the words beside a chip row. */
#optimize .controls-group[hidden] { display: none; }
.optimize-skill-note { align-self: center; text-transform: none; letter-spacing: 0; }
/* III, IV and V: a tap target each however short the numeral. */
#optimize-skill-group .select-chip { min-width: 36px; }
.optimize-verdict { color: var(--phosphor); }
/* An out-of-stock material: red, struck through, with a ✕ before it. */
.optimize-chip-mark { display: none; margin-right: var(--sp-2); }
.hotkey-chip.optimize-cycle-chip.excluded,
.hotkey-chip.optimize-cycle-chip.excluded:hover {
  color: var(--red);
  border-color: var(--red);
  background: rgba(255, 92, 92, 0.12);
  box-shadow: 0 0 8px rgba(255, 92, 92, 0.3);
  text-shadow: none;
}
.optimize-cycle-chip.excluded .optimize-chip-mark { display: inline; }
.optimize-cycle-chip.excluded .optimize-chip-name { text-decoration: line-through; }
/* A chip that is never a key shows its ✕ dimmed: a tap marks it out of stock. */
.optimize-cycle-chip.out-only .optimize-chip-mark { display: inline; opacity: 0.4; }
.optimize-cycle-chip.out-only.excluded .optimize-chip-mark { opacity: 1; }
/* More…: a chip-sized dropdown at the end of the Key row. */
.controls select.optimize-more { font-size: var(--fs-xs); letter-spacing: 0.08em; max-width: 16em; }
#optimize-body tr.optimize-empty td { text-align: left; color: var(--amber); white-space: normal; }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* A wrapped card keeps the name's flags on the name's line. */
  #optimize-table td[data-label="Product"] { min-width: 0; }
  #optimize-table tr.optimize-family-start td { border-top: none; }
  #optimize-table tr.optimize-family-start { border-top: 2px solid rgba(0, 255, 136, 0.55); }
  .controls .optimize-units input[type="text"] { width: 110px; }
  .controls select.optimize-more { font-size: 16px; }
}

/* A phone held upright: Rig kind's and Key's long chip rows flow on after
   the name across the whole row, 10px sides, as the Agents page's Region
   does. */
@media (max-width: 768px) {
  .controls .controls-group.hub-picker.optimize-wide-picker { flex-wrap: wrap; gap: var(--sp-4); }
  .optimize-wide-picker > .hub-picker-label { flex: 0 0 auto; }
  .optimize-wide-picker > .select-chips { display: contents; }
  .optimize-wide-picker .select-chip { padding-left: var(--sp-5); padding-right: var(--sp-5); }
}

}
@layer pages {
/* Bubble charts under a table (tools/bubble-chart.js: Optimize, Station
   trading, Production). A state's colour is --bc-c, set per chart from the page's own
   state list; a bubble's outline is --bc-o where the page colours it. */
.bubble-chart { margin-top: var(--sp-7); border-top: 1px solid var(--line); padding-top: var(--sp-6); position: relative; }
.bubble-chart-head {
  margin: 0 0 var(--sp-5);
  font-size: var(--fs-md);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mint-dim);
}

.bubble-chart-legend { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4); }
.bubble-chart-legend[hidden] { display: none; }
.bc-chip { display: inline-flex; align-items: center; gap: var(--sp-3); min-height: 32px; text-transform: none; letter-spacing: 0.04em; }
.bc-chip .bc-count { color: var(--text-dim); font-weight: 400; }
.bc-swatch { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--bc-c); background: color-mix(in srgb, var(--bc-c) 35%, transparent); }
button.bc-chip:not(.active) { opacity: 0.55; }
button.bc-chip:not(.active) .bc-swatch { background: none; }
.bc-ring-chip { border: 1px solid var(--edge); padding: var(--sp-2) var(--sp-5); font-size: var(--fs-xs); font-weight: 600; color: var(--mint-dim); }
.bc-ring-chip .bc-swatch { border: 2px solid var(--text-bright); background: none; }
.bubble-chart-keys { margin: 0 0 var(--sp-4); font-size: var(--fs-sm); }
.bubble-chart-keys[hidden] { display: none; }
.bubble-chart-size { margin: 0 0 var(--sp-4); font-size: var(--fs-sm); display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.bubble-chart-size[hidden] { display: none; }
.bc-size-svg { overflow: visible; }
.bc-size-svg .bc-size-ref { fill: none; stroke: var(--mint-dim); stroke-width: 1.2; }
.bc-size-svg .bc-title { fill: var(--text-dim); font-size: var(--fs-sm); }
.bc-key-icon { width: 11px; height: 11px; vertical-align: -1px; fill: none; stroke: var(--mint); stroke-width: 1.4; }
.bc-outline-icon { stroke: var(--bc-o); stroke-width: 2; }

.bubble-chart-plot { width: 100%; min-width: 0; }
.bubble-chart-plot[hidden] { display: none; }
.bubble-chart-svg { display: block; max-width: 100%; height: auto; font-family: var(--mono); font-size: var(--fs-sm); overflow: hidden; }
.bubble-chart-svg .bc-grid { stroke: var(--row-line); stroke-width: 1; }
.bubble-chart-svg .bc-axis { stroke: var(--mint-dim); stroke-opacity: 0.6; stroke-width: 1; }
.bubble-chart-svg .bc-guide { stroke: var(--text-dim); stroke-width: 1; stroke-dasharray: 3 4; }
.bubble-chart-svg .bc-tick { fill: var(--text-dim); }
.bubble-chart-svg .bc-zero-label { fill: var(--mint); }
.bubble-chart-svg .bc-title { fill: var(--mint-dim); }
.bubble-chart-svg .bc-corner { fill: var(--text-dim); font-style: italic; opacity: 0.8; }
.bubble-chart-svg .bc-family { fill: none; stroke: var(--mint-dim); stroke-opacity: 0.45; stroke-width: 1; }
.bubble-chart-svg .bc-hit { fill: transparent; }
.bubble-chart-svg .bc-b { cursor: pointer; }
.bubble-chart-svg .bc-m { fill: var(--bc-c); fill-opacity: 0.3; stroke: var(--bc-c); stroke-width: 1.25; }
.bubble-chart-svg .bc-m.bc-hollow { fill: none; }
.bubble-chart-svg .bc-star { fill: var(--amber); stroke: var(--screen-bg); stroke-width: 0.8; }
.bubble-chart-svg .bc-pin { fill: var(--bc-c); stroke: none; pointer-events: none; }
.bubble-chart-svg .bc-ring { fill: none; stroke: var(--text-bright); stroke-width: 1.75; }
.bubble-chart-svg .bc-outlined .bc-m { stroke: var(--bc-o); stroke-width: 1.75; }
.bubble-chart-svg .bc-out { opacity: 0.28; }
.bubble-chart-svg.bc-ringview .bc-family { stroke-opacity: 0.2; }
.bubble-chart-svg :is(.bc-hot, .bc-sel) { opacity: 1; }
.bubble-chart-svg :is(.bc-hot, .bc-sel) .bc-m { stroke: var(--text-bright); stroke-width: 2.5; fill-opacity: 0.55; }
.bubble-chart-note { margin-top: var(--sp-3); }
.bubble-chart-empty[hidden] { display: none; }
.bubble-chart.is-empty > :not(.bubble-chart-head, .bubble-chart-empty, style) { display: none; }

/* The tooltip: fixed to the viewport, kept inside it by the script. */
.bubble-chart-tip {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 60;
  max-width: min(320px, calc(100vw - 16px));
  padding: var(--sp-4) var(--sp-5);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
  color: var(--text-bright);
  font-size: var(--fs-sm);
  line-height: 1.5;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms, visibility 0s 150ms;
}
.bubble-chart-tip.on { opacity: 1; visibility: visible; transition: opacity 150ms; }
.bubble-chart-tip strong { color: var(--phosphor); }
.bubble-chart-tip .bc-loss-word { color: color-mix(in srgb, var(--text-bright) 60%, var(--screen-bg)); }

/* The row a bubble opens, lit a moment. */
:is(#optimize-body, #optimize-plan-body, #station-body, #production-body, #lp-body, #reactions-body, #agents-families-body) .bubble-row-flash td { background: rgba(0, 255, 136, 0.18); }
:is(#optimize-body, #optimize-plan-body, #station-body, #production-body, #lp-body, #reactions-body, #agents-families-body) td { transition: background 150ms; }

@media (prefers-reduced-motion: reduce) {
  .bubble-chart-tip, .bubble-chart-tip.on, :is(#optimize-body, #optimize-plan-body, #station-body, #production-body, #lp-body, #reactions-body, #agents-families-body) td { transition: none; }
}
.optimize-top-n { width: 3.4em; min-height: 26px; }
.bubble-chart-source { margin: var(--sp-1) 0 0; font-size: var(--fs-sm); color: var(--text-dim); }
.bubble-chart-source:empty { display: none; }

}
@layer pages {
/* Admin: Data budget (admin/data-budget.js). Tiles of one figure each, a
   label over it and a line under it; a figure past its limit turns amber.
   Sparklines are inline SVG, stretched to their cell. */
.budget-h {
  margin: 18px 0 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mint);
}

.budget-h:first-child { margin-top: 4px; }

.budget-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.budget-tile {
  min-width: 0;
  padding: 8px 10px;
  background: var(--input-bg);
  border: 1px solid var(--line);
  border-radius: 2px;
}

.budget-tile-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-label);
}

.budget-tile-value {
  margin-top: 3px;
  font-size: 16px;
  font-weight: 700;
  color: var(--text-bright);
  font-variant-numeric: tabular-nums;
}

.budget-tile-sub {
  margin-top: 2px;
  font-size: 10.5px;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

.budget-tile.budget-over { border-color: var(--amber); }
.budget-tile.budget-over .budget-tile-value, .budget-over { color: var(--amber); }

.budget-note, .budget-empty {
  margin: 4px 0 8px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

.budget-empty::before { content: "> "; color: var(--phosphor); opacity: 0.8; }

.budget-spark { display: block; width: 100%; min-width: 90px; height: 28px; }
.budget-spark polyline { fill: none; stroke: var(--phosphor); stroke-width: 1.4; vector-effect: non-scaling-stroke; }
.budget-spark-limit { stroke: var(--amber); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.budget-spark-empty { color: var(--text-dim); }

.budget-trends td[data-label="24 h"], .budget-trends td[data-label="14 d"] { width: 28%; }

/* Admin: Server (admin/server.js). A card per gauge: its title and latest
   value (amber past a limit), a line under them, then the chart, drawn at
   the card's pixel width. */
.section-header > #server-range { margin-left: auto; }
.srv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: var(--sp-4); }
.srv-card { min-width: 0; padding: var(--sp-4) var(--sp-5); background: var(--input-bg); border: 1px solid var(--line); border-radius: 2px; }
.srv-card.srv-over { border-color: var(--amber); }
.srv-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--sp-1) var(--sp-4); }
.srv-title { font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-label); }
.srv-now { font-size: 16px; font-weight: 700; color: var(--text-bright); font-variant-numeric: tabular-nums; }
.srv-sub { min-height: 15px; margin: var(--sp-1) 0 var(--sp-2); font-size: var(--fs-xs); line-height: 1.4; color: var(--text-dim); overflow-wrap: anywhere; }
.srv-svg { display: block; max-width: 100%; height: auto; overflow: hidden; touch-action: pan-y; font-family: var(--mono); font-size: var(--fs-xs); }
.srv-svg .srv-gl { stroke: var(--row-line); stroke-width: 1; }
.srv-svg .srv-axis { stroke: var(--mint-dim); stroke-opacity: 0.6; stroke-width: 1; }
.srv-svg .srv-tick { fill: var(--text-dim); }
.srv-svg .srv-limit { stroke: var(--amber); stroke-width: 1; stroke-dasharray: 3 3; }
.srv-svg .srv-line { fill: none; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.srv-svg .srv-area { stroke: none; fill-opacity: 0.16; }
.srv-svg .srv-line.s1 { stroke: var(--phosphor); }
.srv-svg .srv-dot.s1 { fill: var(--phosphor); }
.srv-svg .srv-line.s2 { stroke: var(--amber); }
.srv-svg .srv-dot.s2 { fill: var(--amber); }
.srv-svg .srv-line.s3 { stroke: var(--mint-dim); }
.srv-svg .srv-dot.s3 { fill: var(--mint-dim); }
.srv-svg .srv-area.s1 { fill: var(--phosphor); }
.srv-svg .srv-area.s2 { fill: var(--amber); }
.srv-svg .srv-hair { stroke: var(--text-bright); stroke-width: 1; stroke-opacity: 0.7; }
.srv-svg [hidden] { display: none; }
.srv-svg .srv-hit { fill: transparent; }
.srv-keys { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-5); margin-top: var(--sp-1); font-size: var(--fs-xs); }
.srv-key-a { color: var(--phosphor); }
.srv-key-b { color: var(--amber); }
.srv-key-c { color: var(--mint-dim); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .budget-tiles { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .budget-trends td[data-label="24 h"], .budget-trends td[data-label="14 d"] { width: auto; }
  /* In a card the sparkline takes the value's side of the row. */
  .budget-trends .budget-spark { display: inline-block; width: 55%; vertical-align: middle; }
}

}
@layer pages {
/* The LP store's capacity curve (tools/lp-staircase.js): the staircase of
   a store's liquid offers, the shaded ISK a day up to the LP per day, the
   dashed LP value and the vertical mark at the LP per day. */
.lps-plot { width: 100%; min-width: 0; touch-action: pan-y; }
.lps-plot[hidden], .lps-text[hidden] { display: none; }
.lps-svg { display: block; max-width: 100%; height: auto; font-family: var(--mono); font-size: var(--fs-sm); overflow: hidden; }
.lps-svg .bc-grid { stroke: var(--row-line); stroke-width: 1; }
.lps-svg .bc-axis { stroke: var(--mint-dim); stroke-opacity: 0.6; stroke-width: 1; }
.lps-svg .bc-tick { fill: var(--text-dim); }
.lps-svg .bc-title { fill: var(--mint-dim); }
.lps-svg .lps-area { fill: var(--phosphor); fill-opacity: 0.18; stroke: none; }
.lps-svg .lps-stair { fill: none; stroke: var(--phosphor); stroke-width: 1.5; stroke-linejoin: round; }
.lps-svg .lps-value { stroke: var(--amber); stroke-width: 1.25; stroke-dasharray: 5 4; }
.lps-svg .lps-value-label { fill: var(--amber); }
.lps-svg .lps-mark { stroke: var(--text-bright); stroke-width: 1; stroke-dasharray: 2 3; }
.lps-svg .lps-mark-label { fill: var(--text-bright); }
.lps-svg .lps-sel { fill: var(--text-bright); fill-opacity: 0.25; stroke: var(--text-bright); stroke-width: 1.5; pointer-events: none; }
.lps-note:empty { display: none; }
.lps-text { margin-top: var(--sp-3); }
.lps-text strong { color: var(--amber); }
.lps-svg :is(.lps-value-label, .lps-mark-label) { paint-order: stroke; stroke: var(--screen-bg); stroke-width: 3px; stroke-linejoin: round; }

/* The LP store's ISK/LP over time (tools/lp-history.js): the finance chart's
   lines mode, the best ISK/LP solid, the median dashed in amber. */
.lph-note:empty { display: none; }
.lph-body[hidden] { display: none; }
.fc-svg path.fc-line-2 { stroke: var(--amber); stroke-width: 1.5; stroke-dasharray: 5 3; }
.fc-svg .fc-dot.fc-line-2 { fill: var(--amber); }
.fc-svg .fc-mark.fc-line-2 { stroke: var(--amber); }
.fc-key-1 { color: var(--phosphor); }
.fc-key-2 { color: var(--amber); }
/* Rollups: words more than figures, so cells read left to right and the
   error and recent-activity cells wrap instead of widening the table. */
.budget-rollups th, .budget-rollups td { text-align: left; }
.budget-rollups td[data-label="Recent"], .budget-rollups td[data-label="Last error"] { white-space: normal; min-width: 160px; overflow-wrap: anywhere; }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* As cards, the values sit right as in every other card. */
  .budget-rollups td { text-align: right; }
  .budget-rollups td[data-label="Recent"], .budget-rollups td[data-label="Last error"] { min-width: 0; }
}

}
@layer pages {
/* News (tools/news.js): the hub and universe-wide chips sit in the
   header and the source filter in the folded explainer. A story is a
   top line (lane and category, place and hub tags, age), a headline, a lead,
   an abstract and a link, in a card on the front page and the desks, a
   headline and a meta line in a row in the wire's log. A
   lane has its own terminal colour: green for economics, amber for politics,
   mint for game balance. */
.news-hubs, .news-universe, .news-cats, .news-rare { margin: var(--sp-2) 0 0; }
/* The desk the menu opened, after the page name: "News // Front page". */
.news-desk-name::before { content: "// "; content: "// " / ""; color: var(--text-dim); }
.news-desk-name:empty { display: none; }
.news-sub { margin: var(--sp-6) 0 0; font-size: var(--fs-md); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-label); }
.news-chip { min-height: 32px; }
/* A hub chip's colour bar, as a hub picker's chip has it (hub-chips.css). */
.news-hubs .news-chip { display: inline-flex; align-items: center; }
.news-hubs .news-chip .hub-bar { margin-right: var(--sp-3); }
.news-hubs[hidden], .news-universe[hidden], .news-cats[hidden], .news-rare[hidden], .news-source-pick[hidden] { display: none; }
.news-source-pick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-6); margin: var(--sp-4) 0 var(--sp-2); }
.news-source-label { color: var(--text-label); font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; }
.news-card-econ { --lane: var(--phosphor); }
.news-card-pol { --lane: var(--amber); }
.news-card-bal { --lane: var(--mint); }
.news-card-other { --lane: var(--edge); }
.news-list { list-style: none; margin: var(--sp-4) 0 0; padding: 0; }
.news-item { padding: var(--sp-5) 0 var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--edge); border-left: 2px solid var(--lane, var(--edge)); }
.news-item:last-child { border-bottom: 0; }
.news-card-title { margin: 0; font-size: 14px; line-height: 1.35; color: var(--phosphor); overflow-wrap: anywhere; }
.news-item .news-card-title { font-size: var(--fs-lg); }
.news-meta { margin: var(--sp-1) 0 0; color: var(--text-label); font-size: var(--fs-sm); line-height: 1.4; }
/* What the rules say a story may affect, after its lead. */
.news-affects { color: var(--text-label); }
.news-affect-label { color: var(--text-dim); }
.news-area { color: var(--text-bright); }
/* A story's label (hud.js newsLabelHtml), the small tag before its headline in
   a card's top line, a Flash line and the ticker: one shape, the colour and the
   word saying which. */
.news-label { display: inline-block; padding: 0 var(--sp-2); border: 1px solid currentColor; font-size: var(--fs-xs); font-weight: 700; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap; vertical-align: baseline; cursor: help; }
.news-label-breaking { color: var(--red); }
.news-label-update { color: #ff8a3d; }
.news-label-confirmed { color: var(--phosphor); }
.news-label-exclusive { color: var(--hub-metropolis); }
.news-label-report { color: var(--text-label); }
.news-label-note { color: var(--text-label); }
.news-possible { margin: 2px 0; font-size: 0.85em; color: var(--text-label); }
.news-possible .news-link-btn { font-size: inherit; }
.news-lane-econ { color: var(--phosphor); }
.news-lane-pol { color: var(--amber); }
.news-lane-bal { color: var(--mint); }
.news-lead { margin: var(--sp-3) 0 0; max-width: 80ch; overflow-wrap: anywhere; font-size: var(--fs-lg); line-height: 1.5; color: var(--text-bright); }
.news-excerpt { margin: var(--sp-3) 0 0; max-width: 80ch; overflow-wrap: anywhere; font-size: var(--fs-md); line-height: 1.55; }
.news-more { margin: 0; display: flex; flex-wrap: wrap; column-gap: var(--sp-7); min-width: 0; font-size: var(--fs-sm); line-height: 1.4; }
/* A link names its page and may be long: it wraps inside the card, at the size of the card's meta line. */
.news-more .news-page-link { min-width: 0; max-width: 100%; white-space: normal; overflow-wrap: anywhere; font-size: var(--fs-sm); line-height: 1.4; }
/* A story's link scrolls to one of these under the sticky nav. */
#fin-minerals, #fin-plex, #fin-events, #news-archive, .fc-events-ul li { scroll-margin-top: calc(var(--nav-height, 56px) + 8px); }
.fc-events-ul li.fc-ev-pick { outline: 1px solid var(--phosphor); outline-offset: 2px; }
/* The full story is a native disclosure: closed by default, Enter or Space opens it. */
.news-full { margin: var(--sp-3) 0 0; }
.news-full > summary { display: inline-flex; align-items: center; gap: var(--sp-3); min-height: 32px; padding: 0 var(--sp-1); cursor: pointer; color: var(--phosphor); font-size: var(--fs-md); list-style: none; }
.news-full > summary::-webkit-details-marker { display: none; }
.news-full > summary::after { content: "\25BE"; font-size: var(--fs-sm); }
.news-full[open] > summary::after { content: "\25B4"; }
.news-full > summary:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }
.news-full-body { margin: var(--sp-1) 0 0; padding: var(--sp-2) 0 var(--sp-1) var(--sp-5); border-left: 1px solid var(--edge); font-size: var(--fs-md); line-height: 1.55; overflow-wrap: anywhere; }
.news-full-body p { margin: var(--sp-3) 0 0; }
.news-full-body ul { margin: var(--sp-3) 0 0; padding-left: var(--sp-7); }
.news-full-body li { padding: 1px 0; }
.news-empty { padding: var(--sp-7) 0; }
/* The phone note clamp sets a display that would show it hidden. */
#news-empty[hidden] { display: none; }
.news-sources-list { margin: 0 0 var(--sp-4); padding-left: var(--sp-7); font-size: var(--fs-md); }
.news-sources-list li { padding: var(--sp-1) 0; }
.news-sources-list a { color: var(--phosphor); }

/* The front page and the desks: a 12-column grid of cards whose width is
   their slot in the column rhythm (tools/news.js, the story templates below);
   the headline's size follows the story's severity. The Archive and the
   Editor's notes keep the fixed sizes (sm to full). A card too narrow to
   leave room for another beside it widens over the strip (tools/news.js
   masonry).
   The rows are 4px units and a card is as tall as its own story: the script
   (tools/news.js, masonry) places each child: its first column and width and
   its first row and height in units, so a card that ends sooner leaves its
   space to the next one, as in a newspaper's columns. A phone has one column
   and lets the rows size themselves. */
.news-front { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-rows: 4px; column-gap: var(--sp-6); row-gap: 0; margin-top: var(--sp-4); }
.news-front > * { align-self: start; }
.news-front[hidden] { display: none; }
.news-card { grid-column: span 3; min-width: 0; padding: var(--sp-5) var(--sp-6) var(--sp-6); background: var(--input-bg); border: 1px solid var(--edge); border-top: 2px solid var(--lane, var(--edge)); }
.news-card-sm { grid-column: span 3; }
.news-card-md { grid-column: span 4; }
.news-card-lg { grid-column: span 6; padding: var(--sp-6) var(--sp-7) var(--sp-7); }
.news-card-wide { grid-column: span 6; }
.news-card-full { grid-column: span 12; }
.news-card-wide .news-card-title, .news-card-full .news-card-title { font-size: 15px; }
.news-sev-1 .news-card-title { font-size: 14px; line-height: 1.35; }
.news-sev-2 .news-card-title { font-size: 17px; line-height: 1.3; }
.news-sev-3 .news-card-title { font-size: 24px; line-height: 1.22; }
.news-card-sm .news-lead, .news-card-sm .news-excerpt { font-size: var(--fs-md); }
.news-card-lg .news-lead { font-size: 14px; line-height: 1.55; }
.news-card-lg .news-excerpt { font-size: var(--fs-lg); line-height: 1.65; }
.news-card .news-lead, .news-card .news-excerpt { max-width: none; }
/* The top line comes before the headline, so it takes the headline's space above. */
.news-topline { margin: 0 0 var(--sp-2); }
/* A preview: a small chart or figure of the data the story links to, in a box of
   a fixed height so nothing moves when it fills. */
.news-preview { height: 158px; margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px dashed var(--edge); overflow: hidden; }
.news-preview p { margin: 0; }
/* Wide enough for the caption to take two lines at most: the box holds the
   chart, not a gap under it. */
@media (min-width: 1101px) {
  .news-preview { height: 134px; }
}
.news-meta time { white-space: nowrap; }
.news-pv-head { font-size: var(--fs-sm); line-height: 16px; color: var(--text-bright); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.news-pv-cap, .news-pv-note { font-size: var(--fs-sm); line-height: 15px; color: var(--text-label); }
.news-pv-cap { max-height: 45px; overflow: hidden; margin-top: 1px; }
.news-preview .fin-spark, .news-pv-bars { display: block; width: 100%; height: 64px; margin: 0; }
/* The plot: a value axis (high, unit, low) beside the chart, marks over it, the
   first and last day under it. */
.news-pv-plot { display: flex; gap: var(--sp-3); height: 64px; margin-top: var(--sp-2); }
.news-pv-y { position: relative; flex: none; width: 58px; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; font-size: var(--fs-xs); line-height: 12px; color: var(--text-label); white-space: nowrap; }
.news-pv-y span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.news-pv-area { position: relative; flex: 1; min-width: 0; height: 64px; }
.news-pv-shade { position: absolute; top: 0; bottom: 0; background: var(--lane, var(--phosphor)); opacity: 0.2; pointer-events: none; }
.news-pv-shade.pv-before { opacity: 0.08; }
.news-pv-mark { position: absolute; top: 0; bottom: 0; border-left: 1px dashed var(--text-bright); pointer-events: none; }
.news-pv-base { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--text-dim); pointer-events: none; }
.news-pv-x { display: flex; justify-content: space-between; margin: 1px 0 0 64px; font-size: var(--fs-xs); line-height: 13px; color: var(--text-label); }
.news-pv-bars rect { fill: var(--lane, var(--phosphor)); fill-opacity: 0.55; }
.news-pv-bars rect.pv-peak { fill-opacity: 1; }
.news-pv-figure { font-size: 30px; line-height: 64px; color: var(--lane, var(--phosphor)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.news-group-title { grid-column: 1 / -1; margin: var(--sp-6) 0 var(--sp-2); font-size: 15px; }
.news-group-note { grid-column: 1 / -1; margin: 0 0 var(--sp-3); }
/* The stories come first and the markets after them. */
.news-front > .news-markets-head, .news-front > .news-fin { order: 1; }
.news-front > .news-archive-head, .news-front > .news-archive-card { order: 2; }
.news-page-link { display: inline-flex; align-items: center; min-height: 32px; white-space: nowrap; color: var(--phosphor); }
.news-link-btn { padding: 0; border: 0; background: none; font: inherit; letter-spacing: inherit; text-transform: none; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
/* The script's placement (grid[data-packed]); a phone's media query below does not apply it. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .news-front[data-packed] > * { grid-column: var(--cs) / span var(--cw); grid-row: var(--rt) / span var(--rs); }
}
@media (max-width: 1100px) {
  .news-card, .news-card-sm, .news-card-md, .news-card-wide { grid-column: span 6; }
  .news-card-lg { grid-column: span 12; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .news-front { grid-auto-rows: auto; row-gap: var(--sp-6); }
  .news-card, .news-card-sm, .news-card-md, .news-card-lg, .news-card-wide { grid-column: span 12; }
  .news-sev-1 .news-card-title { font-size: 14px; }
  .news-sev-2 .news-card-title { font-size: 16px; }
  .news-sev-3 .news-card-title { font-size: 19px; }
  .news-card-lg { padding: var(--sp-5) var(--sp-6) var(--sp-6); }
}

/* The story templates (tools/news.js templateHtml): a card's width is its slot
   in the column rhythm (--span of twelve columns; --span-md of a medium-wide
   window, which halves the twelve), its template the class news-t-*. */
.news-w { grid-column: span var(--span, 3); }
@media (max-width: 1100px) {
  .news-w { grid-column: span var(--span-md, 6); }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .news-w { grid-column: span 12; }
}
/* The figure a figure lead or a data card shows big, in its lane's colour. */
.news-figure { margin: var(--sp-2) 0 var(--sp-1); line-height: 1.15; overflow-wrap: anywhere; }
.news-figure-value { font-size: 26px; font-weight: 700; color: var(--lane, var(--phosphor)); }
.news-figure-cap { font-size: var(--fs-sm); color: var(--text-label); }
.news-t-data .news-figure { margin-top: 0; }
.news-t-data .news-figure-value { font-size: 30px; }
/* A data card's headline is small whatever its severity: the figure is its face. */
.news-card.news-w.news-t-data .news-card-title { font-size: 14px; line-height: 1.35; }
.news-t-roundup { border-left: 2px solid var(--lane, var(--edge)); }
/* A cluster's related stories (tools/news.js relatedHtml): "also:" lines under
   the lead, each opening to its full story, or a "+N related" fold. */
.news-also { margin: var(--sp-4) 0 0; padding-top: var(--sp-2); border-top: 1px dashed var(--edge); }
.news-span-line { margin: 0; font-size: var(--fs-sm); line-height: 1.4; color: var(--text-label); font-weight: 400; }
.news-also-list { list-style: none; margin: var(--sp-1) 0 0; padding: 0; }
.news-also-list > li { border-top: 1px solid var(--row-line); }
.news-also-list > li:first-child { border-top: 0; }
.news-also-item > summary { display: block; min-height: 32px; padding: var(--sp-2) 0; cursor: pointer; list-style: none; font-size: var(--fs-md); line-height: 1.4; color: var(--text-bright); overflow-wrap: anywhere; }
.news-also-item > summary::-webkit-details-marker { display: none; }
.news-also-item > summary:focus-visible, .news-related > summary:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }
.news-also-item[open] > summary { color: var(--phosphor); }
.news-also-tag { color: var(--text-dim); }
.news-also-age { color: var(--text-label); font-size: var(--fs-sm); white-space: nowrap; }
.news-related { margin: var(--sp-3) 0 0; }
.news-related > summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-4); min-height: 32px; padding: var(--sp-2) var(--sp-1); cursor: pointer; list-style: none; color: var(--phosphor); font-size: var(--fs-md); border-top: 1px dashed var(--edge); }
.news-related > summary::-webkit-details-marker { display: none; }
.news-related > summary::after { content: "\25BE"; font-size: var(--fs-sm); }
.news-related[open] > summary::after { content: "\25B4"; }
/* Game balance: a patch's changes by subject as bars. */
.news-mix { list-style: none; margin: var(--sp-4) 0 0; padding: 0; font-size: var(--fs-sm); line-height: 1.3; }
.news-mix li { display: grid; grid-template-columns: minmax(7em, 40%) minmax(0, 1fr) 3.5em; align-items: center; gap: var(--sp-3); padding: 1px 0; }
.news-mix-name { color: var(--text-label); overflow-wrap: anywhere; }
.news-mix-bar { height: 8px; background: var(--row-line); }
.news-mix-bar i { display: block; height: 100%; background: var(--lane, var(--mint)); opacity: 0.75; }
.news-mix-n { text-align: right; color: var(--text-bright); }
/* The Front page's band: its own grid of twelve columns over the full width,
   placed by the same script (tools/news.js fitBand keeps it within the first
   screen). The lead's headline is the page's largest. */
.news-front > .news-band { grid-column: 1 / -1; margin-top: 0; }
.news-band .news-card { border-top-width: 3px; }
/* A column of a third or less keeps the severity's order of sizes in a smaller range. */
.news-narrow.news-sev-3 .news-card-title { font-size: 19px; line-height: 1.25; }
.news-narrow.news-sev-2 .news-card-title { font-size: 16px; }
.news-band-side .news-lead, .news-band-medium .news-lead { font-size: var(--fs-md); line-height: 1.5; }
/* A band slot drawn down to one row: the label, the headline and the age, which open to all of it. */
.news-band .news-card:has(> .news-band-fold) { padding: var(--sp-2) var(--sp-5); }
.news-band-fold > summary { display: block; min-height: 32px; padding: var(--sp-1) 0; cursor: pointer; list-style: none; font-size: var(--fs-md); line-height: 1.4; overflow-wrap: anywhere; }
.news-band-fold > summary::-webkit-details-marker { display: none; }
.news-band-fold > summary:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }
.news-band-head { color: var(--phosphor); font-weight: 700; }
.news-band-fold .news-related { margin-top: var(--sp-1); }
.news-pager { grid-column: 1 / -1; display: flex; justify-content: center; align-items: center; gap: var(--sp-5); margin: var(--sp-5) 0 0; }
.news-pager-top { justify-content: flex-end; margin: 0 0 var(--sp-4); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .news-band-lead.news-sev-3 .news-card-title { font-size: 20px; }
  .news-figure-value { font-size: 22px; }
  .news-t-data .news-figure-value { font-size: 24px; }
  .news-band .news-card { padding: var(--sp-4) var(--sp-5) var(--sp-4); }
}
/* A phone held sideways: the band's slots two to a row. */
@media (pointer: coarse) and (max-height: 500px) and (min-width: 600px) {
  .news-band .news-w { grid-column: span 6; }
  .news-band .news-band-lead:only-child { grid-column: span 12; }
}

/* The Front page's finance block (tools/finance-chart.js): the mineral
   index wide, PLEX beside it, the minerals ticker under both. */
.news-fin-lead { grid-column: span 8; }
.news-fin-side { grid-column: span 4; }
.news-fin-ticker { grid-column: span 12; }
.news-fin-events { grid-column: span 12; }
.news-fin-controls { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-6); margin-top: var(--sp-3); }
.news-chip:disabled { opacity: 0.4; cursor: default; }
.fc-plot { position: relative; width: 100%; min-width: 0; margin-top: var(--sp-4); touch-action: pan-y; }
.fc-svg { display: block; max-width: 100%; height: auto; font-family: var(--mono); font-size: var(--fs-sm); overflow: hidden; }
.fc-svg:focus:not(:focus-visible) { outline: none; }
.fc-svg:focus-visible { outline: 1px solid var(--phosphor); }
.fc-svg .fc-grid { stroke: var(--row-line); stroke-width: 1; }
.fc-svg .fc-base { stroke: var(--text-dim); stroke-dasharray: 3 4; }
.fc-svg .fc-axis { stroke: var(--mint-dim); stroke-opacity: 0.6; stroke-width: 1; }
.fc-svg .fc-tick { fill: var(--text-dim); }
.fc-svg .fc-vol { fill: var(--mint-dim); }
.fc-svg .fc-vgrid { stroke: var(--mint-dim); stroke-width: 1; }
.fc-svg .fc-bar { fill: var(--mint-dim); fill-opacity: 0.45; }
.fc-svg .fc-bar.fc-thin { fill: none; stroke: var(--mint-dim); stroke-width: 1; stroke-dasharray: 2 2; }
.fc-svg .fc-none { fill: none; stroke: var(--text-dim); stroke-width: 1.25; }
.fc-svg .fc-line { fill: none; stroke: var(--phosphor); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.fc-svg .fc-dot { fill: var(--phosphor); }
.fc-svg .fc-hair { stroke: var(--text-bright); stroke-width: 1; stroke-opacity: 0.7; }
.fc-svg .fc-mark { fill: var(--screen-bg); stroke: var(--text-bright); stroke-width: 2; }
.fc-svg .fc-hit { fill: transparent; }
.fc-svg [hidden] { display: none; }
.fc-svg .fc-ev { stroke-width: 2.5; stroke-linecap: butt; }
.fc-svg .fc-ev-sov { stroke: var(--amber); }
.fc-svg .fc-ev-incursion { stroke: var(--hub-forge); }
.fc-svg .fc-ev-battle { stroke: var(--red); }
.fc-ev-k-sov { color: var(--amber); }
.fc-ev-k-incursion { color: var(--hub-forge); }
.fc-ev-k-battle { color: var(--red); }
.fc-ev-label { display: inline-block; margin-top: var(--sp-1); max-width: 28ch; }
.fc-events-list { margin-top: var(--sp-3); font-size: var(--fs-md); }
.fc-events-list summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--mint-dim); }
.fc-events-ul { margin: var(--sp-2) 0 0; padding: 0; list-style: none; }
.fc-events-more { margin-top: var(--sp-3); }
.fc-events-ul li { padding: var(--sp-1) 0; border-top: 1px solid var(--row-line); overflow-wrap: anywhere; }
.fc-caption { margin: var(--sp-4) 0 0; font-size: var(--fs-md); line-height: 1.5; color: var(--text-bright); }
.fc-key { margin: var(--sp-2) 0 0; }
.fc-tip {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 60;
  max-width: min(260px, calc(100vw - 16px));
  padding: var(--sp-4) var(--sp-5);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
  color: var(--text-bright);
  font-size: var(--fs-sm);
  line-height: 1.5;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms, visibility 0s 150ms;
}
.fc-tip.on { opacity: 1; visibility: visible; transition: opacity 150ms; }
.fc-tip strong { color: var(--phosphor); }
.fin-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-4); }
.fin-tile {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-1) var(--sp-4);
  align-items: baseline;
  min-height: 56px;
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  font: inherit;
  color: var(--text-bright);
  background: var(--screen-bg);
  border: 1px solid var(--edge);
  cursor: pointer;
}
.fin-tile:hover, .fin-tile:focus-visible { border-color: var(--phosphor); }
.fin-tile-name { font-weight: 700; color: var(--phosphor); min-width: 0; overflow-wrap: break-word; }
.fin-tile-basket { cursor: default; }
.fin-tile-basket:hover { border-color: var(--edge); }
.fin-tile-note { grid-column: 1 / -1; font-size: var(--fs-sm); line-height: 1.4; color: var(--text-dim); }
.fin-tiles-baskets { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fin-tile-price { grid-column: 1; font-size: var(--fs-md); }
.fin-tile-chg { grid-column: 2; grid-row: 1; font-size: var(--fs-md); font-weight: 700; }
.fin-spark { grid-column: 1 / -1; display: block; width: 100%; height: 30px; }
.fin-spark path { fill: none; stroke: var(--phosphor); stroke-width: 1.5; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.fin-spark-bars rect { fill: var(--mint-dim); fill-opacity: 0.5; }
@media (max-width: 1100px) {
  .news-fin-lead, .news-fin-side { grid-column: span 12; }
}
@media (max-width: 640px) {
  .fin-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fin-tile-name { font-size: var(--fs-md); }
}
@media (prefers-reduced-motion: reduce) {
  .fc-tip, .fc-tip.on { transition: none; }
}

/* Flash: a board of dense rows, the strongest first. Each row has a severity
   marker (one to three bars, so colour is not the only cue), the area, the
   headline with its deviations beneath, the age and the link. */
.news-flash[hidden], .flash-go:empty { display: none; }
.flash-list { list-style: none; margin: var(--sp-4) 0 0; padding: 0; }
.flash-row {
  --sev: var(--amber);
  display: grid;
  grid-template-columns: 30px 96px minmax(0, 1fr) 78px 190px;
  grid-template-areas: "sev area main age go";
  gap: var(--sp-1) var(--sp-5);
  align-items: start;
  padding: var(--sp-3) 0 var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--edge);
  border-left: 2px solid var(--sev);
}
.flash-row:last-child { border-bottom: 0; }
.flash-b1 { --sev: var(--amber); }
.flash-b2 { --sev: #ff8a3d; }
.flash-b3 { --sev: var(--red); }
.flash-sev { grid-area: sev; display: inline-flex; align-items: flex-end; gap: var(--sp-1); height: 16px; margin-top: var(--sp-1); }
.flash-sev i { display: block; width: 6px; background: var(--row-line); border: 1px solid var(--edge); box-sizing: border-box; }
.flash-sev i:nth-child(1) { height: 7px; }
.flash-sev i:nth-child(2) { height: 11px; }
.flash-sev i:nth-child(3) { height: 15px; }
.flash-sev i.on { background: var(--sev); border-color: var(--sev); }
.flash-tag { grid-area: area; display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.flash-area { font-size: var(--fs-sm); letter-spacing: 0.06em; text-transform: uppercase; padding-top: var(--sp-1); }
.flash-main { grid-area: main; min-width: 0; }
.flash-head { margin: 0; font-size: var(--fs-lg); line-height: 1.4; color: var(--text-bright); overflow-wrap: anywhere; }
.flash-why { margin: var(--sp-1) 0 0; font-size: var(--fs-md); line-height: 1.45; color: var(--text-dim); overflow-wrap: anywhere; }
.flash-devs { margin: 1px 0 0; font-size: var(--fs-md); line-height: 1.4; color: var(--sev); overflow-wrap: anywhere; }
.flash-fig { margin: 0; }
.flash-fig > summary { display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--sp-1); cursor: pointer; list-style: none; font-size: var(--fs-sm); color: var(--text-label); }
.flash-fig > summary::-webkit-details-marker { display: none; }
.flash-fig > summary::after { content: "\25BE"; margin-left: var(--sp-2); }
.flash-fig[open] > summary::after { content: "\25B4"; }
.flash-fig > p { margin: 0 0 var(--sp-2); padding-left: var(--sp-5); border-left: 1px solid var(--edge); font-size: var(--fs-md); line-height: 1.5; overflow-wrap: anywhere; }
.flash-age { grid-area: age; padding-top: var(--sp-1); font-size: var(--fs-sm); color: var(--text-label); white-space: nowrap; }
.flash-go { grid-area: go; justify-self: end; }
.flash-go .news-page-link { font-size: var(--fs-md); line-height: 1.4; white-space: normal; text-align: right; }
.flash-also { list-style: none; margin: var(--sp-1) 0 0; padding: 0; font-size: var(--fs-md); line-height: 1.4; color: var(--text-bright); overflow-wrap: anywhere; }
.flash-also li { padding: 1px 0; }
.flash-also-devs { color: var(--sev); font-size: var(--fs-sm); }
.flash-also .news-page-link { white-space: normal; }
.flash-coverage-list { margin: var(--sp-2) 0 0; padding-left: var(--sp-7); font-size: var(--fs-md); }
.flash-coverage-list li { padding: var(--sp-1) 0; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .flash-row {
    grid-template-columns: 30px minmax(0, 1fr) auto;
    grid-template-areas: "sev area age" "main main main" "go go go";
  }
  .flash-go { justify-self: start; }
  .flash-why { color: var(--text-label); }
}

/* The Editor's desk (tools/news.js): a note leads at full width and the
   others follow two to a row, in the cards above. A note reads core first:
   the lead, then each consequence's sentence with its confidence as a small
   tag (low dim, medium amber; there is no high) and, smaller beneath it, what
   would confirm or refute it and the rule that fired; last the speculation
   label, small but always visible, and the folded evidence. The explainer
   frames the label in amber. */
.news-card-ed { --lane: var(--text-bright); }
.news-lane-ed { color: var(--text-bright); }
.ed-label { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--sp-5); margin: var(--sp-4) 0 0; padding: var(--sp-1) var(--sp-4); border: 1px dashed var(--amber); color: var(--amber); font-size: var(--fs-md); line-height: 1.45; overflow-wrap: anywhere; }
.ed-label .news-page-link { color: var(--amber); }
.ed-sub { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-label); }
.ed-cons { margin: var(--sp-2) 0 0; padding-left: 0; list-style: none; }
.ed-con { padding: var(--sp-1) 0; border-bottom: 1px solid var(--row-line); }
.ed-con:last-child { border-bottom: 0; }
.ed-con-head { margin: 0; font-size: var(--fs-lg); line-height: 1.45; color: var(--text-bright); overflow-wrap: anywhere; }
.news-card-full .ed-con-head { font-size: 14.5px; }
.ed-conf { display: inline-block; margin-right: var(--sp-2); padding: 0 var(--sp-3); border: 1px solid currentColor; font-size: var(--fs-xs); line-height: 16px; letter-spacing: 0.06em; text-transform: uppercase; vertical-align: 1px; }
.ed-conf-low { color: var(--text-dim); }
.ed-conf-medium { color: var(--amber); }
.ed-ind { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); line-height: 1.45; color: var(--text-dim); overflow-wrap: anywhere; }
.ed-ind p { margin: var(--sp-2) 0 0; }
.ed-ind ul { margin: 0; padding-left: var(--sp-7); }
.ed-ind li { padding: 1px 0; }
.ed-ind .news-page-link { min-height: 24px; }
.ed-fired { color: var(--text-label); }
.ed-outcome { margin-left: var(--sp-2); padding: 0 var(--sp-3); border: 1px solid var(--line); color: var(--text-bright); font-size: var(--fs-xs); white-space: nowrap; }
.ed-prev { margin: var(--sp-2) 0; color: var(--text-label); font-size: var(--fs-sm); }
.ed-verdict { color: var(--text-bright); }
.ed-held, .ed-hit { color: var(--text-label); font-size: var(--fs-xs); }
.ed-held-yes { color: var(--mint); }
.ed-held-no { color: var(--amber); }
.ed-more > summary { cursor: pointer; }
.ed-more > summary::marker { color: var(--text-label); }
.ed-disclaimer { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); line-height: 1.45; color: var(--amber); overflow-wrap: anywhere; }
.ed-evidence > summary { color: var(--amber); font-size: var(--fs-sm); }
.ed-disclaimer .news-page-link { color: var(--amber); min-height: 24px; }
.ed-evidence { font-size: var(--fs-md); }
.ed-ev-list { padding-left: var(--sp-7); }
.ed-ev { padding: var(--sp-1) 0; }
.ed-ev-lane { font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; }
.ed-ev-label { color: var(--text-bright); font-weight: 400; }
.ed-ev-src { color: var(--text-dim); font-size: var(--fs-sm); }
.ed-below { margin-top: 0; }
.ed-rules .ed-label { display: block; }
.ed-rule-list li { scroll-margin-top: calc(var(--nav-height, 56px) + 8px); }
/* A story, a note or a rule a link opened, marked for a moment. */
.news-card-pick { outline: 1px solid var(--phosphor); outline-offset: 2px; }
[data-guid] { scroll-margin-top: calc(var(--nav-height, 56px) + 8px); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .ed-cons { padding-left: 0; }
  .ed-ind .news-page-link, .ed-disclaimer .news-page-link { min-height: 32px; }
}


/* A flash line's place: the region or market in words, then the hub tags (hud.js hubTagHtml). */
.flash-where { font-size: var(--fs-xs); color: var(--text-label); overflow-wrap: anywhere; }
/* A politics story's category (FW, Ganking/gatecamps, ...), in the card's
   meta line and under a Flash line's area. */
.news-cat { color: var(--text-bright); }
.flash-cat { font-size: var(--fs-sm); color: var(--amber); overflow-wrap: normal; }
}
@layer pages {
/* War room (tools/warroom.js), a News desk: the chips, the fronts' day bar,
   then the map beside its list of events (the list under the map on a
   phone and a narrow window), the legend under both. The map is a canvas
   in a terminal frame; its zoom buttons and the tooltip float over it. */
.war-room[hidden], .war-fw-bar[hidden], .war-tip[hidden], #war-more[hidden], #war-panel-all[hidden] { display: none; }
.war-controls { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-7); margin: var(--sp-3) 0 0; }
.war-controls .hotkey-group { margin: 0; }
.war-dot { display: inline-block; flex: none; width: 8px; height: 8px; margin-right: var(--sp-3); border-radius: 50%; background: var(--c); box-shadow: 0 0 6px var(--c); vertical-align: middle; }
.war-sq { display: inline-block; width: 6px; height: 6px; margin-right: var(--sp-3); background: var(--c); vertical-align: middle; }
.war-btn { min-width: 32px; min-height: 32px; padding: 0 var(--sp-4); border: 1px solid var(--panel-border); background: var(--panel-bg); color: var(--phosphor); font: inherit; font-size: 14px; line-height: 1; cursor: pointer; }
.war-btn:hover, .war-btn:focus-visible { border-color: var(--phosphor); }
.war-btn:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }
.war-btn-text { font-size: var(--fs-md); letter-spacing: 0.04em; }
/* The list rows and the tooltip read as text, not as the site's capitalised buttons. */
.war-item-btn, .war-item-story, .war-tip, .war-tip .war-btn, .war-more, #war-panel-all { text-transform: none; letter-spacing: normal; }
.war-fw-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-5); margin: var(--sp-4) 0 0; }
.war-fw-track { position: relative; flex: 1 1 200px; display: flex; min-width: 0; padding-bottom: 14px; }
.war-fw-bar input[type="range"] { flex: 1 1 auto; width: 100%; min-width: 0; min-height: 32px; accent-color: var(--phosphor); }
/* The Havoc rework on the slider: a tick at its day, its name under it. */
.war-fw-mark { position: absolute; bottom: 0; left: calc(8px + var(--at, 0) * (100% - 16px)); padding: 0 var(--sp-2); border-left: 2px solid var(--amber); color: var(--amber); font-size: var(--fs-xs); line-height: 14px; pointer-events: none; white-space: nowrap; }
.war-fw-mark[hidden] { display: none; }
.war-fw-bar output { flex: 1 1 100%; order: 5; color: var(--text-bright); font-size: var(--fs-md); line-height: 1.4; overflow-wrap: anywhere; }

.war-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); gap: var(--sp-6); margin: var(--sp-5) 0 0; }
.war-map-wrap { position: relative; min-width: 0; height: clamp(300px, 64vh, 680px); border: 1px solid var(--panel-border); background: radial-gradient(ellipse at 50% 45%, #041026 0%, var(--screen-bg) 70%); overflow: hidden; }
#war-map { display: block; touch-action: none; cursor: grab; }
#war-map.war-dragging { cursor: grabbing; }
#war-map:focus-visible { outline: 1px solid var(--phosphor); outline-offset: -2px; }
.war-zoom { position: absolute; top: 8px; right: 8px; display: flex; flex-direction: column; gap: var(--sp-2); }
.war-zoom .war-btn { background: rgba(3, 8, 23, 0.85); }
.war-tip { position: absolute; top: 0; left: 0; z-index: 2; width: min(300px, calc(100% - 16px)); padding: var(--sp-4) var(--sp-5); border: 1px solid var(--phosphor); background: rgba(1, 4, 12, 0.94); box-shadow: 0 0 14px rgba(0, 255, 136, 0.18); font-size: var(--fs-md); line-height: 1.45; color: var(--text); pointer-events: none; }
.war-tip[data-touch="true"] { pointer-events: auto; }
.war-tip p { margin: 0 0 var(--sp-1); overflow-wrap: anywhere; }
.war-tip-sys strong { color: var(--text-bright); }
.war-tip-kind { color: var(--text-bright); }
.war-tip-what { color: var(--phosphor); }
.war-tip-when, .war-tip-src, .war-tip-hint { color: var(--text-label); font-size: var(--fs-sm); }
.war-tip-facts { color: var(--text-dim); font-size: var(--fs-sm); }
.war-tip-story { color: var(--text-bright); }
.war-tip-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: var(--sp-3) 0 0; }
.war-sec { font-size: var(--fs-sm); }
.war-sec-0 { color: var(--mint); }
.war-sec-1 { color: var(--amber); }
.war-sec-2 { color: var(--red); }

.war-panel { display: flex; flex-direction: column; min-width: 0; max-height: clamp(300px, 64vh, 680px); border: 1px solid var(--panel-border); background: var(--panel-bg); }
.war-panel-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line); }
.war-panel-head { margin: 0; color: var(--text-label); font-size: var(--fs-sm); letter-spacing: 0.06em; text-transform: uppercase; }
.war-list { flex: 1 1 auto; min-height: 0; margin: 0; padding: 0; list-style: none; overflow-y: auto; overscroll-behavior: contain; }
.war-item { display: flex; flex-direction: column; border-bottom: 1px solid var(--row-line); }
.war-item-on { background: rgba(0, 255, 136, 0.08); }
.war-item-btn { display: flex; flex: 1 1 auto; align-items: flex-start; gap: 0; min-width: 0; min-height: 32px; padding: var(--sp-3) var(--sp-2) var(--sp-3) var(--sp-4); border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.war-item-btn:hover, .war-item-btn:focus-visible { background: rgba(0, 255, 136, 0.06); }
.war-item-btn .war-dot { margin-top: var(--sp-2); }
.war-item-main { display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; }
.war-item-top { color: var(--text-label); font-size: var(--fs-sm); line-height: 1.35; overflow-wrap: anywhere; }
.war-item-top strong { color: var(--text-bright); font-weight: 600; }
.war-item-what { color: var(--phosphor); font-size: var(--fs-md); line-height: 1.4; overflow-wrap: anywhere; }
.war-item-meta { color: var(--text-dim); font-size: var(--fs-sm); line-height: 1.35; overflow-wrap: anywhere; }
.war-item-retracted { opacity: 0.6; }
.war-item-retracted .war-item-what, .war-item-retracted .war-item-top { text-decoration: line-through; text-decoration-color: var(--text-dim); }
.war-item-size { flex: none; padding: 0 0 0 var(--sp-3); color: var(--text-bright); font-size: var(--fs-md); font-variant-numeric: tabular-nums; }
/* The story link sits under the row's text, so the text keeps the panel's width. */
.war-item-story { flex: none; align-self: flex-start; min-height: 32px; margin: 0 0 var(--sp-3) var(--sp-7); padding: 0 var(--sp-3); border: 1px solid var(--panel-border); background: none; color: var(--phosphor); font: inherit; font-size: var(--fs-sm); white-space: nowrap; cursor: pointer; }
.war-item-story:hover, .war-item-story:focus-visible { border-color: var(--phosphor); }
.war-item-story .news-label { font-size: var(--fs-xs); line-height: 13px; }
.war-empty { padding: var(--sp-6) var(--sp-4); }
.war-more { margin: var(--sp-3) var(--sp-4); }

.war-legend { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-label); }
.war-leg-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-6); margin: var(--sp-1) 0; }
.war-leg-label { min-width: 64px; color: var(--text-dim); letter-spacing: 0.06em; text-transform: uppercase; }
.war-leg { display: inline-flex; align-items: center; white-space: nowrap; }
.war-leg-wrap { white-space: normal; }
.war-dia { display: inline-block; flex: none; width: 7px; height: 7px; margin-right: var(--sp-3); border: 1.5px solid var(--c); transform: rotate(45deg); vertical-align: middle; }
.war-dia-fill { background: color-mix(in srgb, var(--c) 40%, transparent); }
.war-ring { display: inline-block; flex: none; width: 9px; height: 9px; margin-right: var(--sp-3); border: 1.5px solid var(--c); border-radius: 50%; vertical-align: middle; }
.war-ring-dash { border-style: dashed; }
.war-leg-row .hotkey-chip { min-height: 32px; }
.war-leg-src { margin: var(--sp-2) 0 0; max-width: 110ch; color: var(--text-dim); overflow-wrap: anywhere; }

/* The panel's Events and Wars chips, the wars list and a war's report. */
#war-wars[hidden], #war-new[hidden], #war-list[hidden], .war-report[hidden], .war-territory[hidden] { display: none; }
.war-panel-tabs { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4) 0; }
.war-report { flex: 1 1 auto; min-height: 0; padding: var(--sp-3) var(--sp-4) var(--sp-5); overflow-y: auto; overscroll-behavior: contain; font-size: var(--fs-md); line-height: 1.45; }
.war-report-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); margin: 0 0 var(--sp-3); }
.war-report .war-btn, .war-sys-btn { text-transform: none; letter-spacing: normal; }
.war-report-id { color: var(--text-label); font-size: var(--fs-sm); }
.war-report-title { margin: 0 0 var(--sp-2); color: var(--text-bright); font-size: var(--fs-lg); font-weight: 600; overflow-wrap: anywhere; }
.war-report-fig { margin: var(--sp-3) 0 var(--sp-2); color: var(--phosphor); overflow-wrap: anywhere; }
.war-report-sub { margin: var(--sp-5) 0 var(--sp-2); color: var(--text-label); font-size: var(--fs-sm); letter-spacing: 0.06em; text-transform: uppercase; }
.war-report .war-item-meta { display: block; margin: 0 0 var(--sp-1); }
.war-ratio { display: block; height: 4px; margin: var(--sp-2) 0 var(--sp-1); background: linear-gradient(90deg, #ff7a59 0 var(--r), #4da3ff var(--r) 100%); opacity: 0.85; }
.war-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.war-table th, .war-table td { padding: var(--sp-1) var(--sp-2); border-bottom: 1px solid var(--row-line); text-align: right; white-space: nowrap; }
.war-table th:first-child, .war-table td:first-child { text-align: left; }
.war-table td:first-child { white-space: normal; overflow-wrap: break-word; }
.war-table th { color: var(--text-label); font-weight: normal; }
.war-timeline, .war-stat-chart { display: block; width: 100%; height: 96px; margin: var(--sp-4) 0 0; background: rgba(0, 255, 136, 0.03); }
.war-stat-chart { height: 120px; }
.war-axis { stroke: var(--text-dim); stroke-width: 0.6; }
.war-axis-labels { display: flex; justify-content: space-between; gap: var(--sp-3); margin: var(--sp-1) 0 0; color: var(--text-dim); font-size: var(--fs-xs); }
.war-sys-list { margin: 0; padding: 0; list-style: none; }
/* A busiest system: its button focuses the map, "route ›" beside it plans a trip there. */
.war-sys-list li:has(> .route-link) { display: flex; align-items: center; border-bottom: 1px solid var(--row-line); }
.war-sys-list li:has(> .route-link) > .war-sys-btn { flex: 1 1 auto; border-bottom: 0; }
.war-sys-btn { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); width: 100%; min-height: 32px; padding: var(--sp-2) var(--sp-3); border: 0; border-bottom: 1px solid var(--row-line); background: none; color: var(--text); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer; }
.war-sys-btn:hover, .war-sys-btn:focus-visible { background: rgba(0, 255, 136, 0.06); }
.war-sys-btn .war-item-size { margin-left: auto; }
.war-sys-btn .war-ratio { flex: 1 1 100%; }
.war-table .war-sys-btn { width: auto; padding: 0; border: 0; }
.war-check { margin: var(--sp-5) 0 0; padding: var(--sp-2) var(--sp-4) var(--sp-3); border-left: 2px solid var(--panel-border); }
.war-check-agree { border-left-color: var(--mint); }
.war-check-differ { border-left-color: var(--amber); }
.war-up { color: var(--mint); }
.war-down { color: var(--red); }

/* Territory, under the legend while the Sov overlay is on. */
.war-territory { margin: var(--sp-4) 0 0; max-width: 640px; }
.war-territory-head { margin: 0 0 var(--sp-2); color: var(--text-label); font-size: var(--fs-sm); letter-spacing: 0.04em; }

/* Stats under the map, side by side where they fit. */
.war-stats { margin: var(--sp-6) 0 0; }
.war-stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: var(--sp-6); }
.war-stat { min-width: 0; padding: var(--sp-2) var(--sp-5) var(--sp-4); border: 1px solid var(--panel-border); background: var(--panel-bg); font-size: var(--fs-md); }
.war-stat .war-report-sub { margin-top: var(--sp-3); }
.war-stat-note { margin: var(--sp-3) 0 0; color: var(--text-dim); font-size: var(--fs-sm); line-height: 1.4; }
.war-bars { margin: 0; padding: 0; list-style: none; }
.war-bars li { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--sp-1) var(--sp-4); margin: 0 0 var(--sp-3); }
.war-bar-label { color: var(--text-label); font-size: var(--fs-sm); }
.war-bar { grid-column: 1 / -1; grid-row: 2; height: 8px; width: var(--w); min-width: 1px; background: var(--phosphor); opacity: 0.7; }
.war-bar-val { grid-column: 2; grid-row: 1; color: var(--text); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
  .war-layout { grid-template-columns: minmax(0, 1fr); }
  .war-panel { max-height: 60vh; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .war-map-wrap { height: clamp(260px, 58vh, 520px); }
  .war-controls { gap: var(--sp-1) var(--sp-6); }
  /* The War room's small tables stay tables on a phone and scroll sideways
     in their .table-scroll, where the shared card layout would stack them. */
  .war-table { display: table; width: max-content; min-width: 100%; }
  .war-table thead { display: table-header-group; }
  .war-table tbody { display: table-row-group; }
  .war-table tbody tr, .war-table tbody tr:nth-child(even) { display: table-row; background: none; border: none; border-radius: 0; padding: 0; margin: 0; }
  .war-table th, .war-table td { display: table-cell; padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--row-line); white-space: nowrap; overflow-wrap: normal; }
  .war-table td:first-child { white-space: normal; min-width: 110px; }
  .war-table td::before, .war-table td::after { content: none; }
}
}
@layer pages {
/* The shared New Eden map (tools/eve-map.js) where a page builds it itself:
   Outposts and Build systems. A canvas in a terminal frame with a fixed
   height, so the page does not move when the map loads; its zoom buttons,
   status line and tooltip float over it. The War room has its own markup. */
.eve-map { position: relative; min-width: 0; height: clamp(260px, 52vh, 460px); margin: var(--sp-3) 0 var(--sp-2); border: 1px solid var(--panel-border); background: radial-gradient(ellipse at 50% 45%, #041026 0%, var(--screen-bg) 70%); overflow: hidden; }
.eve-map-canvas { display: block; touch-action: none; cursor: grab; }
.eve-map-canvas.eve-map-dragging { cursor: grabbing; }
.eve-map-canvas:focus-visible { outline: 1px solid var(--phosphor); outline-offset: -2px; }
.eve-map-zoom { position: absolute; top: 8px; right: 8px; display: flex; flex-direction: column; gap: var(--sp-2); }
.eve-map-btn { min-width: 32px; min-height: 32px; padding: 0 var(--sp-4); border: 1px solid var(--panel-border); background: rgba(3, 8, 23, 0.85); color: var(--phosphor); font: inherit; font-size: 14px; line-height: 1; cursor: pointer; }
.eve-map-btn:hover, .eve-map-btn:focus-visible { border-color: var(--phosphor); }
.eve-map-btn:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 2px; }
.eve-map-btn-text { font-size: var(--fs-md); letter-spacing: 0.04em; }
.eve-map-status { position: absolute; left: 8px; bottom: 4px; margin: 0; pointer-events: none; }
.eve-map-status:empty { display: none; }
.eve-map-tip { position: absolute; top: 0; left: 0; z-index: 2; width: min(300px, calc(100% - 16px)); padding: var(--sp-4) var(--sp-5); border: 1px solid var(--phosphor); background: rgba(1, 4, 12, 0.94); box-shadow: 0 0 14px rgba(0, 255, 136, 0.18); font-size: var(--fs-md); line-height: 1.45; color: var(--text); text-transform: none; letter-spacing: normal; pointer-events: none; }
.eve-map-tip[hidden] { display: none; }
.eve-map-tip[data-touch="true"] { pointer-events: auto; }
.eve-map-tip p { margin: 0 0 var(--sp-1); overflow-wrap: anywhere; }
.eve-map-tip strong { color: var(--text-bright); }
.eve-map-tip .eve-map-tip-note { color: var(--text-label); font-size: var(--fs-sm); }
.eve-map-legend { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-6); margin: 0 0 var(--sp-3); font-size: var(--fs-sm); color: var(--text-label); }
.eve-map-legend span { display: inline-flex; align-items: center; gap: var(--sp-2); white-space: nowrap; }
.eve-map-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--c); }
.eve-map-legend i.sq { border-radius: 0; }
.eve-map-legend b { font-weight: 400; color: var(--text); }
.eve-map-legend i.eve-map-ramp { border-radius: 0; width: 120px; height: 10px; }
.eve-map-legend i.ring { box-sizing: border-box; background: transparent; border: 1.5px solid rgba(217, 255, 233, 0.55); }
.eve-map-swatch { display: inline-block; width: 10px; height: 10px; margin-right: var(--sp-3); vertical-align: -1px; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .eve-map { height: clamp(240px, 50vh, 380px); }
}
/* A table row picked on the map. */
tbody tr.map-picked, tbody tr.map-picked:nth-child(even) { background: rgba(125, 255, 178, 0.1); box-shadow: inset 3px 0 0 var(--phosphor); }
/* The route cards of Cargo and Arbitrage (tools/route-map.js) sit above a table the page is about, so the map is shorter than Outposts'. A row there is picked by a click. */
.route-map-fold .eve-map { height: clamp(240px, 38vh, 340px); }
tbody tr[data-map-key], #agents-list-body tr[data-system-id] { cursor: pointer; }
}
@layer pages {
/* The Flash ticker (ticker.js): one line under the menu. Its height is fixed
   from the first paint, so the page never moves when the items arrive. */
.flashbar {
  position: relative;
  display: flex;
  align-items: stretch;
  height: 34px;
  background: linear-gradient(180deg, #02061a 0%, #010410 100%);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-md);
}
.flashbar[hidden], html[data-flashbar="off"] .flashbar { display: none; }
/* On the Flash desk the ticker would repeat the page's own list. */
html:has(#news.page-active #news-flash:not([hidden])) :is(.flashbar, .flashbar-reopen-row) { display: none; }
/* Hidden ticker: a slim row with one button where the close button was. */
.flashbar-reopen-row { display: none; }
html[data-flashbar="off"] .flashbar-reopen-row { display: flex; justify-content: flex-end; border-bottom: 1px solid var(--line); }
.flashbar-reopen { min-height: 32px; padding: 0 var(--sp-6); font: inherit; font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); background: transparent; border: 0; border-left: 1px solid var(--panel-border); cursor: pointer; }
.flashbar-reopen:hover, .flashbar-reopen:focus-visible { color: var(--phosphor); background: rgba(0, 255, 136, 0.08); outline: none; }

.flashbar-label {
  flex: none;
  display: flex;
  align-items: center;
  padding: 0 var(--sp-6) 0 32px;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--phosphor);
  text-shadow: 0 0 6px var(--phos-a60);
  text-decoration: none;
  border-right: 1px solid var(--panel-border);
}
.flashbar-label::before { content: "\25B6"; margin-right: var(--sp-4); font-size: 8px; }
.flashbar-label:hover { color: var(--mint); }
.flashbar-label:focus-visible, .flashbar-link:focus-visible, .flashbar-close:focus-visible { outline: 1px solid var(--phosphor); outline-offset: -2px; }

/* clip, not hidden: a focused link must not scroll the strip by itself. */
.flashbar-viewport { position: relative; flex: 1 1 auto; min-width: 0; overflow: hidden; overflow: clip; }
.flashbar-viewport::before, .flashbar-viewport::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 24px;
  z-index: 1;
  pointer-events: none;
}
.flashbar-viewport::before { left: 0; background: linear-gradient(90deg, #02061a, transparent); }
.flashbar-viewport::after { right: 0; background: linear-gradient(270deg, #02061a, transparent); }

.flashbar-track {
  display: flex;
  width: max-content;
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}
.flashbar-track.is-live {
  will-change: transform;
  animation: flashbar-run var(--dur, 60s) linear infinite;
}
@keyframes flashbar-run {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(-1 * var(--shift, 0px)), 0, 0); }
}
.flashbar:hover .flashbar-track,
.flashbar:focus-within .flashbar-track,
.flashbar.is-held .flashbar-track { animation-play-state: paused; }
.flashbar.is-seek .flashbar-track { animation: none; transform: translate3d(var(--seek, 0px), 0, 0); }

.flashbar-item { --sev: var(--amber); flex: none; display: flex; align-items: stretch; }
.flashbar-b2 { --sev: #ff8a3d; }
.flashbar-b3 { --sev: var(--red); }
/* The separator between two items. */
.flashbar-item::after { content: "//"; align-self: center; padding: 0 var(--sp-1); color: var(--edge); }

.flashbar-link {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 32px;
  padding: 0 var(--sp-6);
  color: var(--text-bright);
  text-decoration: none;
  white-space: nowrap;
}
a.flashbar-link:hover .flashbar-head, a.flashbar-link:focus-visible .flashbar-head { color: var(--mint); text-decoration: underline; }
.flashbar-where { color: var(--text-label); }
.flashbar-cat { color: var(--amber); }
/* A line's correlated lines (newsCluster.ts), after its headline: "+2: Amarr, Jita". */
.flashbar-also { color: var(--text-label); }
.flashbar .hub-bar { margin-right: var(--sp-2); }

.flashbar-sev { display: inline-flex; align-items: flex-end; gap: var(--sp-1); height: 11px; }
.flashbar-sev i { display: block; width: 3px; background: var(--row-line); border: 1px solid var(--edge); box-sizing: border-box; }
.flashbar-sev i:nth-child(1) { height: 5px; }
.flashbar-sev i:nth-child(2) { height: 8px; }
.flashbar-sev i:nth-child(3) { height: 11px; }
.flashbar-sev i.on { background: var(--sev); border-color: var(--sev); }

.flashbar-close {
  flex: none;
  width: 40px;
  padding: 0;
  font: inherit;
  font-size: 18px;
  line-height: 1;
  color: var(--text-dim);
  background: transparent;
  border: 0;
  border-left: 1px solid var(--panel-border);
  cursor: pointer;
}
.flashbar-close:hover { color: var(--phosphor); background: rgba(0, 255, 136, 0.08); }

.flashbar-show {
  min-height: 32px;
  padding: 0 var(--sp-2);
  font: inherit;
  color: var(--accent);
  background: transparent;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
}
.flashbar-show:hover { color: var(--text-bright); }

/* Still: one copy of the items in a row to scroll by hand. The bar is taller
   by the scrollbar, so the links keep their height. */
@media (prefers-reduced-motion: reduce) {
  .flashbar { height: 46px; }
  .flashbar-viewport { overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
  .flashbar-viewport::before, .flashbar-viewport::after { display: none; }
  .flashbar-track.is-live, .flashbar.is-seek .flashbar-track { animation: none; transform: none; }
  .flashbar-item[aria-hidden] { display: none; }
  .flashbar-track { height: 34px; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .flashbar-label { padding-left: var(--sp-7); padding-right: var(--sp-5); letter-spacing: 0.14em; }
  .flashbar-link { padding: 0 var(--sp-5); }
}
/* A phone held sideways: the ticker stays, as one slim line. */
@media (pointer: coarse) and (max-height: 500px) {
  .flashbar, .flashbar-track { height: 24px; }
  .flashbar { font-size: var(--fs-sm); }
  .flashbar-link { min-height: 0; padding: 0 var(--sp-4); }
  .flashbar-label { padding-left: var(--sp-5); padding-right: var(--sp-4); }
  .flashbar-close, .flashbar-reopen { min-height: 0; width: 32px; }
  .flashbar-reopen { width: auto; }
}
}
@layer pages {
/* The risk badge (risk-grade.js): the News Flash severity bars
   (.flashbar-sev, flashbar.css) lit for the level and coloured by it. */
.risk-l1 { --sev: var(--phosphor); }
.risk-l2 { --sev: var(--amber); }
.risk-l3 { --sev: var(--red); }

.risk-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 24px;
  padding: var(--sp-1) var(--sp-3);
  font: inherit;
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sev);
  background: transparent;
  border: 1px solid var(--sev);
  border-radius: 2px;
  cursor: pointer;
}
.risk-badge:hover, .risk-badge:focus-visible { background: rgba(255, 255, 255, 0.06); }
.risk-badge:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 1px; }

/* A button that reads as a link, in a status line ("... hidden — show"). */
.risk-link { min-height: 32px; padding: 0 var(--sp-2); font: inherit; color: var(--accent); background: transparent; border: 0; text-decoration: underline; cursor: pointer; }
.risk-link:hover { color: var(--text-bright); }

.risk-pop {
  position: fixed;
  z-index: 60;
  max-width: min(360px, calc(100vw - 16px));
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-md);
  line-height: 1.45;
  color: var(--text-bright);
  background: var(--panel-bg, #02061a);
  border: 1px solid var(--sev);
  border-radius: 2px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.6);
}
.risk-pop-head { margin-bottom: var(--sp-2); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sev); }
.risk-pop ul { margin: 0; padding: 0; list-style: none; }
.risk-pop li { padding: var(--sp-1) 0; border-top: 1px solid var(--row-line); }
.risk-pop li.risk-l2 .risk-pop-label { color: var(--amber); }
.risk-pop li.risk-l3 .risk-pop-label { color: var(--red); }
.risk-pop-caveats { margin-top: var(--sp-3); padding-top: var(--sp-2); border-top: 1px solid var(--edge); font-size: var(--fs-sm); color: var(--text-label); }
.risk-pop-caveats li { border-top: 0; padding: 1px 0; }
.risk-pop-label { font-weight: 600; color: var(--text-label); }
.risk-pop-link { display: inline-flex; align-items: center; min-height: 32px; margin-top: var(--sp-2); font-size: var(--fs-sm); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .risk-badge { min-height: 32px; padding: var(--sp-2) var(--sp-5); }
}

/* The badge under a figure it grades (Arbitrage's and Cargo's net, Today's best's cards). */
.cell-risk { margin-top: var(--sp-2); }

/* A row's details: the facts behind its grade and the reason for its Score,
   side by side where there is room. */
.risk-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: var(--sp-5) var(--sp-7); margin-top: var(--sp-3); }
.risk-facts, .risk-why { min-width: 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-label); }
.risk-facts ul, .risk-why ul { margin: var(--sp-2) 0 0; padding: 0; list-style: none; columns: auto; }
.risk-facts li, .risk-why li { padding: var(--sp-1) 0; border-top: 1px solid var(--row-line); overflow-wrap: anywhere; }
.risk-facts li.risk-l2 .risk-pop-label { color: var(--amber); }
.risk-facts li.risk-l3 .risk-pop-label { color: var(--red); }
.risk-facts .risk-pop-head { color: var(--sev); }
.risk-why .risk-pop-head { color: var(--mint-dim); }
.risk-facts .risk-pop-caveats li { border-top: 0; }

/* Market health by an item's name (itemsearch.js showName). */
.item-detail h3 .item-health { display: inline-flex; align-items: center; gap: var(--sp-3); margin-left: auto; font-size: var(--fs-sm); font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-label); text-shadow: none; }

/* The explainer page (tools/risk-explainer.js): one card to a factor, a
   definition list inside, stacking on a phone. */
.risk-ex h3 { margin: var(--sp-5) 0 var(--sp-2); font-size: var(--fs-lg); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mint-dim); }
.risk-ex-factor { margin: var(--sp-4) 0; padding: var(--sp-4) var(--sp-5); border: 1px solid var(--edge); border-radius: 2px; }
.risk-ex-factor h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-md); color: var(--text-bright); }
.risk-ex-factor dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--sp-1) var(--sp-5); margin: 0; font-size: var(--fs-sm); line-height: 1.5; }
.risk-ex-factor dt { color: var(--text-label); }
.risk-ex-factor dd { margin: 0; min-width: 0; color: var(--text-bright); overflow-wrap: anywhere; }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .risk-ex-factor dl { grid-template-columns: 1fr; }
  .risk-ex-factor dd { margin-bottom: var(--sp-2); }
}
}
@layer pages {
/* Item search's price history (itemhistory.js): a compact panel, the chart a
   small one until it is enlarged, its figures under it. Beside the order book
   on a wide screen (.item-market), under it otherwise. */
.item-history { margin: var(--sp-6) 0; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--edge); background: var(--screen-bg); min-width: 0; }
.item-history[hidden] { display: none; }
.item-hist-head { display: flex; align-items: center; gap: var(--sp-5); }
.item-hist-head .item-side-title { flex: 1 1 auto; min-width: 0; }
.item-hist-size { flex: none; padding: var(--sp-1) var(--sp-4); font-size: var(--fs-xs); }
.item-hist-sub { margin-left: var(--sp-4); font-size: var(--fs-md); font-weight: 400; color: var(--text-dim); text-transform: none; letter-spacing: 0; }
.item-hist-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); align-items: start; }
.item-hist-chart { min-width: 0; }
.item-hist-stats { margin: var(--sp-3) 0 0; min-width: 0; font-size: var(--fs-md); }
.item-hist-stats > div { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-1) var(--sp-4); padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); }
.item-hist-stats dt { color: var(--text-dim); }
.item-hist-stats dd { margin: 0; text-align: right; color: var(--text-bright); }
.item-hist-since { margin: var(--sp-3) 0 0; }
.item-hist-help { margin-top: var(--sp-2); }
.item-hist-help > summary { cursor: pointer; list-style: none; min-height: 32px; display: flex; align-items: center; color: var(--accent); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
.item-hist-help > summary::-webkit-details-marker { display: none; }
.item-hist-help > summary::before { content: "▸ "; color: var(--phosphor); }
.item-hist-help[open] > summary::before { content: "▾ "; }
.item-history .fc-caption { margin-top: var(--sp-2); }
.item-history .fc-plot { margin-top: var(--sp-2); }
@media (min-width: 761px) and (max-width: 1179px) {
  .item-hist-body { grid-template-columns: minmax(0, 1fr) 260px; gap: var(--sp-4) var(--sp-7); }
}

}
@layer pages {
/* The folds under Item search's market panels (itemfolds.js): the More
   regions fold's summary, a few figures, one line of meaning, details nested. */
.item-folds { margin: var(--sp-6) 0; }
.item-folds[hidden] { display: none; }
.item-fold { margin: 0; border-top: 1px solid var(--row-line); }
.item-folds .item-fold > summary { min-height: 44px; }
.item-fold-body { padding: 0 0 var(--sp-4) var(--sp-6); min-width: 0; }
.item-fold-stats { margin: 0 0 var(--sp-2); font-size: var(--fs-md); }
.item-fold-stats > div { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-1) var(--sp-4); padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); }
.item-fold-stats dt { color: var(--text-dim); }
.item-fold-stats dd { margin: 0; text-align: right; color: var(--text-bright); }
.item-fold-line { margin: var(--sp-2) 0; }
.item-fold-list { margin: var(--sp-2) 0; padding: 0; list-style: none; font-size: var(--fs-md); }
.item-fold-list > li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-4); padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); min-width: 0; }
.item-fold-cost { margin-left: auto; color: var(--text-bright); }
.item-fold-dim { color: var(--text-dim); }
.item-fold-more { margin: var(--sp-2) 0; }
.item-fold-more > summary { cursor: pointer; list-style: none; min-height: 44px; display: flex; align-items: center; color: var(--accent); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
.item-fold-more > summary::-webkit-details-marker { display: none; }
.item-fold-more > summary::before { content: "▸ "; color: var(--phosphor); }
.item-fold-more[open] > summary::before { content: "▾ "; }
.item-mark { display: inline-block; padding: 0 var(--sp-3); border: 1px solid var(--edge); color: var(--amber); font-size: var(--fs-xs); white-space: nowrap; }
.item-mark-new { color: var(--phosphor); }
.item-mark-best { color: var(--phosphor); border-color: var(--phosphor); }
.item-depth { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
.item-depth-side h5 { margin: var(--sp-2) 0; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.08em; color: var(--phosphor); }
@media (min-width: 761px) {
  .item-depth { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-7); }
}

}
@layer pages {
/* Hauling radar (tools/outposts.js): the chip rows in the header; the region row
   is a hub-chip row (hud.js) of the regions last picked and a dropdown for
   the rest; the gone finds in a second table. */
.outposts-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.outposts-group > button:not(.hotkey-chip) { margin-left: auto; }
.outposts-map-block { min-width: 0; margin: var(--sp-3) 0 0; }
.outposts-chip { min-height: 32px; }
.outposts-chip:disabled { opacity: 0.4; cursor: default; }
.outposts-route-btn { min-height: 32px; margin-top: var(--sp-2); padding: var(--sp-1) var(--sp-4); font-size: var(--fs-md); white-space: nowrap; }
.outposts-gone-title { margin: var(--sp-7) 0 var(--sp-2); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }

}
@layer pages {
/* The Route planner (tools/routes.js): chip rows in the header (Mode, From,
   To, Stops, Ship), two folds (jump drive; wormholes and avoid), a table of
   route options with a details row each, the shared map and its legend. */
.routes-group { flex: 0 1 auto; min-width: 0; margin: var(--sp-1) var(--sp-5) 0 0; align-items: center; }
.routes-place { flex: 1 1 100%; margin-right: 0; }
.routes-place > .routes-swap { margin-left: auto; }
.routes-chip { min-height: 32px; }
.routes-chip[hidden], .routes-other-input[hidden] { display: none; }
.routes-other-input { width: 12.5em; max-width: 100%; min-height: 32px; }
.routes-field { display: inline-flex; align-items: center; gap: var(--sp-3); min-width: 0; font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-label); }
.routes-small input[type="number"] { width: 4.2em; min-height: 32px; }
.routes-small select { min-height: 32px; }
.routes-swap { min-width: 32px; min-height: 32px; padding: 0 var(--sp-4); }
#routes-refresh { min-height: 32px; }

/* A stop or an avoided place: the name between small buttons. */
.routes-stop { display: inline-flex; align-items: center; min-width: 0; max-width: 100%; border: 1px solid var(--panel-border); }
.routes-stop-name { padding: 0 var(--sp-3); overflow-wrap: anywhere; font-size: var(--fs-md); color: var(--text-bright); }
.routes-stop-btn { min-width: 32px; min-height: 32px; padding: 0 var(--sp-3); border: 0; background: none; color: var(--text-label); }
.routes-stop-btn:disabled { opacity: 0.35; }

.routes-fold { margin: var(--sp-1) 0 0; min-width: 0; }
.routes-fold > summary { min-height: 32px; display: flex; align-items: center; cursor: pointer; font-size: var(--fs-md); color: var(--text-label); overflow-wrap: anywhere; }
.routes-fold[hidden] { display: none; }
.routes-fold-body { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-6); padding: var(--sp-2) 0 var(--sp-4); min-width: 0; }
.routes-sub-group { flex: 1 1 100%; min-width: 0; }
.routes-sub-title { margin: var(--sp-2) 0; font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-label); }
.routes-own-list { list-style: none; margin: 0 0 var(--sp-2); padding: 0; font-size: var(--fs-md); }
.routes-own-list li { overflow-wrap: anywhere; }
.routes-own-form { display: flex; flex-wrap: wrap; gap: var(--sp-3); min-width: 0; }
.routes-own-form input[type="text"] { flex: 0 1 14em; min-width: 0; min-height: 32px; }
.routes-own-form input[type="number"] { width: 4.5em; min-height: 32px; }
.routes-own-form select, .routes-own-form button { min-height: 32px; }

/* What the trip's purpose needs: the load against the gank break-even and the jump drive's trade. */
.routes-brief { display: flex; flex-direction: column; gap: var(--sp-2); margin: var(--sp-3) 0 0; font-size: var(--fs-md); overflow-wrap: anywhere; }
.routes-brief[hidden] { display: none; }

/* The answer: the trip, its jumps and risk as the page's headline, with the
   route's copy button; a phone keeps it in view as a strip while the map and
   the list scroll under it. */
.routes-headline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-5); margin: var(--sp-3) 0 0; }
.routes-headline:empty { display: none; }
.routes-headline-text { font-size: 1.5em; line-height: 1.3; color: var(--text-bright); overflow-wrap: anywhere; }
.routes-headline-fig { color: var(--phosphor); }
.routes-headline-risk { font-size: 0.65em; text-transform: uppercase; letter-spacing: 0.08em; }
.routes-headline-risk.risk-l1 { color: var(--phosphor); }
.routes-headline-risk.risk-l2 { color: var(--amber); }
.routes-headline-risk.risk-l3 { color: var(--red, var(--amber)); }
.routes-headline-sub { flex: 1 1 100%; font-size: var(--fs-md); color: var(--text-dim); overflow-wrap: anywhere; }
.routes-copy, .routes-age button { min-height: 32px; padding: 0 var(--sp-5); }
.routes-age { margin: var(--sp-2) 0 0; }

.routes-table td { vertical-align: top; }
.routes-table td[data-label="Route"] { text-align: left; }
.routes-table:not(.routes-has-jf) .routes-jf-col { display: none; }
.routes-pick { min-height: 32px; padding: var(--sp-1) var(--sp-4); text-align: left; white-space: normal; }
.routes-pick[aria-pressed="true"] { border-color: var(--phosphor); color: var(--text-bright); }
.routes-more { min-height: 32px; margin-left: var(--sp-2); padding: 0 var(--sp-4); font-size: var(--fs-md); }
.routes-more[aria-expanded="true"] { color: var(--text-bright); }
.routes-detail-row > td { text-align: left; white-space: normal; }
.routes-detail-row[hidden] { display: none; }
.routes-why { margin: var(--sp-1) 0 var(--sp-3); overflow-wrap: anywhere; }
.routes-game { min-height: 32px; padding: 0 var(--sp-5); }
.routes-sys-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.routes-sys { display: flex; flex-wrap: wrap; gap: 0 var(--sp-4); padding: var(--sp-2) 0; border-top: 1px solid var(--panel-border); font-size: var(--fs-md); overflow-wrap: anywhere; }
.routes-sys-n { min-width: 2em; color: var(--text-label); }
.routes-sys-name { color: var(--text-bright); }
.routes-sys-tags { flex: 1 1 14em; min-width: 0; color: var(--text-label); }
.routes-sys-wormhole { box-shadow: inset 2px 0 0 #d070ff; }
.routes-sys-jump { box-shadow: inset 2px 0 0 #ffd24d; }
.routes-sys-stop .routes-sys-n, .routes-sys-flag { color: var(--phosphor); }
.routes-legend-btn { min-height: 32px; padding: 0 var(--sp-4); font-size: var(--fs-sm); }
.routes-legend-btn[aria-pressed="true"] { color: var(--text-bright); border-color: var(--phosphor); }

/* The Route slider: the range between its two ends, the stops' labels under
   it in the same order (the one picked lit, Balanced marked with a diamond). */
.routes-ladder { display: flex; align-items: flex-start; gap: var(--sp-3) var(--sp-6); flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; }
.routes-ladder > .hotkey-group-label { padding-top: var(--sp-4); }
.routes-ladder-body { flex: 1 1 auto; min-width: 0; max-width: 46em; }
.routes-ladder-track { display: flex; align-items: center; gap: var(--sp-4); min-width: 0; }
.routes-ladder-end { flex: 0 0 auto; font-size: var(--fs-sm); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-label); }
#routes-ladder { flex: 1 1 auto; min-width: 0; min-height: 32px; margin: 0; accent-color: var(--phosphor); cursor: pointer; }
#routes-ladder:disabled { cursor: default; opacity: 0.55; }
.routes-ladder-ticks { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-1) var(--sp-3); min-width: 0; }
.routes-tick { padding: 1px var(--sp-3); border: 1px solid transparent; background: none; font: inherit; font-size: var(--fs-sm); white-space: nowrap; color: var(--text-label); cursor: pointer; }
.routes-tick.active { border-color: var(--phosphor); color: var(--text-bright); }

/* The slider sits directly above the map, which is the page's main view: 4:3
   on a desktop, held to 72% of the window's height so the route list under
   it stays within a scroll. */
.routes-stage { min-width: 0; margin: var(--sp-2) 0; }
.routes-stage .routes-ladder-body { max-width: none; }
.routes-map-fold .eve-map { width: 100%; height: auto; aspect-ratio: 4 / 3; min-height: 300px; max-height: 72vh; margin: var(--sp-2) 0; }
.eve-map-legend svg.eve-map-burst { flex: 0 0 auto; margin-right: calc(-1 * var(--sp-1)); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* A phone's map is open, always: tall in portrait, most of the window's
     height in landscape. */
  .routes-map-fold .eve-map { aspect-ratio: 4 / 5; min-height: 280px; max-height: 64vh; }
  /* A phone shows the picked stop's label only; the slider moves between them. */
  .routes-ladder { align-items: center; flex-wrap: wrap; gap: 0 var(--sp-4); }
  /* The two ends name the slider; its label would leave it a thumb wide. */
  .routes-ladder > .hotkey-group-label { display: none; }
  .routes-ladder-body { flex: 1 1 100%; max-width: none; }
  .routes-tick:not(.active) { display: none; }
  .routes-headline { position: sticky; top: 0; z-index: 5; margin: 0; padding: var(--sp-3) 0; background: var(--panel-bg-2); border-bottom: 1px solid var(--panel-border); }
  .routes-headline-text { font-size: 1.2em; }  .routes-ladder-ticks { justify-content: center; }
  .routes-tick.active { border-color: transparent; padding: 0; cursor: default; }
  .routes-other-input { flex: 1 1 8em; width: auto; }
  /* An opened row puts its chips under the label and the swap button. */
  .routes-place > .hotkey-chip-list { order: 1; }
  .routes-detail-row > td::before { content: none; }
  .routes-table .routes-jf-col { display: block; }
  .routes-table:not(.routes-has-jf) .routes-jf-col { display: none; }
}
@media (max-width: 768px) and (orientation: landscape), (pointer: coarse) and (max-height: 500px) and (orientation: landscape) {
  .routes-map-fold .eve-map { aspect-ratio: auto; height: 60vh; min-height: 200px; max-height: none; }
}
}
@layer pages {
/* SKINR market (tools/skinr.js): action cards lead, then one chart, then
   short tables; a hull row picks the chart's hull. */
.skinr-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.skinr-chip { min-height: 32px; }
.skinr-asof { margin: var(--sp-3) 0 var(--sp-4); overflow-wrap: anywhere; }
.skinr-title { margin: var(--sp-7) 0 var(--sp-2); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.skinr-hull-row { cursor: pointer; }
.skinr-hull-row.skinr-picked td { background: rgba(120, 255, 190, 0.07); }
.skinr-history { margin-top: var(--sp-5); }
.skinr-hist-note:empty { display: none; }

/* Cards: the first row is the action, the second smaller context. */
.skinr-cards-main { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.skinr-cards-context { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-top: var(--sp-3); }
.skinr-mini { padding: var(--sp-3) var(--sp-5); }
.skinr-mini .plex-v-head { font-size: var(--fs-lg); margin: 0; }
.skinr-mini p { margin-bottom: 0; }
.skinr-picks { list-style: none; margin: 0 0 var(--sp-3); padding: 0; }
.skinr-picks li { margin: 0 0 var(--sp-3); }
.skinr-pick-line { color: var(--text-dim); font-size: var(--fs-sm); }
.skinr-rest { margin: 0 0 var(--sp-3); }
.skinr-rest > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--mint-dim); }

/* A row's details: the secondary figures in a wrapping line. */
.skinr-facts { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-6); }
.skinr-fact-label { color: var(--mint-dim); }
}
@layer pages {
/* PLEX (tools/plex.js): tiles, charts drawn by the finance chart, key
   figures, the order book, calculators and the rules with their sources. */
.plex-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.plex-asof { margin: var(--sp-3) 0 var(--sp-4); font-size: 14px; color: var(--text-bright); overflow-wrap: anywhere; }
.plex-asof-label { color: var(--mint-dim); text-transform: uppercase; letter-spacing: 0.08em; font-size: var(--fs-md); }
.page-status > .plex-asof { margin: 0; }
.plex-title { margin: var(--sp-7) 0 var(--sp-2); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.plex-sub { margin: var(--sp-6) 0 var(--sp-2); font-size: var(--fs-md); letter-spacing: 0.06em; text-transform: uppercase; color: var(--mint-dim); }
.plex-controls { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-6); margin-top: var(--sp-2); }
.plex-controls .hotkey-group { flex: 0 1 auto; }

/* Tiles: the finance tile of News, with changes and a range under it. */
.plex-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-4); }
.plex-tile { align-content: start; min-width: 0; }
.plex-tile.plex-picked { border-color: var(--phosphor); }
.plex-tile .fin-tile-chg { font-size: 16px; color: var(--text-bright); }
.plex-chgs { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-5); font-size: var(--fs-sm); }
.plex-chg { white-space: nowrap; color: var(--text-dim); }
.plex-range { grid-column: 1 / -1; display: grid; gap: var(--sp-1); }
.plex-range-bar { position: relative; display: block; height: 4px; background: var(--row-line); border: 1px solid var(--edge); }
.plex-range-dot { position: absolute; top: -4px; width: 2px; height: 10px; margin-left: -1px; background: var(--phosphor); }
.plex-range-text { font-size: var(--fs-sm); color: var(--text-dim); overflow-wrap: anywhere; }

/* Charts: the finance chart's classes with the colours this page needs. */
.plex-chart { position: relative; min-width: 0; }
.plex-chart .fc-svg .fc-hl { stroke: var(--mint-dim); stroke-width: 1.5; }
.plex-chart .fc-svg .fc-hl.fc-thin { stroke-dasharray: 2 2; }
.plex-chart .fc-svg .fc-avg { stroke: var(--text-bright); stroke-width: 2; }
.plex-chart .fc-svg .fc-body { stroke-width: 1; }
.plex-chart .fc-svg .fc-body.fc-up { fill: var(--phosphor); stroke: var(--phosphor); }
.plex-chart .fc-svg .fc-body.fc-down { fill: var(--red); stroke: var(--red); }
.plex-chart .fc-svg .fc-body.fc-thin { fill: none; }
.plex-chart .fc-svg path.fc-ov { stroke-width: 1.5; }
.plex-chart .fc-svg path.fc-ov-1 { stroke: var(--amber); }
.plex-chart .fc-svg path.fc-ov-2 { stroke: var(--hub-forge); }
.plex-chart .fc-svg .fc-dot.fc-ov-1 { fill: var(--amber); }
.plex-chart .fc-svg .fc-dot.fc-ov-2 { fill: var(--hub-forge); }
.plex-chart .fc-svg .fc-mark.fc-ov-1 { stroke: var(--amber); }
.plex-chart .fc-svg .fc-mark.fc-ov-2 { stroke: var(--hub-forge); }
.fc-key-ov-1 { color: var(--amber); }
.fc-key-ov-2 { color: var(--hub-forge); }
.plex-chart .fc-svg path.fc-line-1 { stroke: var(--phosphor); stroke-dasharray: none; }
.plex-chart .fc-svg path.fc-line-2 { stroke: var(--amber); stroke-dasharray: none; }
.plex-chart .fc-svg path.fc-line-3 { stroke: var(--hub-forge); stroke-width: 1.5; }
.plex-chart .fc-svg path.fc-line-4 { stroke: var(--hub-metropolis); stroke-width: 1.5; }
.plex-chart .fc-svg .fc-dot.fc-line-1 { fill: var(--phosphor); }
.plex-chart .fc-svg .fc-dot.fc-line-2 { fill: var(--amber); }
.plex-chart .fc-svg .fc-dot.fc-line-3 { fill: var(--hub-forge); }
.plex-chart .fc-svg .fc-dot.fc-line-4 { fill: var(--hub-metropolis); }
.plex-chart .fc-svg .fc-mark.fc-line-1 { stroke: var(--phosphor); }
.plex-chart .fc-svg .fc-mark.fc-line-2 { stroke: var(--amber); }
.plex-chart .fc-svg .fc-mark.fc-line-3 { stroke: var(--hub-forge); }
.plex-chart .fc-svg .fc-mark.fc-line-4 { stroke: var(--hub-metropolis); }
.plex-chart .fc-svg .fc-area { fill: var(--red); fill-opacity: 0.22; stroke: none; }
.fc-key-3 { color: var(--hub-forge); }
.fc-key-4 { color: var(--hub-metropolis); }

.plex-legend { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-6); margin: var(--sp-4) 0 0; font-size: var(--fs-md); color: var(--text-bright); min-height: 18px; }
.plex-key { display: inline-flex; align-items: center; gap: var(--sp-3); }
.plex-swatch { display: inline-block; width: 16px; height: 3px; background: var(--phosphor); }
.plex-swatch.sw-ov1 { background: var(--amber); }
.plex-swatch.sw-ov2 { background: var(--hub-forge); }
.plex-swatch.sw-l1 { background: var(--phosphor); }
.plex-swatch.sw-l2 { background: var(--amber); }
.plex-swatch.sw-l3 { background: var(--hub-forge); }
.plex-swatch.sw-l4 { background: var(--hub-metropolis); }
.plex-swatch.sw-up { height: 9px; background: var(--phosphor); }
.plex-swatch.sw-down { height: 9px; background: var(--red); }
.plex-swatch.sw-hl { width: 3px; height: 12px; background: var(--mint-dim); }

/* Tables inside the page. */
.plex-mini { width: 100%; border-collapse: collapse; font-size: var(--fs-md); margin: var(--sp-3) 0; }
.plex-mini th, .plex-mini td { padding: var(--sp-2) var(--sp-4); text-align: left; border-bottom: 1px solid var(--row-line); vertical-align: top; }
.plex-mini thead th { color: var(--mint-dim); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.05em; }
.plex-mini tbody th { font-weight: 400; color: var(--text-bright); }
.plex-mini .plex-picked-row th, .plex-mini .plex-picked-row td { background: rgba(120, 255, 190, 0.07); }
.plex-sales { min-width: 22ch; line-height: 1.5; }

/* Calculators. */
.plex-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--sp-4) var(--sp-6); margin: var(--sp-4) 0; align-items: end; }
.plex-fields label { display: grid; gap: var(--sp-1); font-size: var(--fs-md); color: var(--mint-dim); min-width: 0; }
.plex-fields input, .plex-fields select { width: 100%; min-width: 0; min-height: 34px; }
.plex-calcs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6); margin-top: var(--sp-4); }
.plex-calc { min-width: 0; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--edge); background: var(--screen-bg); }
.plex-calc h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-lg); color: var(--phosphor); }
.plex-calc#plex-calc-sp, .plex-calc#plex-calc-plan { grid-column: 1 / -1; }
.plex-steps { margin-top: var(--sp-2); font-size: var(--fs-md); }
.plex-steps summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--accent); }
.plex-steps ul { margin: var(--sp-2) 0 0; padding-left: var(--sp-7); color: var(--text-bright); overflow-wrap: anywhere; }
.plex-rule-list { margin: var(--sp-3) 0; padding-left: var(--sp-7); font-size: var(--fs-lg); color: var(--text-bright); }
.plex-rule-list li { margin: 0 0 var(--sp-4); overflow-wrap: anywhere; }
.plex-rule-list p { margin: 0 0 var(--sp-1); }

#plex-status:empty { display: none; }

/* The desk: one card per item and ISK, Core trend insurance under them. */
.plex-bookline { grid-column: 1 / -1; font-size: var(--fs-sm); color: var(--text-dim); overflow-wrap: anywhere; }
.desk-label { color: var(--amber); }
.plex-desk { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--sp-5); margin-top: var(--sp-4); }
.plex-desk-card { min-width: 0; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--edge); background: var(--screen-bg); font-size: var(--fs-lg); color: var(--text-bright); overflow-wrap: anywhere; }
.plex-desk-card .desk-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2) var(--sp-5); margin-bottom: var(--sp-3); }
.plex-desk-card h4 { margin: 0; font-size: var(--fs-lg); color: var(--phosphor); }
.plex-desk-card p { margin: 0 0 var(--sp-3); }
.plex-core-card { margin-top: var(--sp-5); }
.desk-band { position: relative; height: 10px; margin: 0 0 var(--sp-3); border: 1px solid var(--edge); background: var(--screen-bg); }
.desk-band-zone { position: absolute; top: 0; bottom: 0; background: var(--edge); opacity: 0.6; }
.desk-band-mark { position: absolute; top: -4px; bottom: -4px; width: 3px; margin-left: -1px; background: var(--phosphor); }
.desk-k { color: var(--mint-dim); text-transform: uppercase; letter-spacing: 0.06em; font-size: var(--fs-sm); margin-right: var(--sp-2); }
.desk-stance { display: inline-block; padding: var(--sp-1) var(--sp-4); border: 1px solid currentColor; font-size: var(--fs-sm); letter-spacing: 0.06em; white-space: normal; }
.desk-item { color: var(--phosphor); }
.desk-isk { color: var(--amber); }
.desk-neutral { color: var(--text-dim); }

/* Verdict cards: one per item, the colour carries the level. */
.plex-verdicts { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-5); margin-top: var(--sp-4); }
.plex-verdict { min-width: 0; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--edge); border-left-width: 4px; background: var(--screen-bg); font-size: var(--fs-md); color: var(--text-bright); overflow-wrap: anywhere; }
.plex-verdict h4 { margin: 0; font-size: var(--fs-lg); color: var(--text-bright); }
.plex-verdict p { margin: 0 0 var(--sp-3); }
.plex-v-price { font-size: var(--fs-md); color: var(--text-dim); }
.plex-v-head { font-size: 17px; font-weight: 700; line-height: 1.25; }
.plex-v-ends { display: flex; justify-content: space-between; gap: var(--sp-4); font-size: var(--fs-sm); color: var(--text-dim); }
.plex-v-why { color: var(--text-dim); }
.plex-v-buy { border-color: var(--phosphor); }
.plex-v-buy .plex-v-head { color: var(--phosphor); }
.plex-v-wait { border-color: var(--amber); }
.plex-v-wait .plex-v-head { color: var(--amber); }
.plex-v-fair, .plex-v-none { border-left-color: var(--mint-dim); }
.plex-how > summary { font-size: var(--fs-lg); }
.plex-how { margin-top: var(--sp-7); }

@media (max-width: 1100px) {
  .plex-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plex-calcs { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .plex-tiles { gap: var(--sp-3); }
  .plex-tile .fin-tile-chg { grid-column: 1 / -1; grid-row: auto; font-size: 14px; }
  .plex-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The page's own small tables stay tables on a phone and scroll sideways in
   their .table-scroll, where the shared card layout would stack every cell
   (the key figures table keeps it). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .plex-mini { display: table; width: max-content; min-width: 100%; }
  .plex-mini thead { display: table-header-group; }
  .plex-mini tbody { display: table-row-group; }
  .plex-mini tbody tr, .plex-mini tbody tr:nth-child(even) { display: table-row; background: none; border: none; border-radius: 0; padding: 0; margin: 0; }
  .plex-mini th, .plex-mini td { display: table-cell; text-align: left; white-space: nowrap; overflow-wrap: normal; padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--row-line); }
  .plex-mini td::before, .plex-mini td::after { content: none; }
  .plex-mini tbody th { white-space: normal; min-width: 96px; max-width: 124px; }
  .plex-mini td.plex-sales { white-space: normal; min-width: 260px; }
  .plex-mini a, .plex-rule-list a { display: inline-block; padding: var(--sp-4) 0; }
}
}
@layer pages {
/* --- Chip folds (chipfold.js) ---
   A chip row of four or more takes a phone's screen before any data does, so
   on a phone it folds to one line: the label and what is picked, a tap
   opening the chips under it. A container marked data-filters-fold folds its
   other controls (numbers, selects, ticks, the remaining rows) behind one
   "Filters (n changed)" line, Refresh beside it; a filter panel (Preset,
   Category, Tech) does the same. Every chip stays in the page: the folding
   is display only, so hotkeys, aria and saved picks work as on a desktop.
   The rows that stay on a phone as one sideways line are styled below. */
.chip-fold-btn, .fold-summary, .chip-scroll-btn { display: none; }

/* A summary line: "Filters (2 changed)" and, in small type, what changed. It
   shows on a phone, and on a desktop in a container marked
   data-fold-at="always" (below). */
.fold-summary {
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  font-size: var(--fs-sm);
  text-align: left;
  color: var(--phosphor);
  border-color: var(--edge);
  background: rgba(0, 255, 136, 0.06);
}
.fold-summary::after { content: "▾"; flex: 0 0 auto; color: var(--mint-dim); }
.fold-open > .fold-summary { border-color: var(--phosphor); }
.fold-open > .fold-summary::after { content: "▴"; }
.fold-name { flex: 0 0 auto; font-weight: 700; }
.fold-count { flex: 0 0 auto; color: var(--amber); }
.fold-detail { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-label); font-size: var(--fs-xs); text-transform: none; letter-spacing: 0; }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .chip-fold > .hotkey-group-label, .chip-fold > .hub-picker-label, .chip-fold > .info-pair {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 48%;
    padding-top: 0;
    min-height: 36px;
    display: flex;
    align-items: center;
    white-space: normal;
    line-height: 1.25;
  }
  .chip-fold > .chip-fold-btn {
    display: flex;
    flex: 1 1 0;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    min-width: 0;
    min-height: 36px;
    padding: var(--sp-2) var(--sp-5);
    font-size: var(--fs-sm);
    text-align: left;
    color: var(--phosphor);
    border-color: var(--edge);
    background: rgba(0, 255, 136, 0.06);
  }
  .chip-fold-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .chip-fold-btn::after { content: "▾"; flex: 0 0 auto; color: var(--mint-dim); }
  .chip-fold-open > .chip-fold-btn { border-color: var(--phosphor); }
  .chip-fold-open > .chip-fold-btn::after { content: "▴"; }

  .fold-summary {
    display: flex;
    flex: 1 1 0;
    min-height: 40px;
    padding: var(--sp-3) var(--sp-5);
  }

  /* Folded controls: out of sight until the summary opens them. !important
     because many of them carry display rules of their own. The primary rows
     come first, then the summary, the opened controls, the buttons. */
  [data-filters-fold]:not(.fold-open) > .fold-member:not(:has(> .hub-chips, > .select-chips)) { display: none !important; }
  [data-filters-fold] > [data-fold] { order: 1; }
  [data-filters-fold] > .fold-summary { order: 2; }
  [data-filters-fold] > .fold-member, [data-filters-fold] .controls-more > * { order: 3; }
  [data-filters-fold] > button:not(.fold-summary) { order: 4; flex: 0 0 auto; }
  /* Room for "Options ▾" beside the buttons (Today's best has two): a
     narrower summary would run under them. */
  [data-filters-fold] > .fold-summary { min-width: 8em; }
  [data-filters-fold].fold-open > .controls-more { display: contents; }
  .controls[data-filters-fold] { gap: var(--sp-3) var(--sp-5); }
  .section-header[data-filters-fold] > button:not(.fold-summary) { align-self: center; }

  /* Numbers two to a line, name over field, once the summary is open. */
  [data-filters-fold].fold-open > label:has(> input[type="number"]),
  [data-filters-fold].fold-open .controls-more > label:has(> input[type="number"]) {
    display: flex;
    flex: 1 1 calc(50% - 10px);
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    min-width: 0;
  }
  [data-filters-fold].fold-open > label > input[type="number"],
  [data-filters-fold].fold-open .controls-more > label > input[type="number"] { width: 100%; }

  /* A filter panel: Preset, Category and Tech behind one line. */
  .panel-fold { display: flex; flex-direction: column; flex: 1 1 100%; min-width: 0; }
  .panel-fold:not(.fold-open) > .hotkey-panel { display: none; }
  .panel-fold > .fold-summary { flex: 0 0 auto; width: 100%; margin-bottom: var(--sp-4); }
  .panel-fold.fold-open > .hotkey-panel { margin-top: var(--sp-1); }
  .hotkey-panel { gap: var(--sp-2); margin-bottom: var(--sp-4); }
}

/* A filter panel that folds on a desktop too (data-fold-at="always"): the
   Preset row stays and the summary sits beside it, naming Category, Tech and
   the rest, which open under the row. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .panel-fold[data-fold-at="always"] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-6);
    margin-bottom: var(--sp-4);
  }
  .panel-fold[data-fold-at="always"] > .hotkey-panel { display: contents; }
  .panel-fold[data-fold-at="always"] > .fold-summary {
    display: flex;
    order: 1;
    flex: 0 1 auto;
    padding: var(--sp-2) var(--sp-5);
    font-size: var(--fs-xs);
  }
  .panel-fold[data-fold-at="always"] .hotkey-presets { order: 0; flex: 0 1 auto; }
  .panel-fold[data-fold-at="always"] > .hotkey-panel > .hotkey-group:not(.hotkey-presets) { order: 2; flex: 1 1 100%; }
  .panel-fold[data-fold-at="always"]:not(.fold-open) > .hotkey-panel > .hotkey-group:not(.hotkey-presets) { display: none; }

  /* A page head's Options (data-filters-fold with data-fold-at="always"):
     the primary rows, then "Options (n changed)" and Refresh on the line
     they end; the secondary inputs open under them. */
  [data-filters-fold][data-fold-at="always"]:not(.fold-open) > .fold-member:not(:has(> .hub-chips, > .select-chips)) { display: none !important; }
  [data-filters-fold][data-fold-at="always"] > [data-fold] { order: 1; }
  [data-filters-fold][data-fold-at="always"] > .fold-summary {
    display: flex;
    order: 2;
    flex: 0 1 auto;
    padding: var(--sp-2) var(--sp-5);
    font-size: var(--fs-xs);
  }
  [data-filters-fold][data-fold-at="always"] > button:not(.fold-summary) { order: 2; flex: 0 0 auto; }
  [data-filters-fold][data-fold-at="always"] > .fold-member, [data-filters-fold][data-fold-at="always"] .controls-more > * { order: 3; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* Notes between the controls and the results: two lines, a tap opens them. */
  .module-page .screen > p.last-sync:not(.note-open), #news-wire > p.last-sync:not(.note-open) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    cursor: pointer;
  }
  /* A status line (.page-status): two lines, a tap opens it. Beside a pager
     it gets three lines of the narrower column; with Notes shown too the row
     is too narrow, so the line takes the row and the buttons follow. */
  .page-status { margin: var(--sp-3) 0; }
  .page-status > .status-title { flex-basis: 100%; }
  .page-status > .last-sync:not(.page-note, .page-warn) { flex: 1 1 100%; }
  .page-status:has(.pagination-inline:not(:empty, [hidden])) > .last-sync:not(.page-note, .page-warn) { flex-basis: 8em; }
  .page-status:has(.notes-toggle:not([hidden])) > .last-sync:not(.page-note, .page-warn) { flex-basis: 100%; }
  .page-status > .page-warn { flex: 1 1 8em; }
  .page-status > .last-sync:not(.page-note, .page-warn, .note-open) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    cursor: pointer;
  }
  .page-status:has(.pagination-inline:not(:empty, [hidden])) > .last-sync:not(.page-note, .page-warn, .note-open) { -webkit-line-clamp: 3; }
  .page-status:has(.notes-toggle:not([hidden])) > .last-sync:not(.page-note, .page-warn, .note-open) { -webkit-line-clamp: 2; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .module-page .screen > p.last-sync, #news-wire > p.last-sync { margin: var(--sp-3) 0; }

  /* The sync age beside Trade settings, not above it. */
  header .header-tools { flex-wrap: nowrap; align-items: center; gap: var(--sp-6); }
  header .data-age { flex: 1 1 0; min-width: 0; }
  header .settings-widget { flex: 0 0 auto; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* Production's bulk buttons side by side, a line of their own. */
  .filter-and-bulk-row { gap: var(--sp-3); margin-bottom: var(--sp-3); }
  .bulk-add-buttons { flex: 1 1 100%; flex-wrap: nowrap; gap: var(--sp-2); }
  .bulk-add-buttons > .info-pair { flex: 1 1 0; min-width: 0; }
  .bulk-add-buttons > .info-pair > button { flex: 1 1 auto; min-width: 0; padding: var(--sp-3) var(--sp-3); font-size: var(--fs-xs); letter-spacing: 0.04em; line-height: 1.2; }
  .bulk-add-buttons > .info-pair > .info-tip { flex: 0 0 32px; width: 32px; min-width: 32px; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  /* Open, the summary takes its own row and the controls follow. */
  [data-filters-fold].fold-open > .fold-summary { flex-basis: 100%; }
}

/* A phone held sideways has no height to spare: every row of the container
   folds behind its summary, the primary and hub rows too (chipfold.js
   SHORT_SCREEN), and so do the rows beside the container in its header. The
   summary names what each is set to. */
@media (pointer: coarse) and (max-height: 500px) {
  [data-filters-fold]:not(.fold-open) > .fold-member { display: none !important; }
  [data-filters-fold] > [data-fold].fold-member { order: 3; }
  .fold-peer { display: none !important; }

  /* Sideways there is width and no height: the status line shares its row
     with Notes and the pager, its title stands inline, and the sort strip's
     column guide sits at the strip's end instead of under it. */
  .fold-summary { min-height: 34px; padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
  .panel-fold > .fold-summary { margin-bottom: var(--sp-2); }
  .route-map-fold > summary { display: flex; align-items: center; min-height: 32px; padding: 0; margin: 0; }
  .page-status > .status-title { flex-basis: auto; }
  .page-status:has(.notes-toggle:not([hidden])) > .last-sync:not(.page-note, .page-warn) { flex-basis: 8em; }
  .mobile-sort > .mobile-col-guide:not([open]) { flex: 0 0 auto; }
  /* Cargo's list status (the hauling choice's answer and the routes' note):
     two lines, a tap opens it. */
  #cargo-routes-status.last-sync { margin: var(--sp-3) 0; }
  #cargo-routes-status.last-sync:not(.note-open) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    cursor: pointer;
  }
  /* Cargo and Arbitrage: the Filters line and the route map's line share a
     row until one of them opens. */
  :is(#cargo, #arbitrage) > .screen { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0 var(--sp-5); }
  :is(#cargo, #arbitrage) > .screen > * { flex: 1 1 100%; min-width: 0; }
  :is(#cargo, #arbitrage) > .screen > .panel-fold:not(.fold-open):has(~ .route-map-fold:not([hidden], [open])),
  :is(#cargo, #arbitrage) > .screen > .route-map-fold:not([hidden], [open]) { flex-basis: calc(50% - var(--sp-5)); }
}

/* A desktop's chip rows and notes, set tighter: the same controls, less air
   between them, so the results start higher. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .section-header { gap: var(--sp-4) var(--sp-6); margin-bottom: var(--sp-5); }
  .controls { gap: var(--sp-3) var(--sp-6); }
  .hotkey-panel { gap: var(--sp-2); margin-bottom: var(--sp-4); }
  .hotkey-group { gap: var(--sp-4); }
  .hotkey-chip { padding-top: var(--sp-1); padding-bottom: var(--sp-1); }
  .hotkey-group-label { padding-top: var(--sp-2); }
  .phone-fold.explainer > summary { padding: var(--sp-3) 0; margin-bottom: var(--sp-1); }
  .last-sync { margin-bottom: var(--sp-4); }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .hotkey-chip { min-width: 32px; }
}

/* On a desktop the Outposts rows share lines. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .outposts-group { flex: 0 1 auto; margin: 0 var(--sp-6) 0 0; }
  .section-header > #outposts-refresh { margin-left: auto; }
}

}

/* Above every page rule (the overrides layer): a folded row's own display,
   flex and gap rules, and its chips away until it is opened, whatever a
   page's picker rules say. */
@layer overrides {
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .chip-fold {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    flex-basis: 100%;
    gap: 0 var(--sp-5);
  }

  /* The chips: away until the line is opened, then across the whole row. */
  .chip-fold > .hotkey-chip-list, .chip-fold > .hub-chips, .chip-fold > .select-chips { display: none; }
  .chip-fold.chip-fold-open > .hotkey-chip-list,
  .chip-fold.chip-fold-open > .hub-chips,
  .chip-fold.chip-fold-open > .select-chips {
    display: flex;
    flex: 1 0 100%;
    flex-wrap: wrap;
    gap: var(--sp-4);
    margin: var(--sp-3) 0 var(--sp-2);
  }

  /* Sideways rows: News' desks, every hub or region picker, and any group
     marked data-fold="scroll" stay on the page as one line, the label first
     and the chips scrolling beside it. A picker is one by the chips it
     holds, so it stays one when a page builds it again. The row crosses with
     a thumb: both axes pan (the page still scrolls up and down), the scroll
     stays in the row, and an edge with chips beyond it fades under an arrow
     button (chipfold.js). */
  :is([data-fold="scroll"], :is(.hub-picker, .hotkey-group):has(> .hub-chips, > .select-chips)) {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--sp-5);
    min-width: 0;
    max-width: 100%;
  }
  /* A sideways row its page hides (News' Category row off the Politics desk). */
  [data-fold="scroll"][hidden] { display: none; }
  :is([data-fold="scroll"], :is(.hub-picker, .hotkey-group):has(> .hub-chips, > .select-chips)) > :is(.hotkey-group-label, .hub-picker-label) {
    padding-top: 0;
    min-width: 0;
    min-height: 36px;
    display: flex;
    align-items: center;
  }
  :is([data-fold="scroll"], :is(.hub-picker, .hotkey-group):has(> .hub-chips, > .select-chips)) > :is(.hotkey-chip-list, .hub-chips, .select-chips) {
    flex: 1 1 auto;
    flex-wrap: nowrap;
    gap: var(--sp-4);
    margin: 0;
    min-width: 0;
  }
  :is([data-fold="scroll"], :is(.hub-picker, .hotkey-group):has(> .hub-chips, > .select-chips)) .hotkey-chip { flex: 0 0 auto; white-space: nowrap; }

  :is(.hotkey-group, .hub-picker, .mobile-sort, .outposts-group):has(> :is(.hotkey-chip-list, .hub-chips, .select-chips, .mobile-sort-chips)) { position: relative; }

  :is([data-fold="scroll"], :is(.hub-picker, .hotkey-group):has(> .hub-chips, > .select-chips)) > :is(.hotkey-chip-list, .hub-chips, .select-chips) {
    overflow-x: auto;
    overflow-y: hidden;
    padding: var(--sp-1) 0;
    scrollbar-width: none;
  }
  :is([data-fold="scroll"], :is(.hub-picker, .hotkey-group):has(> .hub-chips, > .select-chips)) > :is(.hotkey-chip-list, .hub-chips, .select-chips),
  .mobile-sort-chips {
    touch-action: pan-x pan-y;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  :is(.hotkey-chip-list, .hub-chips, .select-chips, .mobile-sort-chips)::-webkit-scrollbar { display: none; }

  /* A chip is whole or hidden under an arrow: the row comes to rest with a
     chip's edge just clear of the arrow's 32px. */
  :is(.hotkey-chip-list, .hub-chips, .select-chips, .mobile-sort-chips, .build-strip) { scroll-padding-inline: 32px; scroll-snap-type: x proximity; }
  :is(.hotkey-chip-list, .hub-chips, .select-chips, .mobile-sort-chips, .build-strip) > * { scroll-snap-align: start; }

  [data-chip-scroll][data-more-right]:not([data-more-left]) {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
  }
  [data-chip-scroll][data-more-left]:not([data-more-right]) {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px);
    mask-image: linear-gradient(90deg, transparent 0, #000 28px);
  }
  [data-chip-scroll][data-more-left][data-more-right] {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
  }

  .chip-scroll-btn {
    position: absolute;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    min-width: 32px;
    min-height: 32px;
    padding: 0;
    font-size: 20px;
    line-height: 1;
    letter-spacing: 0;
    text-transform: none;
    color: var(--phosphor);
    border-color: var(--edge);
    background: var(--panel-bg);
  }
  .chip-scroll-btn[hidden] { display: none; }
}
}
@layer pages {
/* Item search's order book (itemsearch.js). */
/* More regions (itemsearch.js renderExtras): a fold under the strip, closed,
   so the order book is on the first screen; its note says how many regions
   there are, or which one is picked. */
.item-extras { margin: 0 0 var(--sp-3); }
.item-extras[hidden] { display: none; }
.item-extras > summary {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  min-height: 32px;
  cursor: pointer;
  list-style: none;
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.item-extras > summary::-webkit-details-marker { display: none; }
.item-extras > summary::before { content: "▸"; color: var(--phosphor); }
.item-extras[open] > summary::before { content: "▾"; }
.item-extras-note { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--text-dim); }
.item-extras-on .item-extras-note { color: var(--phosphor); }
.item-extras .hotkey-chip-list { margin: var(--sp-1) 0 var(--sp-4); }
.item-extra-n { margin-left: var(--sp-2); color: var(--text-dim); font-weight: 400; }
.item-extra-chip.active .item-extra-n { color: inherit; }
.item-extra-age { margin-left: var(--sp-3); color: var(--text-dim); font-weight: 400; }
.item-extra-age.flag-warn { color: var(--amber); }
.item-extra-chip.active .item-extra-age:not(.flag-warn) { color: inherit; }

.item-side-title {
  margin: 0;
  font-size: var(--fs-md);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--phosphor);
}

/* The order book, as in game (itemsearch.js): the sell orders on top, the
   spread, the buy orders under it, one line each. On a wide screen the price
   history sits beside it, so the book is on the first screen; narrower, under
   it. --ob-cols are a line's columns (its tick, price, quantity, station,
   jumps, range on a buy side, time left) and the header uses the same, so
   they line up; --ob-order-w is "+ Notebook"'s. */
.item-market { display: block; }
.item-market > .item-history { margin: var(--sp-7) 0 0; }
@media (min-width: 1180px) {
  .item-market { display: grid; grid-template-columns: minmax(0, 1fr) 430px; gap: var(--sp-7); align-items: start; }
  .item-market > .item-history { margin: 0; }
}
.item-book { min-width: 0; }
.item-side {
  --ob-order-w: 72px;
  --ob-cols: 14px 100px 96px minmax(0, 1fr) 56px 84px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: var(--sp-6);
}
.item-side[data-item-side="buy"] { --ob-cols: 14px 100px 96px minmax(0, 1fr) 56px 70px 84px; }
.item-side > .ob-scroll, .item-side > .ob-pager { grid-column: 1 / -1; }
.ob-bar { display: flex; align-items: baseline; gap: var(--sp-6); min-width: 0; }
.ob-bar .last-sync { margin: 0; }
.item-side-empty .ob-scroll, .item-side-empty .ob-pager, .item-side-empty .controls.mobile-sort { display: none; }

/* The sort strip: the headers sort by what a line shows; the strip adds the
   columns it doesn't (and every column on a phone). */
.item-side .controls.mobile-sort { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-4); min-width: 0; margin: 0; }
.item-side .mobile-sort-label { font-size: 0; }
.item-side .mobile-sort-label::before { content: "Also sort by"; font-size: var(--fs-xs); color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.08em; }
.item-side .mobile-sort-chips { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2); min-width: 0; }
.item-side .mobile-sort-chip { padding: var(--sp-1) var(--sp-4); font-size: var(--fs-xs); }
.item-side .mobile-sort-arrow:not(:empty) { margin-left: var(--sp-2); font-size: 10px; }
.item-side .mobile-sort-chip:is([data-key="price"], [data-key="volume_remain"], [data-key="station_name"], [data-key="jumps_from_hub"], [data-key="_range_rank"], [data-key="_expires_in"]) { display: none; }
.item-side .mobile-sort .filter-count, .item-side .mobile-col-guide { display: none; }

.item-book .table-scroll { overflow: visible; margin-top: var(--sp-4); }
.item-orders-table { display: block; width: 100%; }
.item-orders-table thead { display: block; }
.item-orders-table thead tr {
  display: grid;
  grid-template-columns: var(--ob-cols) var(--ob-order-w);
  column-gap: var(--sp-5);
  align-items: end;
  padding: 0 var(--sp-3);
  background: rgba(0, 255, 136, 0.035);
  border-bottom: 1px solid rgba(0, 255, 136, 0.55);
}
.item-orders-table thead tr::before { content: ""; }
.item-book .ob-scroll thead th { position: static; background: none; border-bottom: none; box-shadow: none; animation: none; }
.item-book .ob-scroll thead th:is([aria-sort="ascending"], [aria-sort="descending"]) { background: rgba(0, 255, 136, 0.09); box-shadow: inset 0 -2px 0 var(--phosphor); }
.item-book .ob-scroll thead th::after { content: none; }
.item-book .ob-scroll th:is([data-key="_value"], [data-key="_m3"], [data-key="system_name"], [data-key="region_name"], [data-key="min_volume"], [data-key="_age"], [data-key="duration"]) { display: none; }
.item-orders-table .th-sort-btn { padding: var(--sp-3) 0; white-space: nowrap; }
.item-orders-table th:is([data-key="price"], [data-key="volume_remain"], [data-key="jumps_from_hub"]) .th-sort-btn { text-align: right; }
.item-orders-table th.order-col { width: auto; }

.ob-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--ob-order-w);
  column-gap: var(--sp-5);
  align-items: center;
  padding: 0 var(--sp-3);
  border-bottom: 1px solid var(--row-line);
}
.ob-row:nth-child(even) { background: rgba(125, 255, 178, 0.022); }
@media (hover: hover) {
  .ob-row:hover { background: rgba(0, 255, 136, 0.07); }
}
.ob-row.open { background: rgba(0, 255, 136, 0.05); box-shadow: inset 2px 0 0 var(--phosphor); }
.ob-main {
  display: grid;
  grid-template-columns: var(--ob-cols);
  column-gap: var(--sp-5);
  align-items: center;
  width: 100%;
  min-width: 0;
  min-height: 30px;
  padding: 0;
  border: none;
  background: none;
  color: var(--mint);
  font-size: var(--fs-md);
  font-weight: 400;
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
}
.ob-main:hover { background: none; border-color: transparent; color: var(--mint); }
.ob-main:focus-visible { outline-offset: -1px; }
.ob-sub { display: contents; }
.ob-unit { display: none; }
.ob-c { min-width: 0; white-space: nowrap; }
.ob-price { text-align: right; color: var(--amber); font-weight: 700; }
/* An order priced far under the market's own: marked, not hidden. */
.ob-low { margin-left: var(--sp-2); font-size: var(--fs-xs); font-weight: 400; cursor: help; }
.ob-qty { text-align: right; color: var(--text-bright); }
.ob-jumps { text-align: right; }
.ob-loc { display: flex; align-items: baseline; gap: var(--sp-2); color: var(--text-bright); }
.ob-loc-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ob-loc > .sec, .ob-loc > .ob-star { flex: none; }
.ob-dim { color: var(--text-dim); }
.ob-star { color: var(--amber); }
.ob-chev { order: -1; }
.ob-chev::before { content: "▸"; color: var(--phosphor); font-size: var(--fs-xs); }
.ob-row.open .ob-chev::before { content: "▾"; }
.ob-row .order-add-btn { justify-self: end; }
.ob-more { grid-column: 1 / -1; padding: var(--sp-2) 0 var(--sp-5) 24px; }
.ob-more[hidden] { display: none; }
.ob-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--sp-1) var(--sp-7); margin: 0; font-size: var(--fs-md); }
.ob-fields > div { display: flex; flex-direction: column; padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); min-width: 0; }
.ob-fields dt { color: var(--text-dim); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.08em; }
.ob-fields dd { margin: 0; color: var(--text-bright); overflow-wrap: anywhere; }
.ob-fields .cell-note { font-size: var(--fs-xs); }

/* The spread between the sides. */
.ob-spread {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-6);
  margin: var(--sp-5) 0;
  padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid var(--phos-a35);
  border-bottom: 1px solid var(--phos-a35);
  background: rgba(0, 255, 136, 0.04);
  font-size: var(--fs-md);
  color: var(--text-bright);
}
.ob-spread[hidden] { display: none; }
.ob-spread-k { color: var(--phosphor); font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; }
.ob-spread b { color: var(--amber); }

/* Under a side: how many of how many are shown, and more. */
.ob-pager { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4); margin-top: var(--sp-4); }
.ob-pager:empty { display: none; }
.ob-pager-info { font-size: var(--fs-sm); color: var(--text-dim); margin-right: var(--sp-2); }

/* Item search's order book on a phone (the phone query, as above): a line is
   two small rows — price and quantity over the station, jumps, range and
   time left — and the line, 48px tall, is the tap target that opens the
   order; "+ Notebook" beside it. The sort strip carries every column, the
   headers being hidden. */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .item-side { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-3); }
  .item-side > .controls.mobile-sort { grid-column: 1 / -1; display: flex; justify-content: flex-start; margin: 0; }
  .item-side .mobile-sort-label { font-size: inherit; }
  .item-side .mobile-sort-label::before { content: none; }
  .item-side .mobile-sort-chips { flex: 1 1 0; flex-wrap: nowrap; justify-content: flex-start; gap: var(--sp-3); }
  .item-side .mobile-sort-chip { padding: var(--sp-4) var(--sp-6); font-size: var(--fs-sm); }
  .item-side .mobile-sort-chip:is([data-key="price"], [data-key="volume_remain"], [data-key="station_name"], [data-key="jumps_from_hub"], [data-key="_range_rank"], [data-key="_expires_in"]) { display: inline-block; }
  .ob-bar { flex-wrap: wrap; gap: 0 var(--sp-5); }
  .item-orders-table thead { display: none; }
  .item-book .table-scroll { margin-top: 0; }

  .ob-row { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--sp-3); padding: 0; }
  .ob-main {
    grid-template-columns: 18px auto minmax(0, 1fr) auto;
    grid-template-areas: "chev price qty exp" "chev sub sub sub";
    column-gap: var(--sp-4);
    row-gap: 1px;
    min-height: 44px;
    padding: var(--sp-2) 0 var(--sp-3);
  }
  .ob-chev { grid-area: chev; align-self: center; }
  .ob-price { grid-area: price; text-align: left; font-size: 14px; line-height: 1.35; }
  .ob-qty { grid-area: qty; text-align: left; font-size: var(--fs-md); color: var(--text-label); }
  .ob-sub { grid-area: sub; display: flex; align-items: baseline; gap: 0 var(--sp-4); min-width: 0; overflow: hidden; font-size: var(--fs-sm); line-height: 1.35; color: var(--text-label); }
  .ob-sub .ob-c { flex: none; }
  .ob-sub .ob-loc { flex: 0 1 auto; min-width: 24px; color: var(--text-bright); }
  .ob-exp { grid-area: exp; text-align: right; font-size: var(--fs-sm); color: var(--text-label); }
  .ob-jumps { text-align: left; }
  .ob-unit { display: inline; }
  .ob-row .order-add-btn { margin: var(--sp-2) 0; min-height: 36px; padding: var(--sp-4) var(--sp-5); }
  .ob-more { padding: var(--sp-1) 0 var(--sp-5) 24px; }
  .ob-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-1) var(--sp-6); }
  .ob-spread { margin: var(--sp-6) 0; }
  .ob-pager .page-btn { min-height: 36px; }
}

}
@layer pages {
/* The bill of materials (tools/bom.js): Production's row details and focus view. */
.bom { margin: 0 0 var(--sp-5); }
.bom.is-loading { opacity: 0.55; }
.bom-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-7); margin-bottom: var(--sp-4); }
.bom-bar label { display: inline-flex; align-items: center; gap: var(--sp-3); }
.bom-bar input { width: 6ch; min-height: 32px; }
.bom-where { color: var(--text-dim); font-size: var(--fs-sm); }
.bom-grid { font-size: var(--fs-md); }
.bom-row { display: grid; grid-template-columns: minmax(0, 2.4fr) minmax(0, 0.9fr) minmax(0, 0.9fr) minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 1.4fr); gap: var(--sp-2) var(--sp-4); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--row-line); align-items: start; }
.bom-row.bom-head { color: var(--mint-dim); border-bottom-color: var(--line); white-space: nowrap; }
.bom-cell > .bom-label { display: none; }
.bom-grid.no-choice .bom-row { grid-template-columns: minmax(0, 2.4fr) minmax(0, 0.9fr) minmax(0, 0.9fr) minmax(0, 1fr) minmax(0, 1.2fr); }
.bom-grid.no-choice .bom-choice, .bom-grid.no-choice .bom-head > :last-child { display: none; }
.bom-flag { font-size: var(--fs-sm); }
.bom-pick { display: inline-flex; border: 1px solid var(--edge); }
.bom-pick button { min-height: 28px; padding: var(--sp-1) var(--sp-4); font-size: var(--fs-xs); letter-spacing: 0.06em; color: var(--mint); background: transparent; border: 0; white-space: nowrap; cursor: pointer; }
.bom-pick button + button { border-left: 1px solid var(--edge); }
.bom-pick button[aria-checked="true"] { background: var(--phos-a20); color: var(--phosphor); }
.bom-sum, .bom-result { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-7); margin-top: var(--sp-4); font-size: var(--fs-md); }
.bom-sum b, .bom-result b { color: var(--mint-dim); font-weight: normal; margin-right: var(--sp-2); }
.bom-result { color: var(--text-bright); }
.bom-note { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--text-label); }

/* The Production focus view: the item's panel above the table. */
.prod-focus { margin: 0 0 var(--sp-6); padding: var(--sp-6) var(--sp-7); border: 1px solid var(--panel-border); background: var(--panel-bg); }
.prod-focus[hidden] { display: none; }
.prod-focus-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-6); margin-bottom: var(--sp-5); }
.prod-focus-head h3 { margin: 0; font-size: var(--fs-lg); color: var(--text-bright); }
.prod-focus-head .prod-focus-actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.prod-focus-numbers { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-7); margin-bottom: var(--sp-5); }
.prod-focus-numbers > div { min-width: 9ch; }
.prod-focus-numbers .k { display: block; color: var(--mint-dim); font-size: var(--fs-xs); letter-spacing: 0.08em; text-transform: uppercase; }
.prod-focus-numbers .v { font-size: var(--fs-lg); color: var(--text-bright); }
.prod-focus-numbers .v.bottleneck { color: var(--amber); }

/* Invention: the decryptor choice, a fold under the totals. */
.bom-inv { margin-top: var(--sp-4); font-size: var(--fs-md); }
.bom-inv > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--text-bright); }
.bom-inv-row { display: grid; grid-template-columns: 3ch minmax(0, 2fr) repeat(5, minmax(0, 1fr)); align-items: center; gap: var(--sp-3); min-height: 32px; border-bottom: 1px solid var(--line); cursor: pointer; }
.bom-inv-row.bom-inv-head { color: var(--mint-dim); font-size: var(--fs-xs); cursor: default; }
.bom-inv-row input { margin: 0; }
.bom-inv-name { overflow-wrap: anywhere; }

@media (max-width: 768px) {
  .bom-row.bom-head { display: none; }
  .bom-row, .bom-grid.no-choice .bom-row { grid-template-columns: repeat(3, minmax(0, 1fr)); padding: var(--sp-4) 0; }
  .bom-cell > .bom-label { display: block; color: var(--text-dim); font-size: var(--fs-xs); }
  .bom-cell.bom-name, .bom-cell.bom-choice { grid-column: 1 / -1; }
  .bom-cell.bom-name > .bom-label, .bom-cell.bom-choice > .bom-label { display: none; }
  .bom-pick { display: flex; width: 100%; }
  .bom-pick button { flex: 1; min-height: 44px; }
  .bom-bar input { min-height: 44px; width: 8ch; }
  .bom-inv > summary { min-height: 44px; }
  .bom-inv-row { grid-template-columns: 40px minmax(0, 1fr) 4ch 4ch 3ch 7ch 7ch; min-height: 44px; gap: var(--sp-2); font-size: var(--fs-sm); }
  .bom-inv-row input { width: 20px; height: 20px; }
  .prod-focus-head .prod-focus-actions { margin-left: 0; width: 100%; }
  .prod-focus-actions button { min-height: 44px; flex: 1; }
}
}
@layer pages {
/* CCP's proprietary notice (Developer License Agreement 7.1), on every page. */
.site-notice { width: 100%; max-width: 1400px; margin: 24px auto 0; padding: var(--sp-6) var(--sp-7) 96px; color: var(--text-dim); font-size: var(--fs-sm); line-height: 1.5; opacity: 0.8; }
.site-notice p { margin: 0 0 var(--sp-3); }
.site-links { display: flex; gap: var(--sp-2) 20px; flex-wrap: wrap; margin: 0 0 var(--sp-3); font-size: var(--fs-md); }
.site-links a { display: inline-flex; align-items: center; min-height: 32px; color: var(--mint-dim); }
.site-links a:hover, .site-links a:focus-visible { color: var(--mint); }

/* About page: blocks of short text in a grid that stacks on a phone. */
.about-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: var(--sp-6) 24px; align-items: start; }
.about-block { min-width: 0; padding-bottom: var(--sp-2); }
.about-block h3 { margin: var(--sp-2) 0 var(--sp-4); font-size: var(--fs-lg); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mint-dim); }
.about-block .last-sync { color: var(--text-bright); }
.about-data { margin: 0 0 var(--sp-6); font-size: var(--fs-md); line-height: 1.55; overflow-wrap: anywhere; }
.about-data dt { color: var(--mint); margin-top: var(--sp-4); }
.about-data dt::before { content: "> "; color: var(--phosphor); opacity: 0.8; }
.about-data dd { margin: 0; color: var(--text-dim); }
.about-sub { margin: var(--sp-6) 0 0; font-size: var(--fs-md); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mint-dim); }
.about-ways { list-style: none; margin: 0 0 var(--sp-6); padding: 0; font-size: var(--fs-md); line-height: 1.55; overflow-wrap: anywhere; }
.about-ways li { margin-bottom: var(--sp-4); color: var(--text-bright); }
.about-ways li[hidden] { display: none; }
.about-way-label { display: inline-block; min-width: 48px; margin-right: var(--sp-3); color: var(--mint-dim); font-weight: 700; }
.about-tbd { color: var(--amber); }
.about-block a { display: inline-block; padding: var(--sp-3) 0; }
}
@layer pages {
/* Capsuleer (tools/capsuleer*.js): the look the category's pages share: the
   demo banner, tiles, alert rows and the landing page's people and cards. */
.cap-title { margin: var(--sp-7) 0 var(--sp-3); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.cap-count { color: var(--text-dim); letter-spacing: 0; }
.cap-up { color: var(--phosphor); }
.cap-down { color: var(--red); }
.cap-warn { color: var(--amber); }

/* Banner: an amber block at the top of every page, then notices for what an
   answer lacks. */
.cap-banner-host:empty { display: none; }
.cap-demo { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-1) var(--sp-6); align-items: start; margin: var(--sp-4) 0; padding: var(--sp-4) var(--sp-5); border: 1px solid var(--amber); border-left-width: 4px; background: rgba(255, 176, 0, 0.07); }
.cap-demo-tag { padding: 1px var(--sp-4); font-weight: 700; letter-spacing: 0.12em; color: #000; background: var(--amber); }
.cap-demo p { margin: 0; font-size: var(--fs-md); line-height: 1.5; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-demo .cap-demo-login { grid-column: 2; }
.cap-demo a { display: inline-block; padding: var(--sp-3) 0; color: var(--amber); text-decoration: underline; }
.cap-notice { margin: var(--sp-3) 0; font-size: var(--fs-md); line-height: 1.5; color: var(--amber); overflow-wrap: anywhere; }

/* A part of a page that needs a paid tier (Capsuleer.locked, Capsuleer.limitNote):
   one quiet block that says what the tier adds and where plans are explained. */
.cap-locked { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-1) var(--sp-6); align-items: start; margin: var(--sp-4) 0; padding: var(--sp-4) var(--sp-5); border: 1px solid var(--edge); border-left: 4px solid var(--mint); background: var(--screen-bg); }
.cap-locked-tag { padding: 1px var(--sp-4); font-weight: 700; letter-spacing: 0.12em; color: #000; background: var(--mint); }
.cap-locked p { margin: 0; font-size: var(--fs-md); line-height: 1.5; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-locked .cap-locked-more { grid-column: 2; color: var(--text-dim); }
.cap-locked a { display: inline-block; padding: var(--sp-3) 0; color: var(--accent); text-decoration: underline; }

/* The page's top bar: Refresh and the status line beside it. */
.cap-bar { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-6); margin: var(--sp-4) 0; }
.cap-bar .last-sync { flex: 1 1 200px; min-width: 0; margin: 0; }
.cap-owner { margin: var(--sp-3) 0 var(--sp-4); font-size: 14px; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-owner-corp { color: var(--text-dim); }

/* Tiles. */
.cap-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); align-items: start; margin-top: var(--sp-4); }
.cap-tile { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; padding: var(--sp-4) var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); color: var(--text-bright); }
.cap-tile:nth-child(2) { grid-column: span 2; }
/* The Cockpit's tiles are as tall as their figures: columns of tiles, each
   under the one above it, so a short tile leaves no hole beside a tall one. */
#capsuleer-cockpit-tiles { display: block; column-count: 4; column-gap: var(--sp-4); }
#capsuleer-cockpit-tiles .cap-tile { break-inside: avoid; margin-bottom: var(--sp-4); }
@media (max-width: 1000px) { #capsuleer-cockpit-tiles { column-count: 3; } }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) { #capsuleer-cockpit-tiles { column-count: 2; } }
@media (max-width: 400px) { #capsuleer-cockpit-tiles { column-count: 1; } }
/* A tile that takes its grid's whole row, its rows in columns. */
.cap-tile.cap-tile-wide { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-1) var(--sp-7); }
.cap-tile-wide > :is(.cap-tile-name, .cap-tile-value, .cap-note) { grid-column: 1 / -1; }
.cap-tile-name { font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.cap-tile-value { font-size: 20px; font-weight: 700; line-height: 1.2; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-row { display: flex; justify-content: space-between; gap: var(--sp-5); font-size: var(--fs-md); line-height: 1.4; }
.cap-row-label { color: var(--text-dim); min-width: 0; overflow-wrap: anywhere; }
.cap-row-value { text-align: right; min-width: 0; overflow-wrap: anywhere; }
.cap-note { margin: var(--sp-1) 0 0; font-size: var(--fs-sm); line-height: 1.45; color: var(--text-dim); overflow-wrap: anywhere; }
.cap-note.cap-warn { color: var(--amber); }
.cap-spark { display: block; width: 100%; height: 36px; margin: var(--sp-1) 0; }
.cap-spark path { fill: none; stroke: var(--phosphor); stroke-width: 1.5; stroke-linejoin: round; vector-effect: non-scaling-stroke; }

/* Alerts: dense rows, a severity marker first. */
.cap-alerts { list-style: none; margin: var(--sp-3) 0 0; padding: 0; }
.cap-alert { display: grid; grid-template-columns: 54px minmax(0, 1fr) auto; gap: var(--sp-4); align-items: baseline; padding: var(--sp-3) 0 var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--row-line); border-left: 3px solid var(--edge); }
.cap-alert-warn { border-left-color: var(--amber); }
.cap-alert-alert { border-left-color: var(--red); }
.cap-sev { font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em; color: var(--text-dim); }
.cap-alert-warn .cap-sev { color: var(--amber); }
.cap-alert-alert .cap-sev { color: var(--red); }
.cap-alert-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cap-alert-title { font-size: var(--fs-lg); line-height: 1.35; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-alert-title a { color: var(--phosphor); }
.cap-alert-detail { font-size: var(--fs-md); line-height: 1.4; color: var(--text-dim); overflow-wrap: anywhere; }
.cap-alert-time { font-size: var(--fs-sm); color: var(--text-dim); text-align: right; white-space: nowrap; }
.cap-alert-none { padding: var(--sp-4) 0; font-size: var(--fs-md); color: var(--text-dim); }

/* Landing page: people and the cards of the pages. */
.cap-people { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--sp-4); }
.cap-person { min-width: 0; padding: var(--sp-4) var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); }
.cap-person-name { font-weight: 700; color: var(--phosphor); overflow-wrap: anywhere; }
.cap-person-line { margin-top: var(--sp-1); font-size: var(--fs-md); line-height: 1.4; color: var(--text-dim); overflow-wrap: anywhere; }
/* The character filter under a page's banner (Capsuleer.characterFilter). */
.cap-char-filter { margin: var(--sp-3) 0 var(--sp-1); }
.cap-char-filter[hidden] { display: none; }
.cap-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); margin-top: var(--sp-3); }
.cap-chip { padding: 1px var(--sp-4); font-size: var(--fs-sm); color: var(--mint-dim); border: 1px solid var(--edge); }
.cap-card-group + .cap-card-group { margin-top: var(--sp-6); }
.cap-card-group-title { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--mint-dim); }
.cap-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-4); }
.cap-card { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-1) var(--sp-5); align-items: center; min-height: 56px; padding: var(--sp-4) var(--sp-5); color: var(--text-bright); background: var(--screen-bg); border: 1px solid var(--edge); text-decoration: none; }
.cap-card:hover, .cap-card:focus-visible { border-color: var(--phosphor); }
.cap-card .ic { grid-row: 1 / 3; width: 24px; height: 24px; fill: none; stroke: var(--phosphor); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.cap-card-name { font-weight: 700; color: var(--phosphor); }
.cap-card-text { grid-column: 2; font-size: var(--fs-md); line-height: 1.4; color: var(--text-dim); overflow-wrap: anywhere; }

@media (max-width: 1000px) {
  .cap-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* The phone layout (the query pagination.js names PHONE_MEDIA_QUERY). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cap-demo { grid-template-columns: minmax(0, 1fr); }
  .cap-demo .cap-demo-login { grid-column: 1; }
  .cap-demo-tag { justify-self: start; }
  .cap-locked { grid-template-columns: minmax(0, 1fr); }
  .cap-locked .cap-locked-more { grid-column: 1; }
  .cap-locked-tag { justify-self: start; }
  .cap-alert { grid-template-columns: 50px minmax(0, 1fr); }
  .cap-alert-time { grid-column: 2; text-align: left; }
  .cap-bar button { min-height: 36px; }
}
@media (max-width: 400px) {
  .cap-tiles { grid-template-columns: minmax(0, 1fr); }
  .cap-tile:nth-child(2) { grid-column: span 1; }
}
}
@layer pages {
/* Capsuleer orders (tools/capsuleer-orders.js): the controls, the badges and
   the order tables grouped by station. A phone shows each row as a card
   through the shared table rules (phone.css). */
.cap-ord-controls, .cap-con-controls { display: flex; flex-direction: column; gap: var(--sp-3); margin: var(--sp-4) 0 var(--sp-5); }
.cap-ord-controls .hotkey-chip, .cap-con-controls .hotkey-chip { min-height: 28px; }
.cap-ord-controls .hotkey-chip[hidden], .cap-con-controls .hotkey-chip[hidden] { display: none; }
.cap-ord-tiles { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.cap-ord-tiles .cap-tile:nth-child(2) { grid-column: auto; }
/* Slots by character: a fold of one line a character. */
.cap-ord-slots { margin-top: var(--sp-2); }
.cap-ord-slots > summary { display: flex; align-items: center; min-height: 32px; cursor: pointer; font-size: var(--fs-sm); color: var(--text-dim); }
.cap-ord-slots[open] > summary { color: var(--mint-dim); }
.cap-ord-slots > summary::after { content: "\25BE"; margin-left: var(--sp-3); }
.cap-ord-slots[open] > summary::after { content: "\25B4"; }

.cap-ord-group { margin-top: var(--sp-2); }
.cap-ord-table td { vertical-align: top; }
.cap-ord-table td[data-label="Item"] { min-width: 150px; }
.cap-ord-table td[data-label="Standing"] { min-width: 190px; }
.cap-ord-table td:is([data-label="Price to beat"], [data-label="Relist cost"], [data-label="Days of volume"]) { min-width: 130px; }
.cap-ord-table td:is([data-label="Price"], [data-label="Remaining"], [data-label="Price to beat"], [data-label="Relist cost"], [data-label="Days of volume"], [data-label="At stake"], [data-label="Expires"], [data-label="Standing"], [data-label="Station"], [data-label="Character"]) { white-space: normal; }
.cap-ord-table td[data-label="Price to beat"] strong { color: var(--phosphor); }
.cap-ord-table td:is([data-label="Relist cost"], [data-label="At stake"], [data-label="ISK filled"]) { color: var(--amber); }
.cap-ord-table td[data-label="Actions"] { white-space: nowrap; }
.cap-ord-row-behind > td:first-child { box-shadow: inset 2px 0 0 var(--amber); }
.cap-ord-note { display: block; font-size: var(--fs-xs); line-height: 1.35; color: var(--text-label, var(--text-dim)); font-weight: 400; }

.cap-ord-badge { display: inline-block; padding: 0 var(--sp-3); font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em; border: 1px solid currentColor; }
.cap-ord-best { color: var(--phosphor); }
.cap-ord-behind { color: var(--amber); }
.cap-ord-unknown { color: var(--text-dim); }
.cap-ord-side { display: inline-block; margin-left: var(--sp-3); padding: 0 var(--sp-2); font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em; border: 1px solid var(--edge); vertical-align: 1px; }
.cap-ord-sell { color: var(--amber); }
.cap-ord-buy { color: var(--phosphor); }
.cap-ord-corp { color: var(--mint-dim); }

.cap-ord-actions { display: inline-flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: flex-end; }
.cap-ord-btn { min-height: 28px; padding: var(--sp-1) var(--sp-4); font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.06em; color: var(--mint-dim); background: transparent; border: 1px solid var(--edge); cursor: pointer; }
.cap-ord-btn:hover:not(:disabled) { color: var(--phosphor); border-color: var(--phosphor); }
.cap-ord-btn:disabled { opacity: 0.45; cursor: not-allowed; }

@media (max-width: 1000px) {
  .cap-ord-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-ord-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cap-ord-controls .hotkey-group, .cap-con-controls .hotkey-group { flex-direction: column; gap: var(--sp-1); }
  .cap-ord-controls .hotkey-group-label, .cap-con-controls .hotkey-group-label { padding-top: 0; }
  .cap-ord-controls .hotkey-chip, .cap-con-controls .hotkey-chip { min-height: 32px; }
  .cap-ord-table td[data-label="Item"] { min-width: 0; }
  .cap-ord-table td[data-label="Actions"] { white-space: normal; }
  .cap-ord-btn { min-height: 36px; padding: var(--sp-2) var(--sp-6); }
  .cap-ord-note { display: block; }
}
@media (max-width: 400px) {
  .cap-ord-tiles { grid-template-columns: minmax(0, 1fr); }
}
}
@layer pages {
/* Capsuleer ledger (tools/capsuleer-ledger.js): the window chips and export
   beside Refresh, tiles three across, the winners and losers lists and the
   figures' colour in the tables. The tile, bar and chart parts are the
   shared ones (capsuleer.css, news.css). */
.capl-bar { align-items: center; }
.capl-bar .hotkey-chip-list { flex: 0 0 auto; }
.capl-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); align-items: start; margin-top: var(--sp-4); }
.capl-table { margin-top: var(--sp-3); }
.capl-table td { color: var(--text-bright); }
.capl-table td.cap-up { color: var(--phosphor); }
.capl-table td.cap-down { color: var(--red); text-shadow: none; }
.capl-table td[data-label="Activity"] { text-align: left; white-space: normal; }
#capsuleer-ledger .hotkey-chip-list + .last-sync { margin-top: var(--sp-4); }
.capl-internal { margin: var(--sp-4) 0 0; overflow-wrap: anywhere; }
.capl-internal[hidden], #capsuleer-ledger-chars-section[hidden] { display: none; }
.capl-table td[data-label="Character"] { text-align: left; white-space: normal; overflow-wrap: anywhere; }
.capl-sub { margin: 0 0 var(--sp-2); font-size: var(--fs-md); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.capl-wl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6); }
.capl-list { list-style: none; margin: 0; padding: 0; }
.capl-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 var(--sp-5); padding: var(--sp-3) 0; border-bottom: 1px solid var(--row-line); }
.capl-name { min-width: 0; font-size: var(--fs-lg); color: var(--text-bright); overflow-wrap: anywhere; }
.capl-fig { font-size: var(--fs-lg); font-weight: 700; text-align: right; white-space: nowrap; }
.capl-detail { grid-column: 1 / -1; font-size: var(--fs-sm); color: var(--text-dim); }
.capl-none { display: block; font-size: var(--fs-md); color: var(--text-dim); }
#capsuleer-ledger .fc-plot { margin-bottom: var(--sp-2); }

@media (max-width: 1000px) {
  .capl-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* The phone layout (the query pagination.js names PHONE_MEDIA_QUERY). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .capl-bar button, .capl-bar .hotkey-chip { min-height: 36px; }
  .capl-wl { grid-template-columns: minmax(0, 1fr); }
  .capl-table td[data-label="Activity"], .capl-table td[data-label="Character"] { text-align: right; }
}
@media (max-width: 400px) {
  .capl-tiles { grid-template-columns: minmax(0, 1fr); }
}
}
@layer pages {
/* Capsuleer Industry (tools/capsuleer-industry.js): slot tiles with idle
   highlighting, job timers, the Fill idle slots panel and the blueprint
   table's busy rows. The shared tile, alert and table looks are capsuleer.css
   and tables.css. */

/* Six tiles in a row where the cockpit's second tile spans two. */
.ind-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ind-tiles .cap-tile:nth-child(2) { grid-column: auto; }
.ind-tiles .cap-tile.ind-idle { border-color: var(--amber); background: rgba(255, 176, 0, 0.06); }

/* Timers: the time left over a thin bar, the bar filling as the job runs. */
.ind-timer { display: inline-flex; flex-direction: column; gap: var(--sp-1); min-width: 96px; }
.ind-ready { color: var(--phosphor); font-weight: 700; }
.ind-bar { display: block; height: 4px; background: var(--row-line); }
.ind-bar > span { display: block; height: 100%; background: var(--phosphor); }

/* Fill idle slots. */
.ind-fill { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--sp-4); align-items: start; }
.ind-fill-pool { min-width: 0; padding: var(--sp-4) var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); }
.ind-fill-pool h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-md); letter-spacing: 0.04em; color: var(--mint-dim); overflow-wrap: anywhere; }
.ind-fill-list { margin: 0; padding: 0 0 0 20px; }
.ind-fill-list li { padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); line-height: 1.4; overflow-wrap: anywhere; }
.ind-fill-list li:last-child { border-bottom: none; }
.ind-fill-main { display: block; color: var(--text-bright); }
.ind-fill-what { color: var(--text-dim); }
.ind-fill-profit { display: block; }
.ind-fill-from { display: block; }
.ind-fill-science { grid-column: 1 / -1; margin: 0; }
.ind-fill-add { grid-column: 1 / -1; justify-self: start; min-height: 36px; }

/* Slots by character: one compact line per character. */
.ind-slots-by:empty { display: none; }
.ind-slots-by { margin: var(--sp-4) 0 0; }
.ind-slots-title { margin: 0 0 var(--sp-2); font-size: var(--fs-md); letter-spacing: 0.04em; color: var(--mint-dim); }
.ind-slots-list { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-1) var(--sp-6); }
.ind-slots-list li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-1) var(--sp-5); padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); line-height: 1.4; }
.ind-slots-name { color: var(--text-bright); overflow-wrap: anywhere; }
.ind-slots-figs { color: var(--text-dim); }

/* The Character column shows only when the answer spans several characters. */
#capsuleer-industry.cap-solo .cap-char-col { display: none; }

/* A blueprint already in a job, and the small link inside a table cell. */
tr.ind-busy td { opacity: 0.7; }
.ind-link { display: inline-block; padding: var(--sp-1) 0; font-size: var(--fs-sm); color: var(--phosphor); }

@media (max-width: 1000px) {
  .ind-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 400px) {
  .ind-tiles { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .ind-fill { grid-template-columns: minmax(0, 1fr); }
  .ind-fill-add { min-height: 40px; }
  .ind-link { padding: var(--sp-4) 0; }
  .ind-timer { min-width: 0; align-items: flex-end; }
}
}
@layer pages {
/* Capsuleer assets (tools/capsuleer-assets.js): chip rows in the header, the
   figure tiles, the map fold, and the tables' task buttons. */
.cap-assets-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.cap-assets-group ~ button:not(.hotkey-chip) { margin-left: auto; }
.cap-assets-chip { min-height: 32px; }
.cap-assets-tiles .cap-tile:nth-child(2) { grid-column: auto; }
.cap-assets-filter { margin: var(--sp-4) 0 0; font-size: var(--fs-md); color: var(--amber); overflow-wrap: anywhere; }
.cap-assets-clear { min-height: 32px; padding: var(--sp-1) var(--sp-5); font-size: var(--fs-md); }
.cap-assets-actions .order-add-btn { min-height: 32px; }
.cap-assets-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-5); margin: var(--sp-3) 0; }
.cap-assets-actions .last-sync { flex: 1 1 200px; min-width: 0; margin: 0; }
.cap-assets-btn { min-height: 32px; margin: var(--sp-1) var(--sp-2) var(--sp-1) 0; white-space: nowrap; }
.cap-assets-btn:disabled { opacity: 0.4; cursor: default; }
.cap-assets-tasks { white-space: normal; }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { .cap-assets-tasks .cap-assets-btn { display: block; width: 100%; margin: var(--sp-1) 0; } }
#capsuleer-assets td[data-label="Located at"], #capsuleer-assets td[data-label="System"], #capsuleer-assets td[data-label="Item"] { text-align: left; }
/* Column widths on a desktop, so a long station name wraps instead of
   squeezing the item column to a letter wide; a phone shows each row as a card. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #capsuleer-assets-sell-table :is(th, td):nth-child(1) { min-width: 130px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(2) { min-width: 50px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(3) { min-width: 160px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(4) { min-width: 80px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(5) { min-width: 140px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(6) { min-width: 130px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(7) { min-width: 160px; }
  #capsuleer-assets-sell-table :is(th, td):nth-child(8) { min-width: 64px; }
  #capsuleer-assets-places-table :is(th, td):nth-child(1) { min-width: 220px; }
  #capsuleer-assets-ships-table :is(th, td):nth-child(1) { min-width: 140px; }
  #capsuleer-assets-ships-table :is(th, td):nth-child(2) { min-width: 200px; }
}
/* The Character column shows only when the answer spans several characters. */
#capsuleer-assets-body.cap-solo .cap-char-col { display: none; }
#capsuleer-assets tbody tr[data-i], #capsuleer-assets tbody tr[data-place], #capsuleer-assets tbody tr[data-category] { cursor: pointer; }
#capsuleer-assets .cap-assets-map-fold .eve-map { margin-top: var(--sp-2); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-assets-actions .order-add-btn { min-height: 36px; }
}
}
@layer pages {
/* Capsuleer contracts (tools/capsuleer-contracts.js): the figure tiles, the
   item lists in a row and the task buttons; the chip rows are Orders' (the
   .cap-con-controls rules in capsuleer-orders.css). */
.cap-con-chip { min-height: 32px; }
.cap-con-chip-n { color: var(--text-dim); }
.cap-con-chip.active .cap-con-chip-n { color: inherit; }
.cap-con-tiles .cap-tile:nth-child(2) { grid-column: auto; }
.cap-con-btn { min-height: 32px; margin: var(--sp-1) var(--sp-2) var(--sp-1) 0; white-space: nowrap; }
.cap-con-btn:disabled { opacity: 0.4; cursor: default; }
.cap-con-tasks { white-space: normal; }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { .cap-con-tasks .cap-con-btn { display: block; width: 100%; margin: var(--sp-1) 0; } }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { #capsuleer-contracts :is(td[data-label="Contract"], td[data-label="Located at"], td[data-label="Route"]) { text-align: left; } }
.cap-con-internal { display: inline-block; padding: 0 var(--sp-3); font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); border: 1px solid var(--edge); vertical-align: middle; }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { #capsuleer-contracts .cap-char-col { min-width: 110px; text-align: left; } }
.cap-con-items { margin-top: var(--sp-1); font-size: var(--fs-md); }
.cap-con-items summary { display: inline-flex; align-items: center; min-height: 32px; padding: var(--sp-1) 0; cursor: pointer; color: var(--mint-dim); }
.cap-con-items ul { margin: var(--sp-1) 0 0; padding: 0 0 0 var(--sp-6); list-style: none; }
.cap-con-items li { padding: 1px 0; overflow-wrap: anywhere; }
/* Column widths on a desktop, so a long title or station wraps instead of
   squeezing a neighbour; a phone shows each row as a card. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #capsuleer-contracts-ex-table :is(th, td):nth-child(1), #capsuleer-contracts-co-table :is(th, td):nth-child(1) { min-width: 190px; }
  #capsuleer-contracts-ex-table :is(th, td):nth-child(2), #capsuleer-contracts-co-table :is(th, td):nth-child(2) { min-width: 120px; }
  #capsuleer-contracts-ex-table :is(th, td):nth-child(3) { min-width: 170px; }
  #capsuleer-contracts-co-table :is(th, td):nth-child(3) { min-width: 190px; }
  #capsuleer-contracts-co-table :is(th, td):nth-child(4) { min-width: 120px; }
  #capsuleer-contracts-co-table :is(th, td):nth-child(6) { min-width: 130px; }
}
#capsuleer-contracts-co-body tr[data-key] { cursor: pointer; }
#capsuleer-contracts .route-map-fold { margin-top: var(--sp-5); }
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-con-btn { min-height: 36px; }
  #capsuleer-contracts td:first-child[data-label="Contract"] {
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-4);
    font-size: 13.5px;
    border-bottom-color: rgba(0, 255, 136, 0.22);
  }
  #capsuleer-contracts td:first-child[data-label="Contract"]::before { content: none; }
  #capsuleer-contracts td:first-child[data-label="Contract"] .cell-note { font-size: var(--fs-sm); font-weight: 400; }
}
}
@layer pages {
/* Capsuleer planets (tools/capsuleer-planets.js): chip row, tiles, the meters
   for programs and stores, and the item lists. */
.cap-pl-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.cap-pl-group ~ button:not(.hotkey-chip) { margin-left: auto; }
.cap-pl-chip { min-height: 32px; }
.cap-pl-chip-n { color: var(--text-dim); }
.cap-pl-chip.active .cap-pl-chip-n { color: inherit; }
.cap-pl-tiles .cap-tile:nth-child(2) { grid-column: auto; }
.cap-pl-btn { min-height: 32px; white-space: nowrap; }
.cap-pl-btn:disabled { opacity: 0.4; cursor: default; }
.cap-meter { display: inline-block; vertical-align: middle; width: 72px; height: 8px; background: rgba(125, 255, 178, 0.12); border: 1px solid var(--edge); }
.cap-meter > i { display: block; height: 100%; background: var(--phosphor); }
.cap-meter.full > i { background: var(--amber); }
.cap-pl-who { display: inline-block; font-size: var(--fs-sm); font-weight: 400; color: var(--mint-dim); overflow-wrap: anywhere; }
.cap-pl-items { font-size: var(--fs-md); }
.cap-pl-items summary { display: inline-flex; align-items: center; min-height: 32px; padding: var(--sp-1) 0; cursor: pointer; color: var(--mint-dim); }
.cap-pl-items ul { margin: var(--sp-1) 0 0; padding: 0 0 0 var(--sp-6); list-style: none; }
.cap-pl-items li { padding: 1px 0; overflow-wrap: anywhere; }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { #capsuleer-planets :is(td[data-label="Extractor"], td[data-label="Colony"], td[data-label="Product"], td[data-label="Structure"], td[data-label="Contents"], td[data-label="Status"], td[data-label="Factories"]) { text-align: left; } }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #capsuleer-planets-timers-table :is(th, td):nth-child(1) { min-width: 140px; }
  #capsuleer-planets-timers-table :is(th, td):nth-child(2) { min-width: 130px; }
  #capsuleer-planets-timers-table :is(th, td):nth-child(6) { min-width: 150px; }
  #capsuleer-planets-timers-table :is(th, td):nth-child(7) { min-width: 140px; }
  #capsuleer-planets-colonies-table :is(th, td):nth-child(1) { min-width: 170px; }
  #capsuleer-planets-colonies-table :is(th, td):nth-child(2) { min-width: 140px; }
  #capsuleer-planets-colonies-table :is(th, td):nth-child(4) { min-width: 190px; }
  #capsuleer-planets-colonies-table :is(th, td):nth-child(5) { min-width: 150px; }
  #capsuleer-planets-storage-table :is(th, td):nth-child(1) { min-width: 190px; }
  #capsuleer-planets-storage-table :is(th, td):nth-child(2) { min-width: 160px; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-pl-btn { min-height: 36px; }
  #capsuleer-planets td:first-child.cap-pl-title {
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-4);
    font-size: 13.5px;
    border-bottom-color: rgba(0, 255, 136, 0.22);
  }
  #capsuleer-planets td:first-child.cap-pl-title::before { content: none; }
  #capsuleer-planets td:first-child.cap-pl-title .cell-note, #capsuleer-planets td:first-child.cap-pl-title .filter-count { font-size: var(--fs-sm); font-weight: 400; }
}
}
@layer pages {
/* Capsuleer mining (tools/capsuleer-mining.js): the option chips and number
   fields in the header, the tiles, the hours field of a day and the marks. */
.cap-mi-group { flex: 1 1 auto; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.cap-mi-chip { min-height: 32px; }
.cap-mi-tiles .cap-tile:nth-child(2) { grid-column: auto; }
.cap-mi-best { display: inline-block; padding: 0 var(--sp-3); font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #000; background: var(--phosphor); }
.cap-mi-hours { width: 78px; min-height: 32px; padding: var(--sp-1) var(--sp-3); text-align: right; }
#capsuleer-mining .cap-meter { display: inline-block; width: 56px; vertical-align: middle; height: 8px; background: rgba(125, 255, 178, 0.12); border: 1px solid var(--edge); }
#capsuleer-mining .cap-meter > i { display: block; height: 100%; background: var(--phosphor); }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { #capsuleer-mining .cap-char-col { min-width: 110px; text-align: left; } }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) { #capsuleer-mining :is(td[data-label="Ore"], td[data-label="System"], td[data-label="Day"]) { text-align: left; } }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #capsuleer-mining-ore-table :is(th, td):nth-child(1), #capsuleer-mining-market-table :is(th, td):nth-child(1) { min-width: 170px; }
  #capsuleer-mining-ore-table :is(th, td):nth-child(3), #capsuleer-mining-ore-table :is(th, td):nth-child(4) { min-width: 120px; }
  #capsuleer-mining-ore-table :is(th, td):nth-child(5) { min-width: 190px; }
  #capsuleer-mining-day-table :is(th, td):nth-child(3) { min-width: 150px; }
  #capsuleer-mining-system-table :is(th, td):nth-child(1) { min-width: 150px; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-mi-hours { width: 96px; min-height: 36px; }
  #capsuleer-mining td:first-child.cap-mi-title {
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-4);
    font-size: 13.5px;
    border-bottom-color: rgba(0, 255, 136, 0.22);
  }
  #capsuleer-mining td:first-child.cap-mi-title::before { content: none; }
  #capsuleer-mining td:first-child.cap-mi-title .cell-note { font-size: var(--fs-sm); font-weight: 400; }
}
}
@layer pages {
/* Capsuleer LP & skills (tools/capsuleer-skills.js): the tiles of the two
   parts, the tags that mark a figure recorded or estimated, and the "How"
   cell of a skill. The shared tile and table looks are capsuleer.css and
   tables.css; a phone shows each row as a card through phone.css. */
.csk-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.csk-tiles .cap-tile:nth-child(2) { grid-column: auto; }
/* The Character column shows only when the answer spans several characters. */
#capsuleer-skills.cap-solo .cap-char-col { display: none; }
.csk-actions { margin: var(--sp-2) 0 var(--sp-4); }
.csk-actions .order-add-btn { min-height: 32px; }

.csk-lvl { color: var(--phosphor); white-space: nowrap; }
.csk-tag { display: inline-block; padding: 0 var(--sp-2); font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; vertical-align: 1px; border: 1px solid currentColor; cursor: help; }
.csk-est { color: var(--amber); }
.csk-rec { color: var(--phosphor); }
.csk-queued { color: var(--mint-dim); }

.csk-how { margin-top: var(--sp-1); }
.csk-how summary { display: inline-block; padding: var(--sp-1) 0; font-size: var(--fs-sm); color: var(--phosphor); cursor: pointer; }
.csk-how > .filter-count { display: block; margin: var(--sp-1) 0; line-height: 1.45; }
.csk-inputs { list-style: none; margin: var(--sp-2) 0 0; padding: 0; font-size: var(--fs-sm); line-height: 1.5; }
.csk-inputs li { display: flex; justify-content: space-between; gap: var(--sp-5); padding: 1px 0; border-bottom: 1px solid var(--row-line); }
.csk-input-label { color: var(--text-dim); min-width: 0; overflow-wrap: anywhere; }
#capsuleer-skills-skills-table td:is([data-label="How"], [data-label="Effect"], [data-label="Skill"]),
#capsuleer-skills-skills-table th:is([data-key="how"], [data-key="effect"], [data-key="name"]),
#capsuleer-skills-stores-table td[data-label="Best offer"],
#capsuleer-skills-stores-table th[data-key="best_name"],
#capsuleer-skills-offers-table td:is([data-label="Required items"], [data-label="Sell at"]) { text-align: left; }
#capsuleer-skills-skills-table td[data-label="How"] { min-width: 220px; max-width: 360px; white-space: normal; }
#capsuleer-skills-skills-table td[data-label="Effect"] { min-width: 150px; white-space: normal; }
#capsuleer-skills-stores-table td[data-label="Best offer"] { min-width: 180px; white-space: normal; }
#capsuleer-skills-offers-table td[data-label="Item"] { min-width: 150px; }

@media (max-width: 1000px) {
  .csk-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  #capsuleer-skills-skills-table td[data-label="How"],
  #capsuleer-skills-skills-table td[data-label="Effect"],
  #capsuleer-skills-stores-table td[data-label="Best offer"],
  #capsuleer-skills-offers-table td[data-label="Item"] { min-width: 0; max-width: none; }
  .csk-actions .order-add-btn { min-height: 40px; width: 100%; }
  .csk-how summary { padding: var(--sp-5) 0; }
}
@media (max-width: 400px) {
  .csk-tiles { grid-template-columns: minmax(0, 1fr); }
}
}
@layer pages {
/* The logged-in pilot behind the site's own pages (pilot.js): the marker on
   the Trade settings button, the bar at the top of the panel and the small
   notes under a figure that comes from the pilot. */
.pilot-tag { display: inline-block; padding: 0 var(--sp-3); font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--phosphor); border: 1px solid var(--phosphor); }
.settings-btn.pilot-on::after { content: "Pilot"; padding: 0 var(--sp-2); font-size: 10px; letter-spacing: 0.1em; color: var(--phosphor); border: 1px solid var(--phosphor); }
.settings-pilot { margin: 0 0 var(--sp-6); padding: var(--sp-4) var(--sp-5); font-size: var(--fs-sm); line-height: 1.55; color: var(--text-bright); background: rgba(0, 255, 136, 0.05); border: 1px solid var(--edge); border-left: 3px solid var(--phosphor); overflow-wrap: anywhere; }
.settings-pilot[data-pilot="manual"], .settings-pilot[data-pilot="none"] { border-left-color: var(--edge); color: var(--text-dim); }
.settings-pilot a { color: var(--phosphor); text-decoration: underline; }
.settings-pilot .settings-chip { margin-top: var(--sp-3); min-height: 32px; }
.settings-grid :is(select, input):disabled { opacity: 0.7; border-style: dashed; }
.pilot-note { color: var(--phosphor); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .settings-pilot .settings-chip { min-height: 40px; }
}
}
@layer pages {
/* Capsuleer corp (tools/capsuleer-corp.js): the role access list, the gate
   notice a part shows when the character lacks its role, tiles in an
   auto-fit grid, the fuel timeline and the small lists. The tile, bar, chart
   and table looks are the shared ones (capsuleer.css, capsuleer-ledger.css). */
.capc-bar { align-items: center; }
.capc-bar .hotkey-chip-list { flex: 0 0 auto; }
.capc-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--sp-4); margin-top: var(--sp-4); }
.capc-tiles:empty { display: none; }
.capc-tiles .cap-tile:nth-child(2) { grid-column: auto; }
.capc-need { margin-left: var(--sp-3); font-size: var(--fs-sm); letter-spacing: 0; text-transform: none; color: var(--text-dim); }
.capc-window { margin-left: var(--sp-3); font-size: var(--fs-sm); letter-spacing: 0; text-transform: none; color: var(--text-dim); }
.capc-sub { margin-top: var(--sp-6); }
.capc-table { margin-top: var(--sp-3); }
.capc-gate { margin: var(--sp-3) 0; padding: var(--sp-4) var(--sp-5); font-size: var(--fs-md); line-height: 1.5; color: var(--amber); border: 1px solid var(--amber); border-left-width: 4px; background: rgba(255, 176, 0, 0.07); overflow-wrap: anywhere; }
.capc-gate a { color: var(--amber); text-decoration: underline; }

/* Roles and what each part needs. */
.capc-access { margin: var(--sp-3) 0 var(--sp-2); }
.capc-roles { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-5); font-size: var(--fs-md); color: var(--text-dim); }
.capc-roles .cap-chips { margin-top: 0; }
.capc-access-list { list-style: none; margin: var(--sp-4) 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 0 var(--sp-7); }
.capc-access-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 var(--sp-5); padding: var(--sp-2) 0 var(--sp-2) var(--sp-4); border-bottom: 1px solid var(--row-line); border-left: 3px solid var(--phosphor); font-size: var(--fs-md); line-height: 1.4; }
.capc-access-list li.capc-miss { border-left-color: var(--amber); }
.capc-access-name { color: var(--text-bright); overflow-wrap: anywhere; }
.capc-access-need { grid-column: 1; color: var(--text-dim); overflow-wrap: anywhere; }
.capc-access-state { grid-column: 2; grid-row: 1; align-self: start; text-align: right; color: var(--phosphor); white-space: nowrap; }
.capc-miss .capc-access-state { color: var(--amber); }

/* Fuel timeline: one row per structure, the bar as long as the fuel lasts. */
.capc-timeline { margin: var(--sp-3) 0; }
.capc-tl-row { display: grid; grid-template-columns: minmax(110px, 26%) minmax(0, 1fr) minmax(130px, 34%); gap: var(--sp-5); align-items: center; padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); }
.capc-tl-name { color: var(--text-bright); overflow-wrap: anywhere; }
.capc-tl-label { color: var(--text-dim); overflow-wrap: anywhere; }
.capc-tl-track { position: relative; display: block; height: 12px; background: rgba(255, 255, 255, 0.04); border: 1px solid var(--edge); }
.capc-bar-fill { position: absolute; left: 0; top: 0; bottom: 0; display: block; background: var(--phosphor); }
.capc-bar-fill.capc-amber { background: var(--amber); }
.capc-bar-fill.capc-red { background: var(--red); }
.capc-tl-mark { position: absolute; top: -2px; bottom: -2px; width: 0; border-left: 1px dashed var(--text-dim); }
.capc-tl-axis { border-bottom: none; padding-bottom: 0; color: var(--text-dim); font-size: var(--fs-sm); }
.capc-tl-ticks { height: 14px; background: none; border: none; }
.capc-tl-ticks span { position: absolute; top: 0; transform: translateX(-50%); }

.capc-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.capc-list li { display: grid; grid-template-columns: minmax(130px, 26%) minmax(0, 1fr); gap: 0 var(--sp-6); padding: var(--sp-3) 0; border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); line-height: 1.45; }
.capc-list-name { color: var(--text-bright); overflow-wrap: anywhere; }
.capc-list-detail { color: var(--text-dim); overflow-wrap: anywhere; }
.capc-list .capl-none { grid-column: 1 / -1; }

/* Moon mining settings. */
.capc-inputs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-4) var(--sp-6); margin: var(--sp-4) 0; }
.capc-inputs label { display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--fs-sm); letter-spacing: 0.04em; text-transform: uppercase; color: var(--mint-dim); }
.capc-inputs input { width: 130px; min-height: 32px; }
.capc-fold { margin-top: var(--sp-6); }
.capc-fold > summary { cursor: pointer; padding: var(--sp-3) 0; font-size: var(--fs-md); color: var(--mint-dim); }
.capc-fold[hidden] { display: none; }
#capsuleer-corp .fc-plot { margin-bottom: var(--sp-2); }

/* The phone layout (the query pagination.js names PHONE_MEDIA_QUERY). */
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .capc-bar button, .capc-bar .hotkey-chip, .capc-inputs button { min-height: 36px; }
  .capc-inputs input { min-height: 36px; }
  .capc-tl-row { grid-template-columns: minmax(0, 1fr); gap: var(--sp-1); }
  .capc-tl-axis .capc-tl-name, .capc-tl-axis .capc-tl-label { display: none; }
  .capc-list li { grid-template-columns: minmax(0, 1fr); gap: var(--sp-1); }
  .capc-access-list { grid-template-columns: minmax(0, 1fr); }
  .capc-fold > summary { padding: var(--sp-5) 0; }
}
@media (max-width: 400px) {
  .capc-tiles { grid-template-columns: minmax(0, 1fr); }
  .capc-inputs label, .capc-inputs input { width: 100%; }
}
}
@layer pages {
/* Capsuleer automation (tools/capsuleer-automation.js): the watcher, channel
   and report cards, the forms that edit them, the digest preview and the box
   of what the site never does. */
.cap-auto-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-4); margin: var(--sp-3) 0; }
.cap-auto-actions .order-add-btn, .cap-auto-buttons .order-add-btn, .cap-auto-preview .order-add-btn { min-height: 32px; }
.cap-auto-actions .cap-note { flex: 1 1 200px; min-width: 0; }
.cap-auto-controls { margin: var(--sp-3) 0; }
.cap-auto-chip { min-height: 32px; }

.cap-auto-list { display: grid; gap: var(--sp-4); }
.cap-auto-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-4) var(--sp-6); align-items: start; min-width: 0; padding: var(--sp-4) var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); border-left-width: 3px; border-left-color: var(--phosphor); }
.cap-auto-off { border-left-color: var(--edge); opacity: 0.8; }
.cap-auto-main { min-width: 0; }
.cap-auto-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-4); color: var(--text-bright); overflow-wrap: anywhere; }
.cap-auto-badge { display: inline-block; padding: 0 var(--sp-3); font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em; color: var(--text-dim); border: 1px solid currentColor; }
.cap-auto-on { color: var(--phosphor); }
.cap-auto-facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--sp-2) var(--sp-6); margin: var(--sp-3) 0 0; }
.cap-auto-facts > div { min-width: 0; }
.cap-auto-facts dt { font-size: var(--fs-sm); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.cap-auto-facts dd { margin: 0; font-size: var(--fs-md); line-height: 1.4; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-auto-buttons { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2); }
.cap-auto-buttons .order-add-btn:disabled { opacity: 0.4; cursor: default; }

.cap-auto-form { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; margin: var(--sp-4) 0; padding: var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); }
.cap-auto-form-title { margin: 0; font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.cap-auto-group { flex: 1 1 100%; min-width: 0; align-items: center; }
.cap-auto-fields { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-6); }
.cap-auto-field { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; font-size: var(--fs-md); color: var(--text-label, var(--text-dim)); }
.cap-auto-wide { flex: 1 1 320px; }
.cap-auto-input { display: flex; align-items: center; gap: var(--sp-3); }
.cap-auto-input input { box-sizing: border-box; width: 9em; max-width: 100%; min-height: 32px; padding: var(--sp-1) var(--sp-4); font: inherit; font-size: var(--fs-lg); color: var(--text-bright); background: var(--input-bg); border: 1px solid var(--edge); }
.cap-auto-input input[type="text"] { width: 16em; }
.cap-auto-wide .cap-auto-input input { width: 100%; }
.cap-auto-input input:focus-visible { outline: 1px solid var(--phosphor); outline-offset: 1px; }
.cap-auto-unit { font-size: var(--fs-md); color: var(--text-dim); }

.cap-auto-preview { margin: var(--sp-4) 0; padding: var(--sp-5); background: var(--screen-bg); border: 1px solid var(--phosphor); }
.cap-auto-preview-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--sp-3) var(--sp-5); color: var(--text-bright); overflow-wrap: anywhere; }
.cap-auto-lines { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.cap-auto-detail { white-space: pre-line; }

.cap-never { margin: var(--sp-7) 0 var(--sp-3); padding: var(--sp-5) var(--sp-6); background: rgba(255, 176, 0, 0.05); border: 1px solid var(--amber); border-left-width: 4px; }
.cap-never-title { margin: 0 0 var(--sp-2); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--amber); }
.cap-never ul { margin: var(--sp-2) 0; padding-left: var(--sp-7); }
.cap-never li { margin: var(--sp-1) 0; font-size: var(--fs-md); line-height: 1.5; color: var(--text-bright); overflow-wrap: anywhere; }
.cap-never-sources { list-style: none; margin: var(--sp-1) 0 0; padding: 0; }
.cap-never-sources li { margin: 0; padding: 0; font-size: var(--fs-md); line-height: 1.5; color: var(--text-dim); }
.cap-never a { display: inline-block; padding: var(--sp-2) 0; color: var(--phosphor); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .cap-auto-card { grid-template-columns: minmax(0, 1fr); }
  .cap-auto-buttons { justify-content: flex-start; }
  .cap-auto-actions .order-add-btn, .cap-auto-buttons .order-add-btn, .cap-auto-preview .order-add-btn { min-height: 36px; }
  .cap-auto-chip { min-height: 36px; }
  .cap-auto-input input { min-height: 36px; }
  .cap-auto-field { flex: 1 1 100%; }
  .cap-auto-input input[type="number"] { width: 7em; }
  .cap-auto-input input[type="text"] { width: 100%; }
  .cap-never a, #capsuleer-automation .cap-alert-title a { display: inline-block; padding: var(--sp-4) 0; }
}
}
@layer pages {
/* Account (tools/account.js): tiles, tables and the payment steps. The tile,
   notice and demo looks are the shared Capsuleer ones (capsuleer.css). */
/* Account text that exists only while EVE SSO is on (pageShell.ts) stays out of sight until then. */
[data-sso-only][hidden], [data-sso-off][hidden] { display: none; }
#account .cap-tiles { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
#account .cap-tile-value { overflow-wrap: anywhere; }
#account .cap-tile .cap-note + .cap-note { margin-top: var(--sp-2); }
.acc-notice { margin: var(--sp-4) 0; padding: var(--sp-4) var(--sp-5); font-size: var(--fs-md); line-height: 1.5; }
.acc-table { margin-top: var(--sp-3); }
#account .cap-title { margin-top: var(--sp-7); }
#account .cap-count { margin-left: var(--sp-3); font-size: var(--fs-sm); letter-spacing: 0; text-transform: none; color: var(--text-dim); }

/* A link that looks like a terminal button. */
.acc-button { display: inline-block; padding: var(--sp-4) var(--sp-6); min-height: 32px; box-sizing: border-box; color: var(--mint); border: 1px solid var(--edge); border-radius: 2px; background: rgba(0, 255, 136, 0.02); font: 700 11px var(--mono); text-transform: uppercase; letter-spacing: 0.1em; text-decoration: none; }
.acc-button:hover { background: rgba(0, 255, 136, 0.08); border-color: var(--phosphor); color: var(--phosphor); }
#account button { min-height: 32px; }
#account button:disabled { opacity: 0.45; cursor: not-allowed; }

.acc-tag { width: 9em; min-height: 32px; box-sizing: border-box; }
.acc-steps { margin: var(--sp-4) 0; padding-left: var(--sp-7); font-size: var(--fs-md); line-height: 1.6; color: var(--text-bright); }
.acc-steps li { margin: var(--sp-2) 0; overflow-wrap: anywhere; }
.acc-corps { margin: var(--sp-3) 0; padding-left: var(--sp-7); font-size: var(--fs-md); line-height: 1.6; color: var(--text-bright); }
.acc-corps li { overflow-wrap: anywhere; }

@media (max-width: 768px) {
  #account .cap-tiles { grid-template-columns: minmax(0, 1fr); }
  .acc-tag { width: 100%; max-width: 12em; }
  #account p > button, #account p > .acc-button { margin: var(--sp-1) var(--sp-2) var(--sp-1) 0; }
}
}
@layer pages {
/* Admin: ISK payments (admin/billing.js). The summary tiles are the data
   budget's; this adds the alarm, the status tabs and the action cells. */
#billing[hidden] { display: none; }
.billing-alarm { margin: 6px 0 10px; padding: 8px 10px; font-size: 12px; line-height: 1.5; color: var(--text-bright); border: 1px solid var(--red); border-left-width: 4px; background: rgba(255, 64, 64, 0.08); overflow-wrap: anywhere; }
.billing-alarm strong { color: var(--red); letter-spacing: 0.1em; }
.billing-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.billing-tabs button { min-height: 32px; }
.billing-notefield { margin: 6px 0; font-size: 12px; }
.billing-notefield input { width: min(420px, 100%); }
.billing-target { width: 12em; min-height: 32px; box-sizing: border-box; }
.billing-actions { white-space: normal; }
.billing-actions button { min-height: 32px; margin: 2px 2px 2px 0; }
}
@layer pages {
/* Admin: backups (admin/admin.js). The delete button, or the reason a row
   has none, sits beside the download link; the keep-newest control is one
   line that wraps on a phone. */
.backup-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-5); margin: var(--sp-3) 0; font-size: var(--fs-md); }
.backup-tools input { width: 5em; min-height: 32px; box-sizing: border-box; }
.backup-tools button, .backup-actions button { min-height: 32px; }
.backup-actions { white-space: normal; }
.backup-actions button { margin-left: var(--sp-3); }
.backup-lock { margin-left: var(--sp-3); font-size: var(--fs-sm); color: var(--text-dim); }
#backups-body td:first-child { overflow-wrap: anywhere; }
}
@layer pages {
/* The Mining pages (tools/mining*.js): the hub breakdown and place lists in a
   board row, the hull picker, the type fold of the map, the answer line each
   page opens with, the how-to steps and the source notes. */
.mining-chip { min-height: 32px; }
.mining-title { margin: var(--sp-5) 0 var(--sp-2); font-size: var(--fs-md); }
.mining-count { font-weight: 400; color: var(--text-dim); }
.mining-best { font-weight: 700; color: var(--phosphor); }
.mining-tag { display: inline-block; padding: 0 var(--sp-3); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; border: 1px solid var(--edge); color: var(--text-dim); }
.mining-more { margin-top: var(--sp-2); }
.mining-more > summary { cursor: pointer; font-size: var(--fs-sm); color: var(--phosphor); min-height: 32px; display: inline-flex; align-items: center; }
.mining-hubs { display: grid; gap: 1px; margin: var(--sp-2) 0; min-width: 0; }
.mining-hubrow { display: grid; grid-template-columns: 4.5em repeat(3, minmax(0, 1fr)); gap: var(--sp-3); padding: var(--sp-1) 0; border-bottom: 1px solid var(--edge); font-size: var(--fs-sm); }
.mining-hubhead { font-weight: 700; color: var(--text-dim); }
.mining-where-title { margin: var(--sp-3) 0 var(--sp-1); font-size: var(--fs-sm); font-weight: 700; }
.mining-where, .mining-assumptions { margin: 0 0 var(--sp-3); padding-left: 1.2em; font-size: var(--fs-sm); }
.mining-where li, .mining-assumptions li { margin: 2px 0; }
.mining-sources { margin: var(--sp-4) 0; }
.mining-sources > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; font-size: var(--fs-sm); color: var(--phosphor); }
.mining-source { margin: 0 0 var(--sp-4); }
.mining-source p { margin: 0 0 var(--sp-1); }
.mining-pick { min-height: 32px; margin-top: var(--sp-2); }
/* The hull shown below: lit like a chip that is on, not the browser's grey. */
.mining-pick:disabled { color: var(--phosphor); border-color: var(--phosphor); background: var(--phos-a10); cursor: default; }
.mining-igrow { grid-template-columns: minmax(7em, 1.4fr) repeat(3, minmax(0, 1fr)); }
.mining-filterfold { flex: 1 1 100%; min-width: 0; }
.mining-filterfold > summary { cursor: pointer; min-height: 32px; display: inline-flex; align-items: center; font-size: var(--fs-sm); color: var(--phosphor); }
.mining-filters { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); margin-top: var(--sp-2); }
.mining-map-frame .eve-map { height: clamp(320px, 64vh, 680px); }
.mining-bestnow { margin: var(--sp-3) 0; padding: var(--sp-3) var(--sp-5); border-left: 3px solid var(--phosphor); background: rgba(0, 255, 136, 0.06); font-size: var(--fs-md); line-height: 1.5; overflow-wrap: anywhere; }
.mining-bestnow[hidden] { display: none; }
.mining-bestnow strong { color: var(--text-bright); }
.mining-bestnow .route-link { margin: 0 var(--sp-2) 0 0; padding: 0 var(--sp-1); }
.mining-steps { margin: var(--sp-2) 0 var(--sp-3); padding-left: 1.5em; font-size: var(--fs-sm); line-height: 1.5; }
.mining-steps li { margin: 2px 0; }
.mining-only { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); margin: var(--sp-2) 0; font-size: var(--fs-sm); }
.mining-only[hidden] { display: none; }
.mining-only button { min-height: 32px; }
.mining-page .eve-map-legend { gap: var(--sp-1) var(--sp-5); }
.mining-page .eve-map-legend i { width: 11px; height: 11px; }
.eve-map-legend .mining-legend-title { flex: 1 0 100%; white-space: normal; color: var(--text); }
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .mining-page :is(td.mining-name, th:first-child) { text-align: left; min-width: 260px; }
  #mining-board-table :is(th, td):nth-child(n+2), #mining-ig-table :is(th, td):nth-child(n+2) { min-width: 110px; }
  #mining-yield-table :is(th, td):nth-child(4) { min-width: 240px; }
  /* A header over figures that sit to the right of their column sits there too. */
  :is(#mining-hull-table, #mining-yield-table, #mining-ig-table, #mining-board-table) th:nth-child(n+2) .th-sort-btn { text-align: right; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .mining-hubrow { grid-template-columns: 3.6em repeat(3, minmax(0, 1fr)); gap: var(--sp-2); font-size: var(--fs-xs); }
  .mining-igrow { grid-template-columns: 5em repeat(3, minmax(0, 1fr)); }
  .mining-page td:first-child.mining-name { padding-top: var(--sp-4); padding-bottom: var(--sp-4); font-size: 13.5px; border-bottom-color: rgba(0, 255, 136, 0.22); }
  .mining-page td:first-child.mining-name::before { content: none; }
  .mining-map-frame .eve-map { height: clamp(300px, 58vh, 520px); }
  .mining-bestnow .route-link { display: inline-flex; align-items: center; min-height: 32px; }
}
}
@layer pages {
/* Fight calendar (tools/fight-calendar.js): the chip rows in the header, a
   strip of the next seven days on a desktop, then the entries in groups. A
   kind has one colour (--k) in its tag, its marks and its row's edge. */
.fc-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.fc-chip { min-height: 32px; }
.fc-chip-short { display: none; }
.fc-n { color: var(--text-dim); font-weight: 400; }
.fc-chip.active .fc-n { color: inherit; }
.fc-k-sov { --k: var(--hub-forge); }
.fc-k-war { --k: var(--red); }
.fc-k-fw { --k: var(--amber); }
.fc-k-incursion { --k: #c08cff; }
.fc-k-wormhole { --k: var(--hub-sinq); }

.fc-strip { margin: var(--sp-4) 0 var(--sp-5); padding: var(--sp-4) var(--sp-6) var(--sp-3); border: 1px solid var(--panel-border); background: var(--panel-bg); }
.fc-strip[hidden] { display: none; }
.fc-axis, .fc-lane { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: var(--sp-5); align-items: start; }
.fc-axis { height: 18px; }
.fc-axis-name, .fc-lane-name { font-size: var(--fs-sm); color: var(--text-label); text-transform: uppercase; letter-spacing: 0.06em; line-height: 18px; }
.fc-axis-track, .fc-lane-track { position: relative; min-width: 0; }
.fc-axis-track { height: 18px; }
.fc-lane { margin-top: var(--sp-2); }
.fc-lane-track { height: 100%; border-top: 1px solid var(--row-line); background: repeating-linear-gradient(90deg, transparent 0, transparent calc(100% / 7 - 1px), var(--row-line) calc(100% / 7 - 1px), var(--row-line) calc(100% / 7)); }
.fc-day { position: absolute; top: 0; padding-left: var(--sp-2); border-left: 1px solid var(--line); font-size: var(--fs-xs); line-height: 18px; color: var(--text-dim); white-space: nowrap; }
.fc-day.fc-now { color: var(--text); border-left-color: var(--phosphor); }
.fc-mark { position: absolute; width: 10px; height: 10px; margin: 4px 0 0 -5px; padding: 0; min-width: 0; min-height: 0; border: 1px solid var(--k); background: var(--k); box-shadow: 0 0 6px var(--k); cursor: pointer; }
.fc-mark::after { content: ""; position: absolute; inset: -8px; }
.fc-mark:hover, .fc-mark:focus-visible { outline: 1px solid var(--text-bright); outline-offset: 2px; }

.fc-section > h3 { margin: var(--sp-7) 0 var(--sp-2); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.fc-section > ul { list-style: none; margin: 0; padding: 0; }
.fc-item {
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr) 220px auto;
  gap: var(--sp-2) var(--sp-7);
  align-items: start;
  padding: var(--sp-4) var(--sp-5);
  border-left: 3px solid var(--k);
  border-bottom: 1px solid var(--row-line);
}
.fc-item.fc-ended { opacity: 0.6; }
.fc-item.fc-flash { background: var(--phos-a20); }
.fc-when { display: flex; flex-direction: column; min-width: 0; }
.fc-when strong { color: var(--text-bright); font-size: var(--fs-lg); }
.fc-stamp { font-size: var(--fs-xs); color: var(--text-dim); }
.fc-what { min-width: 0; overflow-wrap: anywhere; }
.fc-what > strong { color: var(--text-bright); }
.fc-what p { margin: var(--sp-1) 0 0; font-size: var(--fs-md); color: var(--text-label); line-height: 1.4; }
.fc-tag { display: inline-block; padding: 0 var(--sp-3); margin-right: var(--sp-2); border: 1px solid var(--k); color: var(--k); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; }
.fc-where { min-width: 0; font-size: var(--fs-md); overflow-wrap: anywhere; }
.fc-system { color: var(--text-bright); }
.fc-region { color: var(--text-dim); }
.fc-links { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-5); justify-content: flex-end; align-items: center; min-width: 0; }
.fc-links .route-link { margin: 0; padding: 9px 4px; }
.fc-meter { display: inline-block; width: 64px; height: 6px; margin-left: var(--sp-4); border: 1px solid var(--line); vertical-align: middle; }
.fc-meter > i { display: block; height: 100%; background: var(--k); }
.fc-more { margin-top: var(--sp-3); min-height: 32px; }

@media (max-width: 1100px) {
  .fc-item { grid-template-columns: 130px minmax(0, 1fr) auto; }
  .fc-where { grid-column: 2; }
  .fc-links { grid-column: 3; grid-row: 1 / span 2; flex-direction: column; align-items: flex-end; }
}

/* A desktop's chip rows share a line. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .fc-group { flex: 0 1 auto; margin: 0 var(--sp-6) 0 0; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .fc-strip { display: none; }
  .fc-chip-long { display: none; }
  .fc-chip-short { display: inline; }
  .fc-item { grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-1) var(--sp-5); padding: var(--sp-4) var(--sp-4); }
  .fc-when { grid-column: 1; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-5); }
  .fc-what, .fc-where { grid-column: 1 / -1; }
  .fc-links { grid-column: 2; grid-row: 1; flex-direction: row; justify-content: flex-end; }
  .fc-links .route-link { padding: 10px 6px; }
}
}
@layer pages {
/* Ship loss (tools/ship-loss.js): the hull box, the fit paste fold, the
   insurance tier grid and the replacement list's header. */
#ship-loss .screen { overflow: visible; }
#ship-loss-hull {
  width: 100%;
  padding: var(--sp-6) var(--sp-6) var(--sp-6) 32px;
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: 14px;
}
#ship-loss-hull::placeholder, #ship-loss-fit::placeholder { color: var(--text-dim); }
#ship-loss-hull:focus, #ship-loss-fit:focus {
  outline: none;
  border-color: var(--phosphor);
  box-shadow: 0 0 0 1px var(--phos-a20), 0 0 10px rgba(0, 255, 136, 0.3);
}
#ship-loss .search-result-item .cell-note { margin-left: auto; }

.ship-loss-fit { margin: var(--sp-2) 0; }
.ship-loss-fit > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; font-size: var(--fs-sm); color: var(--phosphor); }
#ship-loss-fit {
  display: block;
  width: 100%;
  min-height: 9em;
  margin: var(--sp-2) 0;
  padding: var(--sp-4) var(--sp-6);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: 14px;
  resize: vertical;
}
.ship-loss-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.ship-loss-actions button { min-height: 32px; }
.ship-loss-actions .fit-lab-link { display: inline-flex; align-items: center; min-height: 32px; font-size: var(--fs-sm); }

.ship-loss-title { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); margin: var(--sp-4) 0 var(--sp-2); font-size: var(--fs-lg); }
.ship-loss-fitname { color: var(--text-dim); font-weight: 400; }
.ship-loss-sub { margin: 0; font-size: var(--fs-md); }
.ship-loss-count { font-weight: 400; color: var(--text-dim); }
.ship-loss-verdict { margin: var(--sp-3) 0; font-size: var(--fs-md); }
.ship-loss-parts-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); margin: var(--sp-4) 0 var(--sp-2); }
.ship-loss-parts-head .order-add-btn { min-height: 32px; }
.ship-loss-unknown { margin: var(--sp-3) 0; font-size: var(--fs-sm); }
.ship-loss-unknown > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--amber); }
.ship-loss-unknown ul { margin: 0 0 var(--sp-2); padding-left: 1.2em; overflow-wrap: anywhere; }

.ship-loss-tiers { margin: var(--sp-2) 0; font-size: var(--fs-sm); }
.sl-row { display: grid; grid-template-columns: minmax(8em, 1.3fr) repeat(5, minmax(0, 1fr)); gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--row-line); align-items: baseline; }
.sl-head { color: var(--mint-dim); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; border-bottom-color: var(--line); }
.sl-row > span:nth-child(n+2) { text-align: right; }
.sl-cell::before { content: none; }
.sl-name { color: var(--text-bright); font-weight: 700; }
.sl-best { background: rgba(0, 255, 136, 0.06); box-shadow: inset 2px 0 0 var(--phosphor); }
.sl-tag { display: inline-block; padding: 0 var(--sp-3); font-size: var(--fs-xs); font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; border: 1px solid var(--phosphor); color: var(--phosphor); }
.sl-cell.is-neg { color: var(--red); }

@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  #ship-loss-parts-table :is(th, td):first-child { text-align: left; min-width: 260px; }
  #ship-loss-parts-table :is(th, td):nth-child(n+3):not(.order-cell) { min-width: 130px; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .sl-head { display: none; }
  .sl-row { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: var(--sp-2); padding: var(--sp-3); }
  .sl-row > span:nth-child(n+2) { text-align: left; }
  .sl-cell::before { content: attr(data-label); display: block; color: var(--text-label); font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
  .sl-name::before { content: none; }
}
@media (min-width: 600px) and ((max-width: 768px) or ((pointer: coarse) and (max-height: 500px))) {
  .sl-row { grid-template-columns: minmax(7em, 1.3fr) repeat(5, minmax(0, 1fr)); }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  #ship-loss-fit, #ship-loss-hull { font-size: 16px; }
  #ship-loss-parts-table td:first-child { padding-top: var(--sp-4); padding-bottom: var(--sp-4); text-align: left; font-size: 13.5px; font-weight: 700; border-bottom-color: rgba(0, 255, 136, 0.22); }
  #ship-loss-parts-table td:first-child::before { content: none; }
}
}
@layer pages {
/* The offline notice (pwa.js): a small pill at the top edge, over the page. */
#offline-bar {
  position: fixed;
  top: env(safe-area-inset-top, 0px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  padding: 3px 12px;
  border: 1px solid var(--amber);
  border-top: 0;
  border-radius: 0 0 6px 6px;
  background: var(--navy);
  color: var(--amber);
  font: 500 11px/1.4 var(--mono);
  white-space: nowrap;
  pointer-events: none;
}
#offline-bar[hidden] { display: none; }
}
@layer pages {
/* Fitting (tools/fit-window.js, tools/fit-lab.js): the window's three panes
   (add, fit, numbers) side by side on a wide screen and one at a time, behind
   the tab chips and a summary strip, on a narrower one; then the "What it
   meets" card: stat blocks, the tank grid, the loss, gank and mining tables. */
#fit-lab .screen { overflow: visible; }
/* The links into the Fit lab from Ship loss and Mining yield. */
.fit-lab-link { display: inline-flex; align-items: center; min-height: 32px; }

.fw { margin-top: var(--sp-4); }
.fw[hidden] { display: none; }
.fw-note { color: var(--text-dim); font-size: var(--fs-sm); font-weight: 400; }
.fw-h { margin: 0 0 var(--sp-3); font-size: var(--fs-lg); }
.fw-col { display: none; min-width: 0; }
.fw[data-has-ship="1"][data-tab="fit"] .fw-fit,
.fw[data-has-ship="1"][data-tab="add"] .fw-add,
.fw[data-has-ship="1"][data-tab="stats"] .fw-stats,
.fw[data-has-ship="0"] .fw-fit { display: block; }
.fw[data-has-ship="0"] :is(.fw-strip, .fw-tabs) { display: none; }

.fw-strip { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--sp-2) var(--sp-6); padding: var(--sp-3) var(--sp-5); background: var(--panel-bg-2); border: 1px solid var(--edge); font-size: var(--fs-md); }
.fw-strip-ship { color: var(--text-bright); font-weight: 700; }
.fw-strip-stats { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-6); font-variant-numeric: tabular-nums; }
.fw-tabs { margin: var(--sp-3) 0; }

/* Add: search, kinds, the results and the market tree. */
.fw-search, .fw-name-in, #fit-lab-paste {
  display: block;
  width: 100%;
  min-height: 32px;
  margin: 0 0 var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  background: var(--input-bg);
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: var(--mono);
  font-size: var(--fs-lg);
}
#fit-lab-paste { resize: vertical; min-height: 9em; }
.fw-search::placeholder, .fw-name-in::placeholder, #fit-lab-paste::placeholder { color: var(--text-dim); }
:is(.fw-search, .fw-name-in, #fit-lab-paste):focus { outline: none; border-color: var(--phosphor); box-shadow: 0 0 0 1px var(--phos-a20), 0 0 10px var(--phos-a35); }
.fw-filters, .fw-popular, .fw-chooser { flex-wrap: wrap; margin-bottom: var(--sp-3); }
.fw-results { display: flex; flex-direction: column; margin-bottom: var(--sp-3); }
/* A row: icon and the whole name, wrapping between words; CPU/PG and the badge
   beneath. */
.fw-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "icon name name" "icon use tag";
  align-items: center;
  column-gap: var(--sp-4);
  width: 100%;
  min-height: 32px;
  padding: var(--sp-2) var(--sp-4);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--row-line);
  color: var(--text-bright);
  font: inherit;
  font-size: var(--fs-md);
  letter-spacing: normal;
  text-align: left;
  text-transform: none;
  cursor: pointer;
}
.fw-row > .type-icon { grid-area: icon; }
.fw-row:hover, .fw-row:focus-visible { background: var(--phos-a10); }
.fw-row-name { grid-area: name; min-width: 0; line-height: 1.25; }
.fw-row-use { grid-area: use; min-width: 0; color: var(--text-dim); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.fw-row-use:empty { display: none; }
.fw-tag { grid-area: tag; justify-self: end; min-width: 0; color: var(--mint-dim); font-size: var(--fs-xs); text-align: right; }
.fw-tag:empty { display: none; }
.fw-line { display: flex; align-items: stretch; }
.fw-line > .fw-row { flex: 1 1 auto; width: auto; min-width: 0; }
.fw-fill { flex: 0 0 auto; min-width: 3em; background: none; border: 0; border-bottom: 1px solid var(--row-line); color: var(--phosphor); font: inherit; font-size: var(--fs-sm); letter-spacing: normal; text-transform: none; cursor: pointer; }
.fw-fill:hover, .fw-fill:focus-visible { background: var(--phos-a10); }
.fw-exp, .fw-link { background: none; border: 0; color: var(--phosphor); font: inherit; letter-spacing: normal; text-transform: none; cursor: pointer; }
.fw-exp { flex: 0 0 auto; min-width: 3.5em; border-bottom: 1px solid var(--row-line); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.fw-exp:hover, .fw-exp:focus-visible { background: var(--phos-a10); }
.fw-link { display: inline; min-height: 0; padding: 0; text-decoration: underline; }
.fw-vars { margin-left: var(--sp-6); border-left: 1px solid var(--edge); }
.fw-hint, .fw-hidden { margin: 0 0 var(--sp-3); }
.fw-hint:empty, .fw-hidden:empty { display: none; }
.fw-more { min-height: 32px; margin: var(--sp-3) 0; }
.fw-browse, .fw-fold { margin: var(--sp-3) 0; font-size: var(--fs-md); }
.fw-fold > summary, .fw-meets > summary { display: flex; align-items: center; gap: var(--sp-3); min-height: 32px; cursor: pointer; color: var(--phosphor); }
.fw-results[hidden], .fw-browse[hidden], .fw-snaps[hidden] { display: none; }
/* The drill-down: a one-line path, then the level's groups and modules. */
.fw-crumb { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; min-height: 32px; margin: 0 0 var(--sp-2); border-bottom: 1px solid var(--edge); font-size: var(--fs-sm); }
.fw-crumb-trail { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--sp-2); flex: 1 1 auto; min-width: 0; }
.fw-crumb-back, .fw-crumb-step { flex: 0 1 auto; min-width: 0; padding: 0 var(--sp-2); background: none; border: 0; color: var(--phosphor); font: inherit; letter-spacing: normal; text-align: left; text-transform: none; cursor: pointer; }
.fw-crumb-back { flex: 0 0 auto; min-width: 28px; font-size: var(--fs-lg); line-height: 1; }
.fw-crumb-step:hover, .fw-crumb-back:hover, .fw-crumb-step:focus-visible, .fw-crumb-back:focus-visible { background: var(--phos-a10); }
.fw-crumb-here { flex: 0 1 auto; min-width: 3em; color: var(--text-bright); font-weight: 700; }
.fw-crumb-sep { flex: 0 0 auto; color: var(--text-dim); }
.fw-drill { grid-template-areas: "name n"; grid-template-columns: minmax(0, 1fr) auto; }
.fw-drill-n { grid-area: n; color: var(--text-dim); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.fw-drill:hover .fw-drill-n, .fw-drill:focus-visible .fw-drill-n { color: var(--phosphor); }

/* Fit: the hull, the resource bars, the racks. */
.fw-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3) var(--sp-6); margin-bottom: var(--sp-4); }
.fw-ship { display: flex; align-items: center; gap: var(--sp-4); min-width: 0; font-size: var(--fs-lg); }
.fw-name-in { flex: 1 1 10em; width: auto; margin: 0; }
.fw-bars { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.fw-bar { display: grid; grid-template-columns: 8.5em minmax(0, 1fr) auto; align-items: center; gap: var(--sp-4); font-size: var(--fs-md); font-variant-numeric: tabular-nums; }
.fw-bar-name { color: var(--text-label); white-space: nowrap; }
.fw-meter { display: block; height: 10px; background: var(--input-bg); border: 1px solid var(--edge); }
.fw-meter > span { display: block; height: 100%; background: var(--phosphor); }
.fw-bar.is-over .fw-meter > span { background: var(--red); }
.fw-bar.is-over .fw-bar-num { color: var(--red); }
.fw-bar-num { text-align: right; color: var(--text-bright); }
.fw-faults { margin: var(--sp-3) 0; padding-left: 1.2em; font-size: var(--fs-md); overflow-wrap: anywhere; }
.fw-hero { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-6); margin-bottom: var(--sp-4); }
.fw-hero-side { flex: 1 1 14em; min-width: 0; }
.fw-hero-side .fw-bars { margin-bottom: 0; }
.fw-hull-slot { flex: 0 1 0; min-width: 1px; margin-inline: auto; }
.fw-hull-slot:has(.is-ready) { flex-basis: 15em; }
/* The ship's dotted outline, a canvas cut to the ship's own box. */
.fw-hull { margin: 0; min-height: 1px; opacity: 0; filter: drop-shadow(0 0 var(--sp-3) var(--phos-a60)); }
.fw-hull.is-ready { opacity: 1; transition: opacity 0.4s; }
.fw-hull[hidden] { display: none; }
.fw-hull canvas, .fw-hull svg { display: block; width: 100%; height: auto; }
/* Drawn outline: dotted rim, faint lines inside; strokes keep their pixel width at any size. */
.fw-hull svg path { fill: none; vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
.fw-hull svg .o { stroke: var(--phosphor); stroke-width: 2.2px; stroke-dasharray: 0.1 5; }
.fw-hull svg .i path { stroke: var(--phos-a60); stroke-width: 1.1px; }
@media (prefers-reduced-motion: reduce) { .fw-hull.is-ready { transition: none; } }
.fw-rack { margin: var(--sp-4) 0; }
.fw-rack > h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--mint-dim); }
.fw-rack > h4 { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); }
/* The rack's heat chip, at the end of the header line. */
.fw-heat { margin-left: auto; min-height: 32px; }
.fw-heat:hover, .fw-heat:focus-visible, .fw-heat.active { color: var(--amber); border-color: var(--amber); }
.fw-slot.is-overload { border-color: var(--amber); }
/* Slot tiles, two or more to a row; the one with its menu open takes the row. */
.fw-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 14em), 1fr)); gap: var(--sp-2); align-items: start; }
.fw-tiles > .fw-slot:has(.fw-chooser, .fw-menu) { grid-column: 1 / -1; }
.fw-slot { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--sp-2) var(--sp-3); position: relative; min-width: 0; min-height: 32px; border: 1px solid var(--edge); background: var(--screen-bg); }
.fw-slot.fw-empty { align-items: center; width: 100%; padding: var(--sp-2) var(--sp-5); border-style: dashed; color: var(--text-dim); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer; }
.fw-slot.fw-empty:hover, .fw-slot.fw-empty:focus-visible { color: var(--phosphor); border-color: var(--phosphor); }
.fw-slot.is-drop { border-color: var(--phosphor); background: var(--phos-a20); }
.fw-slot.is-target { border-color: var(--phosphor); border-style: solid; color: var(--phosphor); background: var(--phos-a10); box-shadow: 0 0 0 1px var(--phos-a20); }
.fw-slot.has-fault { border-color: var(--red); }
.fw-mod { display: flex; align-items: center; flex: 1 1 9em; gap: var(--sp-4); min-width: 0; min-height: 32px; padding: var(--sp-2) var(--sp-4); background: none; border: 0; color: var(--text-bright); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer; }
.fw-mod:hover, .fw-mod:focus-visible { background: var(--phos-a10); }
.fw-mod, .fw-charge { text-transform: none; letter-spacing: normal; }
.fw-txt { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.fw-name { line-height: 1.25; }
.fw-state { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; }
.is-offline .fw-state, .is-offline .fw-name { color: var(--text-dim); }
.is-online .fw-state { color: var(--mint-dim); }
.is-active .fw-state { color: var(--phosphor); }
.is-overload .fw-state { color: var(--amber); }
.fw-charge { order: 2; flex: 1 1 100%; min-height: 32px; margin: 0 var(--sp-4) var(--sp-3); padding: var(--sp-2) var(--sp-4); background: none; border: 1px solid var(--edge); color: var(--mint); font: inherit; font-size: var(--fs-sm); line-height: 1.25; text-align: left; cursor: pointer; }
.fw-charge.is-empty { color: var(--amber); border-style: dashed; }
.fw-x { flex: 0 0 auto; min-width: 32px; min-height: 32px; background: none; border: 0; color: var(--text-dim); font: inherit; cursor: pointer; }
.fw-x:hover, .fw-x:focus-visible { color: var(--red); }
.fw-chooser { order: 3; flex: 1 1 100%; max-height: 14em; overflow: auto; padding: var(--sp-3); margin: 0; border-top: 1px solid var(--row-line); }
.fw-menu { order: 3; flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-5); padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--row-line); font-size: var(--fs-md); }
.fw-menu-item { display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--sp-3); background: none; border: 0; color: var(--phosphor); font: inherit; cursor: pointer; }
.fw-bay { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); min-height: 32px; border-bottom: 1px solid var(--row-line); }
.fw-bay-name { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; flex: 1 1 auto; }
.fw-bay-name > span, .fw-crew-name > span { min-width: 0; line-height: 1.25; }
/* Drones, fighters: a name that wraps between words, steppers beside it. */
.fw-crew { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-5); padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); }
.fw-crew-name { display: flex; align-items: center; gap: var(--sp-3); flex: 1 1 11em; min-width: 0; }
.fw-step { display: inline-flex; align-items: center; gap: var(--sp-1); font-variant-numeric: tabular-nums; }
.fw-step-n { min-width: 4.5em; text-align: center; color: var(--text-bright); }
.fw-step .fw-x:disabled { opacity: 0.35; cursor: default; }
.fw-crew-adds { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.fw-crew-add { width: auto; margin-top: var(--sp-3); padding-inline: var(--sp-6); }
.fw-modes, .fw-profiles { flex-wrap: wrap; align-items: center; margin: 0 0 var(--sp-4); }
.fw-shares { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); margin-top: var(--sp-4); }
.fw-rack-hint { margin: 0 0 var(--sp-3); }
.fw-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: var(--sp-4) 0; }
.fw-actions button { min-height: 32px; }

/* The toolbar by the hull name, and what it opens. */
.fw-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin: 0 0 var(--sp-4); }
.fw-tool-wrap { position: relative; }
.fw-tool-menu { position: absolute; z-index: 20; top: 100%; left: 0; display: flex; flex-direction: column; min-width: 100%; max-width: calc(100vw - 2 * var(--sp-5)); margin-top: var(--sp-1); background: var(--screen-bg); border: 1px solid var(--phosphor); }
.fw-tool-item { display: flex; align-items: center; min-height: 32px; padding: 0 var(--sp-5); background: none; border: 0; color: var(--phosphor); font: inherit; font-size: var(--fs-sm); letter-spacing: normal; text-transform: none; text-align: left; white-space: nowrap; cursor: pointer; }
.fw-tool-item:hover:not(:disabled), .fw-tool-item:focus-visible { background: var(--phos-a10); }
.fw-tool-item:disabled { color: var(--text-dim); cursor: default; }
.fw-tool { display: inline-flex; align-items: center; justify-content: center; min-height: 32px; padding: 0 var(--sp-4); background: none; border: 1px solid var(--edge); color: var(--phosphor); font: inherit; font-size: var(--fs-sm); letter-spacing: normal; text-transform: none; cursor: pointer; }
.fw-tool:hover:not(:disabled), .fw-tool:focus-visible, .fw-tool[aria-expanded="true"] { border-color: var(--phosphor); background: var(--phos-a10); }
.fw-tool:disabled { color: var(--text-dim); cursor: default; }
.fw-notice { margin: 0 0 var(--sp-4); color: var(--mint); font-size: var(--fs-sm); }
.fw-panel { margin: 0 0 var(--sp-4); padding: var(--sp-4) var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); }
.fw-panel-h { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--mint-dim); }
.fw-panel-acts { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-4); }
.fw-save { display: flex; gap: var(--sp-4); }
.fw-save .fw-name-in { flex: 1 1 auto; margin: 0; }
.fw-saved { margin: 0; padding: 0; list-style: none; }
.fw-saved-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3) var(--sp-5); padding: var(--sp-3) 0; border-bottom: 1px solid var(--row-line); }
.fw-saved-txt { display: flex; flex-direction: column; flex: 1 1 10em; min-width: 0; }
.fw-saved-name { color: var(--text-bright); overflow-wrap: anywhere; }
.fw-saved-acts { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
/* Popular fits on an empty hull: one tap loads a fit. */
.fw-popular { margin: var(--sp-4) 0; }
.fw-popular h4 { margin: 0 0 var(--sp-3); }
.fw-pop-list { margin: 0; padding: 0; list-style: none; }
.fw-pop-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); width: 100%; min-height: 44px; padding: var(--sp-3) 0; background: none; border: 0; border-bottom: 1px solid var(--row-line); color: inherit; font: inherit; text-align: left; cursor: pointer; }
.fw-pop-txt { display: flex; flex-direction: column; min-width: 0; }
.fw-pop-txt strong { color: var(--text-bright); font-weight: 600; }
.fw-pop-gist { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fw-pop-load { color: var(--phosphor); flex: none; }
.fw-rename { min-height: 32px; width: 100%; padding: 0 var(--sp-4); background: var(--input-bg); border: 1px solid var(--phosphor); border-radius: 2px; color: var(--text-bright); font-family: var(--mono); font-size: var(--fs-md); }

/* Snapshots: bars in a strip pinned to the foot of the window. */
.fw-snaps { position: sticky; bottom: 0; z-index: 6; display: flex; gap: var(--sp-4); margin-top: var(--sp-5); padding: var(--sp-4); overflow-x: auto; background: var(--panel-bg-2); border: 1px solid var(--edge); box-shadow: 0 -4px 12px var(--black); }
.fw[data-has-ship="0"] .fw-snaps { display: none; }
.fw-snap { display: flex; flex-direction: column; flex: 0 0 11.5em; min-width: 0; border: 1px solid var(--edge); background: var(--screen-bg); }
.fw-snap.is-here { border-color: var(--phosphor); box-shadow: 0 0 0 1px var(--phos-a20); }
.fw-snap-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 0 var(--sp-2) 0 var(--sp-3); }
.fw-snap-top .fw-rename { min-height: 28px; }
.fw-snap-name { min-width: 0; min-height: 28px; padding: 0 var(--sp-2); background: none; border: 0; color: var(--text-bright); font: inherit; font-size: var(--fs-md); font-weight: 700; letter-spacing: normal; text-align: left; text-transform: none; cursor: text; }
.fw-snap-acts { display: flex; flex: 0 0 auto; }
.fw-snap-x { min-width: 28px; min-height: 28px; padding: 0 var(--sp-3); background: none; border: 0; color: var(--text-dim); font: inherit; font-size: var(--fs-xs); letter-spacing: normal; text-transform: none; cursor: pointer; }
.fw-snap-x:hover, .fw-snap-x:focus-visible { color: var(--phosphor); }
.fw-snap-x[data-snap-delete]:hover, .fw-snap-x[data-snap-delete]:focus-visible { color: var(--red); }
.fw-snap-body { display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3) var(--sp-3); background: none; border: 0; border-top: 1px solid var(--row-line); color: inherit; font: inherit; letter-spacing: normal; text-align: left; text-transform: none; cursor: pointer; }
.fw-snap-body:hover, .fw-snap-body:focus-visible { background: var(--phos-a10); }
.fw-snap-stat { display: grid; grid-template-columns: 3em minmax(0, 1fr) 3.6em; align-items: center; gap: var(--sp-3); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.fw-snap-lab { color: var(--text-label); }
.fw-snap-bar { display: block; height: 6px; background: var(--input-bg); }
.fw-snap-bar > span { display: block; height: 100%; background: var(--phosphor); }
.fw-snap-val { text-align: right; color: var(--text-bright); white-space: nowrap; }
.fw-snap-val .d { display: none; color: var(--amber); }
.fw-snap:hover .fw-snap-val:has(.d) .v, .fw-snap:focus-within .fw-snap-val:has(.d) .v { display: none; }
.fw-snap:hover .fw-snap-val .d, .fw-snap:focus-within .fw-snap-val .d { display: inline; }
.fw-snap.is-here .fw-snap-val .d { display: none; }
.fw-snap.is-here:hover .fw-snap-val .v { display: inline; }
.fw-paste { margin: var(--sp-3) 0; }
.fw-pick { max-width: 44em; }
.fw-ghost { position: fixed; z-index: 60; padding: var(--sp-3) var(--sp-5); background: var(--panel-bg-2); border: 1px solid var(--phosphor); color: var(--text-bright); font-size: var(--fs-md); pointer-events: none; }
.fw-meets { margin-top: var(--sp-5); }
.fw-meets-hub { margin: var(--sp-3) 0; }

.fit-lab-chips { margin-bottom: var(--sp-4); }
.fit-lab-card { min-width: 0; font-size: var(--fs-md); }
.fit-lab-card p { margin: var(--sp-3) 0; }
.fit-lab-card h4, .fw .fl-block h4 { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--mint-dim); }
.fit-lab-card .hotkey-chip-list { flex-wrap: wrap; }
.fit-lab-unknown { margin: var(--sp-3) 0; font-size: var(--fs-sm); }
.fit-lab-unknown > summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; color: var(--amber); }
.fit-lab-unknown ul { margin: 0 0 var(--sp-2); padding-left: 1.2em; overflow-wrap: anywhere; }

/* Numbers: blocks that flow into as many columns as fit. */
.fl-blocks { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: var(--sp-4); }
.fl-block { min-width: 0; padding: var(--sp-4) var(--sp-5); background: var(--screen-bg); border: 1px solid var(--edge); }
.fl-kv { display: flex; justify-content: space-between; gap: var(--sp-4); padding: var(--sp-1) 0; font-size: var(--fs-md); }
.fl-kv > span { color: var(--text-label); }
.fl-kv > strong { color: var(--text-bright); font-weight: 600; text-align: right; }
.fl-list { margin: var(--sp-3) 0 0; padding-left: 1.2em; overflow-wrap: anywhere; font-size: var(--fs-md); }
.fl-res { margin-top: var(--sp-3); font-variant-numeric: tabular-nums; font-size: var(--fs-md); }
.fl-res-row { display: grid; grid-template-columns: 1.4fr 1.3fr repeat(4, 1fr) 1.4fr; gap: var(--sp-2); padding: var(--sp-1) 0; border-bottom: 1px solid var(--row-line); }
.fl-res-row > span:nth-child(n+2) { text-align: right; }
.fl-res-head { color: var(--mint-dim); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }

/* Tank: one row a damage profile. */
.fl-tank { font-variant-numeric: tabular-nums; }
.fl-tank-row { display: grid; grid-template-columns: minmax(8em, 1.4fr) repeat(3, minmax(0, 1fr)) minmax(0, 1.4fr); gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--row-line); align-items: baseline; }
.fl-tank-row > span:nth-child(n+2) { text-align: right; }
.fl-tank-head { color: var(--mint-dim); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; border-bottom-color: var(--line); }
.fl-tank-name { color: var(--text-bright); font-weight: 700; }

.fl-parts-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); margin: var(--sp-4) 0 var(--sp-2); }
.fl-parts-head h4 { margin: 0; }
.fl-parts-head .order-add-btn { min-height: 32px; }
.fl-best td { background: var(--phos-a10); }
.fl-best td:first-child { box-shadow: inset 2px 0 0 var(--phosphor); }
.fl-fleet { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-6); margin: var(--sp-4) 0 var(--sp-2); }
.fl-count { display: inline-flex; align-items: center; gap: var(--sp-3); }
.fl-count input { width: 4.5em; min-height: 32px; padding: 0 var(--sp-3); background: var(--input-bg); border: 1px solid var(--edge); color: var(--text-bright); font-family: var(--mono); font-size: var(--fs-lg); }
.fl-outcome { font-size: var(--fs-lg); }
.fl-note { color: var(--text-dim); font-size: var(--fs-sm); }
.fl-nw { white-space: nowrap; }
/* The capacitor chart: a band of lows and highs against 0 to 100%. */
.fl-chart { display: block; width: 100%; height: auto; margin-top: var(--sp-3); }
.fl-chart-grid { stroke: var(--row-line); stroke-width: 1; }
.fl-chart-text { fill: var(--text-dim); font-size: var(--fs-xs); }
.fl-chart-hi { fill: none; stroke: var(--phos-a60); stroke-width: 1; }
.fl-chart-lo { fill: none; stroke: var(--phosphor); stroke-width: 1.5; }

/* A wide screen: the three panes together. */
@media (min-width: 1100px) {
  /* A narrow add list (names wrap), the hull and its slot tiles in the middle
     and the numbers in a compact column on the right. */
  .fw[data-has-ship="1"] .fw-cols { display: grid; grid-template-columns: minmax(15em, 17em) minmax(0, 1fr) minmax(18em, 20em); gap: var(--sp-6); align-items: start; }
  .fw[data-has-ship="1"] .fw-col { display: block; }
  .fw[data-has-ship="1"] .fw-tabs, .fw[data-has-ship="1"] .fw-strip { display: none; }
  .fw-add { position: sticky; top: var(--sp-4); max-height: 90vh; overflow: auto; }
  .fl-blocks { grid-template-columns: 1fr; gap: var(--sp-3); }
  .fl-block { padding: var(--sp-3) var(--sp-4); }
}
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .fit-lab-card table :is(th, td):first-child { text-align: left; min-width: 220px; }
}
@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .fw-strip { position: sticky; top: 0; z-index: 5; }
  .fw-row, .fw-exp, .fw-fill, .fw-slot, .fw-mod, .fw-charge, .fw-x, .fw-tool, .fw-snap-name, .fw-snap-x, .fw-crumb, .fw-crumb-step, .fw-crumb-back, .fw-rename { min-height: 44px; }
  .fw-x { min-width: 44px; }
  .fw-heat { min-height: 44px; min-width: 44px; }
  .fw-search, .fw-name-in { min-height: 44px; }
  .fw-fold > summary { min-height: 44px; }
  .fw-filters .hotkey-chip, .fw-modes .hotkey-chip, .fw-profiles .hotkey-chip { min-height: 44px; }
  .fl-count input { min-height: 44px; }
  .fw-tool { padding: 0 var(--sp-4); font-size: var(--fs-md); }
  .fw-snap-x, .fw-snap-name { min-width: 44px; }
  .fw-crumb-back { min-width: 44px; }
  .fw-tool-item { min-height: 44px; font-size: var(--fs-md); }
  .fw-tool-wrap:last-child .fw-tool-menu { left: auto; right: 0; }
  .fw-snaps { bottom: calc(55px + env(safe-area-inset-bottom, 0px)); }
  .fw-rename, .fw-snap-top .fw-rename { font-size: 16px; }
  .fw-snaps { gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); }
  .fw-snap-body { gap: 0; padding-bottom: var(--sp-2); }
  .fw-snap-stat { line-height: 1.5; }
  .fw-snap { flex-basis: 13em; }
  .fw-snap-stat { grid-template-columns: 2.6em minmax(0, 1fr) 6em; }
  .fw-snap-val .d, .fw-snap:hover .fw-snap-val .d { display: inline; margin-left: var(--sp-2); }
  .fw-snap:hover .fw-snap-val:has(.d) .v, .fw-snap:focus-within .fw-snap-val:has(.d) .v { display: inline; }
  .fw-snap.is-here .fw-snap-val .d { display: none; }
  .fw-hull-slot:has(.is-ready) { flex-basis: 10em; }
  .fw-search, .fw-name-in, #fit-lab-paste, .fl-count input { font-size: 16px; }
  .fw-bar { grid-template-columns: 8em minmax(0, 1fr) auto; gap: var(--sp-3); }
  .fl-tank-head { display: none; }
  .fl-tank-row { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--sp-2); padding: var(--sp-3); }
  .fl-tank-row > span:nth-child(n+2) { text-align: left; }
  .fl-tank-row > span[data-label]::before { content: attr(data-label); display: block; color: var(--text-label); font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
  .fl-tank-name { grid-column: 1 / -1; }
}
@media (min-width: 600px) and ((max-width: 768px) or ((pointer: coarse) and (max-height: 500px))) {
  .fl-tank-row { grid-template-columns: minmax(7em, 1.4fr) repeat(4, minmax(0, 1fr)); }
  .fl-tank-name { grid-column: auto; }
}
}
@layer pages {
/* Fitting, combat figures (tools/fit/combat.js): a weapon tile's reach line,
   the weapon detail, the Application fold with its target chips, range and
   chart, the ammo table, and the boosts and projected effects. */
.fw-fig { font-size: var(--fs-xs); color: var(--text-dim); overflow-wrap: anywhere; }

.fc-weapon { padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); }
.fc-weapon > strong { display: block; color: var(--text-bright); font-size: var(--fs-md); overflow-wrap: anywhere; }

.fc-targets, .fc-bursts, .fc-picks, .fc-space { flex-wrap: wrap; margin: var(--sp-2) 0; }
.fw-burn { margin: var(--sp-2) 0 0; color: var(--amber); }
.fc-atk { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); margin: var(--sp-2) 0; font-size: var(--fs-md); color: var(--text-label); }
.fc-atk label { display: inline-flex; align-items: center; gap: var(--sp-2); }
.fc-num { width: 5em; min-height: 32px; padding: 0 var(--sp-2); border: 1px solid var(--edge); background: var(--screen-bg); color: var(--text-bright); font: inherit; font-variant-numeric: tabular-nums; }
.fc-num:focus-visible { border-color: var(--phosphor); outline: none; }
.fc-range { display: block; margin: var(--sp-3) 0; font-size: var(--fs-md); color: var(--text-label); }
.fc-range > span { display: flex; justify-content: space-between; gap: var(--sp-4); }
.fc-range strong { color: var(--text-bright); font-weight: 600; }
.fc-range input[type="range"] { display: block; width: 100%; min-height: 32px; margin: 0; accent-color: var(--phosphor); }

.fc-chart { display: block; width: 100%; height: auto; margin: var(--sp-2) 0; touch-action: manipulation; cursor: crosshair; }
.fc-axis { stroke: var(--edge); stroke-width: 1; }
.fc-line { fill: none; stroke: var(--phosphor); stroke-width: 1.5; stroke-linejoin: round; }
.fc-mark { stroke: var(--amber); stroke-width: 1; stroke-dasharray: 3 3; }
.fc-dot { fill: var(--amber); }
.fc-tick { fill: var(--text-dim); font-family: var(--mono); }

.fc-ammo { font-variant-numeric: tabular-nums; font-size: var(--fs-md); }
.fc-ammo-row { display: grid; grid-template-columns: minmax(0, 1fr) 4.5em minmax(0, 7.5em); gap: var(--sp-3); padding: var(--sp-1) 0; border-bottom: 1px solid var(--row-line); }
.fc-ammo-row > span { overflow-wrap: anywhere; }
.fc-ammo-row > span:nth-child(n+2) { text-align: right; }
.fc-ammo-head { color: var(--mint-dim); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.fc-ammo-row.is-loaded > span:first-child { color: var(--text-bright); font-weight: 700; }
.fc-ammo-row.is-best > span:nth-child(2) { color: var(--phosphor); font-weight: 700; }

.fc-eff { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); min-height: 32px; font-size: var(--fs-md); }
.fc-eff > span:first-child { color: var(--text-label); }
.fc-step { display: inline-flex; align-items: center; gap: var(--sp-3); }
.fc-step > strong { min-width: 1.5em; text-align: center; color: var(--text-bright); font-variant-numeric: tabular-nums; }
.fc-btn { min-width: 32px; min-height: 32px; border: 1px solid var(--edge); background: var(--screen-bg); color: var(--phosphor); font: inherit; cursor: pointer; }
.fc-btn:hover:not(:disabled), .fc-btn:focus-visible { border-color: var(--phosphor); }
.fc-btn:disabled { color: var(--text-dim); cursor: default; }
.fc-up { color: var(--phosphor); }
.fc-down { color: var(--amber); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .fc-chip, .fc-btn, .fc-num, .fc-range input[type="range"] { min-height: 44px; }
  .fc-btn { min-width: 44px; }
  .fc-eff { min-height: 44px; }
}
}
@layer pages {
/* Fitting, price strip, fit comparison and swap preview (tools/fit/extras.js):
   the fit's cost with its shopping list, the table of key figures against the
   fit now, and the delta line under the add list's hint. Phone touch sizes
   for the window's tabs and tips close the file. */
.fw-price { margin: var(--sp-3) 0; padding: var(--sp-3) var(--sp-5); background: var(--panel-bg-2); border: 1px solid var(--edge); }
.fw-price[hidden] { display: none; }
.fw[data-has-ship="0"] .fw-price { display: none; }
.fx-price-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3) var(--sp-5); }
.fx-price-line { color: var(--text-bright); font-variant-numeric: tabular-nums; margin: 0; }
.fx-acts { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.fx-list, .fx-cmp { display: grid; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.fx-row { display: grid; grid-template-columns: minmax(0, 1fr) 5em 5.5em 5.5em; gap: var(--sp-3); align-items: baseline; padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); }
.fx-row.is-missing .fx-num { color: var(--amber); }
.fx-head { color: var(--text-label); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; }
.fx-name { min-width: 0; overflow-wrap: anywhere; }
.fx-kind { color: var(--text-dim); }
.fx-num { text-align: right; white-space: nowrap; }

.fx-compare { margin-top: var(--sp-4); }
.fx-compare[hidden] { display: none; }
.fx-picks { flex-wrap: wrap; margin: var(--sp-3) 0; }
.fx-cmp { overflow-x: auto; }
.fx-cmp-row { display: grid; grid-template-columns: minmax(7em, 1.4fr) repeat(var(--fx-cols), minmax(5.5em, 1fr)); gap: var(--sp-3); align-items: start; padding: var(--sp-2) 0; border-bottom: 1px solid var(--row-line); }
.fx-col-head { overflow: hidden; text-overflow: ellipsis; }
.fx-col-head.is-now { color: var(--text-bright); }
.fx-v { display: block; color: var(--text-bright); }
.fx-d { font-size: var(--fs-xs); color: var(--text-dim); }
.fx-d.is-up { color: var(--mint); }
.fx-d.is-down { color: var(--red); }
.fx-cmp-row .fx-d { display: block; }

.fx-swap { min-height: 1.5em; margin: 0 0 var(--sp-3); }
.fx-swap .fx-d { display: inline-block; margin-right: var(--sp-3); font-size: var(--fs-sm); }

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .fw-tabs .hotkey-chip { min-height: 44px; }
  .fw-price .fw-tool, .fx-picks .hotkey-chip { min-height: 44px; }
  .fw-price .fw-fold > summary { min-height: 44px; }
  /* The "?" tips keep their small drawn size and take a 44 px finger box that overlaps the line around them. */
  #fit-lab .info-tip { min-width: 44px; min-height: 44px; margin: calc(-1 * var(--sp-4)) calc(-1 * var(--sp-3)); }
  /* A pane never sets the page's width: what is wider than the screen is clipped, not scrolled. */
  .fw-col { max-width: 100%; overflow-x: clip; }
  .fx-row { grid-template-columns: minmax(0, 1fr) 4.5em 4.5em; }
  .fx-row > .fx-kind { display: none; }
}
}
@layer pages {
/* FW economics (tools/fw-economics.js): a block a warzone with a card a
   militia (--f is the militia's colour: the four races' hub swatches), a
   line chart of systems held, then the front's systems and the flips. A
   direction is always a sign and an arrow as well as a colour. */
.fwe-n { color: var(--text-dim); font-weight: 400; }
.fwe-chip { min-height: 32px; }
.fwe-chip.active .fwe-n { color: inherit; }
.fwe-dim { color: var(--text-dim); }
.fwe-swatch { display: inline-block; width: 8px; height: 8px; margin-right: var(--sp-3); background: var(--text-dim); vertical-align: baseline; }
.fwe-up { color: var(--mint); }
.fwe-down { color: var(--amber); }
.fwe-sys { color: var(--text-bright); }

.fwe-zone { margin: var(--sp-5) 0 var(--sp-7); }
.fwe-zone > h3, .fwe-section > h3 { margin: var(--sp-6) 0 var(--sp-3); font-size: var(--fs-lg); letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint-dim); }
.fwe-lead { margin-left: var(--sp-4); font-size: var(--fs-md); letter-spacing: 0; text-transform: none; color: var(--text-bright); }
.fwe-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6); }
.fwe-card { min-width: 0; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--line); border-top: 3px solid var(--f); background: var(--panel-bg); }
.fwe-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); }
.fwe-card h4 { margin: 0; font-size: var(--fs-lg); color: var(--text-bright); }
.fwe-held strong { font-size: 18px; color: var(--text-bright); }
.fwe-card p { margin: var(--sp-3) 0 0; font-size: var(--fs-md); line-height: 1.45; color: var(--text-label); overflow-wrap: anywhere; }
.fwe-deltas { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-6); }
.fwe-deltas b { font-weight: 600; }
.fwe-lp { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--row-line); }
.fwe-lp > p:first-child { margin-top: 0; }
.fwe-lpline strong { color: var(--text-bright); }
.fwe-offers { list-style: none; margin: var(--sp-3) 0 0; padding: 0; font-size: var(--fs-md); }
.fwe-offers > li { display: grid; grid-template-columns: minmax(0, 1fr) 64px 56px; gap: var(--sp-4); padding: var(--sp-2) 0; border-top: 1px solid var(--row-line); }
.fwe-offers > .fwe-offers-head { border-top: 0; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.06em; color: var(--mint-dim); }
.fwe-offers .num { text-align: right; white-space: nowrap; }
.fwe-oname { min-width: 0; overflow-wrap: anywhere; }
.fwe-slow { padding: 0 var(--sp-2); border: 1px solid var(--edge); font-size: var(--fs-xs); color: var(--text-dim); }
.fwe-est strong { color: var(--amber); }
.fwe-tag { display: inline-block; padding: 0 var(--sp-3); margin-right: var(--sp-2); border: 1px solid var(--amber); color: var(--amber); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; }

.fwe-chart { margin: var(--sp-5) 0 0; padding: var(--sp-4) var(--sp-6); border: 1px solid var(--line); background: var(--panel-bg); }
.fwe-chart svg { display: block; width: 100%; height: auto; }
.fwe-chart figcaption { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-1) var(--sp-6); margin-top: var(--sp-2); font-size: var(--fs-xs); color: var(--text-dim); }
.fwe-key { color: var(--text-label); }
.fwe-axis { stroke: var(--row-line); stroke-width: 1; }
.fwe-tick { fill: var(--text-dim); font-size: 10px; font-family: var(--mono); }

.fwe-section[hidden] { display: none; }
.fwe-rows, .fwe-flip-list { list-style: none; margin: var(--sp-3) 0 0; padding: 0; }
.fwe-rows > li { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(0, 1.3fr) 90px minmax(0, 1.6fr); gap: var(--sp-1) var(--sp-6); align-items: center; padding: var(--sp-3) var(--sp-5); border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); }
.fwe-r-sys, .fwe-r-held { min-width: 0; overflow-wrap: anywhere; }
.fwe-meter { display: inline-block; width: 64px; height: 6px; margin-right: var(--sp-3); border: 1px solid var(--line); vertical-align: middle; }
.fwe-meter > i { display: block; height: 100%; background: var(--mint); }
.fwe-state { margin-left: var(--sp-3); color: var(--text-dim); }
.fwe-state-contested { color: var(--amber); }
.fwe-state-vulnerable { color: var(--red); font-weight: 600; }
.fwe-flip-list > li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-5); padding: var(--sp-3) var(--sp-5); border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); }
.fwe-day { min-width: 44px; color: var(--text-dim); }
.fwe-change { margin-left: auto; }
.fwe-more { margin-top: var(--sp-3); min-height: 32px; }
.fwe-months { margin: var(--sp-6) 0 0; }
.fwe-months figcaption { font-size: var(--fs-xs); color: var(--text-dim); }
.fwe-bars { display: flex; align-items: flex-end; gap: 2px; height: 48px; margin-top: var(--sp-2); padding: var(--sp-2); border: 1px solid var(--line); background: var(--panel-bg); }
.fwe-bar { flex: 1 1 0; min-width: 2px; background: var(--mint-dim); }

@media (max-width: 900px) {
  .fwe-cards { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .fwe-tick { font-size: 15px; }
  .fwe-lead { display: block; margin: var(--sp-2) 0 0; }
  .fwe-rows > li { grid-template-columns: minmax(0, 1fr) auto; padding: var(--sp-4) var(--sp-3); }
  .fwe-r-sys { grid-column: 1 / -1; }
  .fwe-r-contest { grid-column: 1 / -1; }
  .fwe-change { margin-left: 0; flex-basis: 100%; }
  .fwe-card { padding: var(--sp-4); }
}
}
@layer pages {
/* Battle reports (tools/battle-reports.js): the chip rows in the header, a
   list of battles each with a bar of the ISK lost by side (--s is a side's
   colour: A blue, B rust, the others grey, and always named in words too),
   and an opened battle with a timeline, the class mix and the parties. */
.br-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.br-dim { color: var(--text-dim); }
.br-unnamed { color: var(--text-dim); }
.br-items { list-style: none; margin: var(--sp-4) 0 0; padding: 0; }
.br-item { padding: var(--sp-5) var(--sp-5) var(--sp-4); border-bottom: 1px solid var(--row-line); border-left: 3px solid var(--edge); }
.br-head { display: grid; grid-template-columns: 170px minmax(0, 1.4fr) minmax(0, 1.2fr) auto; gap: var(--sp-2) var(--sp-7); align-items: center; }
.br-when { display: flex; flex-direction: column; min-width: 0; }
.br-when strong { color: var(--text-bright); font-size: var(--fs-lg); }
.br-stamp { font-size: var(--fs-xs); color: var(--text-dim); }
.br-where { min-width: 0; overflow-wrap: anywhere; font-size: var(--fs-md); }
.br-system { color: var(--text-bright); }
.br-region { color: var(--text-dim); }
.br-figs { font-size: var(--fs-md); color: var(--text-label); }
.br-figs strong { color: var(--text-bright); }
.br-links { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-5); justify-content: flex-end; align-items: center; min-width: 0; }
.br-open, .br-back, .br-more { min-height: 32px; }
.br-bar { display: flex; height: 8px; margin: var(--sp-4) 0 var(--sp-3); border: 1px solid var(--line); background: var(--panel-bg); }
.br-bar > i { display: block; height: 100%; min-width: 1px; }
.br-sides { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-7); }
.br-side { flex: 1 1 220px; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-4); font-size: var(--fs-md); border-left: 3px solid var(--s); padding-left: var(--sp-4); }
.br-side-name { color: var(--s); font-weight: 600; }
.br-side-who { color: var(--text-bright); min-width: 0; overflow-wrap: anywhere; }
.br-side-fig { flex-basis: 100%; font-size: var(--fs-sm); color: var(--text-label); }
.br-nosides { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--text-dim); }
.br-mix { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-5); margin-top: var(--sp-3); font-size: var(--fs-sm); color: var(--text-label); }
.br-class b { color: var(--text-bright); font-weight: 600; }
.br-pods { color: var(--text-dim); }
.br-more { margin-top: var(--sp-4); }

.br-detail-head h3 { margin: var(--sp-4) 0 var(--sp-2); font-size: 16px; color: var(--text-bright); }
.br-detail-sub { margin: 0; font-size: var(--fs-md); color: var(--text-label); line-height: 1.5; }
.br-detail-sub strong { color: var(--text-bright); }
.br-detail-links { margin: var(--sp-2) 0 0; display: flex; flex-wrap: wrap; gap: 0 var(--sp-5); }
.br-timeline { margin: var(--sp-6) 0 0; padding: var(--sp-4) var(--sp-6); border: 1px solid var(--line); background: var(--panel-bg); }
.br-timeline figcaption { font-size: var(--fs-xs); color: var(--text-dim); }
.br-timeline svg { display: block; width: 100%; height: auto; }
.br-axis { stroke: var(--edge); stroke-width: 1; }
.br-tick { fill: var(--text-dim); font-size: 10px; font-family: var(--mono); }
.br-sideboxes { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--sp-6); margin-top: var(--sp-6); }
.br-sidebox { min-width: 0; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--line); border-top: 3px solid var(--s); background: var(--panel-bg); }
.br-sidebox h4 { margin: 0; font-size: var(--fs-lg); color: var(--s); }
.br-sidefig { margin: var(--sp-2) 0 var(--sp-4); font-size: var(--fs-md); color: var(--text-label); }
.br-sidefig strong { color: var(--text-bright); }
.br-mixlist, .br-parties { list-style: none; margin: var(--sp-3) 0 0; padding: 0; }
.br-mixlist > li { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr) auto; gap: var(--sp-4); align-items: center; padding: var(--sp-1) 0; font-size: var(--fs-md); }
.br-mixname { min-width: 0; overflow-wrap: anywhere; color: var(--text-label); }
.br-mixbar { display: block; height: 6px; border: 1px solid var(--line); }
.br-mixbar > i { display: block; height: 100%; background: var(--s); }
.br-mixlist b { color: var(--text-bright); font-weight: 600; }
.br-moreclasses { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); }
.br-parties { margin-top: var(--sp-5); border-top: 1px solid var(--row-line); }
.br-parties > li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 var(--sp-5); padding: var(--sp-3) 0; border-bottom: 1px solid var(--row-line); font-size: var(--fs-md); }
.br-pname { min-width: 0; overflow-wrap: anywhere; color: var(--text-bright); }
.br-pfig { text-align: right; color: var(--text-label); white-space: nowrap; }
.br-psub { grid-column: 1 / -1; font-size: var(--fs-sm); color: var(--text-dim); }

/* A desktop's chip rows share a line. */
@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .br-group { flex: 0 1 auto; margin: 0 var(--sp-6) 0 0; }
}

@media (max-width: 1100px) {
  .br-head { grid-template-columns: 130px minmax(0, 1fr) auto; }
  .br-figs { grid-column: 2; }
  .br-links { grid-column: 3; grid-row: 1 / span 2; flex-direction: column; align-items: flex-end; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .br-tick { font-size: 15px; }
  .br-head { grid-template-columns: minmax(0, 1fr); gap: var(--sp-1) var(--sp-5); }
  .br-when { grid-column: 1; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-5); }
  .br-where, .br-figs, .br-links { grid-column: 1 / -1; }
  .br-links { grid-row: auto; flex-direction: row; justify-content: flex-start; }
  .br-item { padding: var(--sp-4) var(--sp-3); }
  .br-sideboxes { grid-template-columns: minmax(0, 1fr); }
  .br-sidebox { padding: var(--sp-4); }
  .br-mixlist > li { grid-template-columns: minmax(0, 110px) minmax(0, 1fr) auto; }
}
}
@layer pages {
/* Hotspot radar (tools/hotspots.js): the window and kind chips in the header,
   the map, then the ranked table. A kind has one colour (--k) in its tag and
   on the map. */
.hs-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.hs-chip { min-height: 32px; }
.hs-chip-short { display: none; }
.hs-table td { vertical-align: top; text-align: left; }
.hs-table th { text-align: left; }
.hs-system strong { color: var(--text-bright); }
.hs-heat strong { color: var(--text-bright); font-size: var(--fs-lg); }
.hs-tag { display: inline-block; padding: 0 var(--sp-3); margin: 0 var(--sp-1) var(--sp-1) 0; border: 1px solid var(--k); color: var(--k); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; white-space: nowrap; }
.hs-mix { display: flex; width: 96px; height: 6px; margin-bottom: var(--sp-1); border: 1px solid var(--line); }
.hs-mix > i { display: block; height: 100%; }
.hs-mix-s { background: var(--mint); }
.hs-mix-g { background: var(--amber); }
.hs-mix-u { background: var(--text-dim); }
.hs-go { white-space: nowrap; }
.hs-tip-links { margin-top: var(--sp-2); }
/* The map sits under the table and its pager. */
#hs-legend { margin-top: var(--sp-7); }
#hs-map { height: clamp(300px, 56vh, 560px); }

@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .hs-group { flex: 0 1 auto; margin: 0 var(--sp-6) 0 0; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .hs-chip-long { display: none; }
  .hs-chip-short { display: inline; }
  #hs-map { height: clamp(280px, 50vh, 420px); }
}
}
@layer pages {
/* Roam mode of the Route planner (tools/roam.js): the mode switch and its
   controls in the header, then a loop panel in place of the route stage: the
   map beside the numbered stops, each with why it was chosen. */
/* !important: the phone's chip folds (overrides layer) set display on the primary groups. */
#routes[data-mode="roam"] .routes-only, #routes[data-mode="roam"] .section-header > .fold-summary { display: none !important; }
#routes .roam-only[hidden] { display: none !important; }
#routes details.explainer[hidden] { display: none; }
.routes-mode { align-items: center; }

.roam-panel { min-width: 0; margin: var(--sp-3) 0; }
.roam-summary { margin: 0 0 var(--sp-3); font-size: var(--fs-md); line-height: 1.45; color: var(--text-label); overflow-wrap: anywhere; }
.roam-summary:empty { display: none; }
.roam-body { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: var(--sp-6); align-items: start; min-width: 0; }
.roam-mapcol, .roam-listcol { min-width: 0; }
.roam-mapcol .eve-map { height: clamp(320px, 62vh, 620px); margin-top: var(--sp-2); }
.roam-stops { list-style: none; margin: 0; padding: 0; }
.roam-stop { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: var(--sp-2) var(--sp-4); align-items: start; padding: var(--sp-4) var(--sp-4); border-bottom: 1px solid var(--row-line); border-left: 3px solid var(--mint); cursor: pointer; }
.roam-stop.roam-home { border-left-color: var(--edge); cursor: default; }
.roam-n { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; background: var(--mint); color: var(--screen-bg); font-size: var(--fs-md); font-weight: 700; }
.roam-home .roam-n { background: none; border: 1px solid var(--edge); color: var(--text-label); }
.roam-what { min-width: 0; font-size: var(--fs-md); overflow-wrap: anywhere; }
.roam-what strong { color: var(--text-bright); }
.roam-dist { margin-left: var(--sp-3); font-size: var(--fs-xs); color: var(--text-dim); }
.roam-why, .roam-via { margin: var(--sp-1) 0 0; font-size: var(--fs-md); line-height: 1.4; color: var(--text-label); }
.roam-via { font-size: var(--fs-sm); color: var(--text-dim); }
.roam-links { display: flex; flex-wrap: wrap; gap: 0 var(--sp-4); justify-content: flex-end; min-width: 0; }
.roam-aside { margin-top: var(--sp-3); }
.roam-avoid { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); line-height: 1.5; color: var(--text-label); overflow-wrap: anywhere; }
.roam-tag { display: inline-block; padding: 0 var(--sp-3); margin-right: var(--sp-2); border: 1px solid var(--edge); color: var(--text-dim); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; }
.roam-tag-blob { border-color: var(--red); color: var(--red); }

@media (max-width: 1100px) {
  .roam-body { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  .roam-mapcol .eve-map { height: clamp(280px, 50vh, 420px); }
  .roam-stop { grid-template-columns: 28px minmax(0, 1fr); }
  .roam-links { grid-column: 2; justify-content: flex-start; }
}
}
@layer pages {
/* War economy (tools/war-economy.js): the chip rows in the header, the table
   of burn against stock and the bubble chart under it. */
.we-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.we-group[hidden] { display: none; }
#we-table td:nth-child(n+3):not(.order-cell) { white-space: nowrap; }
#we-table .cell-note { white-space: normal; }
}
@layer pages {
/* Doctrine pulse (tools/doctrine-pulse.js): the chip rows in the header, the
   most-lost line and the table of fit families with their dominant modules. */
.dp-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.dp-group[hidden] { display: none; }
.dp-group.dp-short { flex: 0 1 auto; margin-right: calc(var(--sp-7) + var(--sp-4)); }
#dp-table th:nth-child(2), #dp-table td:nth-child(2) { width: 24ch; }
#dp-table .dp-mods { text-align: left; }
.dp-war { display: inline-block; max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.dp-n { color: var(--text-dim); font-weight: 400; }
.dp-hulls { margin: var(--sp-3) 0; line-height: 1.7; }
.dp-hulls[hidden] { display: none; }
.dp-mods { min-width: 0; }
.dp-mod { display: block; line-height: 1.5; }
.dp-rack { display: inline-block; min-width: 3.2em; color: var(--text-dim); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; }
.dp-open { white-space: nowrap; }
.dp-open .route-link { display: inline-flex; align-items: center; min-height: 32px; }
}
@layer pages {
/* The Exploration pages (tools/exploration.js, exploration-sites.js): the chip
   row in the header, the map, the system and site tables, the level, quiet
   and effect tags, the loot tags and price lists. */
.xp-group { flex: 1 1 100%; min-width: 0; margin: var(--sp-2) 0 0; align-items: center; }
.xp-chip { min-height: 32px; }
.xp-search { display: flex; align-items: center; gap: var(--sp-3); flex: 1 1 100%; margin: var(--sp-2) 0 0; }
.xp-search input { flex: 1 1 8em; min-width: 0; max-width: 16em; min-height: 32px; }
.xp-table td { vertical-align: top; white-space: normal; }
.xp-table td.xp-name { text-align: left; }
.xp-table td.xp-go, .xp-table .xp-hole { white-space: nowrap; }
.xp-name .mining-more > :not(summary) { max-width: 48ch; }
/* On a phone card the fold starts a line of its own, clear of the cell's label. */
.xp-name > .mining-more { clear: both; }
.xp-name > details { display: inline-block; margin: 0 0 0 var(--sp-3); vertical-align: middle; }
.xp-name > details[open] { display: block; margin-top: var(--sp-2); }
.xp-name a { display: inline-flex; align-items: center; min-height: 32px; overflow-wrap: anywhere; }
.xp-name strong { color: var(--text-bright); }
.xp-tag { display: inline-block; padding: 0 var(--sp-3); margin: 0 var(--sp-1) var(--sp-1) 0; border: 1px solid var(--edge); color: var(--text-dim); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; white-space: nowrap; }
.xp-shattered { border-color: var(--amber); color: var(--amber); }
.xp-effect { display: inline-block; padding: 0 var(--sp-3); border: 1px solid var(--k, var(--edge)); color: var(--k, var(--text-dim)); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; white-space: nowrap; }
.xp-fx-pulsar { --k: #4da3ff; }
.xp-fx-magnetar { --k: #c08cff; }
.xp-fx-wolf-rayet { --k: #ffb000; }
.xp-fx-black-hole { --k: #9aa7b8; }
.xp-fx-cataclysmic-variable { --k: #3fe0d0; }
.xp-fx-red-giant { --k: #ff7a59; }
.xp-level { display: inline-block; padding: 0 var(--sp-3); border: 1px solid var(--edge); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; color: var(--text-dim); }
.xp-l1 { border-color: var(--amber); color: var(--amber); }
.xp-l2 { border-color: var(--red); color: var(--red); }
.xp-quiet { display: inline-block; padding: 0 var(--sp-3); border: 1px solid var(--edge); font-size: var(--fs-xs); letter-spacing: 0.06em; text-transform: uppercase; line-height: 16px; color: var(--text-dim); }
.xp-q3 { border-color: var(--accent); color: var(--accent); }
.xp-q4 { border-color: var(--phosphor); color: var(--phosphor); }
.xp-hole { white-space: nowrap; }
.xp-holes strong { color: var(--text-bright); }
.xp-go { white-space: nowrap; }
.xp-go .route-link, .xp-tip-links .route-link { display: inline-flex; align-items: center; min-height: 32px; margin: 0 var(--sp-2) 0 0; padding: 0 var(--sp-1); }
.xp-tip-links { margin-top: var(--sp-2); }
.xs-loot-tag { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: 32px; margin: 0 var(--sp-2) var(--sp-1) 0; padding: 0 var(--sp-4); border: 1px solid var(--edge); background: transparent; color: var(--accent); font: inherit; font-size: var(--fs-xs); cursor: pointer; }
.xs-loot-tag.active { border-color: var(--phosphor); color: var(--phosphor); }
.xs-items { display: grid; margin: var(--sp-2) 0; min-width: 0; }
.xs-item { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-3); padding: var(--sp-1) 0; border-bottom: 1px solid var(--row-line); font-size: var(--fs-sm); }
.xs-item > span { min-width: 0; overflow-wrap: anywhere; }
.xs-item > span:nth-child(n+2) { text-align: right; }
.xs-itemhead { font-weight: 700; color: var(--text-dim); }
/* The map leads the page; the list follows it. */
#xe-map { height: clamp(300px, 56vh, 560px); margin-bottom: var(--sp-5); }

@media (min-width: 769px) and (not ((pointer: coarse) and (max-height: 500px))) {
  .xp-group { flex: 0 1 auto; margin: 0 var(--sp-6) 0 0; }
  .xp-search { flex: 0 1 auto; margin: 0; }
  .exploration-page :is(td.xp-name, th:first-child) { min-width: 260px; }
  .xp-table td.xp-holes { min-width: 15em; }
  .xp-table :is(th, td) { text-align: left; }
  #xs-table :is(th, td):nth-child(2) { width: 14%; }
  #xs-table :is(th, td):nth-child(3) { width: 22%; }
}

@media (max-width: 768px), (pointer: coarse) and (max-height: 500px) {
  #xe-map { height: clamp(260px, 42vh, 380px); }
  .exploration-page td.xp-name { padding-top: var(--sp-4); padding-bottom: var(--sp-4); }
  .xs-item a { display: inline-flex; align-items: center; min-height: 32px; }
}
}
