@import url("./tokens-4EF72C5C.css");

/* ---------------------------------------------------------------- the idea
   Hangar answers one question: can I put these ships in space right now?
   EVE answers its own version of that with the HUD, so this reads as a HUD.

   Three rules hold the sheet together.

   1. Colour is data. Saturated colour never appears on chrome, brand or
      controls — only on a fact about your stock. Four meanings, no more:
      you have it, a rule says yes, it needs attention, it isn't there.
   2. Depth comes from value, not from lines or shadows. Panels have no
      border. The void/well/hull ladder does the separating, the way EVE's
      translucent windows stack over black.
   3. Surfaces that do different jobs look different. CCP's HUD rework calls
      this proximity and similarity; the console you operate is a darker,
      recessed surface, and the readouts it drives are lit slabs.
   ---------------------------------------------------------------------- */

* {
  box-sizing: border-box;
}
body {
  margin: 0;
  background: var(--void);
  color: var(--text);
  font-family: var(--font);
  font-size: 13px;
  line-height: 1.55;
  font-stretch: var(--w-normal);
  /* Figures that get compared have to line up. */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}
button,
input,
textarea,
select {
  font: inherit;
  font-stretch: inherit;
}
button,
a,
input,
textarea,
select {
  -webkit-tap-highlight-color: transparent;
}
button {
  cursor: pointer;
}
a {
  color: inherit;
  text-decoration: none;
}
button:disabled {
  opacity: 0.35;
  cursor: default;
}
/* Neutral and bright: a focus ring is chrome, and chrome is never coloured. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}
/* A clip-path crops the element's own outline, so every chamfered control
   carries its focus ring on the inside, where the cut cannot reach it. The
   ring follows the same cut corners as the fill. */
.primary:focus-visible,
.secondary:focus-visible,
.elsewhere:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--text);
}
.primary:focus-visible {
  box-shadow: inset 0 0 0 2px var(--void);
}
[hidden] {
  /* biome-ignore lint/complexity/noImportantStyles: The hidden attribute must override component display rules. */
  display: none !important;
}
::selection {
  background: var(--seam-lit);
  color: #fff;
}

/* ------------------------------------------------------------------- type
   One family. Width does the work size usually does: racks, tables and
   labels run condensed the way EVE fills a window, and the readiness count
   runs wide because it is the number you came for. */
h1 {
  font-size: clamp(24px, 2.6vw, 31px);
  font-weight: 500;
  font-stretch: var(--w-normal);
  letter-spacing: -0.015em;
  line-height: 1.15;
  margin: 0 0 10px;
  max-width: 20ch;
}
h2 {
  font-size: 13px;
  font-weight: 600;
  font-stretch: var(--w-narrow);
  letter-spacing: 0.03em;
  margin: 0;
}
h3 {
  font-size: 13px;
  font-weight: 600;
  font-stretch: var(--w-dense);
  margin: 0;
}
p {
  margin: 8px 0;
}
.page-heading {
  margin: 30px 0 24px;
}
.page-heading p {
  color: var(--muted);
  font-size: 13px;
  max-width: 58ch;
  margin: 0;
}
.helper {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.6;
  max-width: 62ch;
}
.panel-heading .helper {
  margin: 4px 0 0;
}
/* A footnote, not a banner: sentence case, no tracking, no colour. */
.eyebrow {
  font-size: 12px;
  color: var(--faint);
  font-weight: 400;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------- the shell
   A Neocom down the left, a HUD across the top. The sidebar is the darkest
   thing on screen because it is the frame, not the content. */
.sidebar {
  width: 232px;
  position: fixed;
  inset: 0 auto 0 0;
  background: var(--neocom);
  border-right: 1px solid var(--seam);
  padding: 26px 16px;
  display: flex;
  flex-direction: column;
  z-index: 5;
}
.brand {
  display: flex;
  gap: 11px;
  align-items: center;
  font-size: 19px;
  font-weight: 600;
  font-stretch: var(--w-dense);
  letter-spacing: 0.14em;
  padding: 0 4px;
}
/* The mark repeats the favicon's cut corners, which is where the chamfer on
   every panel below comes from. */
.brand-icon {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  background: var(--text);
  color: var(--neocom);
  font-size: 17px;
  font-weight: 700;
  font-stretch: var(--w-dense);
  letter-spacing: 0;
  clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
}
.brand small {
  display: block;
  font-size: 9px;
  letter-spacing: 0.16em;
  font-weight: 400;
  font-stretch: var(--w-narrow);
  color: var(--faint);
  margin-top: -2px;
}
.sidebar-label {
  font-size: 12px;
  color: var(--faint);
  margin: 36px 8px 8px;
}
nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
nav a {
  padding: 9px 12px;
  color: var(--muted);
  display: flex;
  gap: 11px;
  align-items: center;
  font-size: 13px;
  font-stretch: var(--w-dense);
  border-left: 2px solid transparent;
}
nav a span {
  font-size: 15px;
  width: 18px;
  color: var(--faint);
}
nav a:hover {
  background: var(--void);
  color: var(--text);
}
/* The open page is marked by a lit edge and a lit surface. No accent colour:
   position is chrome, and chrome stays neutral. */
nav a.active {
  background: var(--hull);
  color: var(--text);
  border-left-color: var(--text);
}
nav a.active span {
  color: var(--text);
}
nav b {
  font-size: 11px;
  font-weight: 500;
  font-stretch: var(--w-narrow);
  color: var(--faint);
  margin-left: auto;
}
.local-card {
  margin-top: auto;
  padding: 14px 12px;
  background: var(--void);
  font-size: 12px;
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px);
}
.local-card > strong {
  display: block;
  font-weight: 600;
  font-stretch: var(--w-narrow);
  margin-bottom: 6px;
}
.quiet {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 3px 0;
  font-size: 12px;
  text-align: left;
}
.quiet:hover {
  color: var(--text);
}
.local-card .quiet {
  display: block;
}
.sidebar-bottom {
  font-size: 11px;
  color: var(--faint);
  margin: 20px 0 0 4px;
}
main {
  margin-left: 232px;
}
.workspace {
  padding: 0 32px;
  max-width: 1560px;
  margin: auto;
}

/* ----------------------------------------------------------------- the HUD
   EVE's HUD never scrolls away, so neither does this. The readiness count is
   the answer the tool exists to give; it used to sit three panels down the
   page as five grey dashes. It is chrome now, on every page. */
.hud {
  position: sticky;
  top: 0;
  z-index: 4;
  height: 64px;
  background: var(--neocom);
  border-bottom: 1px solid var(--seam);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 0 32px;
}
.hud-readout {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}
.hud-count {
  margin: 0;
  min-width: 0;
}
#readiness-title {
  display: block;
  font-size: 18px;
  font-weight: 600;
  font-stretch: var(--w-wide);
  letter-spacing: -0.01em;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The count says how full the request is. This says what to do about the rest,
   which is the part you cannot work out from the count alone. */
.hud-note {
  display: block;
  font-size: 12px;
  font-stretch: var(--w-dense);
  color: var(--muted);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hud-note.clear {
  color: var(--exact);
}
.sync-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 0 0 auto;
}
#save-status {
  font-size: 12px;
  font-stretch: var(--w-dense);
  color: var(--faint);
}

/* ------------------------------------------------------------ the medallion
   CCP kept the capacitor circular through the HUD rework because the shape
   is the identity. One segment is one requested ship, so the ring reads the
   way a capacitor already reads: how full am I, right now.
   Drawn as SVG because the content policy forbids the inline styles a CSS
   ring would need, and because arcs are what SVG is for. */
.medallion {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  display: block;
}
/* An empty segment still has to read as a segment: the ring is the gauge, and
   a gauge you cannot see the empty part of does not tell you anything. */
.medallion .seg {
  fill: none;
  stroke: var(--seam-lit);
  stroke-width: 8;
}
.medallion .seg.exact {
  stroke: var(--exact);
}
.medallion .seg.variant {
  stroke: var(--variant);
}
/* The bezel. A capacitor is an instrument set into a housing, and the ring on
   its own reads as a donut chart instead. */
.medallion .bezel {
  fill: none;
  stroke: var(--seam);
  stroke-width: 1;
}
/* The one piece of motion in the app. It runs only when the count actually
   changes, and it runs once: a charge sweeping the ring, which is the thing
   that just happened. */
.medallion.lit .sweep {
  fill: none;
  stroke: var(--text);
  stroke-width: 8;
  opacity: 0;
  animation: charge 620ms ease-out 1;
}
@keyframes charge {
  0% {
    opacity: 0.5;
    stroke-dashoffset: 0;
  }
  100% {
    opacity: 0;
    stroke-dashoffset: -95;
  }
}

/* --------------------------------------------------------------- surfaces
   Panels carry no border. They are lit slabs on a dark ground, cut at two
   corners the way the mark is cut. */
.panel {
  background: var(--hull);
  padding: 20px;
  clip-path: polygon(
    var(--cut) 0,
    100% 0,
    100% calc(100% - var(--cut)),
    calc(100% - var(--cut)) 100%,
    0 100%,
    0 var(--cut)
  );
}
/* A console takes input; a readout reports. They used to be the same slab,
   which is the similarity trap CCP's HUD rework calls out: things that do
   different jobs should not look alike. A console is recessed, not lit. */
.console {
  background: var(--well);
  box-shadow: inset 2px 0 0 var(--seam);
}
.fit-panel {
  align-self: start;
}
/* Reading a fit against the results below is the whole task, so the console
   rides down with them instead of leaving an empty column behind. */
@media (min-width: 901px) and (min-height: 700px) {
  .fit-panel {
    position: sticky;
    top: 80px;
    max-height: calc(100vh - 96px);
    overflow-y: auto;
  }
}
/* Panels stacked straight down a page need the gap; the ones inside .results
   and .two-column get theirs from the grid. */
.page > .panel + .panel {
  margin-top: 16px;
}
.panel-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 16px;
}
.panel-heading > div {
  min-width: 0;
}
.divider {
  border-top: 1px solid var(--seam);
  margin: 18px 0;
}
.checker-grid {
  display: grid;
  grid-template-columns: 288px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
.results {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}
.two-column {
  display: grid;
  grid-template-columns: 330px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
.origins {
  display: block;
  color: var(--muted);
}

/* --------------------------------------------------------------- controls
   Buttons are raised steel; inputs are wells sunk below the surface they sit
   on. Value says which way a control faces, so no control needs colour. */
.primary,
.secondary {
  border: 0;
  padding: 9px 14px;
  font-size: 12px;
  font-weight: 600;
  font-stretch: var(--w-dense);
  color: var(--text);
  background: var(--hull-lit);
  clip-path: polygon(
    var(--cut-sm) 0,
    100% 0,
    100% calc(100% - var(--cut-sm)),
    calc(100% - var(--cut-sm)) 100%,
    0 100%,
    0 var(--cut-sm)
  );
}
/* Brightness, not hue, marks the main action. */
.primary {
  background: var(--text);
  color: var(--void);
}
.primary:hover:not(:disabled) {
  background: #fff;
}
.secondary:hover:not(:disabled) {
  background: var(--hull-hot);
}
.danger {
  color: var(--short);
}
label {
  display: block;
  font-size: 12px;
  font-weight: 500;
  font-stretch: var(--w-dense);
  color: var(--muted);
  margin: 14px 0 6px;
}
input,
select,
textarea {
  width: 100%;
  border: 1px solid var(--seam);
  background: var(--well);
  color: var(--text);
  padding: 9px 11px;
  font-size: 13px;
}
.console input,
.console select,
.console textarea,
dialog input,
dialog select,
dialog textarea {
  background: var(--void);
}
select {
  padding-right: 24px;
}
input:hover,
select:hover,
textarea:hover {
  border-color: var(--seam-lit);
}
input::placeholder,
textarea::placeholder {
  color: var(--faint);
}
textarea {
  resize: vertical;
}
input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--seam-lit);
  margin: 0;
  flex: 0 0 auto;
}
.check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 400;
  color: var(--text);
  margin: 18px 0 8px;
}
.fit-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
}
.import-actions,
.paste-actions,
.dialog-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}
.dialog-actions {
  justify-content: flex-end;
  margin-top: 20px;
}
.stock-form {
  display: grid;
  grid-template-columns: 2fr 2fr 95px auto;
  gap: 12px;
  align-items: end;
  margin-bottom: 18px;
}
.stock-form label,
.request-form label,
dialog label {
  margin-top: 0;
}
.stock-form button,
.request-form button {
  height: 38px;
}
.request-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 110px auto;
  align-items: end;
  gap: 12px;
  margin-bottom: 18px;
}
.stock-filter {
  margin: 0 0 12px;
}
.stock-qty {
  width: 92px;
  text-align: right;
  padding: 5px 8px;
}
#paste-text {
  font-family: inherit;
  resize: vertical;
}
.sync-button .spinner {
  display: inline-block;
  width: 0.8em;
  height: 0.8em;
  margin-right: 0.45em;
  vertical-align: -0.08em;
  border: 2px solid currentcolor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ----------------------------------------------------------------- tables
   Dense on purpose. This audience reads the overview; the job is to make the
   density legible, not to thin it out. */
.table-wrap {
  overflow-x: auto;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-stretch: var(--w-dense);
}
th {
  text-align: left;
  color: var(--faint);
  font-size: 12px;
  font-weight: 500;
  font-stretch: var(--w-narrow);
  padding: 0 8px 9px;
  border-bottom: 1px solid var(--seam);
  white-space: nowrap;
}
td {
  padding: 10px 8px;
  border-bottom: 1px solid var(--well);
}
td small {
  display: block;
  font-size: 11px;
  color: var(--faint);
  margin-top: 2px;
}
th:first-child,
td:first-child {
  padding-left: 0;
}
th:last-child,
td:last-child {
  padding-right: 0;
}
tbody tr:last-child td {
  border: 0;
}
.numeric {
  text-align: right;
}
/* An item you are short of, and one you have covered. */
.missing {
  color: var(--short);
  font-weight: 600;
}
.covered {
  color: var(--exact);
}
/* In these columns .covered only ever marks an em dash: nothing to move,
   nothing to buy. Nothing is not a state worth colouring. */
td.covered {
  color: var(--faint);
}
td.movable {
  color: var(--haul);
}
.empty {
  color: var(--faint);
  padding: 18px 0;
  font-size: 12px;
}

/* ------------------------------------------------------------------ marks
   Tags and badges are the same cut shape at two sizes. A badge that carries
   a state colour is stating a fact about your stock; a neutral one is only
   labelling. */
.tag {
  display: inline-block;
  white-space: nowrap;
  font-size: 11px;
  font-stretch: var(--w-narrow);
  letter-spacing: 0.02em;
  border: 1px solid var(--seam);
  padding: 3px 8px;
  color: var(--faint);
  flex: 0 0 auto;
}
.badge {
  font-size: 11px;
  font-stretch: var(--w-narrow);
  padding: 3px 8px;
  white-space: nowrap;
  background: var(--hull-lit);
  color: var(--muted);
  clip-path: polygon(5px 0, 100% 0, 100% calc(100% - 5px), calc(100% - 5px) 100%, 0 100%, 0 5px);
}
.badge.exact,
.badge.counted,
.badge.tally {
  background: color-mix(in oklab, var(--exact) 18%, var(--hull));
  color: var(--exact);
}
.badge.variant {
  background: color-mix(in oklab, var(--variant) 18%, var(--hull));
  color: var(--variant);
}
.badge.supply {
  background: color-mix(in oklab, var(--haul) 18%, var(--hull));
  color: var(--haul);
}
.badge.selected {
  background: var(--hull-hot);
  color: var(--text);
}
.badge.spare-ship,
.badge.browsing {
  background: transparent;
  border: 1px solid var(--seam);
  color: var(--faint);
}
.supply-note {
  color: var(--haul);
}
.spare-note {
  color: var(--faint);
}

/* ------------------------------------------------------- the fit being read
   A hull is a thing, so it gets a picture of a thing rather than another row
   of text. */
.hull-card {
  margin: 18px 0 10px;
  padding: 14px;
  background: var(--hull);
  display: flex;
  align-items: center;
  gap: 13px;
  clip-path: polygon(
    var(--cut) 0,
    100% 0,
    100% calc(100% - var(--cut)),
    calc(100% - var(--cut)) 100%,
    0 100%,
    0 var(--cut)
  );
}
.hull-symbol {
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  color: var(--muted);
  border: 1px solid var(--seam-lit);
  transform: rotate(45deg);
}
.hull-symbol span {
  transform: rotate(-45deg);
  font-size: 19px;
}
.hull-card strong {
  font-size: 17px;
  font-weight: 500;
  font-stretch: var(--w-dense);
}
.hull-card small {
  display: block;
  color: var(--muted);
  font-size: 11px;
}
.requirement-group {
  padding: 9px 0;
  border-bottom: 1px solid var(--seam);
}
.requirement-group:last-child {
  border: 0;
}
.group-label {
  font-size: 11px;
  font-stretch: var(--w-narrow);
  color: var(--faint);
  margin-bottom: 6px;
}
.requirement {
  display: flex;
  gap: 7px;
  justify-content: space-between;
  align-items: baseline;
  font-size: 12px;
  margin: 5px 0;
}
.requirement span {
  max-width: 210px;
}
.requirement b {
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
  white-space: nowrap;
}
.alt-indicator {
  font-style: normal;
  color: var(--variant);
  margin-left: 4px;
}
.warning {
  font-size: 12px;
  color: var(--haul);
  border-left: 2px solid var(--haul);
  padding-left: 10px;
  margin-top: 14px;
}

/* ------------------------------------------------------------- ship rows
   One disclosure treatment for every expandable row. A <summary> keeps its
   native marker on its own line as soon as a child is block level, and
   .ship-top has to be a flex row, so the marker is drawn instead. */
.ship-row {
  border-top: 1px solid var(--seam);
  padding: 10px 0;
}
.ship-row:first-child {
  border-top: 0;
  padding-top: 0;
}
.ship-row:last-child {
  padding-bottom: 0;
}
.ship-top {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
}
.ship-name {
  font-size: 13px;
  font-stretch: var(--w-dense);
}
.ship-name small {
  display: block;
  color: var(--faint);
  font-size: 11px;
}
.ship-quality {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
/* A progress element rather than a styled span: the content security policy
   forbids inline styles, and this is what the element is for. It stays
   neutral — the badge beside it is what states the verdict. */
.quality-bar {
  appearance: none;
  width: 44px;
  height: 4px;
  border: 0;
  overflow: hidden;
  background: var(--hull-lit);
  color: var(--muted);
}
.quality-bar::-webkit-progress-bar {
  background: var(--hull-lit);
}
.quality-bar::-webkit-progress-value {
  background: var(--muted);
}
.quality-bar::-moz-progress-bar {
  background: var(--muted);
}
.quality-count {
  font-size: 11px;
  color: var(--faint);
  white-space: nowrap;
}
.ship-group + .ship-group {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--seam);
}
.ship-group h3 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 10px;
}
.group-name small {
  display: block;
  color: var(--muted);
  font-size: 11px;
  font-weight: 400;
  font-stretch: var(--w-normal);
}
.group-why {
  display: flex;
  gap: 6px;
}
.ship-items li,
.why-group li,
.ship-row ul li,
.assigned-ships li {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.line-name {
  flex: 1 1 auto;
  min-width: 0;
}
/* The slot is the same fact on every line, so it belongs in the same place
   on every line. */
.line-slot {
  flex: 0 0 auto;
  color: var(--faint);
  font-size: 11px;
  text-align: right;
}
.ship-items .mark,
.why-group .mark {
  display: inline-block;
  width: 1.1em;
  font-weight: 700;
}
.ship-items li.fits {
  color: var(--exact);
}
.ship-items li.spare,
.why-group li.absent {
  color: var(--haul);
}
.why {
  margin: 8px 0 4px;
  padding: 9px 12px;
  border-left: 2px solid var(--seam-lit);
  background: var(--well);
}
.why p {
  margin: 0 0 8px;
}
.why ul {
  margin: 4px 0 0;
}
.why-group + .why-group {
  margin-top: 8px;
}
.assigned-ships {
  margin-top: 8px;
  font-size: 12px;
  color: var(--muted);
}
details ul {
  padding-left: 18px;
  font-size: 12px;
  color: var(--muted);
  columns: 2;
}
.assigned-ships ul {
  columns: 1;
}

/* ---------------------------------------------------------------- reveals
   Long lists start closed so a page opens on its summary, not its data. The
   count stays in the heading, so collapsing hides rows and never signal. */
.collapse > summary,
.ship-row > summary,
.assigned-ships > summary {
  cursor: pointer;
  list-style: none;
}
.collapse > summary {
  color: var(--muted);
  font-size: 12px;
  padding: 3px 0;
}
.collapse > summary::-webkit-details-marker,
.ship-row > summary::-webkit-details-marker,
.assigned-ships > summary::-webkit-details-marker {
  display: none;
}
.collapse > summary::before,
.ship-row > summary::before,
.assigned-ships > summary::before {
  content: "+";
  display: inline-block;
  width: 1.1em;
  flex: 0 0 auto;
  color: var(--faint);
  font-weight: 600;
}
.collapse[open] > summary::before,
.ship-row[open] > summary::before,
.assigned-ships[open] > summary::before {
  content: "\2212";
}
.collapse > summary:hover {
  color: var(--text);
}
.collapse[open] > summary {
  margin-bottom: 8px;
}
.ship-row > summary,
.assigned-ships > summary {
  display: flex;
  align-items: center;
  gap: 8px;
}
.ship-row > summary > .ship-top {
  flex: 1 1 auto;
  min-width: 0;
}
/* Meta lines read as separate facts, divided by a rule rather than the
   middle dot borrowed from a byline.
   inline-flex, not flex: inside a <summary> a block-level child pushes the
   disclosure marker onto its own line above the name. */
.meta {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0 10px;
  vertical-align: baseline;
}
.meta > span + span {
  padding-left: 10px;
  border-left: 1px solid var(--seam-lit);
}

/* ------------------------------------------------------- readiness detail
   The medallion up top says how full the request is. This says what filled
   it and where those ships are — grouped together, because that is one
   question asked three ways. It had corner ticks marking it as the panel the
   HUD reads from; at this size they were a mark you had to decode rather than
   one you could read, and the panel's own text already says it. */
.readiness {
  display: block;
}
.readout-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.readout-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  margin-top: 4px;
}
.readout-legend .metric {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.readout-legend .metric-number {
  font-size: 17px;
  font-weight: 600;
  font-stretch: var(--w-wide);
  color: var(--muted);
}
.readout-legend .metric-title {
  font-size: 12px;
  font-stretch: var(--w-dense);
  color: var(--muted);
}
.readout-legend .metric small {
  display: none;
}
.readout-legend .exact .metric-number {
  color: var(--exact);
}
.readout-legend .variant .metric-number {
  color: var(--variant);
}
.readout-legend .short .metric-number {
  color: var(--text);
}
.readout-legend .move .metric-number {
  color: var(--haul);
}
/* Ships parked at another station are not missing, they are just not here.
   Naming them turns a bare zero into somewhere to go. */
.readout-elsewhere {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
}
.readout-elsewhere:empty {
  display: none;
}
.elsewhere {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 9px;
  font-size: 12px;
  font-stretch: var(--w-dense);
  color: var(--text);
  background: var(--hull-lit);
  border: 0;
  clip-path: polygon(5px 0, 100% 0, 100% calc(100% - 5px), calc(100% - 5px) 100%, 0 100%, 0 5px);
}
.elsewhere:hover {
  background: var(--hull-hot);
}
.elsewhere span {
  color: var(--haul);
  font-weight: 600;
}
button.elsewhere .where {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.3;
}
button.elsewhere .where small {
  color: var(--faint);
  font-size: 11px;
}
.request-summary {
  font-size: 13px;
  color: var(--text);
  margin-top: 16px;
}
.multibuy-details {
  border-top: 1px solid var(--seam);
  margin-top: 16px;
  padding-top: 14px;
  font-size: 12px;
  color: var(--muted);
}
/* Monospace because this text really is machine input: it goes into EVE's
   Multibuy window, where the columns have to line up. */
#multibuy-preview {
  font-family: var(--font-mono);
  font-size: 12px;
  white-space: pre;
  tab-size: 4;
}

/* -------------------------------------------------------------- hauling
   A shortfall covered by moving is not a shortfall to buy, but it is still
   a shortfall here. */
.haul {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--seam);
}
.haul-title {
  margin: 0 0 10px;
  color: var(--haul);
  font-size: 12px;
  font-stretch: var(--w-dense);
}
.haul td button.elsewhere {
  margin: 2px 4px 2px 0;
}
.manifest {
  border-top: 1px solid var(--seam);
  padding: 12px 0;
}
.manifest:first-of-type {
  border-top: 0;
}
.manifest-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.manifest-head small {
  display: block;
  color: var(--faint);
  font-size: 11px;
}
.manifest-actions {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
button.manifest-place {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--seam-lit);
}
button.manifest-place:hover {
  text-decoration-color: var(--text);
}
.manifest table {
  margin-top: 8px;
}

/* ---------------------------------------------------------------- rules */
.rule-card {
  margin-bottom: 12px;
}
.rule-heading {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 15px;
}
.rule-heading strong {
  font-size: 14px;
  font-weight: 600;
  font-stretch: var(--w-dense);
}
.rule-card .check {
  margin: 0;
  font-size: 12px;
}
.rule-alternatives {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 13px 0;
}
/* An approved alternative is the substitution state, stated as stock: this
   is the thing a rule says yes to. */
.rule-alternatives span {
  padding: 4px 9px;
  font-size: 12px;
  font-stretch: var(--w-dense);
  background: color-mix(in oklab, var(--variant) 14%, var(--hull));
  color: var(--variant);
  clip-path: polygon(5px 0, 100% 0, 100% calc(100% - 5px), calc(100% - 5px) 100%, 0 100%, 0 5px);
}
.rule-direction {
  color: var(--faint);
  font-size: 11px;
  margin: 10px 0 0;
}
.rule-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
/* Two actions, not one run-on word: .quiet has no side padding, so the space
   between the buttons in the markup collapsed to nothing. */
.rule-bottom > div {
  display: flex;
  gap: 14px;
}
.inventory-ships {
  margin-top: 20px;
}
#characters-panel .stack-checkbox {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 12px 0 4px;
}
#characters-panel details {
  margin-top: 12px;
}
#characters-panel summary {
  cursor: pointer;
  color: var(--muted);
}
#characters-panel code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  word-break: break-all;
}

/* ------------------------------------------------------------- overlays */
dialog {
  width: min(630px, calc(100vw - 32px));
  border: 0;
  background: var(--hull);
  color: var(--text);
  padding: 24px;
  max-height: 90vh;
  clip-path: polygon(
    var(--cut) 0,
    100% 0,
    100% calc(100% - var(--cut)),
    calc(100% - var(--cut)) 100%,
    0 100%,
    0 var(--cut)
  );
}
dialog::backdrop {
  background: #030910cc;
  backdrop-filter: blur(4px);
}
dialog textarea {
  font-family: var(--font-mono);
  font-size: 12px;
}
#toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  padding: 12px 20px;
  background: var(--hull-hot);
  color: var(--text);
  border-left: 3px solid var(--exact);
  max-width: 90vw;
  z-index: 10;
}
#toast.error {
  border-left-color: var(--short);
}
footer {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 11px;
  color: var(--faint);
  padding: 28px 0;
}
footer > span:last-child {
  white-space: nowrap;
}
/* The trademark notice has to be present, but it does not have to occupy
   the sidebar. It reveals on hover and on keyboard focus. */
.legal {
  position: relative;
  display: inline-block;
}
.legal-trigger {
  padding: 0;
  border: 0;
  background: none;
  color: var(--faint);
  font: inherit;
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.legal-notice {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  width: 250px;
  padding: 10px 12px;
  background: var(--hull-hot);
  z-index: 20;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.5;
  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms ease;
}
.legal:hover .legal-notice,
.legal:focus-within .legal-notice {
  opacity: 1;
  visibility: visible;
}

/* ------------------------------------------------------------ responsive */
@media (min-width: 1500px) {
  .workspace {
    padding: 0 40px;
  }
  .hud {
    padding: 0 40px;
  }
  .panel {
    padding: 24px;
  }
  .checker-grid {
    grid-template-columns: 320px minmax(0, 1fr);
  }
  .requirement span {
    max-width: 240px;
  }
}
@media (max-width: 1150px) {
  .sidebar {
    width: 196px;
    padding: 22px 12px;
  }
  main {
    margin-left: 196px;
  }
  .workspace,
  .hud {
    padding: 0 20px;
  }
  .checker-grid {
    grid-template-columns: 250px minmax(0, 1fr);
    gap: 14px;
  }
  .panel {
    padding: 16px;
  }
  .two-column {
    grid-template-columns: 290px minmax(0, 1fr);
  }
  .stock-form {
    grid-template-columns: 1fr 1fr;
  }
  .panel-heading {
    flex-wrap: wrap;
  }
}
@media (max-width: 900px) {
  .sidebar {
    width: 172px;
  }
  main {
    margin-left: 172px;
  }
  .brand {
    font-size: 16px;
    gap: 8px;
    letter-spacing: 0.1em;
  }
  .brand small {
    font-size: 8px;
  }
  .brand-icon {
    width: 26px;
    height: 26px;
    font-size: 15px;
  }
  nav a {
    padding: 8px 9px;
    gap: 7px;
    font-size: 12px;
  }
  .checker-grid,
  .two-column {
    grid-template-columns: 1fr;
  }
  .fit-panel {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 18px;
  }
  .fit-panel .panel-heading,
  .fit-panel #fit-summary,
  .fit-panel .fit-actions,
  .fit-panel .divider,
  .fit-panel #fit-warnings,
  .fit-panel .check,
  .fit-panel .helper {
    grid-column: 1 / -1;
  }
  .fit-panel #fit-summary {
    display: none;
  }
  .fit-panel .divider {
    margin: 14px 0;
  }
  details ul {
    columns: 1;
  }
}
@media (max-width: 620px) {
  .sidebar {
    position: static;
    width: 100%;
    padding: 14px 16px 8px;
    border-right: 0;
    border-bottom: 1px solid var(--seam);
  }
  .brand small,
  .sidebar-label,
  .sidebar-bottom {
    display: none;
  }
  nav {
    flex-direction: row;
    margin-top: 14px;
    gap: 2px;
  }
  nav a {
    flex: 1;
    justify-content: center;
    font-size: 11px;
    padding: 8px 4px;
    gap: 5px;
    border-left: 0;
    border-bottom: 2px solid transparent;
  }
  nav a.active {
    border-left: 0;
    border-bottom-color: var(--text);
  }
  nav a span {
    font-size: 14px;
    width: auto;
  }
  nav b {
    display: none;
  }
  .local-card {
    margin: 10px 0 0;
    padding: 0;
    background: none;
    clip-path: none;
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 11px;
  }
  .local-card > strong {
    display: none;
  }
  .local-card::before {
    content: "Backups";
    color: var(--faint);
    font-size: 11px;
    margin-right: auto;
  }
  main {
    margin: 0;
  }
  /* On a phone the HUD sits where a thumb already is, which is where EVE
     puts it too. */
  .hud {
    position: fixed;
    inset: auto 0 0;
    top: auto;
    height: 56px;
    padding: 0 16px;
    border-top: 1px solid var(--seam);
    border-bottom: 0;
  }
  .medallion {
    width: 36px;
    height: 36px;
  }
  #readiness-title {
    font-size: 16px;
  }
  .workspace {
    padding: 0 16px 72px;
  }
  .page-heading {
    margin: 22px 0 18px;
  }
  .fit-panel {
    display: block;
  }
  .request-form {
    grid-template-columns: minmax(0, 1fr) 100px;
  }
  .request-form > div:first-child {
    grid-column: 1 / -1;
  }
  .stock-form {
    grid-template-columns: 1fr 100px;
  }
  .stock-form > div:first-child,
  .stock-form > div:nth-child(2) {
    grid-column: 1 / -1;
  }
  .request-panel th,
  .request-panel td {
    padding-left: 5px;
    padding-right: 5px;
  }
  .request-panel .stock-qty {
    width: 68px;
  }
  .ship-top {
    align-items: start;
  }
  footer {
    display: block;
  }
  footer span {
    display: block;
    margin-top: 4px;
  }
}

/* A spinner and a charge sweep are both there to draw the eye. The button
   text, #save-status and the count itself carry the actual state, so
   stopping them costs nothing. */
@media (prefers-reduced-motion: reduce) {
  .sync-button .spinner {
    animation: none;
    border-top-color: currentcolor;
    opacity: 0.5;
  }
  .medallion.lit .sweep {
    animation: none;
  }
  .legal-notice {
    transition: none;
  }
}
