/* Modernist — design-system tokens and component classes. This file is the source of truth for the system's look; retune it here and see readme.md. */
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;600;800&display=swap');

:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201e1d;
  --color-accent: #ec3013;
  --color-accent-2: #e15b47;
  --color-divider: color-mix(in srgb, #201e1d 40%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  --color-accent-100: #fff2ef;
  --color-accent-200: #ffe0d9;
  --color-accent-300: #ffc4b8;
  --color-accent-400: #ff9783;
  --color-accent-500: #ff563c;
  --color-accent-600: #dd2b0f;
  --color-accent-700: #ae1800;
  --color-accent-800: #7c1405;
  --color-accent-900: #4d170e;

  --color-accent-2-100: #fff2ef;
  --color-accent-2-200: #ffe0da;
  --color-accent-2-300: #ffc4b9;
  --color-accent-2-400: #ff9784;
  --color-accent-2-500: #ef6853;
  --color-accent-2-600: #c94b39;
  --color-accent-2-700: #9e3526;
  --color-accent-2-800: #71261b;
  --color-accent-2-900: #471d16;

  --font-heading: "Archivo", system-ui, sans-serif;
  --font-heading-weight: 800;
  --font-body: "Archivo", system-ui, sans-serif;

  --space-1: 4.0px;
  --space-2: 8.0px;
  --space-3: 12.0px;
  --space-4: 16.0px;
  --space-6: 24.0px;
  --space-8: 32.0px;

  --radius-sm: 0px;
  --radius-md: 0px;
  --radius-lg: 0px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one. */
  --shadow-sm: 0 1px 2px color-mix(in srgb, #2d2b2b 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2d2b2b 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2d2b2b 22%, transparent);
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }

.grayscale{filter:grayscale(1) contrast(1.08)}

/* A listing card's photo. History draws it in greyscale and dimmed so finished offers read as past at
   a glance; hovering (or tabbing to) one brings the colour most of the way back, since the reason
   to point at a past offer is to look at it. */
.sale-card-photo { position: absolute; inset: 0; transition: filter .2s ease, opacity .2s ease; }
.sale-card-photo.is-history { filter: grayscale(1) contrast(1.08); opacity: .75; }
.clickable-card:hover .sale-card-photo.is-history,
.clickable-card:focus-visible .sale-card-photo.is-history { filter: grayscale(.2) contrast(1.08); opacity: 1; }
@media (prefers-reduced-motion: reduce) { .sale-card-photo { transition: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

html, body {
  max-width: 100%;
  overflow-x: clip;
}

*, *::before, *::after { box-sizing: border-box; min-width: 0; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; overflow-wrap: break-word; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }

@media (max-width: 768px) {
  h1 { font-size: 28px; }
  h2 { font-size: 23px; }
  h3 { font-size: 19px; }
  h4 { font-size: 17px; }
}

p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; height: auto; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
.hr {
  height: 2px; border: 0; margin: var(--space-4) 0;
  background: var(--color-divider);
}

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); color: var(--color-bg); }
.btn-primary:hover { background: var(--color-accent-600); }
.btn-primary:active { background: var(--color-accent-700); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); justify-content: flex-start; text-align: left; }

/* — forms — */
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }
.slider-wrap {
  display: flex; align-items: center; min-height: 36px;
}
.slider {
  display: block;
  width: 100%; height: 20px; padding: 0; margin: 0;
  accent-color: var(--color-accent); cursor: pointer; background: transparent;
}
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input, .seg-opt input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.radio .dot {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--color-divider);
}
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked) { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* A select that takes several values: a <details> dressed as an .input, with the header's overflow
   menu as its panel. js/nav-menu.js closes it on an outside click, as it does that menu. */
.multiselect { position: relative; }
.multiselect-summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
}
.multiselect-summary::-webkit-details-marker { display: none; }
.multiselect-summary > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.multiselect-summary svg { flex: none; opacity: .6; transition: transform .12s; }
.multiselect[open] .multiselect-summary { border-color: var(--color-accent); }
.multiselect[open] .multiselect-summary svg { transform: rotate(180deg); }
.multiselect-menu {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 110;
  min-width: 100%; padding: 4px 0;
  display: flex; flex-direction: column;
  background: var(--color-bg);
  border: 2px solid var(--color-divider);
  box-shadow: var(--shadow-md);
}
.multiselect-opt {
  display: flex; align-items: center; gap: 10px;
  padding: 8px var(--space-3); font-size: 14px; white-space: nowrap; cursor: pointer;
}
.multiselect-opt:hover { background: var(--color-surface); }
.multiselect-opt input { width: 16px; height: 16px; margin: 0; flex: none; accent-color: var(--color-accent); cursor: pointer; }
@media (prefers-reduced-motion: reduce) { .multiselect-summary svg { transition: none; } }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta {
  display: flex; align-items: center; gap: 6px; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-accent-2 { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
.tag-neutral { background: var(--color-neutral-100); color: var(--color-neutral-800); }
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }

/* — log level scale (LogsViewer) — deliberately reuses the site's single-accent palette
   (red/neutral) rather than introducing blue/green, which would clash with it. Severity reads
   through fill weight, not hue: muted for Verbose/Debug, plain for the common Information case,
   the softer secondary accent for Warning, the primary accent for Error, and an inverted solid
   fill for Fatal so it visually outranks Error. */
.tag-level-verbose, .tag-level-debug { background: var(--color-neutral-100); color: var(--color-neutral-600); }
.tag-level-information { background: transparent; border: 1px solid var(--color-divider); color: color-mix(in srgb, var(--color-text) 60%, transparent); }
.tag-level-warning { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
.tag-level-error { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-level-fatal { background: var(--color-accent-700); color: var(--color-bg); font-weight: 700; }

/* — level filter chips (multi-select toggle, LogsViewer) — */
.level-chip {
  position: relative; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  user-select: none; font-size: 12px; font-weight: 600; padding: 5px 12px;
  border-radius: calc(var(--radius-md) * 0.75); border: 1px solid var(--color-divider);
  background: transparent; color: color-mix(in srgb, var(--color-text) 55%, transparent);
  transition: background .12s, border-color .12s, color .12s;
}
.level-chip input { position: absolute; opacity: 0; pointer-events: none; }
.level-chip:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.level-chip:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.level-chip.is-active.level-verbose, .level-chip.is-active.level-debug { background: var(--color-neutral-200); border-color: var(--color-neutral-400); color: var(--color-neutral-800); }
.level-chip.is-active.level-information { background: var(--color-neutral-100); border-color: color-mix(in srgb, var(--color-text) 45%, transparent); color: var(--color-text); }
.level-chip.is-active.level-warning { background: var(--color-accent-2-100); border-color: var(--color-accent-2-500); color: var(--color-accent-2-800); }
.level-chip.is-active.level-error { background: var(--color-accent-100); border-color: var(--color-accent-500); color: var(--color-accent-800); }
.level-chip.is-active.level-fatal { background: var(--color-accent-700); border-color: var(--color-accent-700); color: var(--color-bg); }

/* — navigation — */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--color-bg);
  display: flex; align-items: center; gap: var(--space-6);
  padding: var(--space-3) var(--space-4);
  border-bottom: 2px solid var(--color-divider);
}
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px;
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none; color: inherit; white-space: nowrap;
}
/* The tab strip and its overflow menu, kept together in one row. On a wide header the menu is not
   rendered at all, so this is simply the strip. */
.nav-tabs {
  display: flex; align-items: center; gap: var(--space-4);
  min-width: 0;
}
.nav-links {
  display: flex; gap: var(--space-6); align-items: center;
}
.nav-actions {
  display: flex; align-items: center; gap: var(--space-4);
  margin-left: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover, .nav a[aria-current='page'], .nav a.active { color: var(--color-accent); }

/* The overflow menu is a mobile-only device. On a wide header there is room for all five
   destinations, and hiding two of them behind a click there would be tidiness for its own sake. */
.nav-more { display: none; position: relative; }
.nav-more-btn {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 1px solid transparent;
}
.nav-more-btn::-webkit-details-marker { display: none; }
.nav-more-btn:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.nav-more[open] .nav-more-btn { background: color-mix(in srgb, var(--color-text) 10%, transparent); }
.nav-more-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 110;
  min-width: 150px;
  display: flex; flex-direction: column;
  background: var(--color-bg);
  border: 2px solid var(--color-divider);
  box-shadow: var(--shadow-md);
}
.nav-more-menu a {
  padding: 10px var(--space-3);
  font-size: 14px; font-weight: 600;
  white-space: nowrap;
}
.nav-more-menu a:hover { background: var(--color-surface); }
.nav-more-menu a.active, .nav-more-menu a[aria-current='page'] {
  background: var(--color-accent); color: var(--color-bg) !important;
}

@media (max-width: 768px) {
  .nav {
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-2) 0;
    padding: var(--space-2) var(--space-3);
  }
  .nav-brand {
    order: 1;
    font-size: 16px;
  }
  .nav-actions {
    order: 2;
    margin-left: auto;
    gap: var(--space-2);
  }
  .nav-tabs {
    order: 3;
    width: 100%;
    gap: var(--space-2);
  }
  .nav-links {
    /* Takes the row and scrolls within it, while the ⋮ stays pinned at the end outside the
       scrolling box - which is also why the two are siblings rather than nested. */
    flex: 1;
    min-width: 0;
    display: flex;
    gap: var(--space-2);
    align-items: center;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 4px;
    padding-bottom: 2px;
    scrollbar-width: none;
  }
  .nav-links::-webkit-scrollbar {
    display: none;
  }
  .nav-links a {
    padding: 6px 10px;
    border-radius: var(--radius-md);
    white-space: nowrap;
    background: var(--color-surface);
    font-size: 13px;
    font-weight: 600;
  }
  .nav-links a.active, .nav-links a[aria-current='page'] {
    background: var(--color-accent);
    color: var(--color-bg) !important;
  }

  /* Historia, Powiadomienia and Logi move into the ⋮ menu here. Three pills fit a phone row
     without it turning into a scrollable strip of half-visible words, which is what five did. */
  .nav-links a.nav-link-secondary { display: none; }
  .nav-more { display: inline-flex; flex: none; }
}

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 2px solid var(--color-divider);
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-divider);
  word-break: break-word;
}
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
  z-index: 1000;
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 20px;
}
.dialog-body { font-size: 14px; opacity: 0.85; word-break: break-word; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); flex-wrap: wrap; }

/* — layout & responsive utilities — */
.page-container {
  width: 100%;
  max-width: 1360px;
  margin: 0 auto;
  padding: var(--space-6);
}
@media (max-width: 768px) {
  .page-container {
    padding: var(--space-3);
  }
}

.sales-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: var(--space-4);
  padding: var(--space-4) 0;
  width: 100%;
}
@media (max-width: 480px) {
  .sales-grid {
    grid-template-columns: 1fr;
  }
}

/* — filter toolbars — */
.filter-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: flex-end;
  width: 100%;
}
.filter-toolbar .field {
  min-width: 0;
}
@media (max-width: 768px) {
  .filter-toolbar > * {
    flex: 1 1 100% !important;
    min-width: 0 !important;
    width: 100% !important;
  }
  .filter-toolbar .seg {
    display: flex;
    width: 100%;
  }
  .filter-toolbar .seg .seg-opt {
    flex: 1;
    justify-content: center;
    padding: 8px 6px;
    font-size: 12px;
  }
}

/* — results & sorting toolbar — */
.results-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) 0 var(--space-3);
  margin-top: var(--space-2);
  border-bottom: 2px solid var(--color-divider);
  flex-wrap: wrap;
  gap: 12px;
  width: 100%;
}
.sort-control {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  max-width: 100%;
}
.sort-control label {
  font-size: 12px;
  white-space: nowrap;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.sort-control select {
  max-width: 100%;
  min-width: 220px;
  text-overflow: ellipsis;
}
@media (max-width: 600px) {
  .results-toolbar {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
  .sort-control {
    width: 100%;
  }
  .sort-control select {
    width: 100%;
  }
}

/* — sniper job card — */
.sniper-job-card {
  display: flex;
  flex-direction: row;
  align-items: center;
  padding: var(--space-3);
  gap: var(--space-4);
  text-decoration: none;
  color: inherit;
}
.sniper-job-thumb {
  width: 60px;
  height: 45px;
  flex: none;
  background: var(--color-surface);
  overflow: hidden;
  border-radius: var(--radius-sm);
}
.sniper-job-info {
  flex: 1;
  min-width: 0;
}
.sniper-job-price {
  text-align: right;
  flex: none;
}
.sniper-job-tag {
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
}
.sniper-job-arrow {
  flex: none;
}
.sniper-job-meta {
  display: contents;
}

@media (max-width: 640px) {
  .sniper-job-card {
    display: grid;
    grid-template-columns: 50px 1fr auto;
    grid-template-rows: auto auto;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-3);
  }
  .sniper-job-thumb {
    width: 50px;
    height: 40px;
    grid-column: 1;
    grid-row: 1 / 3;
    align-self: center;
  }
  .sniper-job-info {
    grid-column: 2;
    grid-row: 1;
    min-width: 0;
  }
  .sniper-job-arrow {
    grid-column: 3;
    grid-row: 1 / 3;
    align-self: center;
    padding: 0;
  }
  .sniper-job-meta {
    grid-column: 2;
    grid-row: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    flex-wrap: wrap;
  }
  .sniper-job-price {
    text-align: left;
    display: flex;
    align-items: baseline;
    gap: 4px;
  }
  .sniper-job-price .price-label {
    display: none;
  }
}

/* — logger filter: one dropdown per dotted level — */
.context-path {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.context-path .input {
  width: auto;
  min-width: 120px;
  max-width: 100%;
}
.context-path-dot {
  font-family: ui-monospace, monospace;
  opacity: .4;
}

/* — log row — */
.log-row {
  display: grid;
  grid-template-columns: 90px 100px 180px 1fr 90px;
  gap: var(--space-3);
  padding: 9px 4px;
  font-size: 12.5px;
  align-items: center;
  cursor: pointer;
  width: 100%;
}
@media (max-width: 768px) {
  .log-row {
    grid-template-columns: auto 1fr auto;
    gap: 6px 10px;
    padding: 10px 8px;
  }
  .log-row-time {
    grid-column: 1;
    grid-row: 1;
  }
  .log-row-level {
    grid-column: 2;
    grid-row: 1;
    justify-self: start;
  }
  .log-row-icon {
    grid-column: 3;
    grid-row: 1;
    justify-self: end;
  }
  .log-row-msg {
    grid-column: 1 / -1;
    grid-row: 2;
    white-space: normal;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    font-size: 13px;
    line-height: 1.35;
  }
  .log-row-logger {
    grid-column: 1 / -1;
    grid-row: 3;
    font-size: 11px;
    opacity: 0.55;
  }
}

/* — sale details page — */
.sale-detail-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-6);
  flex-wrap: wrap;
  padding-bottom: var(--space-4);
  border-bottom: 2px solid var(--color-divider);
  width: 100%;
}
.sale-detail-price {
  text-align: right;
  flex: none;
}
.sale-detail-main-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: var(--space-6);
  padding: var(--space-6) 0;
  align-items: start;
  width: 100%;
}
.sale-specs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 0 var(--space-8);
  margin-bottom: var(--space-6);
  align-items: start;
  width: 100%;
}
.live-countdown {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(28px, 7vw, 42px);
  line-height: 1;
  margin: 6px 0;
  word-break: break-all;
}
@media (max-width: 600px) {
  .sale-detail-header {
    gap: var(--space-3);
  }
  .sale-detail-price {
    text-align: left;
    width: 100%;
  }
  .sale-detail-main-grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
    padding: var(--space-4) 0;
  }
  .sale-specs-grid {
    grid-template-columns: 1fr;
    gap: 0;
  }
}


/* — watchlist — */

/* The badge stack in a card's top-left corner (sniper, watched). A class rather than inline styles
   because the watchlist has to move it down to seat its own remove button above it. */
.card-badges {
  position: absolute; top: 8px; left: 8px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
}

/* Sits among the tags on the detail header, so it borrows their size and spacing and departs only
   where it must: a border, because it is pressable, and a real 32px-tall hit area, because a chip
   sized purely by its text is a poor target on a phone. Watched is the filled state - same glyph,
   more weight - so pressing it reads as this control changing rather than as a different one. */
.watch-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit; font-size: 11px; font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0 10px; min-height: 28px;
  cursor: pointer;
  color: var(--color-accent);
  background: transparent;
  border: 1px solid var(--color-accent);
  border-radius: calc(var(--radius-md) * 0.75);
}
.watch-toggle svg { display: block; }
.watch-toggle:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.watch-toggle:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.watch-toggle.is-watched { background: var(--color-accent); color: var(--color-bg); }
.watch-toggle.is-watched:hover { background: var(--color-accent-600); }

/* The remove button is a sibling of the card's anchor, not a child of it: a <button> inside an <a>
   is invalid markup, and the click would have to fight the navigation it is nested in. Positioned
   over the card's top-left corner, which on this page is free - the "Zapisane" badge that would
   otherwise sit there is left off a list where every card carries it. */
.watchlist-tile { position: relative; }
.watchlist-remove {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  display: inline-flex; align-items: center; gap: 5px;
  font-family: inherit; font-size: 10px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 4px 8px; min-height: 28px;
  cursor: pointer;
  color: var(--color-bg);
  background: var(--color-neutral-900);
  border: none;
}
.watchlist-remove svg { display: block; }
.watchlist-remove:hover { background: var(--color-accent); }
.watchlist-remove:active { background: var(--color-accent-700); }

/* The sniper badge occupies the same corner. On the watchlist it steps down to make room, keeping
   the pair stacked the way the card stacks its own badges rather than overlapping them. */
.watchlist-tile .card-badges { top: 44px; }

/* — notification settings — */
/* The rules on the left, what they would have sent on the right, side by side and both in view.
   Stacking them would put the consequence a scroll away from the control, which is the one thing
   this page exists to avoid. */
.settings-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--space-4);
  align-items: start;
}
.settings-rules { display: flex; flex-direction: column; gap: var(--space-3); }
/* Sticky under the header, so the tally stays put while the rules are scrolled through. */
.settings-preview { position: sticky; top: 76px; }
.setting-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 15px;
}
.setting-check {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; cursor: pointer; user-select: none;
}
.setting-hint { font-size: 12px; opacity: 0.6; line-height: 1.45; }
/* Whether anything actually reaches a phone, above the rules rather than beside them: no threshold
   on this page is worth tuning while the answer is "nobody is subscribed". */
.delivery-status {
  padding: var(--space-3); font-size: 13px; margin-bottom: var(--space-3);
}
.delivery-status-warn { border-left: 3px solid var(--color-accent); }
.settings-actions {
  display: flex; align-items: center; gap: var(--space-2);
  flex-wrap: wrap; padding-top: var(--space-1);
}
.preview-headline { display: flex; align-items: center; gap: var(--space-3); }
.preview-number {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 34px; line-height: 1; color: var(--color-accent);
}
.preview-tally {
  display: flex; flex-wrap: wrap; gap: 4px var(--space-3);
  font-size: 12px; opacity: 0.75;
}
.preview-list {
  display: flex; flex-direction: column;
  margin-top: var(--space-2); border-top: 1px solid var(--color-divider);
  max-height: 460px; overflow-y: auto;
}
.preview-row {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: 10px 2px;
  border-bottom: 1px solid var(--color-divider);
  color: inherit; text-decoration: none;
}
.preview-row:hover { background: color-mix(in srgb, var(--color-text) 5%, transparent); }
.preview-row-main { flex: 1; min-width: 0; }
.preview-row-title { font-size: 13px; font-weight: 600; }
.preview-row-meta { font-size: 12px; opacity: 0.6; }
.preview-row-notes { font-size: 11px; opacity: 0.5; margin-top: 2px; }
.preview-row-margin {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; white-space: nowrap; color: var(--color-accent);
}

@media (max-width: 900px) {
  .settings-layout { grid-template-columns: 1fr; }
  .settings-preview { position: static; }
}

/* — lightbox gallery — */
.lightbox {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: rgba(0, 0, 0, 0.92);
  z-index: 1100;
  overscroll-behavior: contain;
  /* The gestures are driven by transform, so the browser has to be told not to claim them first -
     for scrolling, and above all for its own pinch-zoom, which would otherwise magnify the page
     furniture around the photo instead of the photo. A passive listener could not take it back. */
  touch-action: none;
}
.lightbox-stage {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
  max-width: min(1100px, 100%);
  will-change: transform, opacity;
}
.lightbox-img {
  max-width: 100%; max-height: 78vh; object-fit: contain;
  border-radius: var(--radius-sm);
  /* Zoom is a transform on the photo alone - the counter and the magnifiers under it must not
     grow with it - and it scales about the middle of the frame the photo was fitted into. */
  transform-origin: center center;
  /* The gesture is tracked on the backdrop; an image that answered pointer events itself would
     eat the drag, and a long-press drag-to-save would fire mid-swipe. */
  pointer-events: none;
  user-select: none; -webkit-user-drag: none;
}
.lightbox-toolbar {
  display: flex; align-items: center; gap: var(--space-4);
}
.lightbox-counter {
  font-size: 14px; font-weight: 600; color: var(--color-bg);
  min-width: 64px; text-align: center;
}
.lightbox-zoom { background: var(--color-bg); }
.lightbox-zoom:disabled { opacity: 0.35; cursor: default; }
.lightbox-hint {
  font-size: 11px; letter-spacing: 0.04em; text-align: center;
  color: color-mix(in srgb, var(--color-bg) 60%, transparent);
  display: none;
}
.lightbox-close {
  position: absolute; top: var(--space-3); right: var(--space-3);
  background: var(--color-bg);
}
.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  background: var(--color-bg);
}
.lightbox-nav-prev { left: var(--space-4); }
.lightbox-nav-next { right: var(--space-4); }

/* Zoomed in, a drag moves the photo rather than the roll, and the cursor is the only thing that
   says so before the user tries it. The hint goes quiet because it describes gestures that now
   mean something else - but it keeps its space, so the photo does not jump when it goes. */
.lightbox.is-zoomed { cursor: grab; }
.lightbox.is-zoomed:active { cursor: grabbing; }
.lightbox.is-zoomed .lightbox-hint { visibility: hidden; }

/* A finger has no hover and no room for a 44px target pinned to the edge of the photo, and it has
   the swipe and the pinch instead - so the arrows and the magnifiers are a pointing-device
   affordance, and the hint takes their place where the gestures are the way around the photo. */
@media (pointer: coarse) {
  .lightbox-nav, .lightbox-zoom { display: none; }
  .lightbox-hint { display: block; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Sniper run summary (/sniper/runs/{no}) — the two-axis comb chart and the
   run's metrics. Chart colours are roles, not raw hex: outcome hues come from
   the dataviz reference palette's first three categorical slots (validated
   all-pairs against --viz-surface: CVD ΔE ≥ 9.2, normal-vision ΔE ≥ 24);
   errors and missing stamps stay neutral and carry a dashed line / × instead
   of a fourth hue. Orange and aqua sit under 3:1 on the surface, so the chart
   always ships with its legend, the shot table and a text readout.
   ══════════════════════════════════════════════════════════════════════ */
.viz-root {
  --viz-surface: var(--color-neutral-100);
  --viz-ink: var(--color-text);
  --viz-ink-2: var(--color-neutral-700);
  --viz-muted: var(--color-neutral-600);
  --viz-grid: #e7e3e3;
  --viz-axis: var(--color-neutral-400);
  --viz-zero: var(--color-neutral-600);
  --viz-waiting: #2a78d6;
  --viz-purchased: #1baf7a;
  --viz-closed: #eb6834;
  --viz-error: var(--color-neutral-700);
  --viz-window: color-mix(in srgb, var(--color-accent) 10%, transparent);
  --viz-window-band: color-mix(in srgb, var(--color-accent) 45%, transparent);
}
.run-chart { background: var(--viz-surface); padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.run-chart-legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); font-size: 12px; color: var(--viz-ink-2); }
.run-chart-key { display: inline-flex; align-items: center; gap: 6px; }
.run-chart-key svg { flex: none; }
.run-chart-scroll { overflow-x: auto; }
.run-chart-svg { display: block; width: 100%; min-width: 720px; height: auto; font-family: var(--font-body); }
.run-chart-tick { font-size: 11px; fill: var(--viz-muted); font-variant-numeric: tabular-nums; }
.run-chart-axis-title { font-size: 12px; fill: var(--viz-ink-2); }
.run-chart-winner-label { font-size: 12px; font-weight: 600; fill: var(--viz-ink); }
.run-chart-shot { cursor: pointer; outline: none; }
.run-chart-hit { pointer-events: stroke; }
.run-chart-shot:focus-visible line:not(.run-chart-hit) { stroke-width: 3.5; }
.run-chart-readout {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--space-3); min-height: 28px;
  padding-top: var(--space-2); border-top: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
  font-size: 12.5px; color: var(--viz-ink-2); font-variant-numeric: tabular-nums;
}
.run-chart-readout-value { font-weight: 700; color: var(--viz-ink); }
.run-chart-readout-badge {
  display: inline-flex; align-items: center; gap: 6px; font-weight: 600; color: var(--viz-ink);
}
.run-chart-readout-badge::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--dot-color, var(--viz-ink-2));
}
.run-chart-readout-item em { font-style: normal; opacity: .6; margin-right: 2px; }

.run-picker { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.run-axis-switch { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 12px; color: var(--color-neutral-700); }
.run-axis-switch .btn { font-size: 12px; padding: 4px 10px; }
.run-result { padding: var(--space-4); gap: var(--space-2); border-left: 4px solid var(--color-neutral-500); }
.run-result.is-success { border-left-color: var(--viz-purchased, #1baf7a); }
.run-result.is-failure { border-left-color: var(--color-accent); }
.run-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-2); margin-top: var(--space-2); }
.run-tile { background: var(--color-surface); padding: var(--space-3); display: flex; flex-direction: column; gap: 2px; }
.run-tile-label { font-size: 12px; opacity: .6; }
.run-tile-value { font-family: var(--font-heading); font-weight: 800; font-size: 26px; line-height: 1.15; }
.run-tile-note { font-size: 12px; opacity: .6; }
.run-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-2); margin-top: var(--space-4); }
.run-metrics .card { padding: var(--space-4); }
.run-metrics .card h6 { margin-bottom: var(--space-2); }
.run-dl { display: flex; flex-direction: column; gap: 6px; margin: 0; font-size: 13px; }
.run-dl > div { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
.run-dl dt { opacity: .6; flex-shrink: 0; }
.run-dl dd { margin: 0; font-variant-numeric: tabular-nums; text-align: right; font-weight: 500; min-width: 0; }
.run-details { margin-top: var(--space-4); background: var(--color-surface); padding: var(--space-3); }
.run-details summary { cursor: pointer; font-family: var(--font-heading); font-weight: 800; }
.run-shots-table { font-size: 12.5px; font-variant-numeric: tabular-nums; margin-top: var(--space-2); }
.run-shots-table tr.is-winner td { font-weight: 700; background: color-mix(in srgb, #1baf7a 12%, transparent); }
.run-trace { margin: var(--space-2) 0 0; padding-left: 0; list-style: none; font-size: 12.5px; }
.run-trace-line { display: grid; grid-template-columns: 72px 1fr; gap: var(--space-2); padding: 3px 0; border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent); }
.run-trace-phase { font-size: 11px; opacity: .55; text-transform: uppercase; letter-spacing: .05em; }
.run-trace-text { word-break: break-word; }
.run-trace-line.is-warn .run-trace-phase { color: var(--color-accent-2-700); opacity: 1; }
.run-trace-line.is-error .run-trace-phase { color: var(--color-accent-700); opacity: 1; }
.run-share { height: 8px; background: color-mix(in srgb, var(--color-text) 8%, transparent); }
.run-share span { display: block; height: 100%; background: var(--color-neutral-700); }

/* ══════════════════════════════════════════════════════════════════════════
   Market price trend (MarketPanel → MarketTrendChart) — a Chart.js canvas
   inside .viz-root, reading the same tokens as the run chart. One series in
   the accent; the fitted trend is a neutral reference line (dashed, keyed in
   the legend), not a second category, and the monthly table is its text twin.
   ══════════════════════════════════════════════════════════════════════ */
.market-trend { background: var(--viz-surface); padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.market-trend-legend { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); font-size: 11px; color: var(--viz-ink-2); }
.market-trend-key { display: inline-flex; align-items: center; gap: 6px; }
.market-trend-key svg { flex: none; }
.market-trend-plot { position: relative; height: 210px; }
.market-trend-data summary { cursor: pointer; font-size: 12px; opacity: .7; }
.market-trend-data table { font-size: 12.5px; font-variant-numeric: tabular-nums; margin-top: var(--space-2); }
.market-trend-data td:not(:last-child) { white-space: nowrap; }

/* ══════════════════════════════════════════════════════════════════════════
   Sniper burst strategies (/sniper/strategies) and the strategy picker on a
   sale. Segment hues reuse the run chart's validated categorical slots under
   their own names - lead, comb, tail - so the meanings never cross: blue here
   is the lead-in, never "WAITING". The shape being compared against is
   neutral, and the lock_timeout line takes the accent, as a limit should.
   ══════════════════════════════════════════════════════════════════════ */
.viz-root {
  --viz-lead: #2a78d6;
  --viz-comb: #eb6834;
  --viz-tail: #1baf7a;
  --viz-old: var(--color-neutral-400);
  --viz-band: color-mix(in srgb, var(--color-text) 6%, transparent);
  --viz-critical: var(--color-accent);
}
.burst-page { max-width: 1160px; }
.burst-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.burst-h2 { margin: 0; font-size: 15px; }
.burst-panel {
  background: var(--color-surface); padding: var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; margin-top: var(--space-4);
}
.burst-panel.viz-root { background: var(--viz-surface); }
.burst-panel-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-4);
}
.burst-base { font-size: 13px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Saved strategies */
.burst-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-2); }
.burst-card { border-left: 4px solid transparent; }
.burst-card.is-base { border-left-color: var(--color-accent); }
.burst-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); }
.burst-card-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 15px; line-height: 1.25; }
.burst-card-tags { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.burst-card-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-2);
  font-size: 12px; opacity: .75; font-variant-numeric: tabular-nums;
}
.burst-card-note { font-size: 12.5px; line-height: 1.45; }
.burst-card-actions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: auto; }
.burst-card-actions .btn { font-size: 12px; padding: 5px 8px; }
.burst-strip { display: block; width: 100%; height: 22px; }

/* Editor */
.burst-fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.burst-fieldset legend {
  padding: 0; margin-bottom: var(--space-2);
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}
.burst-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--space-3) var(--space-4); }
.burst-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.burst-field-wide { grid-column: span 2; }
@media (max-width: 600px) { .burst-field-wide { grid-column: auto; } }
.burst-field > label { font-size: 12px; color: color-mix(in srgb, var(--color-text) 70%, transparent); }
.burst-input { font-variant-numeric: tabular-nums; }
.burst-hint { font-size: 11px; opacity: .55; }
.burst-derived { margin: 0; font-size: 13px; opacity: .85; }
.burst-derived b { font-variant-numeric: tabular-nums; font-weight: 700; }
.burst-error { margin: 0; font-size: 13px; display: flex; gap: 8px; align-items: baseline; }
.burst-error::before {
  content: "!"; flex: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-accent); color: var(--color-bg); font-size: 11px; font-weight: 700;
  display: inline-grid; place-items: center; transform: translateY(2px);
}
.burst-note { margin: 0; font-size: 12px; opacity: .6; }

/* Facts */
.burst-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 var(--space-6); margin: var(--space-4) 0 0; }
.burst-fact { border-top: 2px solid var(--color-divider); padding-top: 10px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.burst-fact dt { order: 2; font-size: 12.5px; opacity: .7; }
.burst-fact dd {
  order: 1; margin: 0; font-family: var(--font-heading); font-weight: 800;
  font-size: 26px; line-height: 1.2; font-variant-numeric: tabular-nums;
}
.burst-fact dd small { font-size: 14px; font-weight: 600; opacity: .7; }

/* Chart */
.burst-legend { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--viz-ink-2); }
.burst-legend li { display: flex; align-items: center; gap: 7px; font-variant-numeric: tabular-nums; }
.burst-legend b { color: var(--viz-ink); font-weight: 600; }
.burst-key { width: 3px; height: 15px; flex: none; display: inline-block; vertical-align: -2px; margin-right: 7px; }
.burst-legend .burst-key, .burst-chart-tip .burst-key { margin-right: 0; }
.burst-key-lead { background: var(--viz-lead, #2a78d6); }
.burst-key-comb { background: var(--viz-comb, #eb6834); }
.burst-key-tail { background: var(--viz-tail, #1baf7a); }
.burst-key-old { background: var(--viz-old, #bab6b6); }
.burst-chart-controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.burst-compare { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.burst-compare .input { width: auto; min-width: 180px; max-width: 280px; min-height: 32px; padding: 4px 8px; font-size: 13px; }
.burst-chart { position: relative; min-width: 0; }
.burst-chart:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.burst-chart-svg { display: block; width: 100%; height: auto; touch-action: pan-y; font-family: var(--font-body); }
.burst-chart-svg text { font-size: 11.5px; fill: var(--viz-ink-2); }
.burst-chart-svg .burst-chart-ax { font-size: 11px; fill: var(--viz-muted); font-variant-numeric: tabular-nums; }
.burst-chart-svg .burst-chart-row { font-size: 12.5px; font-weight: 600; fill: var(--viz-ink); }
.burst-chart-svg .burst-chart-sub { font-size: 11px; fill: var(--viz-muted); font-variant-numeric: tabular-nums; }
.burst-chart-svg .burst-chart-t0 { font-size: 12.5px; font-weight: 700; fill: var(--viz-ink); }
.burst-chart-svg .burst-chart-label { font-weight: 600; fill: var(--viz-ink-2); }
.burst-chart-svg .burst-chart-crit { font-weight: 600; fill: var(--viz-ink); }
.burst-chart-svg .burst-chart-halo { paint-order: stroke; stroke: var(--viz-surface); stroke-width: 4px; stroke-linejoin: round; }
.burst-chart-tip {
  position: absolute; z-index: 2; pointer-events: none;
  background: var(--color-bg); border: 1px solid var(--color-divider); box-shadow: var(--shadow-md);
  padding: 8px 10px; font-size: 12.5px; line-height: 1.45; color: var(--viz-ink-2);
  min-width: 170px; max-width: 280px;
}
.burst-chart-tip-h { display: flex; align-items: center; gap: 7px; color: var(--viz-ink); font-weight: 700; }
.burst-chart-tip .num { font-variant-numeric: tabular-nums; }

/* Checks and tables */
.burst-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; white-space: nowrap; }
.burst-chip i { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; }
.burst-chip-ok i { background: #0ca30c; }
@media (max-width: 600px) { .burst-table .burst-chip { white-space: normal; align-items: baseline; } }
.burst-chip-risk i { background: #fab219; }
.burst-chip-bad i { background: var(--color-accent); }
.burst-scroll { overflow-x: auto; }
.burst-table { font-size: 13px; }
.burst-segments td:first-child { white-space: nowrap; }
.burst-table th.n, .burst-table td.n { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.burst-num-text { font-variant-numeric: tabular-nums; }
.burst-tables {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
  gap: var(--space-4); align-items: start; margin-top: var(--space-4);
}
.burst-tables section { min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.burst-details { margin-top: var(--space-4); background: var(--color-surface); padding: var(--space-3); }
.burst-details summary { cursor: pointer; font-family: var(--font-heading); font-weight: 800; }
.burst-offsets { display: grid; gap: var(--space-3); margin-top: var(--space-3); }
.burst-offsets h3 { margin: 0 0 4px; font-size: 13px; display: flex; align-items: center; }
.burst-offsets p { margin: 0; font-size: 12.5px; line-height: 1.7; opacity: .8; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.burst-footer { margin-top: var(--space-6); font-size: 12px; opacity: .6; display: grid; gap: 6px; max-width: 90ch; }

/* Sniper E2E scenarios (/sniper/scenarios) */
.scenario-sessions {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--space-2); margin-bottom: var(--space-4);
}
.scenario-session { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; }
.scenario-panel { padding: var(--space-4); margin-bottom: var(--space-4); }
.scenario-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.scenario-head-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
/* Na wąskim ekranie tabela przewija się w poziomie (.burst-scroll) zamiast łamać każdą kolumnę słowo pod słowem. */
.scenario-table { min-width: 640px; }
.scenario-table-wide { min-width: 820px; }
.scenario-table .tag { white-space: nowrap; }
.scenario-target {
  display: grid; grid-template-columns: 140px minmax(0, 1fr) 220px auto;
  grid-template-areas: "op sale strategy remove";
  gap: var(--space-2); align-items: end;
}
.scenario-target > * { min-width: 0; }
.scenario-target-op { grid-area: op; }
.scenario-target-sale { grid-area: sale; }
.scenario-target-strategy { grid-area: strategy; }
.scenario-target-remove { grid-area: remove; justify-self: end; }
.scenario-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
@media (max-width: 700px) {
  .scenario-panel { padding: var(--space-3); }
  .scenario-target {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "op remove" "sale sale" "strategy strategy";
  }
}
.burst-footer p { margin: 0; }

/* Strategy picker on a sale (SaleDetails) */
.burst-picker { display: flex; flex-direction: column; gap: 6px; }
.burst-picker-summary { font-size: 11.5px; opacity: .75; font-variant-numeric: tabular-nums; }
.burst-picker-checks { display: flex; flex-direction: column; gap: 3px; }
.burst-picker-checks .burst-chip { white-space: normal; font-size: 11.5px; align-items: baseline; }
