:root {
  color-scheme: light;
  --bg: #f7f8fa;
  --surface: #ffffff;
  --surface-2: #f2f3f5;
  --surface-3: #e9ebef;
  --border: #e3e6ea;
  --border-strong: #d3d7dd;
  --text: #1a1c1e;
  --text-secondary: #626973;
  --text-tertiary: #626973;
  --accent: #2e63e8;
  --accent-hover: #2453cc;
  --accent-strong: #1d46b4;
  --on-accent: #ffffff;
  /* The logo mark keeps its own blue + a white cog in BOTH themes. It cannot ride on
     --accent/--on-accent: those flip to a pale blue with a dark glyph in the dark
     theme, which turns the mark into a washed-out sticker. */
  --brand-mark-bg: #2e63e8;
  --brand-mark-fg: #ffffff;
  --accent-soft: rgba(46, 99, 232, 0.1);
  --accent-softer: rgba(46, 99, 232, 0.055);
  --ring: rgba(46, 99, 232, 0.34);
  --danger: #bd2932;
  --danger-soft: rgba(214, 69, 69, 0.1);
  --success: #16855b;
  --success-soft: rgba(22, 133, 91, 0.1);
  --warning: #8b5908;
  --disabled: #c5c9cf;
  --overlay: rgba(255, 255, 255, 0.86);
  --shadow-xs: 0 1px 2px rgba(19, 25, 36, 0.04), 0 1px 5px rgba(19, 25, 36, 0.025);
  --shadow-sm: 0 10px 26px rgba(19, 25, 36, 0.08), 0 2px 7px rgba(19, 25, 36, 0.05);
  --shadow-md: 0 24px 65px rgba(19, 25, 36, 0.11), 0 4px 12px rgba(19, 25, 36, 0.04);
  --radius-sm: 6px;
  --radius-md: 9px;
  --radius-lg: 13px;
  --radius-xl: 18px;
  --radius-full: 9999px;
  --ease: cubic-bezier(0.2, 0.75, 0.25, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0e0f11;
    --surface: #17181b;
    --surface-2: #1e2024;
    --surface-3: #26282d;
    --border: #292b30;
    --border-strong: #383b42;
    --text: #ecedee;
    --text-secondary: #9aa0a8;
    --text-tertiary: #9197a0;
    --accent: #5b8cff;
    --accent-hover: #77a1ff;
    --accent-strong: #9ab9ff;
    --on-accent: #101522;
    /* Deep enough to carry a white cog against a near-black surface — the dark theme's
       --accent (#5b8cff) is a pale blue meant for text/buttons, not a logo field. */
    --brand-mark-bg: #3566d8;
    --brand-mark-fg: #ffffff;
    --accent-soft: rgba(91, 140, 255, 0.14);
    --accent-softer: rgba(91, 140, 255, 0.075);
    --ring: rgba(91, 140, 255, 0.42);
    --danger: #f0736b;
    --danger-soft: rgba(240, 115, 107, 0.13);
    --success: #5bc79c;
    --success-soft: rgba(91, 199, 156, 0.12);
    --warning: #e2b85e;
    --disabled: #4a4e55;
    --overlay: rgba(14, 15, 17, 0.88);
    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.25);
    --shadow-sm: 0 14px 30px rgba(0, 0, 0, 0.33), 0 2px 8px rgba(0, 0, 0, 0.22);
    --shadow-md: 0 28px 70px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.22);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0e0f11;
  --surface: #17181b;
  --surface-2: #1e2024;
  --surface-3: #26282d;
  --border: #292b30;
  --border-strong: #383b42;
  --text: #ecedee;
  --text-secondary: #9aa0a8;
  --text-tertiary: #9197a0;
  --accent: #5b8cff;
  --accent-hover: #77a1ff;
  --accent-strong: #9ab9ff;
  --on-accent: #101522;
  /* See the prefers-color-scheme block above: the mark keeps a white cog on a deep
     blue in the dark theme too. */
  --brand-mark-bg: #3566d8;
  --brand-mark-fg: #ffffff;
  --accent-soft: rgba(91, 140, 255, 0.14);
  --accent-softer: rgba(91, 140, 255, 0.075);
  --ring: rgba(91, 140, 255, 0.42);
  --danger: #f0736b;
  --danger-soft: rgba(240, 115, 107, 0.13);
  --success: #5bc79c;
  --success-soft: rgba(91, 199, 156, 0.12);
  --warning: #e2b85e;
  --disabled: #4a4e55;
  --overlay: rgba(14, 15, 17, 0.88);
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.25);
  --shadow-sm: 0 14px 30px rgba(0, 0, 0, 0.33), 0 2px 8px rgba(0, 0, 0, 0.22);
  --shadow-md: 0 28px 70px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.22);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  min-width: 320px;
  overscroll-behavior-y: none;
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  overscroll-behavior-y: none;
  color: var(--text);
  background:
    radial-gradient(circle at 50% -18rem, var(--accent-softer), transparent 36rem),
    var(--bg);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Helvetica, Arial,
    sans-serif;
  font-size: 14px;
  line-height: 1.5;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

/* Thin, subtle scrollbars everywhere. Chrome/Linux/Windows always show a classic scrollbar
   whenever a box overflows; macOS overlays + auto-hides them. True overlay/auto-hide isn't
   CSS-controllable cross-browser, so instead we make every scrollbar slim and muted (the
   thumb darkens a little on hover) so it reads as chrome, not furniture. */
* {
  scrollbar-width: thin; /* Firefox */
  scrollbar-color: color-mix(in srgb, var(--border-strong) 55%, transparent) transparent;
}

::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  /* The transparent border + padding-box clip makes the visible thumb ~5px — slimmer and
     inset — rather than filling the full 9px track. */
  background: color-mix(in srgb, var(--border-strong) 55%, transparent);
  background-clip: padding-box;
  border: 2px solid transparent;
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--border-strong) 85%, transparent);
  background-clip: padding-box;
}

button,
input,
select,
textarea {
  color: inherit;
  font: inherit;
}

button,
a,
input {
  -webkit-tap-highlight-color: transparent;
}

button {
  margin: 0;
}

a {
  color: var(--accent);
}

::selection {
  color: var(--text);
  background: var(--accent-soft);
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

[hidden],
[x-cloak] {
  display: none !important;
}

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.skip-link {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 1000;
  padding: 9px 13px;
  color: var(--on-accent);
  background: var(--accent);
  border-radius: var(--radius-md);
  opacity: 0;
  clip-path: inset(50%);
  pointer-events: none;
  transform: translateY(-4px);
  transition:
    opacity 150ms var(--ease),
    transform 150ms var(--ease);
}

.skip-link:focus {
  opacity: 1;
  clip-path: none;
  pointer-events: auto;
  transform: translateY(0);
}

.skip-target {
  display: block;
  width: 0;
  height: 0;
  scroll-margin-top: 88px;
}

.skip-target:focus {
  outline: none;
}

.page {
  width: 100%;
  max-width: 1480px;
  margin: 0 auto;
  padding: 20px 24px 30px;
}

.eyebrow {
  margin: 0;
  color: var(--text-tertiary);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  line-height: 1.35;
  text-transform: uppercase;
}

.button,
.icon-button {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition:
    color 150ms var(--ease),
    background-color 150ms var(--ease),
    border-color 150ms var(--ease),
    box-shadow 150ms var(--ease),
    transform 150ms var(--ease);
}

.button {
  min-height: 40px;
  gap: 8px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 650;
  white-space: nowrap;
}

.button svg,
.icon-button svg,
.brand-mark svg,
.search-input-wrap svg,
.empty-state svg,
.alert svg,
.cart-title-icon svg,
.cart-empty svg,
.cart-dispatch-note svg,
.results-table svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.8;
}

.button--primary {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 1px 2px rgba(16, 52, 145, 0.2);
}

.button--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  box-shadow: 0 4px 12px var(--accent-soft);
  transform: translateY(-1px);
}

.button--primary:active {
  background: var(--accent-strong);
  transform: translateY(0);
}

.button--secondary {
  color: var(--text);
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-xs);
}

.button--secondary:hover {
  background: var(--surface-2);
  border-color: var(--text-tertiary);
}

.button--ghost {
  color: var(--text-secondary);
  background: transparent;
  border-color: transparent;
}

.button--ghost:hover {
  color: var(--text);
  background: var(--surface-2);
}

.button--compact {
  min-height: 32px;
  padding: 0 10px;
  font-size: 12px;
}

.button--wide {
  width: 100%;
}

.button:disabled,
.button[disabled] {
  color: var(--text-tertiary);
  background: var(--surface-2);
  border-color: var(--border);
  box-shadow: none;
  cursor: not-allowed;
  transform: none;
}

.icon-button {
  width: 38px;
  height: 38px;
  padding: 0;
  color: var(--text-secondary);
  background: transparent;
  border-color: transparent;
  border-radius: var(--radius-md);
}

.icon-button:hover {
  color: var(--text);
  background: var(--surface-2);
}

.icon-button--danger:hover {
  color: var(--danger);
  background: var(--danger-soft);
}

.theme-icon {
  display: block;
}

.theme-icon--moon {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-icon--sun {
    display: none;
  }

  :root:not([data-theme="light"]) .theme-icon--moon {
    display: block;
  }
}

:root[data-theme="dark"] .theme-icon--sun {
  display: none;
}

:root[data-theme="dark"] .theme-icon--moon {
  display: block;
}

.field {
  display: grid;
  gap: 7px;
}

.field label {
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 650;
}

.field input,
.search-input-wrap,
.cart-qty-form input,
.cart-qty-input {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(19, 25, 36, 0.025);
  transition:
    border-color 150ms var(--ease),
    box-shadow 150ms var(--ease),
    background-color 150ms var(--ease);
}

.field input {
  width: 100%;
  min-height: 44px;
  padding: 0 12px;
  border-radius: var(--radius-md);
  font-size: 15px;
}

.field input:hover,
.search-input-wrap:hover {
  border-color: var(--text-tertiary);
}

.field input:focus,
.search-input-wrap:focus-within,
.cart-qty-form input:focus,
.cart-qty-input:focus {
  border-color: var(--accent);
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 3px var(--ring);
}

.alert {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 10px 11px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-size: 12px;
}

.alert svg {
  width: 17px;
  height: 17px;
  margin-top: 1px;
}

.alert--danger {
  color: var(--danger);
  background: var(--danger-soft);
  border-color: color-mix(in srgb, var(--danger) 20%, transparent);
}

.alert[role="note"] {
  color: var(--text-secondary);
  background: var(--surface);
  border-color: var(--border);
}

.alert[role="note"] strong {
  color: var(--text);
}

/* Login */

.login-page .page {
  max-width: none;
  padding: 0;
}

.login-screen {
  position: relative;
  display: grid;
  min-height: 100svh;
  place-items: center;
  padding: 48px 20px;
  overflow: hidden;
}

.login-screen::before,
.login-screen::after {
  position: absolute;
  z-index: -1;
  width: 34rem;
  height: 34rem;
  border-radius: 50%;
  content: "";
  filter: blur(1px);
  pointer-events: none;
}

.login-screen::before {
  top: -22rem;
  left: -13rem;
  background: radial-gradient(circle, var(--accent-soft), transparent 68%);
}

.login-screen::after {
  right: -18rem;
  bottom: -25rem;
  background: radial-gradient(circle, var(--accent-soft), transparent 68%);
}

.login-theme-control {
  position: absolute;
  top: 22px;
  right: 24px;
}

.login-card {
  display: grid;
  width: 100%;
  max-width: 390px;
  gap: 18px;
  padding: 32px;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(18px);
}

/* One accent, with light falling down it — NOT accent -> accent-strong. That pairing
   inverts between themes (accent-strong is darker in light, lighter in dark), which
   turned the mark into a pale wash on the dark theme. Overlaying a fixed light-fall on
   a single accent behaves the same in both, and the hairline ring keeps the edge crisp
   against a dark surface, where a colored glow just reads as haze. */
.brand-mark {
  display: inline-grid;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  color: var(--brand-mark-fg);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.17), rgba(0, 0, 0, 0.13)),
    var(--brand-mark-bg);
  border-radius: 10px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 0 0 1px rgba(255, 255, 255, 0.09),
    var(--shadow-xs);
  place-items: center;
}

.brand-mark svg {
  width: 21px;
  height: 21px;
  stroke-width: 1.65;
}

.brand-mark--large {
  width: 44px;
  height: 44px;
  border-radius: 12px;
}

.brand-mark--large svg {
  width: 25px;
  height: 25px;
}

.login-heading {
  display: grid;
  gap: 7px;
}

.login-card h1 {
  margin: 0;
  font-size: 24px;
  font-weight: 720;
  letter-spacing: -0.035em;
  line-height: 1.2;
}

.login-card .subtitle {
  margin: 0;
  color: var(--text-secondary);
  font-size: 13px;
}

.login-card .button--primary {
  min-height: 44px;
  margin-top: 2px;
}

/* App shell and search */

.app-shell {
  display: grid;
  gap: 10px;
}

.cart-page-content {
  display: grid;
  min-width: 0;
  gap: 18px;
}

.cart-page-content .cart {
  margin-top: 0;
}

.app-header {
  position: sticky;
  top: 14px;
  z-index: 30;
  display: flex;
  min-height: 64px;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px 10px 14px;
  /* Glass: the blur carries the effect, the tint only keeps text legible over whatever
     scrolls under it. Letting more through means leaning harder on the blur — drop the
     tint alone and the header stops reading as frosted and starts reading as see-through. */
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  backdrop-filter: blur(22px) saturate(1.35);
}

.brand-lockup {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 11px;
  color: var(--text);
  text-decoration: none;
}

.brand-lockup:hover strong {
  color: var(--accent);
}

.brand-lockup > span:last-child {
  display: grid;
  min-width: 0;
}

.brand-lockup strong {
  overflow: hidden;
  font-size: 14px;
  font-weight: 720;
  letter-spacing: -0.015em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.brand-lockup small {
  overflow: hidden;
  color: var(--text-tertiary);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.header-actions {
  position: relative;
  display: flex;
  align-items: center;
  gap: 3px;
}

.header-nav-link,
.cart-trigger {
  position: relative;
  min-height: 40px;
  padding-inline: 10px;
}

.header-nav-link svg,
.cart-trigger svg,
.logout-button svg {
  width: 17px;
  height: 17px;
}

.header-nav-link.is-active,
.cart-trigger.is-active {
  color: var(--accent);
  background: var(--accent-soft);
}

.header-count-badge,
.cart-count-badge {
  min-width: 18px;
  height: 18px;
  padding-inline: 5px;
}

.cart-control {
  position: relative;
  flex: 0 0 auto;
}

.cart-popover {
  position: absolute;
  top: calc(100% + 9px);
  right: 0;
  z-index: 80;
  display: flex;
  width: min(420px, calc(100vw - 48px));
  max-height: min(70vh, 560px);
  flex-direction: column;
  overflow: hidden;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.cart-popover::before {
  position: absolute;
  top: -10px;
  right: 0;
  left: 0;
  height: 10px;
  content: "";
}

.cart-popover-header,
.cart-popover-summary,
.cart-popover-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.cart-popover-header {
  padding: 16px 16px 12px;
  border-bottom: 1px solid var(--border);
}

.cart-popover-header h2 {
  margin: 2px 0 0;
  font-size: 16px;
  letter-spacing: -0.025em;
}

.cart-popover-close {
  width: 34px;
  height: 34px;
}

.cart-popover-summary {
  padding: 11px 16px;
  color: var(--text-secondary);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.cart-popover-summary strong {
  color: var(--text);
  font-size: 12px;
}

.cart-popover-items {
  min-height: 0;
  margin: 0;
  padding: 4px 8px;
  overflow-y: auto;
  list-style: none;
}

.cart-popover-item {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  padding: 9px 8px;
  border-bottom: 1px solid var(--border);
}

.cart-popover-item:last-child {
  border-bottom: 0;
}

.cart-popover-item-icon,
.cart-popover-empty-icon {
  display: grid;
  width: 34px;
  height: 34px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 9px;
  place-items: center;
}

.cart-popover-item-icon svg,
.cart-popover-empty-icon svg {
  width: 17px;
  height: 17px;
}

.cart-popover-item-copy,
.cart-popover-item-meta {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.cart-popover-item-copy strong,
.cart-popover-item-copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cart-popover-item-copy strong,
.cart-popover-item-meta strong {
  font-size: 11px;
  font-weight: 680;
}

.cart-popover-item-copy small,
.cart-popover-item-meta small,
.cart-popover-more {
  color: var(--text-tertiary);
  font-size: 9px;
}

.cart-popover-item-meta {
  text-align: right;
}

.cart-popover-more {
  margin: 0;
  padding: 5px 16px 10px;
}

.cart-popover-empty {
  display: flex;
  min-height: 128px;
  align-items: center;
  justify-content: center;
  gap: 11px;
  padding: 20px;
  color: var(--text-secondary);
}

.cart-popover-empty strong {
  display: block;
  color: var(--text);
  font-size: 12px;
}

.cart-popover-empty p {
  margin: 2px 0 0;
  font-size: 10px;
}

.cart-popover-footer {
  margin-top: auto;
  padding: 12px;
  background: color-mix(in srgb, var(--surface-2) 68%, var(--surface));
  border-top: 1px solid var(--border);
}

.cart-popover-footer .button--primary {
  flex: 1 1 auto;
}

.logout-button svg {
  width: 17px;
  height: 17px;
}

.search-hero {
  display: grid;
  grid-template-columns: minmax(240px, 0.7fr) minmax(430px, 1.3fr);
  align-items: end;
  gap: 34px;
  padding: 30px 32px;
  background:
    linear-gradient(120deg, var(--accent-softer), transparent 42%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.search-copy {
  display: grid;
  gap: 7px;
}

.search-copy h1 {
  margin: 0;
  font-size: clamp(22px, 2.4vw, 30px);
  font-weight: 735;
  letter-spacing: -0.045em;
  line-height: 1.14;
}

.search-copy > p:last-child {
  max-width: 460px;
  margin: 0;
  color: var(--text-secondary);
  font-size: 13px;
}

.search-bar {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 9px;
}

.search-input-wrap {
  display: flex;
  min-width: 0;
  min-height: 48px;
  flex: 1 1 auto;
  align-items: center;
  gap: 10px;
  padding: 0 10px 0 14px;
  border-radius: var(--radius-md);
}

.search-input-wrap > svg {
  width: 19px;
  height: 19px;
  flex: 0 0 auto;
  color: var(--text-tertiary);
}

.search-input-wrap input {
  width: 100%;
  min-width: 0;
  height: 46px;
  padding: 0;
  color: var(--text);
  background: transparent;
  border: 0;
  outline: 0;
  font-size: 15px;
}

.search-input-wrap input::placeholder {
  color: var(--text-tertiary);
}

.search-input-wrap kbd {
  display: inline-grid;
  width: 25px;
  height: 25px;
  flex: 0 0 auto;
  color: var(--text-tertiary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: inset 0 -1px 0 var(--border-strong);
  font-family: inherit;
  font-size: 11px;
  place-items: center;
}

.search-submit {
  min-height: 48px;
  padding-inline: 20px 16px;
}

.search-submit svg {
  width: 17px;
  height: 17px;
}

.search-bar.htmx-request .search-submit {
  opacity: 0.7;
  pointer-events: none;
}

/* Landing statistics */

.landing-stats {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
}

.stat-card {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 94px;
  align-items: center;
  gap: 12px;
  padding: 15px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  text-decoration: none;
  transition:
    border-color 150ms var(--ease),
    box-shadow 150ms var(--ease),
    transform 150ms var(--ease);
}

.stat-card--link:hover {
  border-color: color-mix(in srgb, var(--accent) 42%, var(--border));
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.stat-icon {
  display: grid;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 10px;
  place-items: center;
}

.stat-icon--violet {
  color: #7955d9;
  background: color-mix(in srgb, #7955d9 12%, transparent);
}

.stat-icon--green {
  color: var(--success);
  background: var(--success-soft);
}

.stat-icon--amber {
  color: var(--warning);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
}

.stat-icon--blue {
  color: var(--accent);
  background: var(--accent-soft);
}

.stat-icon svg {
  width: 19px;
  height: 19px;
}

.stat-icon svg,
.cart-popover svg,
.product-image-dialog-error svg {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.8;
}

.stat-copy {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.stat-copy small,
.stat-copy > span {
  overflow: hidden;
  color: var(--text-tertiary);
  font-size: 10px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stat-copy small {
  font-weight: 720;
  letter-spacing: 0.055em;
  text-transform: uppercase;
}

.stat-copy strong {
  font-size: 17px;
  font-weight: 740;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.stat-card-value {
  position: absolute;
  right: 12px;
  bottom: 9px;
  max-width: calc(100% - 24px);
  overflow: hidden;
  color: var(--text-secondary);
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Empty and loading states */

.results-area {
  position: relative;
  min-width: 0;
}

#results {
  min-height: 192px;
}

.empty-state {
  display: flex;
  min-height: 192px;
  align-items: center;
  justify-content: center;
  gap: 15px;
  padding: 30px;
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}

.empty-state-icon {
  display: grid;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 12px;
  place-items: center;
}

.empty-state-icon svg {
  width: 23px;
  height: 23px;
}

.empty-state h2 {
  margin: 0 0 2px;
  color: var(--text);
  font-size: 14px;
  font-weight: 680;
}

.empty-state p {
  margin: 0;
  font-size: 12px;
}

.htmx-indicator {
  display: none;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  display: block;
}

.results-loading {
  min-height: 330px;
  padding: 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.results-loading.htmx-request + #results {
  display: none;
}

.skeleton-heading,
.skeleton-toolbar,
.skeleton-row {
  display: flex;
  align-items: center;
}

.skeleton-heading {
  justify-content: space-between;
  gap: 20px;
}

.skeleton-toolbar {
  gap: 10px;
  margin: 25px 0 16px;
  padding: 13px;
  background: var(--surface-2);
  border-radius: var(--radius-md);
}

.skeleton-table {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.skeleton-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1.1fr 0.7fr 1fr 1fr;
  gap: 28px;
  min-height: 48px;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
}

.skeleton-row:last-child {
  border-bottom: 0;
}

.skeleton {
  position: relative;
  display: block;
  height: 9px;
  overflow: hidden;
  background: var(--surface-3);
  border-radius: var(--radius-full);
}

.skeleton::after {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--overlay), transparent);
  content: "";
  transform: translateX(-100%);
  animation: skeleton-shimmer 1.45s ease-in-out infinite;
}

.skeleton--title {
  width: 190px;
  height: 17px;
}

.skeleton--summary {
  width: 150px;
}

.skeleton--control {
  width: 150px;
  height: 34px;
  border-radius: var(--radius-md);
}

/* Streaming skeleton rows: shimmer blocks shaped to the real result-row cells, so the
   loading table reads as the finished one (see results_skeleton.html). */
.skeleton--cell {
  width: 100%;
  max-width: 130px;
  height: 11px;
}

.skeleton--sm {
  max-width: 64px;
}

.skeleton--thumb {
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: var(--radius-sm);
}

/* Code-cell shimmer lines: fixed widths (their .product-identity-copy parent is a
   shrink-to-fit flex item, so a percentage width would collapse to zero). */
.skeleton--code {
  width: 108px;
  height: 11px;
}

.skeleton--code-sub {
  width: 68px;
  height: 9px;
  margin-top: 5px;
}

@keyframes skeleton-shimmer {
  100% {
    transform: translateX(100%);
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* The @keyframes spin above (same rotation the product-image .spinner uses) also drives
   .loading-spinner — the small spinner beside the "N/11 atsakė" progress count while
   suppliers stream in (results_skeleton.html), reused rather than a second keyframe. */
.loading-spinner {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  vertical-align: -0.1em;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}

/* Results */

.results-panel {
  min-width: 0;
  padding: 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.results-heading {
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 20px;
  margin-bottom: 10px;
}

/* Title block pushes the summary + Filtrai toggle together to the right edge, instead of
   space-between spreading all three children apart once the toggle is a third item. */
.results-heading > div:first-child {
  margin-right: auto;
}

/* Collapsed-by-default filters live behind this toggle in the heading row (next to the
   supplier count), so the default view stays compact. Click reveals the toolbar in place. */
.filters-toggle {
  display: inline-flex;
  align-items: center;
  align-self: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition:
    color 150ms var(--ease),
    border-color 150ms var(--ease),
    background 150ms var(--ease);
}

.filters-toggle:hover,
.filters-toggle.is-open {
  color: var(--text-primary);
  border-color: var(--border-strong, var(--text-secondary));
}

.filters-toggle .filters-toggle-icon {
  width: 15px;
  height: 15px;
}

.filters-toggle .filters-toggle-chevron {
  width: 14px;
  height: 14px;
  transition: transform 200ms var(--ease);
}

.filters-toggle.is-open .filters-toggle-chevron {
  transform: rotate(180deg);
}

.results-heading h2 {
  margin: 4px 0 0;
  font-size: 19px;
  font-weight: 710;
  letter-spacing: -0.025em;
}

.results-heading h2 span {
  color: var(--text-secondary);
  font-weight: 600;
}

.results-summary {
  margin: 0;
  align-self: center;
  color: var(--text-secondary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  transition: color 200ms var(--ease);
}

/* One-time, subtle signal that every supplier has answered (11/11) — colored text and
   a check already baked into the counter's own textContent (see app.js), not a badge or
   background, so it reads as a quiet state change rather than another toast. Reverts
   automatically (class + check removed) if a retry brings a placeholder row back. */
.results-summary.is-complete {
  color: var(--success);
  font-weight: 650;
}

/* The progress count + its live spinner, right-aligned in the results heading while
   suppliers stream in. */
.results-progress {
  display: flex;
  align-items: center;
  align-self: center;
  gap: 8px;
}

/* Reliable class-driven collapse for the filters toolbar. The grid animates between 0fr and
   1fr rows; the inner element clips with overflow:hidden. State is ONLY the `is-open` class
   (bound to filtersOpen), so nothing measures heights or writes inline styles — it can never
   desync from the button the way x-collapse did after an HTMX panel swap. */
/* A plain display toggle, NOT a height animation. The grid 0fr<->1fr version needed
   `overflow: hidden` on the inner element to clip mid-animation, and that clipped the
   filter dropdown menus the moment they opened past the toolbar's bottom edge — they
   render below the table and were invisible. Nothing here clips, and nothing creates a
   stacking context (no transform/filter/opacity held below 1, no position+z-index), so
   the menus' own z-index keeps them above the table. Keep it that way: see the note on
   .results-toolbar about backdrop-filter trapping them.
   State is still ONLY the is-open class bound to filtersOpen, so it cannot desync. */
.results-filters-collapse {
  display: none;
}

.results-filters-collapse.is-open {
  display: block;
  animation: filters-reveal 160ms var(--ease);
}

/* Opacity-only, and it ends at 1 — so no stacking context survives the animation. */
@keyframes filters-reveal {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.results-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 9px;
  margin: 10px 0 13px;
  padding: 9px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  /* No backdrop-filter: the toolbar no longer sits sticky over scrolling content (it scrolls
     with the page), and a backdrop-filter would form a stacking context that traps the
     dropdown menus (z-index 80) BELOW the table's sticky header/dividers. */
}

.toolbar-control {
  display: grid;
  /* Grow to fill the row and wrap evenly instead of sitting at a fixed width that
     overflowed sideways between ~900px and ~1050px (6 controls that no longer fit one
     row but had no wrap). The basis is the smallest comfortable trigger width; controls
     share the row equally above it and wrap below it, at every viewport. */
  flex: 1 1 160px;
  min-width: 0;
  gap: 5px;
}

.toolbar-label {
  padding-left: 3px;
  color: var(--text-tertiary);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.065em;
  text-transform: uppercase;
}

.dropdown {
  position: relative;
}

.dropdown-trigger {
  display: flex;
  /* Fill the flex-sized .toolbar-control rather than pin a fixed 164px width that could
     not shrink, which is what pushed the toolbar into sideways overflow on tablets. */
  width: 100%;
  min-width: 0;
  min-height: 36px;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 10px 0 11px;
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  text-align: left;
  transition:
    color 150ms var(--ease),
    border-color 150ms var(--ease),
    background-color 150ms var(--ease);
}

/* Tiekėjas holds the longest labels ("N tiekėjai"), so let its control claim a little
   more of the row than the others while still flexing/wrapping with them. */
.toolbar-control:nth-child(2) {
  flex-basis: 200px;
}

.dropdown-trigger:hover,
.dropdown-trigger[aria-expanded="true"] {
  color: var(--text);
  border-color: var(--text-tertiary);
}

.dropdown-trigger svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.9;
  transition: transform 150ms var(--ease);
}

.dropdown-trigger[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

.dropdown-menu {
  /* Hidden by default, shown via the `.is-open` class that Alpine toggles from `open`.
     A CSS class (not x-show, which fights over inline `display`) keeps visibility
     idempotent even when HTMX re-inits the fragment — otherwise a repeat search left a
     dropdown displayed while its state said closed. No x-cloak needed: base is hidden. */
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 80;
  min-width: max(100%, 220px);
  max-height: 260px;
  gap: 2px;
  padding: 5px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

.dropdown-menu.is-open {
  display: grid;
}

.dropdown-menu--right {
  right: 0;
  left: auto;
}

.dropdown-menu [role="option"] {
  display: flex;
  width: 100%;
  min-height: 34px;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 9px;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 12px;
  text-align: left;
}

.dropdown-menu [role="option"]:hover,
.dropdown-menu [role="option"]:focus-visible {
  color: var(--text);
  background: var(--surface-2);
}

.dropdown-menu [role="option"].is-selected {
  color: var(--accent);
  background: var(--accent-soft);
  font-weight: 650;
}

.dropdown-menu [role="option"] svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  fill: none;
  opacity: 0;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2;
}

.dropdown-menu [role="option"].is-selected svg {
  opacity: 1;
}

.results-table-wrapper {
  max-height: min(68vh, 720px);
  overflow: auto;
  overscroll-behavior-y: contain;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  /* scrollbar-color comes from the global thin/muted rule near the top. */
}

.results-table {
  width: 100%;
  min-width: 1120px;
  border-spacing: 0;
  background: var(--surface);
  border-collapse: separate;
  font-variant-numeric: tabular-nums;
}

.results-table th,
.results-table td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}

.results-table th {
  position: sticky;
  top: 0;
  z-index: 5;
  height: 39px;
  color: var(--text-tertiary);
  background: var(--surface-2);
  font-size: 10px;
  font-weight: 750;
  letter-spacing: 0.065em;
  text-transform: uppercase;
  white-space: nowrap;
}

.results-table tbody tr:last-child td {
  border-bottom: 0;
}

.result-row {
  position: relative;
  transition:
    background-color 150ms var(--ease),
    box-shadow 150ms var(--ease),
    opacity 150ms var(--ease);
}

.result-row:hover {
  background: var(--surface-2);
}

.result-row.is-cheapest {
  background: var(--accent-softer);
  box-shadow: inset 3px 0 0 var(--accent);
}

.result-row--notfound,
.result-row--unavailable,
.result-row--reauth {
  color: var(--text-secondary);
  background: color-mix(in srgb, var(--surface-2) 48%, transparent);
}

.results-table td {
  color: var(--text-secondary);
  font-size: 12px;
}

.results-table .provider {
  color: var(--text);
  font-weight: 690;
}

.results-table .code {
  color: var(--text);
  font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  font-size: 11px;
  white-space: nowrap;
}

.product-identity {
  display: flex;
  min-width: 210px;
  align-items: center;
  gap: 9px;
}

.product-thumbnail {
  position: relative;
  display: grid;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  overflow: hidden;
  color: var(--text-tertiary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  place-items: center;
}

button.product-thumbnail {
  padding: 0;
  cursor: zoom-in;
}

button.product-thumbnail:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

button.product-thumbnail:disabled {
  border-color: var(--border);
  box-shadow: none;
  cursor: default;
}

.product-thumbnail img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--surface);
}

.product-thumbnail-fallback {
  display: grid;
  place-items: center;
}

.product-thumbnail-fallback svg {
  width: 20px;
  height: 20px;
  opacity: 0.62;
}

.product-thumbnail.is-broken img {
  display: none;
}

.product-thumbnail--empty {
  opacity: 0.62;
}

.product-identity-copy {
  display: block;
  min-width: 0;
  max-width: 168px;
}

/* On-demand "Alternatyvos" action under an Adcat offer that has substitutes. */
.alt-button {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 5px;
  padding: 2px 9px;
  color: var(--accent);
  background: var(--accent-soft);
  border: 0;
  border-radius: var(--radius-full);
  font-size: 10px;
  font-weight: 680;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition:
    background-color 150ms var(--ease),
    color 150ms var(--ease);
}

.alt-button:hover {
  color: var(--accent-hover);
  background: color-mix(in srgb, var(--accent) 17%, transparent);
}

.alt-button:disabled {
  opacity: 0.55;
  cursor: default;
}

.product-code,
.product-label {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}

.product-label {
  margin-top: 2px;
  color: var(--text-tertiary);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 9px;
}

.results-table td.price {
  color: var(--text);
  font-size: 13px;
  font-weight: 720;
  white-space: nowrap;
}

.price-value {
  display: flex;
  align-items: center;
  gap: 8px;
}

.best-badge,
.status-badge,
.count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  white-space: nowrap;
}

.best-badge {
  min-height: 20px;
  gap: 4px;
  padding: 0 7px;
  color: var(--accent);
  background: var(--accent-soft);
  font-size: 9px;
  font-weight: 750;
  letter-spacing: 0.025em;
  text-transform: uppercase;
}

.best-badge svg {
  width: 11px;
  height: 11px;
  fill: currentColor;
  stroke-width: 1.2;
}

.results-table .manufacturer {
  white-space: nowrap;
}

.results-table .amount,
.results-table .delivery {
  line-height: 1.35;
}

.results-table .link {
  white-space: nowrap;
}

.results-table .link a {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--accent);
  font-weight: 620;
  text-decoration: none;
}

.results-table .link a:hover {
  color: var(--accent-hover);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.results-table .link svg {
  width: 13px;
  height: 13px;
}

/* Toasts: bottom-right stack for streamed-search failures ("Bandyti dar kartą") and
   action prompts (e.g. "Prisijungti" when a provider needs a live login). _toast.html
   appends each one out-of-band into #toast-region, newest last in the DOM; the stack
   is column-reverse so the newest toast renders on top. A provider's placeholder row
   is gone by the time its toast lands (see the template's comment), so the toast is
   the only trace of that failure — it needs to read clearly at a glance. */
.toast-region {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 90;
  display: flex;
  flex-direction: column-reverse;
  gap: 0.6rem;
  max-width: min(92vw, 23rem);
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8rem 0.7rem 0.8rem 0.9rem;
  pointer-events: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  animation: toast-in 280ms cubic-bezier(0.16, 1, 0.3, 1);
  /* Draggable to dismiss (app.js): grab the body and flick it sideways. touch-action keeps
     vertical scrolling working while claiming horizontal drags; will-change keeps the
     slide smooth. Inline transform/opacity/transition are set by app.js during drag + exit. */
  cursor: grab;
  touch-action: pan-y;
  will-change: transform;
}

.toast.is-dragging {
  cursor: grabbing;
  user-select: none;
}

/* The close button and any action keep their normal pointer — you don't "grab" those. */
.toast .toast-close,
.toast .toast-action {
  cursor: pointer;
}

.toast--error {
  border-left-color: var(--danger);
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--danger) 8%, var(--surface)),
    var(--surface) 55%
  );
}

.toast--action {
  border-left-color: var(--accent);
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--accent) 8%, var(--surface)),
    var(--surface) 55%
  );
}

/* Success: the one-shot "search finished" toast app.js appends when every supplier has
   answered. */
.toast--success {
  border-left-color: var(--success);
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--success) 8%, var(--surface)),
    var(--surface) 55%
  );
}

/* Info: a neutral confirmation for an action that completed but produced nothing to add
   (e.g. "Naujų alternatyvų nerasta") — the operation is not a failure, but a green
   "success" would overclaim, so it reads as a calm, accent-tinted note. */
.toast--info {
  border-left-color: var(--accent);
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--accent) 6%, var(--surface)),
    var(--surface) 55%
  );
}

/* Waiting/loading: the streaming "N/M" progress toast + the transient retry/alternatives
   toasts (app.js). Yellow, with a spinner. */
.toast--waiting {
  border-left-color: var(--warning);
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--warning) 10%, var(--surface)),
    var(--surface) 55%
  );
}

.toast-message {
  flex: 1;
  color: var(--text);
  font-size: 13px;
  font-weight: 550;
  line-height: 1.4;
}

.toast-action {
  display: inline-flex;
  flex: none;
  align-items: center;
  min-height: 26px;
  padding: 0 10px;
  color: var(--accent);
  background: var(--accent-soft);
  border: 0;
  border-radius: var(--radius-full);
  font-size: 12px;
  font-weight: 680;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color 150ms var(--ease),
    color 150ms var(--ease);
}

.toast-action:hover {
  color: var(--accent-hover);
  background: color-mix(in srgb, var(--accent) 17%, transparent);
}

.toast-close {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition:
    background-color 150ms var(--ease),
    color 150ms var(--ease);
}

.toast-close:hover {
  color: var(--text);
  background: var(--surface-2);
}

.toast-close svg {
  width: 15px;
  height: 15px;
}

/* The completion toast is built in JS with a plain "✕" glyph instead of the icon sprite. */
.toast-close--text {
  font-size: 14px;
  line-height: 1;
}

/* Slide in from the right edge (the toasts are bottom-right anchored, and this is the same
   axis the swipe-to-dismiss uses, so entry and exit read as one motion). The overshoot
   easing gives it a gentle settle. */
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateX(28px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Redundant with the sitewide prefers-reduced-motion rule further down (which already
   forces every animation to ~0 duration via !important) but kept local and explicit —
   this is the one place the feature is actually seen, so its motion contract should
   be readable without hunting for the global override. */
@media (prefers-reduced-motion: reduce) {
  .toast {
    animation: none;
  }

  .loading-spinner {
    animation: none;
  }
}

/* Suppliers table reuses .cart-table, whose .link cell has no icon sizing — without
   this the external-link icon renders at its default (huge) size and inflates the row,
   throwing off the badge/button alignment in the reachability column. */
.suppliers-table .link a {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--accent);
  text-decoration: none;
}
.suppliers-table .link a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.suppliers-table .link svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.status-cell {
  height: 48px;
}

.status-badge {
  min-height: 23px;
  gap: 5px;
  padding: 0 8px;
  font-size: 10px;
  font-weight: 680;
  text-decoration: none;
}

.status-badge--muted {
  color: var(--text-secondary);
  background: var(--surface-3);
}

.status-badge--action {
  color: var(--accent);
  background: var(--accent-soft);
}

.status-badge--action:hover {
  background: color-mix(in srgb, var(--accent) 17%, transparent);
}

.status-badge--ok {
  color: var(--success);
  background: var(--success-soft);
}

.status-badge--warning {
  color: var(--warning);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
}

.status-badge svg {
  width: 12px;
  height: 12px;
}

/* Suppliers page (view-only config + reachability) */

.supplier-module,
.supplier-slot {
  display: block;
}

.supplier-module {
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
}

.supplier-slot {
  margin-top: 1px;
  color: var(--text-tertiary);
  font-size: 9px;
  font-weight: 720;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.reachability-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.results-table .add-to-cart form {
  display: flex;
  align-items: center;
  gap: 6px;
}

.cart-qty-input {
  width: 44px;
  height: 32px;
  padding: 0 5px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  text-align: center;
}

.results-table .add-to-cart .button svg {
  width: 14px;
  height: 14px;
}

.result-group-row td {
  /* Sticky supplier divider: pins just below the sticky column header (th height 39px)
     while scrolling within that supplier's rows, then the next divider pushes it up. */
  position: sticky;
  top: 39px;
  z-index: 4;
  padding: 8px 12px;
  background: var(--surface-2);
  border-bottom-color: var(--border-strong);
}

.result-group-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.result-group-content strong {
  color: var(--text);
  font-size: 11px;
}

.result-group-content span {
  color: var(--text-tertiary);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}

.result-filter-empty td {
  height: 120px;
  color: var(--text-secondary);
  text-align: center;
}

/* Cart */

.cart {
  min-width: 0;
  margin-top: 18px;
}

.cart-panel {
  min-width: 0;
  padding: 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.cart-panel-header,
.cart-group-header,
.cart-group-footer,
.cart-grand-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.cart-panel-header {
  min-height: 43px;
}

.cart-title {
  display: flex;
  align-items: center;
  gap: 11px;
}

.cart-title-icon {
  display: grid;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 10px;
  place-items: center;
}

.cart-title-icon svg {
  width: 19px;
  height: 19px;
}

.cart-panel-header h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 0;
  font-size: 17px;
  font-weight: 710;
  letter-spacing: -0.02em;
}

.count-badge {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  color: var(--accent);
  background: var(--accent-soft);
  font-size: 10px;
  font-weight: 750;
}

.cart-empty {
  display: flex;
  min-height: 104px;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 15px;
  padding: 20px;
  color: var(--text-secondary);
  background: var(--surface-2);
  border-radius: var(--radius-md);
}

.cart-empty > span {
  display: grid;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  color: var(--text-tertiary);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  place-items: center;
}

.cart-empty svg {
  width: 18px;
  height: 18px;
}

.cart-empty strong {
  display: block;
  color: var(--text);
  font-size: 12px;
}

.cart-empty p {
  margin: 2px 0 0;
  font-size: 11px;
}

.cart-groups {
  display: grid;
  min-width: 0;
  gap: 12px;
  margin-top: 16px;
}

.cart-group {
  min-width: 0;
  padding: 14px;
  background: color-mix(in srgb, var(--surface-2) 54%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.cart-group-header {
  margin-bottom: 10px;
}

.cart-group-header > div {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.cart-group-header h3 {
  margin: 0;
  color: var(--text);
  font-size: 13px;
  font-weight: 710;
}

.cart-group-header span {
  color: var(--text-tertiary);
  font-size: 10px;
}

.cart-table-wrapper {
  max-width: 100%;
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.cart-table {
  width: 100%;
  min-width: 760px;
  border-spacing: 0;
  border-collapse: separate;
  font-variant-numeric: tabular-nums;
}

.cart-table th,
.cart-table td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}

.cart-table th {
  color: var(--text-tertiary);
  background: var(--surface-2);
  font-size: 9px;
  font-weight: 750;
  letter-spacing: 0.065em;
  text-transform: uppercase;
  white-space: nowrap;
}

.cart-table td {
  color: var(--text-secondary);
  font-size: 11px;
}

.cart-table tbody tr:last-child td {
  border-bottom: 0;
}

.cart-table .price,
.cart-table .code {
  white-space: nowrap;
}

.cart-table .line-total {
  color: var(--text);
  font-weight: 690;
}

.cart-item-name {
  min-width: 160px;
}

.cart-item-name strong,
.cart-item-name span {
  display: block;
}

.cart-item-name strong {
  color: var(--text);
  font-size: 11px;
  font-weight: 650;
}

.cart-item-name span {
  margin-top: 1px;
  color: var(--text-tertiary);
  font-size: 9px;
}

.cart-qty-form {
  display: flex;
  align-items: center;
  gap: 5px;
}

.cart-qty-form input {
  width: 46px;
  height: 32px;
  padding: 0 5px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  text-align: center;
}

.cart-table .icon-button {
  width: 32px;
  height: 32px;
}

.cart-table .icon-button svg {
  width: 15px;
  height: 15px;
}

.cart-group-footer {
  margin-top: 10px;
}

.cart-archive-action {
  display: grid;
  flex: 0 1 auto;
  gap: 4px;
}

.cart-archive-action small {
  max-width: 210px;
  color: var(--text-tertiary);
  font-size: 9px;
  line-height: 1.3;
  text-align: center;
}

.cart-subtotal {
  color: var(--text);
  font-size: 11px;
  font-weight: 690;
  font-variant-numeric: tabular-nums;
}

.dispatch-button {
  min-height: 32px;
  padding-inline: 12px;
  font-size: 11px;
}

.cart-dispatch-note {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 7px 0 0;
  color: var(--text-tertiary);
  font-size: 10px;
}

.cart-dispatch-note svg {
  width: 13px;
  height: 13px;
  flex: 0 0 auto;
}

.cart-grand-total {
  margin-top: 14px;
  padding: 14px 2px 0;
  color: var(--text-secondary);
  border-top: 1px solid var(--border-strong);
  font-size: 12px;
  font-weight: 620;
}

.cart-grand-total-amount {
  color: var(--text);
  font-size: 14px;
  font-weight: 740;
  font-variant-numeric: tabular-nums;
}

/* Product image lightbox */

.has-open-dialog {
  overflow: hidden;
}

.product-image-dialog {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 24px;
  color: var(--text);
  background: transparent;
  border: 0;
}

.product-image-dialog[open] {
  display: grid;
  place-items: center;
}

.product-image-dialog::backdrop {
  background: rgba(7, 9, 13, 0.76);
  backdrop-filter: blur(10px);
}

.product-image-dialog-surface {
  display: grid;
  width: min(980px, 100%);
  height: min(820px, 100%);
  margin: 0;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  grid-template-rows: auto minmax(0, 1fr) auto;
}

.product-image-dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}

.product-image-dialog-header h2 {
  margin: 2px 0 0;
  font-size: 16px;
  letter-spacing: -0.025em;
}

.product-image-dialog-body {
  position: relative;
  display: grid;
  min-height: 240px;
  overflow: hidden;
  background:
    linear-gradient(45deg, var(--surface-2) 25%, transparent 25%) 0 0 / 22px 22px,
    linear-gradient(-45deg, var(--surface-2) 25%, transparent 25%) 0 11px / 22px 22px,
    linear-gradient(45deg, transparent 75%, var(--surface-2) 75%) 11px -11px / 22px 22px,
    linear-gradient(-45deg, transparent 75%, var(--surface-2) 75%) -11px 0 / 22px 22px,
    var(--surface);
  place-items: center;
}

.product-image-dialog-image {
  width: 100%;
  height: 100%;
  max-height: calc(100vh - 180px);
  padding: 22px;
  object-fit: contain;
}

.product-image-dialog-loading,
.product-image-dialog-error {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 18px;
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  font-size: 12px;
}

.product-image-dialog-error svg {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  color: var(--danger);
}

.product-image-dialog-error strong {
  color: var(--text);
  font-size: 12px;
}

.product-image-dialog-error p {
  margin: 3px 0 0;
  font-size: 10px;
}

.spinner {
  width: 18px;
  height: 18px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}

.product-image-dialog-caption {
  min-height: 46px;
  margin: 0;
  padding: 14px 18px;
  overflow: hidden;
  color: var(--text-secondary);
  border-top: 1px solid var(--border);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 900px) {
  .search-hero {
    grid-template-columns: 1fr;
    align-items: stretch;
    gap: 20px;
  }

  .results-toolbar {
    flex-wrap: wrap;
  }

  .landing-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .header-action-label {
    display: none;
  }

  /* Tablet: the in-nav search is the priority, so trim the header to essentials —
     the brand collapses to its cog, the "/" keyboard hint drops, and every nav
     action (incl. logout) is icon-only. This frees the width the search needs so its
     placeholder is not truncated. Desktop (>900px) keeps the full brand + labels. */
  .brand-lockup > span:last-child {
    display: none;
  }

  .search-input-wrap kbd {
    display: none;
  }

  .logout-button span {
    display: none;
  }

  .header-nav-link,
  .cart-trigger {
    width: 40px;
    padding: 0;
  }

  .header-count-badge,
  .cart-count-badge {
    position: absolute;
    top: 1px;
    right: -1px;
  }

  .toolbar-control,
  .dropdown,
  .dropdown-trigger {
    flex: 1 1 170px;
  }

  .toolbar-control:nth-child(2) .dropdown-trigger,
  .dropdown-trigger {
    width: 100%;
    min-width: 0;
  }
}

@media (max-width: 640px) {
  .page {
    padding: 10px 10px 28px;
  }

  .app-shell {
    gap: 10px;
  }

  .app-header {
    top: 8px;
    min-height: 56px;
    background: var(--surface);
    border-radius: var(--radius-md);
    backdrop-filter: none;
  }

  .brand-lockup small,
  .logout-button span {
    display: none;
  }

  .app-header .icon-button,
  .app-header .button {
    min-width: 44px;
    height: 44px;
  }

  .logout-button {
    width: 38px;
    padding: 0;
  }

  .search-hero,
  .results-panel,
  .cart-panel {
    padding: 17px;
    border-radius: var(--radius-md);
  }

  .landing-stats {
    grid-template-columns: 1fr;
  }

  .app-shell.has-results .landing-stats {
    display: none;
  }

  .stat-card {
    min-height: 82px;
  }

  .cart-popover {
    position: fixed;
    top: 76px;
    right: 10px;
    left: 10px;
    width: auto;
    max-height: calc(100dvh - 88px);
  }

  .cart-popover-footer {
    padding-bottom: max(12px, env(safe-area-inset-bottom));
  }

  .search-copy > p:last-child {
    font-size: 12px;
  }

  .search-bar {
    align-items: stretch;
    flex-direction: column;
  }

  .search-input-wrap,
  .search-submit {
    width: 100%;
  }

  .search-input-wrap input {
    font-size: 16px;
  }

  .search-input-wrap kbd {
    display: none;
  }

  .empty-state {
    min-height: 170px;
    align-items: center;
    flex-direction: column;
    text-align: center;
  }

  .results-loading {
    padding: 17px;
  }

  .skeleton--summary,
  .skeleton-row span:nth-child(n + 4) {
    display: none;
  }

  .skeleton-row {
    grid-template-columns: 1fr 1fr 1fr;
  }

  .results-heading {
    align-items: flex-start;
    flex-direction: column;
    gap: 7px;
  }

  .results-summary {
    text-align: left;
  }

  .results-toolbar {
    position: static;
    display: grid;
    grid-template-columns: 1fr;
    margin: 15px 0 11px;
    background: var(--surface-2);
    backdrop-filter: none;
  }

  .toolbar-control,
  .dropdown,
  .dropdown-trigger {
    width: 100%;
  }

  .dropdown-trigger {
    min-height: 42px;
    font-size: 13px;
  }

  .dropdown-menu {
    right: 0;
    left: 0;
    min-width: 100%;
  }

  .dropdown-menu [role="option"] {
    min-height: 42px;
    font-size: 13px;
  }

  /* The table scrolls inside its own box, so it must stay within its container's
     padding: a negative right margin here bled it past the right edge, leaving the
     left padded and the right sheared off. It cost both tables — the results panel
     (17px) and the history card (16px) share this wrapper. */
  .results-table-wrapper {
    max-height: 66vh;
  }

  .results-table th,
  .results-table td {
    padding: 10px;
  }

  .results-table .add-to-cart .button span {
    display: none;
  }

  .results-table .add-to-cart .button {
    width: 34px;
    padding: 0;
  }

  .cart-panel-header,
  .cart-grand-total {
    align-items: flex-start;
  }

  .cart-grand-total {
    flex-direction: column;
    gap: 5px;
  }

  .cart-group {
    padding: 10px;
  }

  #current-cart .cart-table-wrapper {
    margin-right: 0;
    overflow: visible;
    background: transparent;
    border: 0;
  }

  #current-cart .cart-table {
    display: block;
    min-width: 0;
  }

  #current-cart .cart-table thead {
    display: none;
  }

  #current-cart .cart-table tbody {
    display: grid;
    gap: 9px;
  }

  #current-cart .cart-table tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 7px 12px;
    padding: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
  }

  #current-cart .cart-table td {
    display: flex;
    min-width: 0;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0;
    border: 0;
  }

  #current-cart .cart-table td[data-label]::before {
    flex: 0 0 auto;
    color: var(--text-tertiary);
    content: attr(data-label);
    font-size: 9px;
    font-weight: 720;
    letter-spacing: 0.055em;
    text-transform: uppercase;
  }

  #current-cart .cart-table .cart-item-name,
  #current-cart .cart-table .code,
  #current-cart .cart-table .cart-unit-price,
  #current-cart .cart-table .cart-quantity {
    grid-column: 1 / -1;
  }

  #current-cart .cart-table .cart-item-name {
    padding-bottom: 9px;
    border-bottom: 1px solid var(--border);
  }

  #current-cart .cart-table .cart-quantity {
    display: grid;
    gap: 6px;
    padding-top: 3px;
  }

  #current-cart .cart-qty-form {
    display: grid;
    grid-template-columns: minmax(68px, 0.42fr) minmax(0, 1fr);
    width: 100%;
  }

  #current-cart .cart-qty-form input,
  #current-cart .cart-qty-form .button {
    width: 100%;
    min-height: 40px;
  }

  #current-cart .cart-table .line-total {
    grid-column: 1;
  }

  #current-cart .cart-table .cart-remove-action {
    grid-column: 2;
    justify-content: flex-end;
  }

  #current-cart .cart-table .cart-remove-action .icon-button {
    width: 40px;
    height: 40px;
  }

  .cart-archive-action {
    width: 100%;
  }

  .cart-archive-action small {
    max-width: none;
  }

  .cart-table-wrapper {
    border-radius: var(--radius-sm);
  }

  .product-image-dialog {
    padding: 8px;
  }

  .product-image-dialog-surface {
    width: 100%;
    height: 100%;
    border-radius: var(--radius-lg);
  }

  .product-image-dialog-image {
    max-height: calc(100dvh - 142px);
    padding: 12px;
  }

  .login-card {
    max-width: 370px;
    padding: 26px 22px;
  }

  .login-theme-control {
    top: 12px;
    right: 12px;
  }
}

@media (max-width: 420px) {
  .brand-lockup > span:last-child {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .header-actions {
    gap: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* Every interface glyph comes from the same Lucide subset and uses one
   presentation weight; contextual rules may size icons but never redraw them. */
svg.lucide {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (prefers-contrast: more) {
  :root {
    --border: var(--border-strong);
  }

  .button,
  .icon-button,
  input,
  .dropdown-trigger {
    border-width: 2px;
  }
}

/* Auto-opening VNC modal (InterCars Turnstile). Large, so the embedded browser is
   usable; mirrors the product-image dialog's backdrop/surface conventions. */
.vnc-dialog {
  border: none;
  border-radius: 14px;
  padding: 0;
  width: min(96vw, 1200px);
  max-width: 96vw;
  background: transparent;
}
.vnc-dialog::backdrop { background: rgba(2, 6, 23, 0.72); backdrop-filter: blur(2px); }
.vnc-dialog-surface {
  display: flex;
  flex-direction: column;
  height: min(88vh, 820px);
  background: var(--surface, #0d1117);
  color: var(--text, #e6edf3);
  border: 1px solid var(--border, #30363d);
  border-radius: 14px;
  overflow: hidden;
}
.vnc-dialog-header {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.75rem 1rem; border-bottom: 1px solid var(--border, #30363d);
}
.vnc-dialog-actions { display: flex; align-items: center; gap: 0.5rem; }
.vnc-dialog-body { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.vnc-dialog-note { margin: 0; padding: 0.5rem 1rem; font-size: 0.85rem; color: var(--text-muted, #8b949e); }
.vnc-dialog-frame { flex: 1; width: 100%; border: 0; background: #000; touch-action: none; }

/* Phones: go near-fullscreen so the scaled framebuffer has real estate, and use the
   dynamic viewport unit so mobile browser chrome doesn't clip the canvas. noVNC's
   resize=scale then fits the whole remote screen in — no cropping, pan/zoom via its
   own touch gestures. */
@media (max-width: 640px) {
  .vnc-dialog { width: 100vw; max-width: 100vw; border-radius: 0; }
  .vnc-dialog-surface { height: 100dvh; border-radius: 0; border: 0; }
  .vnc-dialog-header { padding: 0.5rem 0.75rem; }
  .vnc-dialog-note { padding: 0.4rem 0.75rem; font-size: 0.8rem; }
}

/* Custom search autosuggest dropdown (replaces the native datalist) — server-backed
   history suggestions under the search box. */
.search-input-wrap { position: relative; }
.search-suggest {
  position: absolute;
  z-index: 30;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  max-height: 18rem;
  overflow-y: auto;
}
.search-suggest-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.65rem;
  border-radius: 7px;
  cursor: pointer;
  font-size: 0.95rem;
}
.search-suggest-item.is-active,
.search-suggest-item:hover {
  background: var(--surface-2);
}
.search-suggest-label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The delete control stays laid out (no width jump on hover) but is invisible until
   the row is hovered or keyboard-active. */
.search-suggest-delete {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s var(--ease), color 0.12s var(--ease), background 0.12s var(--ease);
}
.search-suggest-item.is-active .search-suggest-delete,
.search-suggest-item:hover .search-suggest-delete,
.search-suggest-delete:focus-visible {
  opacity: 1;
}
.search-suggest-delete:hover {
  background: var(--danger-soft);
  color: var(--danger);
}
.search-suggest-delete svg {
  width: 14px;
  height: 14px;
}

/* Search-history page: one collapsible card per past search, holding a read-only
   snapshot of what that search returned (rendered with the live .results-table). */
.history-list {
  display: grid;
  gap: 10px;
}

.history-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.history-item:hover {
  border-color: var(--border-strong);
}

.history-item[open] {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

.history-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 13px 16px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

/* Hide the native disclosure triangle; .history-summary-chevron replaces it. */
.history-summary::-webkit-details-marker {
  display: none;
}

.history-summary:hover {
  background: var(--surface-2);
}

.history-summary:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
}

.history-summary-main {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.history-query {
  font-size: 15px;
  font-weight: 650;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* The code is the thing operators copy elsewhere: keep it freely selectable even though
     it lives inside a <summary> (which otherwise suppresses a click-drag as a toggle). */
  user-select: text;
  cursor: text;
}

/* One-tap copy of the code, beside it. Always visible (it is the whole point of the row —
   unlike the delete button it should not hide until hover), laid out at all times so the
   row never shifts; the check-mark confirmation swaps in for ~1.4s on a successful copy
   (see copyCode). */
.history-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}

.history-copy:hover,
.history-copy:focus-visible {
  background: var(--surface-hover, rgba(0, 0, 0, 0.05));
  color: var(--text);
}

.history-copy-icon {
  width: 15px;
  height: 15px;
}

/* The confirmation icon is hidden until the copy succeeds, then it replaces the copy icon. */
.history-copy-icon--done {
  display: none;
  color: var(--success);
}
.history-copy.is-copied {
  color: var(--success);
}
.history-copy.is-copied .history-copy-icon:not(.history-copy-icon--done) {
  display: none;
}
.history-copy.is-copied .history-copy-icon--done {
  display: inline;
}

.history-summary-sub {
  flex: none;
  color: var(--text-tertiary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.history-summary-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

.history-count {
  color: var(--text-secondary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Stays laid out at all times so the row's controls never shift; only its opacity
   changes, and it is always reachable by keyboard. */
.history-delete {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
}

.history-item:hover .history-delete,
.history-item[open] .history-delete,
.history-delete:focus-visible {
  opacity: 1;
}

.history-delete:hover {
  background: var(--danger-soft);
  color: var(--danger);
}

.history-delete svg {
  width: 15px;
  height: 15px;
}

/* Touch has no hover, so never hide it there. */
@media (hover: none) {
  .history-delete {
    opacity: 1;
  }
}

.history-summary-chevron {
  display: inline-flex;
  color: var(--text-tertiary);
  transition: transform 0.18s var(--ease);
}

.history-summary-chevron svg {
  width: 16px;
  height: 16px;
}

.history-item[open] .history-summary-chevron {
  transform: rotate(180deg);
}

.history-item-body {
  padding: 0 16px 16px;
  border-top: 1px solid var(--border);
}

.history-snapshot-note {
  margin: 12px 0;
  color: var(--text-tertiary);
  font-size: 12px;
  line-height: 1.5;
}

/* Skeleton stand-in for the snapshot's note text, inside the real note's own padding
   (.history-snapshot-note) so swapping in the actual two-line text causes no layout shift. */
.history-snapshot-note .skeleton--text-line {
  display: block;
  height: 0.8em;
  width: min(92%, 440px);
  margin: 5px 0;
  border-radius: 4px;
}

.history-snapshot-note .skeleton--text-line--short {
  width: min(55%, 260px);
}

/* The spinner line shown in a card body until its snapshot loads (on demand), and in the
   infinite-scroll sentinel until the next batch of cards arrives. */
.history-loading,
.history-sentinel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: var(--text-secondary);
  font-size: 12px;
}

.history-sentinel {
  padding: 18px 0;
}

/* A snapshot can hold hundreds of offers, and several cards can be open at once, so
   each table scrolls inside its own card rather than stretching the page. Shorter than
   the live table's cap: here it shares the viewport with the other history cards. */
.history-item-body .results-table-wrapper {
  max-height: min(52vh, 460px);
}

@media (max-width: 640px) {
  .history-summary {
    align-items: flex-start;
    flex-direction: column;
    gap: 8px;
  }

  .history-summary-main {
    align-items: flex-start;
    flex-direction: column;
    gap: 2px;
    width: 100%;
  }

  .history-summary-meta {
    justify-content: space-between;
    width: 100%;
  }
}

/* --- Top-bar search (search page only, see _app_header.html): a centered bar that grows
   to fill the middle of the header and shrinks with the viewport, freeing the full page
   height for the results table. Replaces the old .search-hero section. --- */
.header-search {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  align-items: center;
  gap: 8px;
  max-width: 620px;
  margin: 0 14px;
}
.header-search .search-input-wrap { min-height: 44px; }
.header-search .search-input-wrap input { height: 42px; }
.header-search .search-submit { min-height: 44px; padding-inline: 16px 13px; }

@media (max-width: 640px) {
  /* Stay a bar, but drop to its own full-width row beneath brand + actions. */
  .app-header { flex-wrap: wrap; }
  .header-search {
    order: 3;
    flex-basis: 100%;
    max-width: none;
    margin: 6px 0 0;
  }
  /* Override the old hero-column rule (.search-input-wrap/.search-submit { width:100% })
     which, inside this flex row, blew the submit button up to full width and collapsed
     the input. Here the input grows and the button hugs its label. */
  .header-search .search-input-wrap {
    width: auto;
    flex: 1 1 auto;
  }
  .header-search .search-submit {
    width: auto;
    flex: 0 0 auto;
  }
}

/* --- Supplier diagnosis (/suppliers "Diagnozė" column) ------------------------------- */
/* `--error` completes the badge set the diagnosis verdicts map onto: ok / warning
   (degraded) / error (broken) / muted (unknown). It reuses the existing danger tokens so
   both themes are covered by the variables already defined at the top of this file. */
.status-badge--error {
  color: var(--danger);
  background: var(--danger-soft);
}

/* One line per supplier. The column used to be a stack — six wrapping verdict badges, a
   counts paragraph, a running-state paragraph, two buttons — which made every row several
   lines tall and pushed eleven suppliers off the screen. The detail moved into the modal;
   what stays here is the rolled-up verdict, a few numbers, and the buttons. */
.diagnosis-column {
  min-width: 20rem;
  vertical-align: middle;
}

.diagnosis-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.5rem;
}

.diagnosis-line {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}

/* Small enough to sit inside a badge without changing its height. */
.spinner--inline {
  width: 11px;
  height: 11px;
  border-width: 2px;
  flex-shrink: 0;
}

.diagnosis-verdicts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.diagnosis-counts {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}

/* Problems are the actionable half of the diagnosis, so they get the danger accent rather
   than blending into the secondary text above them. */
.diagnosis-problems {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.8125rem;
  color: var(--danger);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.diagnosis-details {
  width: 100%;
  font-size: 0.8125rem;
}

.diagnosis-details summary {
  cursor: pointer;
  color: var(--text-secondary);
}

/* The contract table carries long selectors and long explanations, so let it scroll inside
   its own box instead of pushing the suppliers table into a horizontal page scroll. */
.diagnosis-details .diagnosis-table {
  width: 100%;
  margin-top: 0.4rem;
  border-collapse: collapse;
  display: block;
  overflow-x: auto;
}

.diagnosis-table th,
.diagnosis-table td {
  padding: 0.25rem 0.4rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--surface-3);
}

.diagnosis-table code {
  font-size: 0.75rem;
  word-break: break-all;
}

.diagnosis-name {
  font-weight: 600;
}

.diagnosis-optional {
  font-size: 0.6875rem;
  color: var(--text-secondary);
}

.diagnosis-meaning {
  max-width: 26rem;
  color: var(--text-secondary);
}

.diagnosis-spinner {
  font-size: 0.8125rem;
  color: var(--text-secondary);
}

/* The "not checked" disclosure is deliberately quiet: it is scope information, not a
   problem, so it must not read as an alarm next to the real findings above it. */
.diagnosis-problems--muted {
  color: var(--text-secondary);
}

.diagnosis-uncovered summary {
  color: var(--text-secondary);
}

/* Which response a check ran against. Shown because a count of 0 is ambiguous without it:
   a login-form field reading 0 on the listing is a probe mistake, not a supplier fault. */
.diagnosis-document {
  white-space: nowrap;
  color: var(--text-secondary);
}

/* "Privaloma" — a required dependency, i.e. one whose loss costs the offer rather than
   degrading it. Its own badge because it changes how a red row must be READ, so it has to
   be as scannable as the status next to it. */
.status-badge--neutral {
  color: var(--text);
  background: color-mix(in srgb, var(--text-secondary) 22%, transparent);
}

/* The row is now badges plus one line of numbers; everything explanatory lives in the modal.
   Eleven suppliers' worth of contract tables inline made the badges — the part an operator
   scans across rows — impossible to compare. */
.diagnosis-counts--compact {
  font-size: 0.75rem;
}

.diagnosis-problem-count {
  color: var(--danger);
}

/* Server-rendered source for the modal, kept in the row and cloned by app.js. `hidden`
   alone is enough; the width guard stops a future `display` override from ever laying this
   out and doubling the cell's height. */
.diagnosis-summary-source[hidden] {
  display: none;
}

.diagnosis-status-cell {
  white-space: nowrap;
}

/* --- the diagnosis summary modal ---------------------------------------------------- */
/* Fixed header, scrolling body: a diagnosis runs to ~20 contract rows of long explanations,
   and the supplier's name plus its five verdicts are what must stay in view while reading
   them. */
.diagnosis-dialog {
  border: none;
  border-radius: 14px;
  padding: 0;
  width: min(96vw, 1100px);
  max-width: 96vw;
  background: transparent;
}

.diagnosis-dialog::backdrop {
  background: rgba(2, 6, 23, 0.72);
  backdrop-filter: blur(2px);
}

.diagnosis-dialog-surface {
  display: flex;
  flex-direction: column;
  height: min(88vh, 900px);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
}

.diagnosis-dialog-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  /* Never shrinks and never scrolls away — that is the whole point of it. */
  flex: 0 0 auto;
}

.diagnosis-dialog-heading {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

.diagnosis-dialog-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.diagnosis-dialog-statuses {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.diagnosis-dialog-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.85rem 1rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.diagnosis-dialog-body .diagnosis-section h3 {
  margin: 0 0 0.4rem;
  font-size: 0.9rem;
}

/* Inside the modal the contract table has room to breathe, so it is no longer squeezed into
   a table cell — but it still scrolls on its own rather than widening the dialog. */
.diagnosis-dialog-body .diagnosis-table {
  width: 100%;
  border-collapse: collapse;
  display: block;
  overflow-x: auto;
  font-size: 0.8125rem;
}

.diagnosis-dialog-body .diagnosis-meaning {
  max-width: 32rem;
}

@media (max-width: 640px) {
  .diagnosis-dialog {
    width: 100vw;
    max-width: 100vw;
    border-radius: 0;
  }
  .diagnosis-dialog-surface {
    height: 100dvh;
    border-radius: 0;
    border: 0;
  }
}
