:root {
  --foreground: hsl(222, 47%, 11%);
  --background: hsl(210, 20%, 98%);
  --card: hsl(0, 0%, 100%);
  --card-foreground: hsl(0, 0%, 3.9%);
  --popover: hsl(0, 0%, 100%);
  --popover-foreground: hsl(0, 0%, 3.9%);
  --primary: hsl(0, 0%, 0%);
  --primary-foreground: hsl(0, 0%, 100%);
  --secondary: hsl(210, 40%, 96.1%);
  --secondary-foreground: hsl(222, 47%, 11%);
  --muted: hsl(210, 40%, 96.1%);
  --muted-foreground: hsl(215, 16%, 47%);
  --accent: hsl(210, 40%, 96.1%);
  --accent-foreground: hsl(222, 47%, 11%);
  --destructive: hsl(0, 84%, 60%);
  --destructive-foreground: hsl(0, 0%, 98%);
  --success: hsl(142, 71%, 45%);
  --success-foreground: hsl(0, 0%, 100%);
  --warning: hsl(38, 92%, 50%);
  --warning-foreground: hsl(26, 83%, 14%);
  --border: hsl(214, 32%, 91%);
  --input: hsl(214, 32%, 91%);
  --ring: hsl(0, 0%, 0%);
  --radius: 0.75rem;
}

.dark {
  --background: hsl(0, 0%, 7%);
  --foreground: hsl(0, 0%, 98%);
  --card: hsl(0, 0%, 7%);
  --card-foreground: hsl(0, 0%, 98%);
  --popover: hsl(0, 0%, 7%);
  --popover-foreground: hsl(0, 0%, 98%);
  --primary: white; /* Changed to white */
  --primary-foreground: hsl(0, 0%, 7%);
  --secondary: hsl(0, 0%, 12%);
  --secondary-foreground: hsl(0, 0%, 98%);
  --muted: hsl(0, 0%, 15%);
  --muted-foreground: hsl(0, 0%, 65%);
  --accent: hsl(0, 0%, 20%);
  --accent-foreground: hsl(0, 0%, 98%);
  --destructive: hsl(0, 63%, 31%);
  --destructive-foreground: hsl(0, 0%, 98%);
  --border: hsl(0, 0%, 20%);
  --input: hsl(0, 0%, 20%);
  --ring: hsl(0, 0%, 83%);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Inter', sans-serif;
  background: var(--background);
  color: var(--foreground);
  font-feature-settings: "cv02", "cv03", "cv04", "cv11";
  line-height: 1.5;
  font-size: 16px;
}

.shadcn-container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

.navbar {
  background-color: var(--background);
  border-bottom: 1px solid var(--border);
  padding: 1rem 0;
  position: sticky;
  top: 0;
  z-index: 100;
}

.navbar .navbar-brand {
  font-weight: 600;
  color: var(--foreground);
  text-decoration: none;
  font-size: 1.25rem;
}

.nav-link {
  color: var(--muted-foreground);
  font-weight: 500;
  transition: color 0.2s ease;
  text-decoration: none;
  padding: 0 0.75rem;
  border-radius: var(--radius);
  height: 100%;
  display: inline-flex;
  align-items: center;
}

.nav-link:hover {
  color: var(--foreground);
  background-color: var(--accent);
}

.nav-link.active {
  color: var(--foreground);
  background-color: var(--accent);
}

.logout-link {
  color: var(--destructive-foreground);
  background-color: var(--destructive);
}

/* Section headers */
.section-header {
  font-size: 2rem;
  font-weight: 700;
  margin-bottom: 1.5rem;
  color: var(--foreground);
}

/* Common card styles */
.shadcn-card {
  background-color: var(--card);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.shadcn-card-header {
  margin-bottom: 1.5rem;
}

.shadcn-card-title {
  font-weight: 600;
  font-size: 1.25rem;
  color: var(--foreground);
}

.shadcn-card-description {
  color: var(--muted-foreground);
  font-size: 0.875rem;
}

.shadcn-card-content {
  margin-bottom: 1.5rem;
}

.shadcn-card-footer {
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

/* Button styles */
.shadcn-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 500;
  padding: 0.75rem 1rem;
  background-color: var(--primary);
  color: var(--primary-foreground);
  border-radius: var(--radius);
  font-size: 0.875rem;
  border: none;
  transition: all 0.2s ease;
  cursor: pointer;
  text-decoration: none;
}

.shadcn-button:hover {
  opacity: 0.9;
}

.shadcn-button-secondary {
  background-color: var(--secondary);
  color: var(--secondary-foreground);
}

.shadcn-button-destructive {
  background-color: var(--destructive);
  color: var(--destructive-foreground);
}

.shadcn-button-outline {
  background-color: transparent;
  color: var(--foreground);
  border: 1px solid var(--border);
}

.shadcn-button-outline:hover {
  background-color: var(--accent);
}

.shadcn-button-icon {
  margin-right: 0.5rem;
}

/* Form elements */
.shadcn-form-item {
  margin-bottom: 1.5rem;
}

.shadcn-form-label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 0.5rem;
  color: var(--foreground);
}

/* Responsive table improvements */
.table-responsive {
  border-radius: var(--radius);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}

.table {
  width: 100%;
  margin-bottom: 0;
  white-space: nowrap;
}

.table th {
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  color: var(--muted-foreground);
  font-weight: 600;
  padding: 0.75rem 1rem;
  border-top: none;
  background-color: var(--muted);
}

.table td {
  vertical-align: middle;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
}

.table-hover tbody tr {
  transition: background-color 0.15s ease-in-out;
}

.table-hover tbody tr:hover {
  background-color: var(--accent);
}

.table .badge {
  font-weight: 500;
  padding: 0.35em 0.65em;
  font-size: 0.75em;
}

.table .input-group-sm {
  max-width: 160px;
}

.table .btn-group-sm .btn {
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
}

@media (max-width: 992px) {
  .btn-sm {
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
  }
}

@media (max-width: 768px) {
  .table {
    font-size: 0.875rem;
  }

  .table th, .table td {
    padding: 0.625rem 0.75rem;
  }

  .table .input-group-sm {
    max-width: 130px;
  }
}

@media (max-width: 576px) {
  .table .input-group-sm {
    max-width: 120px;
  }

  .table .btn-group-sm .btn {
    padding: 0.2rem 0.4rem;
    font-size: 0.7rem;
  }
}

.shadcn-form-input {
  width: 100%;
  font-size: 0.875rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--input);
  background-color: var(--background);
  color: var(--foreground);
  transition: all 0.2s ease;
}

.shadcn-form-input:focus {
  outline: none;
  border-color: var(--ring);
  box-shadow: 0 0 0 2px rgb(41, 43, 46, 0.15);
}

.shadcn-form-select {
  width: 100%;
  font-size: 0.875rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--input);
  background-color: var(--background);
  color: var(--foreground);
  transition: all 0.2s ease;
}

.shadcn-form-message {
  font-size: 0.875rem;
  color: var(--destructive);
  margin-top: 0.375rem;
}

/* Table styles */
.shadcn-table {
  width: 100%;
  border-collapse: collapse;
}

.shadcn-table th {
  text-align: left;
  padding: 0.75rem 1rem;
  font-weight: 500;
  color: var(--muted-foreground);
  font-size: 0.875rem;
  border-bottom: 1px solid var(--border);
}

.shadcn-table td {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.875rem;
  color: var(--foreground);
}

.shadcn-table tr:last-child td {
  border-bottom: none;
}

/* Pagination styles */
.pagination {
  display: flex;
  padding-left: 0;
  list-style: none;
  border-radius: 0.25rem;
}

.page-link {
  position: relative;
  display: block;
  padding: 0.5rem 0.75rem;
  margin-left: -1px;
  line-height: 1.25;
  color: #000;
  background-color: var(--background);
  border: 1px solid var(--border);
}

.page-link:hover {
  z-index: 2;
  color: #000;
  text-decoration: none;
  background-color: var(--accent);
  border-color: var(--border);
}

.page-link:focus {
  z-index: 3;
  outline: 0;
  box-shadow: 0 0 0 0.2rem rgba(0, 0, 0, 0.25);
}

.page-item:first-child .page-link {
  margin-left: 0;
  border-top-left-radius: 0.25rem;
  border-bottom-left-radius: 0.25rem;
}

.page-item:last-child .page-link {
  border-top-right-radius: 0.25rem;
  border-bottom-right-radius: 0.25rem;
}

.page-item.active .page-link {
  z-index: 3;
  color: #fff;
  background-color: #000;
  border-color: #000;
}

/* Order details styles */
.progress {
  background-color: var(--muted);
  border-radius: 2px;
  overflow: hidden;
}

.progress-bar {
  transition: width 0.3s ease;
}

.page-item.disabled .page-link {
  color: #6c757d;
  pointer-events: none;
  cursor: auto;
  background-color: var(--background);
  border-color: var(--border);
}

/* Badge styles */
.shadcn-badge {
  display: inline-flex;
  align-items: center; /* vertically center icon and text */
  padding: 0.125rem 0.5rem;
  border-radius: 10px;
  background-color: var(--muted);
  color: var(--muted-foreground);
  font-size: 0.75rem;
  font-weight: 600;
}

.shadcn-badge-primary {
  background-color: var(--primary);
  color: var(--primary-foreground);
}

.shadcn-badge-destructive {
  background-color: var(--destructive);
  color: var(--destructive-foreground);
}

.shadcn-badge-outline {
  background-color: transparent;
  border: 1px solid var(--border);
  color: var(--foreground);
}

/* Delivery badge styles */
.delivery-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.5rem;
  border-radius: 8px;
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.025em;
  box-shadow: 0 1px 3px rgba(16, 185, 129, 0.3);
  transition: all 0.2s ease;
  white-space: nowrap;
  flex-shrink: 0;
}

.delivery-badge:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(16, 185, 129, 0.4);
}

/* Badge overlay positioned in image */
.delivery-badge-overlay {
  position: absolute;
  bottom: 8px;
  left: 8px;
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.5rem;
  border-radius: 8px;
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.025em;
  box-shadow: 0 2px 6px rgba(16, 185, 129, 0.4);
  transition: all 0.2s ease;
  white-space: nowrap;
  flex-shrink: 0;
  z-index: 2;
}

/* Different badge variants */
.delivery-badge-overlay.hot-deal {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  box-shadow: 0 2px 6px rgba(239, 68, 68, 0.4);
}

.delivery-badge-overlay.cheap {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  box-shadow: 0 2px 6px rgba(59, 130, 246, 0.4);
}

.delivery-badge-overlay.premium {
  background: linear-gradient(135deg, #8b5cf6, #7c3aed);
  box-shadow: 0 2px 6px rgba(139, 92, 246, 0.4);
}

.delivery-badge-overlay.instant {
  background: linear-gradient(135deg, #10b981, #059669);
  box-shadow: 0 2px 6px rgba(16, 185, 129, 0.4);
}

.delivery-badge-overlay.instant-delivery {
  background: linear-gradient(135deg, #10b981, #059669);
  box-shadow: 0 2px 6px rgba(16, 185, 129, 0.4);
}

/* Make image container relative for badge positioning */
.service-image-wrapper {
  position: relative;
}

/* Alerts */
.shadcn-alert {
  border-radius: var(--radius);
  padding: 1rem;
  margin-bottom: 1rem;
  border-left: 4px solid var(--muted);
  background-color: var(--background);
}

.shadcn-alert-error {
  border-left-color: var(--destructive);
  background-color: color-mix(in srgb, var(--destructive) 10%, transparent);
}

.shadcn-alert-success {
  border-left-color: hsl(142.1, 76.2%, 36.3%);
  background-color: color-mix(in srgb, hsl(142.1, 76.2%, 36.3%) 10%, transparent);
}

/* Utilities */
.text-muted {
  color: var(--muted-foreground);
}

.text-center {
  text-align: center;
}

.mt-1 { margin-top: 0.25rem; }
.mt-2 { margin-top: 0.5rem; }
.mt-3 { margin-top: 0.75rem; }
.mt.4 { margin-top: 1rem; }
.mt-5 { margin-top: 1.5rem; }
.mb-1 { margin-bottom: 0.25rem; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-3 { margin-bottom: 0.75rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-5 { margin-bottom: 1.5rem; }
.mr-1 { margin-right: 0.25rem; }
.mr-2 { margin-right: 0.5rem; }
.mr-3 { margin-right: 0.75rem; }
.mr-4 { margin-right: 1rem; }
.ml-1 { margin-left: 0.25rem; }
.ml-2 { margin-left: 0.5rem; }
.ml-3 { margin-left: 0.75rem; }
.ml-4 { margin-left: 1rem; }

/* Media queries */
@media (max-width: 768px) {
  .shadcn-container {
    padding: 0 1rem;
  }

  .section-header {
    font-size: 1.5rem;
  }
}
.dark .shadcn-button {
  background-color: var(--primary);
  color: var(--primary-foreground);
}

.service-image-container {
  height: 140px;
  overflow: hidden;
  position: relative;
}

/* ── Metric Cards ─────────────────────────────────────── */
.metric-cards-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.metric-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.metric-card__label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--muted-foreground);
  line-height: 1;
}

.metric-card__value {
  font-size: 1.875rem;
  font-weight: 700;
  color: var(--foreground);
  line-height: 1.2;
  letter-spacing: -0.025em;
}

.metric-card__delta {
  font-size: 0.75rem;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.metric-card__delta--positive { color: var(--success); }
.metric-card__delta--negative { color: var(--destructive); }

/* ── Status Badges ────────────────────────────────────── */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.125rem 0.625rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.5;
}

.status-badge::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: currentColor;
}

.status-badge--completed {
  background-color: hsla(142, 71%, 45%, 0.1);
  color: hsl(142, 71%, 35%);
}

.status-badge--pending {
  background-color: hsla(38, 92%, 50%, 0.1);
  color: hsl(38, 80%, 35%);
}

.status-badge--failed {
  background-color: hsla(0, 84%, 60%, 0.1);
  color: hsl(0, 72%, 45%);
}

/*
 * Extra buckets used by the marketplace orders list. attention = "buyer
 * must act" (strong amber — draws the eye). dispute = "dispute open"
 * (red). refund = "order was refunded" (neutral amber, visually distinct
 * from pending so a user can skim a mixed-status list). muted = "terminal
 * cancelled" (grey).
 */
.status-badge--attention {
  background-color: hsla(38, 92%, 50%, 0.18);
  color: hsl(32, 85%, 32%);
}

.status-badge--dispute {
  background-color: hsla(0, 84%, 60%, 0.12);
  color: hsl(0, 72%, 42%);
}

.status-badge--refund {
  background-color: hsla(25, 95%, 53%, 0.12);
  color: hsl(22, 78%, 38%);
}

.status-badge--muted {
  background-color: hsla(215, 16%, 47%, 0.12);
  color: hsl(215, 16%, 35%);
}

/*
 * Dark-mode overrides for status badges — the HSLA overlays look washed
 * against the near-black card background, so we bump the alpha and
 * lighten the text colour. Scoped to .dark so light-mode is unchanged.
 */
.dark .status-badge--completed {
  background-color: hsla(142, 71%, 45%, 0.2);
  color: hsl(142, 71%, 70%);
}
.dark .status-badge--pending {
  background-color: hsla(38, 92%, 50%, 0.22);
  color: hsl(38, 85%, 72%);
}
.dark .status-badge--failed {
  background-color: hsla(0, 84%, 60%, 0.22);
  color: hsl(0, 85%, 72%);
}
.dark .status-badge--attention {
  background-color: hsla(38, 92%, 50%, 0.28);
  color: hsl(38, 85%, 72%);
}
.dark .status-badge--dispute {
  background-color: hsla(0, 84%, 60%, 0.25);
  color: hsl(0, 85%, 72%);
}
.dark .status-badge--refund {
  background-color: hsla(25, 95%, 53%, 0.25);
  color: hsl(25, 85%, 72%);
}
.dark .status-badge--muted {
  background-color: hsla(215, 16%, 65%, 0.2);
  color: hsl(215, 16%, 75%);
}

/* ── Segment Tabs ─────────────────────────────────────── */
.segment-tabs {
  display: inline-flex;
  background-color: var(--muted);
  border-radius: var(--radius);
  padding: 0.25rem;
  gap: 0.125rem;
}

.segment-tabs__item {
  padding: 0.375rem 0.875rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--muted-foreground);
  border-radius: calc(var(--radius) - 0.125rem);
  border: none;
  background: transparent;
  cursor: pointer;
  transition: all 0.15s ease;
}

.segment-tabs__item:hover {
  color: var(--foreground);
}

.segment-tabs__item--active {
  background: var(--card);
  color: var(--foreground);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

/* ── Data Table ───────────────────────────────────────── */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.data-table thead th {
  text-align: left;
  padding: 0.75rem 1rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted-foreground);
  text-transform: none;
  letter-spacing: normal;
  border-bottom: 1px solid var(--border);
  background: transparent;
}

.data-table tbody td {
  padding: 0.75rem 1rem;
  color: var(--foreground);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.data-table tbody tr:last-child td {
  border-bottom: none;
}

.data-table tbody tr:hover {
  background-color: var(--muted);
}

/* ── Responsive additions ─────────────────────────────── */
@media (max-width: 768px) {
  .metric-cards-grid {
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
  }
  .metric-card__value { font-size: 1.5rem; }
  .metric-card { padding: 0.875rem 1rem; }
  .segment-tabs { width: 100%; }
  .segment-tabs__item { flex: 1; text-align: center; font-size: 0.8125rem; }
}

@media (max-width: 576px) {
  .metric-cards-grid { gap: 0.5rem; }
  .metric-card__label { font-size: 0.75rem; }
  .metric-card__value { font-size: 1.25rem; }
}

/* ══════════════════════════════════════════════════════════════════
 * Orders list page (/market/purchases, /market/sales)
 *
 * Design note: renders as a CSS-grid "table" instead of <table>, so each
 * row is a single <a>-wrapped grid container on mobile (stacks to one
 * column) while staying aligned on desktop. The filter bar uses flex
 * with gap; each input individually clickable.
 * ══════════════════════════════════════════════════════════════════ */
.orders-page .section-header {
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--foreground);
  line-height: 1.15;
  margin-bottom: 1.25rem;
}

/* ── Filter bar ─────────────────────────────────────────── */
.orders-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 1rem;
}

.orders-filter__input,
.orders-filter__select {
  height: 40px;
  padding: 0 0.75rem;
  font-family: inherit;
  font-size: 0.875rem;
  color: var(--foreground);
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  min-width: 0;
}

.orders-filter__input { flex: 1 1 180px; }
.orders-filter__select {
  flex: 1 1 180px;
  /* Keep native chevron — shadcn-style dropdowns would require JS; the
     native select is fine for a minimalist filter bar. Force a light
     padding-right so the caret doesn't overlap long option text. */
  padding-right: 2rem;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23666' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 12px;
}

.orders-filter__input::placeholder {
  color: var(--muted-foreground);
}

.orders-filter__input:focus,
.orders-filter__select:focus {
  outline: none;
  border-color: var(--ring);
  box-shadow: 0 0 0 3px hsla(214, 32%, 75%, 0.35);
}

.orders-filter__submit {
  height: 40px;
  padding: 0 1.25rem;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--primary-foreground);
  background-color: hsl(217, 91%, 60%); /* Stand-out blue — matches FunPay ref */
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 0.15s ease;
  flex: 0 0 auto;
}

.orders-filter__submit:hover {
  background-color: hsl(217, 91%, 54%);
}

.orders-filter__clear {
  height: 40px;
  display: inline-flex;
  align-items: center;
  padding: 0 0.75rem;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  text-decoration: none;
  border-radius: var(--radius);
  transition: color 0.15s ease, background-color 0.15s ease;
}

.orders-filter__clear:hover {
  color: var(--foreground);
  background-color: var(--accent);
}

/* ── Table ─────────────────────────────────────────────── */
.orders-table {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
  margin-top: 0.5rem;
}

.orders-table__head {
  display: grid;
  grid-template-columns:
    140px          /* date */
    110px          /* order # */
    minmax(0, 1fr) /* description */
    210px          /* counterparty */
    160px          /* status */
    110px          /* total */
    48px;          /* chat (mobile-purchases-polish Slice 2b) */
  gap: 1rem;
  padding: 0.75rem 0.5rem;
  border-bottom: 1px solid var(--border);
}

.orders-table__th {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--foreground);
  letter-spacing: 0;
}

.orders-table__row {
  display: grid;
  grid-template-columns:
    140px
    110px
    minmax(0, 1fr)
    210px
    160px
    110px
    48px;          /* chat (mobile-purchases-polish Slice 2b) */
  gap: 1rem;
  padding: 1rem 0.5rem;
  border-bottom: 1px solid var(--border);
  align-items: center;
  transition: background-color 0.1s ease;
}

.orders-table__row:hover {
  background-color: var(--muted);
}

.orders-table__row--attention {
  /* Soft amber wash — "take action" states (delivered, disputed). Mirrors
     the FunPay reference's cream-yellow Refund rows but semantically
     scoped to states that actually demand something from the viewer.
     color-mix avoids hardcoding a second colour; it falls back to the
     raw hsla for browsers that don't grok color-mix yet. */
  background-color: hsla(48, 100%, 88%, 0.45);
  background-color: color-mix(in srgb, hsl(48, 100%, 85%) 50%, var(--card));
}

.orders-table__row--attention:hover {
  background-color: hsla(48, 100%, 85%, 0.65);
  background-color: color-mix(in srgb, hsl(48, 100%, 80%) 55%, var(--card));
}

.dark .orders-table__row--attention {
  background-color: hsla(48, 70%, 35%, 0.25);
}
.dark .orders-table__row--attention:hover {
  background-color: hsla(48, 70%, 35%, 0.35);
}

.orders-table__td {
  font-size: 0.875rem;
  color: var(--foreground);
  min-width: 0; /* Let grid tracks shrink; prevents overflow in descr. */
}

/* ── Column content ────────────────────────────────────── */
.orders-date__abs {
  font-weight: 500;
  color: var(--foreground);
  white-space: nowrap;
}

.orders-date__rel {
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  white-space: nowrap;
}

.orders-order-link {
  font-weight: 500;
  color: var(--foreground);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.orders-order-link:hover {
  color: var(--foreground);
  text-decoration: underline;
}

.orders-desc-link {
  display: block;
  color: var(--foreground);
  text-decoration: none;
  font-weight: 400;
  line-height: 1.35;
  /* Allow 2 lines before ellipsis so titles with emojis / long names
     stay readable without blowing up row height. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.orders-desc-link:hover {
  color: var(--foreground);
  text-decoration: underline;
}

.orders-desc-meta {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
}

.orders-cat-link {
  color: var(--muted-foreground);
  text-decoration: none;
  transition: color 0.1s ease;
}

.orders-cat-link:hover {
  color: var(--foreground);
  text-decoration: underline;
}

.orders-party {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  color: var(--foreground);
  text-decoration: none;
  min-width: 0;
}

.orders-party:hover {
  color: var(--foreground);
}

.orders-party:hover .orders-party__name {
  text-decoration: underline;
}

.orders-party__avatar {
  display: inline-flex;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--muted);
}

.orders-party__avatar svg {
  display: block;
  width: 100%;
  height: 100%;
}

.orders-party__name {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.orders-party--missing {
  cursor: default;
}

.orders-status-pill {
  /* Inherits .status-badge + .status-badge--<bucket>. Additional rules
     here make it clickable (cursor + hover opacity). */
  cursor: pointer;
  text-decoration: none;
  transition: opacity 0.1s ease, transform 0.1s ease;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.orders-status-pill:hover {
  opacity: 0.85;
}

.orders-col-total {
  text-align: right;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Header column alignment for Total — mirror the cell rule. */
.orders-table__head .orders-col-total {
  text-align: right;
}

/* ── Chat column (mobile-purchases-polish Slice 2b) ────────
   Per RFC Decisions 5/9/12: 48px-wide icon column on desktop, repositioned
   into the party row's right cell on mobile. 3 link states + disabled
   placeholder. Badge cluster pattern lifted from .chat-fab__badge:2148. */
.orders-col-chat {
  display: flex;
  align-items: center;
  justify-content: center;
}

.orders-chat-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  color: var(--foreground);
  text-decoration: none;
  font-size: 0.9375rem;
  transition: background-color 0.1s ease, color 0.1s ease;
}

.orders-chat-link:hover {
  background-color: var(--muted);
  color: var(--foreground);
}

.orders-chat-link:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.orders-chat-link--no-thread {
  color: var(--muted-foreground);
}

.orders-chat-link--unread {
  /* Slight emphasis so the unread state is visible at a glance even
     before the badge text registers. */
  color: var(--foreground);
}

.orders-chat-link--disabled {
  /* Inert placeholder — preserves grid alignment for self-orders /
     null-counterparty rows. No pointer cursor, no hover. */
  width: 32px;
  height: 32px;
  display: inline-block;
  pointer-events: none;
}

.orders-chat-link__badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background-color: var(--destructive);
  color: var(--destructive-foreground);
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* ── Empty state ───────────────────────────────────────── */
.orders-empty {
  padding: 3rem 1rem;
  text-align: center;
  color: var(--muted-foreground);
}

.orders-empty__title {
  font-size: 1rem;
  font-weight: 500;
  color: var(--foreground);
  margin: 0 0 0.5rem;
}

.orders-empty__body {
  font-size: 0.875rem;
  margin: 0;
}

.orders-empty__body a,
.orders-empty__reset {
  color: var(--foreground);
  text-decoration: underline;
}

/* ── Responsive: stack rows on narrow viewports ────────── */
@media (max-width: 900px) {
  .orders-table__head {
    display: none; /* Header only makes sense in grid mode */
  }

  .orders-table {
    border-top: none;
    gap: 0.75rem;
  }

  .orders-table__row {
    /* mobile-purchases-polish Slice 2b: chat icon adjacent to party
       (RFC Decision 9). NOT display:none — chat IS the mobile use case. */
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "date   order"
      "desc   desc"
      "party  chat"
      "status status"
      "total  total";
    gap: 0.5rem 0.75rem;
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }

  .orders-col-date { grid-area: date; }
  .orders-col-order { grid-area: order; justify-self: end; }
  .orders-col-desc { grid-area: desc; }
  .orders-col-party { grid-area: party; }
  .orders-col-status { grid-area: status; justify-self: end; }
  .orders-col-chat { grid-area: chat; justify-self: end; }
  .orders-col-total {
    grid-area: total;
    text-align: left;
    font-size: 1rem;
    padding-top: 0.5rem;
    border-top: 1px dashed var(--border);
  }

  .orders-col-total::before {
    content: "Total: ";
    font-weight: 400;
    color: var(--muted-foreground);
  }
}

@media (max-width: 560px) {
  .orders-filter__input,
  .orders-filter__select {
    flex: 1 1 calc(50% - 0.25rem);
  }
  .orders-filter__submit {
    flex: 1 1 100%;
  }
}

/* ══════════════════════════════════════════════════════════════════
 * Order detail page (/market/orders/:shortId)
 *
 * Two-column grid: left = order meta, right = chat panel that sticks
 * to the viewport. On mobile stacks to one column.
 * ══════════════════════════════════════════════════════════════════ */
.order-detail {
  display: grid;
  /*
   * Slightly-wider-left (4:5) keeps the details column compact so short
   * metadata ("Steam", "hello") doesn't create visible whitespace, while
   * giving the chat panel enough room for message bubbles.
   */
  grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
  gap: 1.5rem;
  align-items: start;
}

@media (max-width: 991px) {
  .order-detail {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }
}

.order-detail__left,
.order-detail__right {
  min-width: 0;
}

/* ── Header: title + status ──────────────────────────── */
.order-detail__header {
  margin-bottom: 1.5rem;
}

.order-detail__title {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--foreground);
  line-height: 1.1;
  margin: 0 0 0.125rem;
  word-break: break-word;
}

.order-detail__status {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.15;
}

.order-status--completed { color: hsl(142, 71%, 40%); }
.order-status--attention { color: hsl(32, 85%, 38%); }
.order-status--pending   { color: hsl(38, 80%, 38%); }
.order-status--dispute   { color: hsl(0, 72%, 48%); }
.order-status--refund    { color: hsl(22, 78%, 42%); }
.order-status--muted     { color: hsl(215, 16%, 45%); }

.dark .order-status--completed { color: hsl(142, 71%, 62%); }
.dark .order-status--attention { color: hsl(38, 85%, 65%); }
.dark .order-status--pending   { color: hsl(38, 85%, 65%); }
.dark .order-status--dispute   { color: hsl(0, 85%, 65%); }
.dark .order-status--refund    { color: hsl(25, 85%, 65%); }
.dark .order-status--muted     { color: hsl(215, 16%, 70%); }

/* ── Info/warning banner (dispute + seller-api-failure) ── */
.order-detail__banner {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  margin-bottom: 1.25rem;
}

.order-detail__banner-body {
  flex: 1;
  min-width: 0;
}

.order-detail__banner--info {
  background-color: hsla(217, 91%, 60%, 0.08);
  border-color: hsla(217, 91%, 60%, 0.25);
  color: hsl(217, 91%, 34%);
}

.order-detail__banner--warn {
  background-color: hsla(38, 92%, 50%, 0.1);
  border-color: hsla(38, 92%, 50%, 0.3);
  color: hsl(32, 85%, 32%);
}

.dark .order-detail__banner--info {
  background-color: hsla(217, 91%, 60%, 0.15);
  color: hsl(217, 91%, 75%);
}

.dark .order-detail__banner--warn {
  background-color: hsla(38, 92%, 50%, 0.15);
  color: hsl(38, 85%, 72%);
}

/* ── Meta rows (CATEGORY, LISTING, DESCRIPTION) ──────── */
.order-meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 1.25rem;
  margin-bottom: 1.25rem;
}

.order-meta__row {
  min-width: 0;
}

/*
 * LISTING row spans 2 columns on desktop so long listing names don't
 * collide with the narrow CATEGORY column. DESCRIPTION always spans.
 */
.order-meta__row:nth-child(1) { grid-column: 1 / 2; }
.order-meta__row:nth-child(2) { grid-column: 2 / 3; }
.order-meta__row:nth-child(n+3) { grid-column: 1 / -1; }

@media (max-width: 560px) {
  .order-meta {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
  .order-meta__row,
  .order-meta__row:nth-child(n) { grid-column: 1 / -1; }
}

.order-meta__label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--muted-foreground);
  text-transform: uppercase;
  margin-bottom: 0.25rem;
}

.order-meta__value {
  font-size: 0.9375rem;
  color: var(--foreground);
  line-height: 1.45;
  word-break: break-word;
}

.order-meta__value--strong {
  font-weight: 700;
}

.order-meta__description {
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--foreground);
}

.order-meta__link {
  color: hsl(217, 91%, 55%);
  text-decoration: none;
  font-weight: 500;
}

.order-meta__link:hover {
  text-decoration: underline;
  color: hsl(217, 91%, 48%);
}

.dark .order-meta__link {
  color: hsl(217, 91%, 70%);
}
.dark .order-meta__link:hover { color: hsl(217, 91%, 78%); }

/* ── Delivered content panel ─────────────────────────── */
.order-detail__delivered {
  background-color: hsla(142, 71%, 45%, 0.06);
  border: 1px solid hsla(142, 71%, 45%, 0.25);
  border-radius: var(--radius);
  padding: 0.75rem 0.875rem;
  margin-bottom: 1.25rem;
}

.order-detail__delivered-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: hsl(142, 71%, 30%);
  margin-bottom: 0.5rem;
}

.dark .order-detail__delivered {
  background-color: hsla(142, 71%, 45%, 0.1);
  border-color: hsla(142, 71%, 45%, 0.3);
}
.dark .order-detail__delivered-label { color: hsl(142, 71%, 70%); }

.order-detail__delivered-body {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  font-size: 0.875rem;
  color: var(--foreground);
  background: var(--card);
  padding: 0.75rem;
  border-radius: calc(var(--radius) - 0.25rem);
  border: 1px solid var(--border);
}

/* ── Actions row ─────────────────────────────────────── */
.order-detail__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.order-detail__action-form {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.order-detail__action-form--deliver {
  flex: 1 1 320px;
}

.order-detail__action-form--deliver .form-control {
  flex: 1 1 220px;
  min-width: 180px;
}

/* ── Timestamps ──────────────────────────────────────── */
.order-times {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  padding-top: 1.25rem;
  margin-bottom: 1.25rem;
  border-top: 1px solid var(--border);
}

.order-times__col {
  min-width: 0;
}

.order-times__value {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--foreground);
}

.order-times__rel {
  font-weight: 400;
  color: var(--muted-foreground);
  margin-left: 0.25rem;
}

@media (max-width: 560px) {
  .order-times {
    grid-template-columns: 1fr;
    gap: 0.875rem;
  }
}

/* ── Total (big number) ──────────────────────────────── */
.order-total {
  margin-bottom: 1.5rem;
}

.order-total__value {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--foreground);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  margin-top: 0.125rem;
}

/* ── Review section ──────────────────────────────────── */
.order-review {
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

.order-review__form,
.order-review__respond-form {
  margin-top: 0.625rem;
}

.order-review__textarea {
  width: 100%;
  min-height: 140px;
  padding: 0.875rem 1rem;
  font-family: inherit;
  font-size: 0.9375rem;
  color: var(--foreground);
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  resize: vertical;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.order-review__textarea:focus {
  outline: none;
  border-color: var(--ring);
  box-shadow: 0 0 0 3px hsla(214, 32%, 75%, 0.35);
}

.order-review__rating-block {
  margin-top: 0.875rem;
}

/* ── Click-to-rate stars ─────────────────────────────── */
.stars-input {
  display: inline-flex;
  gap: 0.25rem;
}

.stars-input .star {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  padding: 0;
  font-size: 1.5rem;
  color: hsl(45, 100%, 55%);
  cursor: pointer;
  transition: transform 0.1s ease, color 0.1s ease;
  border-radius: 6px;
}

.stars-input .star:hover {
  transform: scale(1.12);
}

.stars-input .star:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.stars-input .star--active { color: hsl(45, 100%, 50%); }
.stars-input .star i { pointer-events: none; }

.order-review__rating-label {
  font-size: 0.875rem;
  color: var(--muted-foreground);
  margin-top: 0.25rem;
}

/* ── Review read-only display ────────────────────────── */
.order-review__stars {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.625rem;
  font-size: 1.125rem;
}

.order-review__stars .star--active { color: hsl(45, 100%, 50%); }
.order-review__stars .star--inactive { color: var(--border); }

.order-review__author {
  margin-left: 0.25rem;
  font-weight: 600;
  color: var(--foreground);
  font-size: 0.9375rem;
}

.order-review__date {
  color: var(--muted-foreground);
  font-size: 0.8125rem;
}

.order-review__comment {
  margin: 0.75rem 0 0;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--foreground);
  line-height: 1.5;
}

.order-review__response {
  margin-top: 0.875rem;
  padding: 0.75rem 1rem;
  background-color: hsla(217, 91%, 60%, 0.07);
  border-left: 3px solid hsl(217, 91%, 60%);
  border-radius: 0 calc(var(--radius) - 0.25rem) calc(var(--radius) - 0.25rem) 0;
}

.dark .order-review__response {
  background-color: hsla(217, 91%, 60%, 0.12);
}

.order-review__response-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--muted-foreground);
  letter-spacing: 0.06em;
}

.order-review__response-body {
  margin: 0.375rem 0 0.25rem;
  color: var(--foreground);
  white-space: pre-wrap;
  word-break: break-word;
}

.order-review__response-date {
  font-size: 0.75rem;
  color: var(--muted-foreground);
}

.order-review__respond-label {
  display: block;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  margin-bottom: 0.375rem;
}

/* ══════════════════════════════════════════════════════════════════
 * Chat panel (right column)
 *
 * Sticky to the viewport on desktop — the messages area scrolls
 * internally while header + input stay pinned.
 *
 * The `height` is set dynamically by the inline script in
 * order-view.ejs — it measures the column's natural top (which can
 * vary: optional notification marquee, different nav heights across
 * pages) and subtracts from the viewport. The CSS fallback below
 * is generous enough to cover the marquee case (~160px of chrome)
 * so the layout is still usable if the script fails to run.
 * ══════════════════════════════════════════════════════════════════ */
.order-detail__right {
  position: sticky;
  top: 1rem;
  height: calc(100vh - 10rem);
  max-height: calc(100vh - 10rem);
}

@media (max-width: 991px) {
  .order-detail__right {
    position: static;
    /* DEFINITE height (not `auto`) on mobile so the inner
     * `.chat-panel { height: 100% }` resolves to a real pixel value.
     * Without this `height: 100%` resolves to `auto` (CSS spec:
     * percentage heights need a definite parent height), which then
     * makes `.chat-panel__messages { flex: 1; overflow-y: auto }`
     * a no-op — flex:1 on a column container with no definite
     * parent height doesn't constrain children. Result pre-fix:
     * messages stacked vertically, chat panel grew past max-height
     * (parent had no overflow:hidden), buyer saw chat container
     * "stretching with messages" instead of a fixed-height scrollable
     * panel. User-reported 2026-04-30. Both height + max-height kept
     * at 70vh — definite cap, no flex-basis surprises. */
    height: 70vh;
    max-height: 70vh;
  }
}

.chat-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 0.25rem);
  overflow: hidden;
}

.chat-panel__header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border-bottom: 1px solid var(--border);
  background-color: var(--card);
  flex: 0 0 auto;
}

.chat-panel__identity {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  flex: 1;
}

.chat-panel__avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--muted);
  flex: 0 0 auto;
}

.chat-panel__avatar svg {
  display: block;
  width: 100%;
  height: 100%;
}

.chat-panel__name {
  font-weight: 600;
  font-size: 1rem;
  color: var(--foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.chat-panel__actions {
  display: flex;
  gap: 0.375rem;
  flex: 0 0 auto;
}

.chat-panel__btn {
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: transparent;
  color: var(--muted-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
  font-size: 0.9375rem;
}

.chat-panel__btn:hover {
  background-color: var(--accent);
  color: var(--foreground);
}

.chat-panel__btn--copied {
  color: hsl(142, 71%, 40%);
  border-color: hsl(142, 71%, 45%);
  background-color: hsla(142, 71%, 45%, 0.1);
}

/* chat-fixes Slice 3 polish: text-bearing variants of .chat-panel__btn
   (admin force-Refund + buyer Request-Refund + admin Decline). Override
   the 40x40 icon-only square so text labels don't wrap. The Bootstrap
   btn-sm sizing comes from the parent `.btn.btn-sm` classes; we only
   need to release the width clamp + add inline padding + prevent wrap. */
.chat-panel__btn--refund,
.chat-panel__btn--request-refund,
.chat-panel__btn--decline {
  width: auto;
  height: auto;
  padding: 0.25rem 0.625rem;
  gap: 0.375rem;
  white-space: nowrap;
  font-size: 0.8125rem;
  line-height: 1.2;
}

/* chat-fixes Slice 4: mobile breakpoint — hide the inline text label
   on narrow viewports (≤480px) so the chat-panel actions zone doesn't
   crowd out the counterparty name on phone-sized screens. The button
   collapses to icon-only; the title/aria-label still conveys intent. */
@media (max-width: 480px) {
  .chat-panel__btn--refund,
  .chat-panel__btn--request-refund,
  .chat-panel__btn--decline {
    width: 40px;
    height: 40px;
    padding: 0;
    gap: 0;
  }
  .chat-panel__btn-text {
    display: none;
  }
}

/* ── Messages area ───────────────────────────────────── */
.chat-panel__messages {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  background-color: var(--background);
  scroll-behavior: smooth;
}

.chat-panel__messages--empty {
  align-items: center;
  justify-content: center;
}

/* Bubble messages (self/other) */
.chat-msg {
  display: flex;
  gap: 0.5rem;
  max-width: 85%;
}

.chat-msg--self {
  align-self: flex-end;
  flex-direction: row-reverse;
}

.chat-msg__body {
  padding: 0.625rem 0.875rem;
  border-radius: 0.875rem;
  background-color: var(--card);
  border: 1px solid var(--border);
  color: var(--foreground);
  min-width: 0;
}

.chat-msg--self .chat-msg__body {
  background-color: hsl(217, 91%, 94%);
  border-color: hsl(217, 91%, 88%);
  color: hsl(217, 91%, 25%);
}

.dark .chat-msg--self .chat-msg__body {
  background-color: hsla(217, 91%, 60%, 0.22);
  border-color: hsla(217, 91%, 60%, 0.35);
  color: hsl(217, 91%, 82%);
}

.chat-msg--other .chat-msg__body {
  background-color: var(--muted);
}

.chat-msg__text {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 0.9375rem;
  line-height: 1.4;
}

.chat-msg__actions {
  margin-top: 0.375rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

/*
 * mobile-purchases-polish Slice 1b (RFC Decision 4):
 * Scoped action button for system-message <a> tags. Replaces the
 * Bootstrap `btn btn-sm btn-outline-primary` class which was sized for
 * page-level CTAs and visually competed with the system message text +
 * the page Place Order button on /service/:id. Theme-aware via CSS
 * vars. Anchor element preserved (keyboard nav + middle-click). Min
 * 32px height keeps the tap target above the WCAG comfortable-secondary
 * threshold without claiming primary-CTA real estate.
 */
.chat-msg__action {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 32px;
  padding: 0 0.75rem;
  font-size: 0.8125rem;
  font-weight: 500;
  border-radius: 6px;
  border: 1px solid var(--border);
  background-color: transparent;
  color: var(--foreground);
  text-decoration: none;
  transition: background-color 0.15s;
  cursor: pointer;
}

.chat-msg__action:hover {
  background-color: var(--muted);
}

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

/* Default style modifier — same visual treatment as base. */
.chat-msg__action--primary {
  /* Matches base .chat-msg__action — kept as a hook for future variation. */
}

/* Muted secondary modifier for less prominent actions. */
.chat-msg__action--secondary {
  color: var(--muted-foreground);
}

/*
 * Warning modifier — amber-tinted variant for attention-grabbing
 * actions like "View dispute" emitted by marketplace/dispute.js. Closes
 * audit-feature-final.md HIGH #1 (A4 PARTIAL CONTRADICTION):
 * marketplace/dispute.js:358 emits style:"warning"; pre-polish slice
 * the renderer coerced this to --primary, dropping the producer-intended
 * emphasis. Now the action renders amber so disputes visually pop out
 * from regular system-message actions.
 *
 * Theme-aware via --warning / --warning-foreground tokens at :root + .dark.
 * border-color computed from --warning so the outline carries the same hue
 * at slightly higher saturation, matching shadcn's outlined-button idiom.
 */
.chat-msg__action--warning {
  color: var(--warning-foreground);
  background-color: hsla(38, 92%, 50%, 0.12);
  border-color: var(--warning);
}

.chat-msg__action--warning:hover {
  background-color: hsla(38, 92%, 50%, 0.2);
}

.dark .chat-msg__action--warning {
  color: hsl(38, 92%, 70%);
  background-color: hsla(38, 92%, 50%, 0.15);
  border-color: hsla(38, 92%, 50%, 0.5);
}

.dark .chat-msg__action--warning:hover {
  background-color: hsla(38, 92%, 50%, 0.25);
}

.chat-msg__time {
  margin-top: 0.25rem;
  font-size: 0.6875rem;
  color: var(--muted-foreground);
  opacity: 0.8;
}

/* System message — full-width info block, not a chat bubble */
.chat-msg--system {
  max-width: 100%;
  align-self: stretch;
}

.chat-msg--system .chat-msg__body {
  width: 100%;
  background-color: var(--card);
  border: 1px solid var(--border);
  display: flex;
  /*
   * mobile-purchases-polish Slice 1b (RFC Decision 2):
   * System messages are info blocks (not chat bubbles); stack body
   * content vertically at all viewports so text + actions + timestamp
   * never collide with each other or squeeze the timestamp on long
   * bodies. Composes safely with parent .chat-msg's row layout (icon
   * remains horizontal sibling of body) — verified via A13.
   */
  flex-direction: column;
  gap: 0.625rem;
  padding: 0.75rem 1rem;
}

.chat-msg--system .chat-msg__icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: hsla(217, 91%, 60%, 0.14);
  color: hsl(217, 91%, 55%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8125rem;
}

.chat-msg--system .chat-msg__text {
  color: var(--foreground);
  font-size: 0.875rem;
  line-height: 1.45;
}

.dark .chat-msg--system .chat-msg__icon {
  background-color: hsla(217, 91%, 60%, 0.25);
  color: hsl(217, 91%, 72%);
}

/* Support-oriented style (future: when we tag system messages). For now
   all system messages use the same treatment; the class below is reserved
   for when chat.js lights up a `kind: 'support'` subtype. */
.chat-msg--support .chat-msg__icon {
  background-color: hsla(142, 71%, 45%, 0.14);
  color: hsl(142, 71%, 38%);
}

/* ── Input form ──────────────────────────────────────── */
.chat-panel__form {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  padding: 0.75rem;
  border-top: 1px solid var(--border);
  background-color: var(--card);
  flex: 0 0 auto;
}

.chat-panel__input {
  flex: 1;
  padding: 0.625rem 0.875rem;
  font-family: inherit;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--foreground);
  background-color: var(--background);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  resize: none;
  min-height: 40px;
  max-height: 120px;
  overflow-y: auto;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.chat-panel__input:focus {
  outline: none;
  border-color: var(--ring);
  box-shadow: 0 0 0 3px hsla(214, 32%, 75%, 0.35);
}

.chat-panel__send {
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: hsl(217, 91%, 60%);
  color: #fff;
  border: 1px solid transparent;
  border-radius: 50%;
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.1s ease;
  font-size: 0.875rem;
  flex: 0 0 auto;
}

.chat-panel__send:hover {
  background-color: hsl(217, 91%, 54%);
  transform: scale(1.04);
}

.chat-panel__send:active {
  transform: scale(0.96);
}

/* ══════════════════════════════════════════════════════════════════
 * admin-chat-rewrite (.spec/admin-chat-rewrite/rfc.md AC16) — "✨
 * Improve" button + Undo link + inline error banner. Lives next to
 * .chat-panel__send rules so the chat-form layout stays cohesive.
 *
 * Shape: secondary 32-36px button to the LEFT of Send, sparkle icon +
 * "Improve" text. Mobile <480px: text hides → icon-only. Disabled +
 * spinner state shown via .chat-form__improve-btn--inflight modifier
 * (set by client JS).
 * ══════════════════════════════════════════════════════════════════ */

.chat-form__improve-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  height: 36px;
  /* min-width prevents layout shift when inflight text changes
     "Improve" -> "..." and would otherwise shrink the button.
     Polish slice 2026-05-07 (admin-chat-rewrite UX fix). */
  min-width: 108px;
  background-color: var(--secondary, hsl(210, 40%, 96%));
  color: var(--foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1;
  flex: 0 0 auto;
  transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}

.chat-form__improve-btn:hover:not(:disabled) {
  background-color: var(--accent, hsl(210, 40%, 92%));
  border-color: var(--ring, hsl(214, 32%, 75%));
}

.chat-form__improve-btn:focus-visible {
  outline: 2px solid var(--ring, hsl(214, 32%, 65%));
  outline-offset: 2px;
}

.chat-form__improve-btn:disabled,
.chat-form__improve-btn--inflight {
  cursor: not-allowed;
  opacity: 0.65;
}

.chat-form__improve-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9375rem;
  line-height: 1;
}

/* Inflight: hide the sparkle emoji (asymmetric multi-color glyph rotates
   poorly) and the "..." JS-set text; show a proper CSS spinner instead.
   Polish slice 2026-05-07. */
.chat-form__improve-btn--inflight .chat-form__improve-icon,
.chat-form__improve-btn--inflight .chat-form__improve-text {
  visibility: hidden;
}

.chat-form__improve-btn--inflight::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: chat-form-improve-spin 0.7s linear infinite;
}

.chat-form__improve-btn {
  position: relative;
}

@keyframes chat-form-improve-spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 480px) {
  .chat-form__improve-btn .chat-form__improve-text {
    display: none;
  }
  .chat-form__improve-btn {
    padding: 0.375rem 0.5rem;
    width: 36px;
    min-width: 0;
    justify-content: center;
  }
}

.chat-form__improve-undo {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 0.625rem;
  background: transparent;
  color: var(--muted-foreground);
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 500;
  flex: 0 0 auto;
  transition: color 0.15s ease, background-color 0.15s ease;
}

.chat-form__improve-undo:hover {
  color: var(--foreground);
  background-color: var(--muted);
}

.chat-form__improve-undo:focus-visible {
  outline: 2px solid var(--ring, hsl(214, 32%, 65%));
  outline-offset: 2px;
}

.chat-form__improve-error {
  margin: 0 0.75rem 0.25rem 0.75rem;
  padding: 0.5rem 0.75rem;
  background-color: hsla(0, 75%, 55%, 0.08);
  color: var(--destructive);
  border: 1px solid hsla(0, 75%, 55%, 0.25);
  border-radius: var(--radius);
  font-size: 0.8125rem;
  line-height: 1.3;
}

/* ══════════════════════════════════════════════════════════════════
 * service-view-rework Slice 3 additions.
 *
 * The new `/service/:id` catalog page (see views/service-view.ejs,
 * marketplace branch) reuses `.order-detail` / `.chat-panel__*` primitives
 * above and adds three new sub-elements:
 *
 *   1. `.chat-panel__status-dot` — 8px circle next to the seller name in
 *      the chat panel header. Colour keyed off the `--online` / `--offline`
 *      modifier, which is chosen server-side via `computeOnlineStatus`
 *      (marketplace/ui-helpers.js).
 *   2. `.chat-panel__avatar-img` — the `<img>` variant rendered by
 *      `avatarImgOrSvg` when the user has a populated `avatarUrl`. Shares
 *      the 40×40 sizing of `.chat-panel__avatar` so the fallback SVG and
 *      the real image render identically.
 *   3. `.chat-panel__rating` — compact rating line (star + score + Reviews
 *      link) that appears in the marketplace-mode panel only. The Reviews
 *      link uses `.chat-panel__rating-link` with the same HSL as
 *      `.order-meta__link` so links stay visually consistent.
 *
 * Colour tokens reuse the existing palette: `142 71% 45%` (green, matches
 * `.order-status--completed`), `215 16% 55%` (muted grey, same family as
 * `.order-status--muted`), and `217 91% 55%` (blue, matches
 * `.order-meta__link`).
 *
 * Delivery-badge tier modifiers (`.instant-delivery`, `.fast-delivery`,
 * `.slow-delivery` applied ON `.delivery-badge`) were previously defined
 * inline in views/service-view.ejs. They are migrated here so removing
 * the inline <style> block does not regress the legacy branch. The
 * `background` shorthand is required to override the gradient set on
 * `.delivery-badge` above.
 * ══════════════════════════════════════════════════════════════════ */

.chat-panel__status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-left: 0.5rem;
  vertical-align: middle;
  /* Polish 2026-05-01 (service-view-rework L-1): hardcoded
     hsl(215, 16%, 55%) → var(--muted-foreground) so the dot tracks
     the dark-theme palette via the existing token. The online dot
     migrates to var(--success) which equals the legacy literal
     hsl(142, 71%, 45%) — pure rename, zero visual change. */
  background: var(--muted-foreground);
}

.chat-panel__status-dot--online {
  background: var(--success);
}

.chat-panel__status-dot--offline {
  background: var(--muted-foreground);
}

.chat-panel__avatar-img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.chat-panel__rating {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
}

/* sales-count Slice 1 / Decision 5 — symmetric to .chat-panel__rating
   visual treatment. Renders below the seller-name line on /service/:id
   when the service has cachedSalesCount >= 50. Hidden below threshold
   via the EJS conditional in views/service-view.ejs (truthy guard on
   salesCountText). Visible in BOTH marketplace and admin modes per
   planner correction 5. */
.chat-panel__sales-line {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}

.chat-panel__rating-link {
  color: hsl(217, 91%, 55%);
  text-decoration: none;
}

.chat-panel__rating-link:hover {
  text-decoration: underline;
  color: hsl(217, 91%, 48%);
}

.dark .chat-panel__rating-link { color: hsl(217, 91%, 70%); }
.dark .chat-panel__rating-link:hover { color: hsl(217, 91%, 78%); }

/* Delivery-badge tier modifiers (migrated from views/service-view.ejs
 * inline style block per RFC D11). `background` shorthand overrides the
 * gradient on the base `.delivery-badge` rule above. */
.delivery-badge.instant-delivery {
  background: #198754;
}

.delivery-badge.fast-delivery {
  background: #0d6efd;
}

.delivery-badge.slow-delivery {
  background: #dc3545;
}

/* ════════════════════════════════════════════════════════════════════
 * Service-view mobile drawer (RFC: .spec/service-view-mobile/rfc.md)
 *
 * On viewports ≤991px the .order-detail__right column transforms into
 * a fullscreen drawer. JavaScript toggles body.is-chat-drawer-open to
 * control state. See views/service-view.ejs marketplace branch for
 * the FAB markup, close-X button, service-name subtitle, and inline
 * drawer JS bootstrap.
 *
 * Critical: collapsed mobile state uses visibility:hidden + transform
 * (NOT display:none) to preserve scrollHeight per RFC A3 — required
 * so MarketChat.attach's scrollToBottom() works at attach time even
 * before the user has opened the drawer.
 *
 * Z-index allocation:
 *   1050 — sticky navbar (.navbar in shadcn-header.ejs)
 *   1098 — chat FAB (below drawer, above page content)
 *   1100 — drawer (.order-detail__right in mobile-fixed mode)
 * ════════════════════════════════════════════════════════════════════ */

/* Body scroll-lock (D5: class-based, not inline-style, so future
 * overlays compose without stomping each other's body.style.overflow
 * writes the way the existing 3 inline-style sites would). */
body.is-scroll-locked {
  overflow: hidden;
}

@media (max-width: 991px) {
  /* Mobile-default: drawer is offscreen below, hidden, non-interactive.
   * Overrides the existing mobile rule at .order-detail__right which
   * had `position: static; height: auto; max-height: 70vh`.
   *
   * 2026-04-29 hotfix: scoped via `body.has-chat-drawer` to avoid hiding
   * the chat panel on /service-orders/:shortId and /market/order/:id
   * which share the same `.order-detail__right` class but never received
   * FAB+JS bootstrap. Without this scope, those pages had chat-panel
   * permanently offscreen-fixed on mobile — buyers could not read chat
   * or reach the Request Refund button (regression from commit 8c0373c
   * service-view-mobile RFC, ~5 days on prod). The body class is set
   * only in views/service-view.ejs (the page where the FAB JS lives);
   * the other two consumers fall through to the pre-RFC mobile rule
   * at `.order-detail__right` line ~1744 (position: static, max-height:
   * 70vh — chat panel stacks under order details, fully readable). */
  body.has-chat-drawer .order-detail__right {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background-color: var(--background);
    /* Fixed bounding box so the inner .chat-panel { height:100% } +
     * .chat-panel__messages { flex:1; overflow-y:auto } pins the form
     * at the bottom and lets messages scroll between header and form.
     * Using `height` (not min-height) so a long message list doesn't
     * push the input out of the viewport on iOS Safari. */
    height: 100dvh;
    max-height: 100dvh;
    transform: translateY(100%);
    visibility: hidden;
    pointer-events: none;
    /* Visibility delays AFTER slide-down so panel doesn't vanish
     * mid-animation; on slide-up flips immediately. */
    transition: transform 0.25s ease-out, visibility 0s linear 0.25s;
    will-change: transform;
  }
  body.has-chat-drawer.is-chat-drawer-open .order-detail__right {
    transform: translateY(0);
    visibility: visible;
    pointer-events: auto;
    transition: transform 0.25s ease-out, visibility 0s linear 0s;
  }

  /* iPhone X+ home-indicator overlap protection on the chat input.
   * Scoped to drawer-mode pages too — on stacked-layout pages the chat
   * input is mid-page, not against the home indicator. */
  body.has-chat-drawer .chat-panel__form {
    padding-bottom: calc(0.625rem + env(safe-area-inset-bottom, 0px));
  }
}

/* ── FAB (floating chat button) ──────────────────────────────────────
 * Visually patterned after a .filter-fab style from a removed legacy
 * page (reproduced inline here because the source stylesheet was not
 * loaded on /service/:id — verified per RFC F1 at the time of the
 * service-view-mobile rework). */
.chat-fab {
  display: none;
}

.chat-fab__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  margin-left: 0.375rem;
  border-radius: 10px;
  background: #ef4444;
  color: #ffffff;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
}
.chat-fab__badge--hidden {
  display: none;
}

@media (max-width: 991px) {
  .chat-fab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    position: fixed;
    bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px));
    right: 1.5rem;
    z-index: 1098;
    padding: 0.75rem 1.25rem;
    background: var(--foreground);
    color: var(--background);
    border: none;
    border-radius: 50px;
    font-weight: 600;
    font-size: 0.875rem;
    cursor: pointer;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
    transition: transform 0.2s ease, opacity 0.2s ease;
  }
  .chat-fab:hover { opacity: 0.9; transform: translateY(-2px); }
  .chat-fab:active { transform: scale(0.96); }

  /* Hide FAB while drawer is open — close-X inside drawer header
   * replaces it as the dismiss affordance. */
  body.is-chat-drawer-open .chat-fab {
    display: none;
  }

  /* Hide FAB when the Place Order button is in the viewport so the
   * checkout CTA isn't visually overlapped at the bottom of the order
   * form. Body class is toggled by the FAB IIFE in views/service-view.ejs
   * via IntersectionObserver on #placeOrderBtn (RFC mobile-purchases-polish
   * Decision 1). Mirrors the .is-chat-drawer-open precedent above. */
  body.is-place-order-visible .chat-fab {
    display: none;
  }
}

/* ── Drawer chrome (close-X + service-name subtitle) ─────────────────
 * Both live inside .chat-panel__header always; CSS hides them on
 * desktop. Lazy-show via @media keeps the desktop header layout
 * pixel-identical to pre-rework. */
.chat-panel__close-btn {
  display: none;
}

.chat-panel__subtitle {
  display: none;
}

@media (max-width: 991px) {
  .chat-panel__close-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: transparent;
    color: var(--muted-foreground);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
    font-size: 0.9375rem;
    flex: 0 0 auto;
  }
  .chat-panel__close-btn:hover {
    background-color: var(--accent);
    color: var(--foreground);
  }

  /* Service-name subtitle under the seller name. Truncate with ellipsis
   * to keep header at 2 lines max on iPhone SE width (320px). */
  .chat-panel__subtitle {
    display: block;
    font-size: 0.75rem;
    color: var(--muted-foreground);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 0.125rem;
  }
}
/* ════════════════════════ END service-view mobile drawer ═══════════ */

/* ═══════════════════════════════════════════════════════════════════
   deposit-page-rework Slice 1 (.spec/deposit-page-rework/rfc.md
   D6+D11+D17+D18+D20+D21). Slice 3 cleanup 2026-05-15 dropped the
   body.deposit-v2 scope prefix; rules are now canonical and apply
   wherever the .deposit-v2-* classes appear (deposit page only).

   Z-index contract per D11 (audit-payment-safety M-8):
     0    cards (default)
     50   .deposit-v2-submit-bar (sticky-mobile bar)
     1000 Bootstrap dropdowns
     1040 Bootstrap modal-backdrop
     1070 popovers
     1080 tooltips
   Sticky bar deliberately under dropdowns/modals/popovers/tooltips.
   ═══════════════════════════════════════════════════════════════════ */

.deposit-v2-page {
  padding: 2.5rem 0 2rem;
}

.deposit-v2-container {
  max-width: 540px;
  margin: 0 auto;
  padding: 0 1rem;
}

.deposit-v2-header {
  /* Slice 2 design iter-3 2026-05-04: header moved INSIDE the form
     (per user feedback "перенести available в форму чтобы не занимать
     место"). The form's flex gap (1.5rem) now handles spacing between
     header and amount-section, so an explicit margin-bottom here would
     double the gap. Kept rule selector for future styling hooks. */
  margin: 0;
}

.deposit-v2-balance-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.deposit-v2-balance-label {
  color: var(--muted-foreground);
  font-size: 0.8125rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.deposit-v2-balance-amount {
  /* Slice 2 design iter-4 2026-05-04: scaled down from 1.5rem/700
     to fit the in-card sub-header context (right of "Enter amount"
     label inside .deposit-v2-amount-section). The label/amount pair
     is now informational sub-text matching the surrounding card chrome
     rather than a primary page header. */
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--foreground);
  letter-spacing: -0.01em;
}

.deposit-v2-repeat {
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--foreground);
  padding: 0.4rem 0.75rem;
  border-radius: var(--radius);
  font-size: 0.8125rem;
  cursor: pointer;
  transition: background-color 120ms ease;
}

.deposit-v2-repeat:hover {
  background-color: var(--accent);
}

.deposit-v2-repeat:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.deposit-v2-alert {
  background-color: var(--destructive);
  color: var(--card);
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  margin-bottom: 1rem;
  font-size: 0.875rem;
}

.deposit-v2-alert-warning {
  background-color: var(--accent);
  color: var(--foreground);
  border: 1px solid var(--border);
}

.deposit-v2-form {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.deposit-v2-amount-section {
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
}

/* Slice 2 design iter-4 2026-05-04: section-header is a flex row at the
   top of .deposit-v2-amount-section that pairs the "Enter amount" label
   on the left with the AVAILABLE balance display on the right. Replaces
   the iter-3 standalone <header class="deposit-v2-header"> sibling that
   sat above the amount-section card. flex-wrap allows the right side to
   drop below the label on narrow viewports OR when the optional repeat-
   last button widens the balance row past available space. */
.deposit-v2-amount-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}

.deposit-v2-amount-label {
  /* Slice 2 design iter-4 2026-05-04: was display: block + margin-bottom:
     0.5rem to space label above input. Now an inline flex item inside
     .deposit-v2-amount-section-header — wrapper handles spacing. */
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--muted-foreground);
  margin: 0;
}

.deposit-v2-amount-input-wrap {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.25rem;
  margin: 0.5rem 0;
}

.deposit-v2-amount-prefix {
  /* D6: font-size: max(2.5rem, 16px) defensive against iOS zoom on
     tiny viewports — anything ≥16px on text input prevents iOS Safari
     auto-zoom. */
  font-size: max(2.5rem, 16px);
  font-weight: 700;
  color: var(--muted-foreground);
}

.deposit-v2-amount-input {
  /* D6 amount input — type="text" inputmode="decimal" drops type=number
     iOS-zoom + spinner heuristics. font-size: max(2.5rem, 16px) defends
     against iOS auto-zoom on tiny viewports per A8 amendment. */
  font-size: max(2.5rem, 16px);
  font-weight: 700;
  border: none;
  background: transparent;
  text-align: center;
  width: auto;
  max-width: 240px;
  color: var(--foreground);
  font-family: inherit;
  letter-spacing: -0.02em;
}

.deposit-v2-amount-input:focus {
  outline: none;
}

.deposit-v2-amount-input::placeholder {
  color: var(--muted-foreground);
  opacity: 0.5;
}

.deposit-v2-amount-chips {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 0.75rem;
}

.deposit-v2-chip {
  border: 1px solid var(--border);
  background-color: var(--card);
  color: var(--foreground);
  padding: 0.4rem 0.875rem;
  border-radius: 9999px;
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 500;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.deposit-v2-chip:hover {
  background-color: var(--accent);
}

.deposit-v2-chip:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.deposit-v2-chip--selected {
  background-color: var(--primary);
  color: var(--card);
  border-color: var(--primary);
}

.deposit-v2-methods {
  border: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.deposit-v2-method-radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.deposit-v2-method-row {
  /* D4 7 method rows. Compact rows; 60px nominal vertical density per
     RFC. Fee right-aligned. Selected state via left-border accent (no
     ::after checkmark per D4). */
  display: grid;
  grid-template-columns: 32px 1fr auto;
  grid-template-areas:
    "icon name fee"
    "icon desc fee";
  gap: 0 0.75rem;
  align-items: center;
  background-color: var(--card);
  border: 1px solid var(--border);
  border-left: 3px solid transparent;
  border-radius: var(--radius);
  padding: 0.625rem 0.875rem;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
  position: relative;
}

.deposit-v2-method-row:hover {
  background-color: var(--accent);
}

.deposit-v2-method-radio:checked + .deposit-v2-method-row {
  border-left-color: var(--primary);
  background-color: var(--accent);
}

.deposit-v2-method-radio:focus-visible + .deposit-v2-method-row {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.deposit-v2-method-row--disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.deposit-v2-method-icon {
  grid-area: icon;
  font-size: 1.25rem;
  color: var(--foreground);
  text-align: center;
}

.deposit-v2-method-name {
  grid-area: name;
  font-weight: 600;
  color: var(--foreground);
  font-size: 0.9375rem;
}

.deposit-v2-method-desc {
  grid-area: desc;
  color: var(--muted-foreground);
  font-size: 0.8125rem;
}

.deposit-v2-method-fee {
  grid-area: fee;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  font-weight: 500;
  white-space: nowrap;
}

.deposit-v2-method-min-badge {
  position: absolute;
  top: 0.25rem;
  right: 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--destructive);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.deposit-v2-email-wrap {
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}

.deposit-v2-email-input {
  /* font-size ≥16px: defends against iOS Safari auto-zoom on text
     input focus (same iOS quirk D6 mitigates for the amount input). */
  width: 100%;
  font-size: max(0.9375rem, 16px);
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) * 0.75);
  background-color: var(--card);
  color: var(--foreground);
  font-family: inherit;
}

.deposit-v2-email-input:focus {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.deposit-v2-receipt {
  /* D1+D21 live receipt. Lines wording locked verbatim by AC1.2:
     "You pay $X.XX" / "Balance after deposit: $Y.YY". Microcopy below
     submit button: "Balance updates after payment confirms." */
  background-color: var(--accent);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.875rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.deposit-v2-receipt-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.9375rem;
}

.deposit-v2-receipt-label {
  color: var(--muted-foreground);
}

.deposit-v2-receipt-value {
  font-weight: 600;
  color: var(--foreground);
}

.deposit-v2-submit-bar {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1rem 0;
}

.deposit-v2-submit-btn {
  width: 100%;
  padding: 0.875rem 1.25rem;
  background-color: var(--primary);
  color: var(--card);
  border: none;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  transition: opacity 120ms ease;
}

.deposit-v2-submit-btn:hover {
  opacity: 0.92;
}

.deposit-v2-submit-btn:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.deposit-v2-submit-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.deposit-v2-microcopy {
  text-align: center;
  color: var(--muted-foreground);
  font-size: 0.75rem;
}

.deposit-v2-field-error {
  color: var(--destructive);
  font-size: 0.8125rem;
  margin-top: 0.5rem;
  display: none;
}

.deposit-v2-field-error--visible {
  display: block;
}

/* D11 sticky-mobile submit-bar — mobile-only via @media (max-width: 991px). */
@media (max-width: 991px) {
  .deposit-v2-submit-bar {
    /* z-index: 50 per D11 contract — deliberately under Bootstrap
       dropdowns (1000), modals (1040), popovers (1070), tooltips (1080).
       If a future custom component needs to sit above the sticky bar,
       it must use z-index ≥ 51 explicitly. */
    position: sticky;
    bottom: 0;
    z-index: 50;
    background-color: var(--card);
    border-top: 1px solid var(--border);
    padding: 0.75rem 1rem env(safe-area-inset-bottom);
    margin: 0 -1rem;
  }

  /* D11 + audit-payment-safety A13: when input is focused on iOS, the
     sticky bar drops to in-flow → reachable by scrolling, avoids
     virtual-keyboard occlusion. :has() supported in evergreen browsers
     as of mid-2024 per OQ4 (Chrome 105+/Safari 15.4+/Firefox 121+);
     stale Firefox <120 keeps sticky bar always — graceful degradation
     to legacy pre-rework behavior. */
  body:has(input:focus) .deposit-v2-submit-bar,
  body:has(input:focus) .submit-bar {
    position: static;
  }
}

/* Mobile <768px: balance row stacks vertically per D3. */
@media (max-width: 767px) {
  .deposit-v2-balance-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.375rem;
  }

  .deposit-v2-repeat {
    margin-left: 0;
  }
}
/* ════════════════════════ END deposit-page-rework Slice 1 ═══════════ */

/*
 * ════════════════════════ deposit-page-rework Slice 2 ════════════════
 * History rework — Stripe-style activity rows + filter pills + expand
 * toggle. Slice 3 cleanup 2026-05-15 dropped the body.deposit-v2 scope
 * prefix; rules now apply wherever .deposit-v2-history* classes appear
 * (deposit page only).
 *
 * Filter strategy uses additive body classes. D9 pills toggle a mutex
 * set { activity-filter-all, activity-filter-completed,
 * activity-filter-failed }. Initial state = all (set by IIFE on first
 * paint). The collapse rule under "all" hides rows beyond position 10;
 * "completed" hides failed+pending regardless of position; "failed"
 * hides completed+pending AND REVERSES the collapse hide for failed
 * rows beyond position 10 (Slice 2 AC2.5 footgun fix — filtering to
 * "Failed" must reveal all matching rows even when collapsed).
 * ═══════════════════════════════════════════════════════════════════ */

.deposit-v2-history {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}

.deposit-v2-history-heading {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--muted-foreground);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0 0 1rem 0;
}

.deposit-v2-history-empty {
  font-size: 0.9375rem;
  color: var(--muted-foreground);
  text-align: center;
  padding: 2rem 0;
  margin: 0;
}

.deposit-v2-history-pills {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.deposit-v2-history-pill {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted-foreground);
  padding: 0.375rem 0.875rem;
  border-radius: 9999px;
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s ease;
}

.deposit-v2-history-pill:hover {
  background: var(--accent);
  color: var(--foreground);
}

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

.deposit-v2-history-pill--active {
  background: var(--foreground);
  color: var(--background);
  border-color: var(--foreground);
}

.deposit-v2-history-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.deposit-v2-history-row {
  display: grid;
  grid-template-columns: 32px minmax(80px, 1fr) auto auto auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.9375rem;
}

.deposit-v2-history-row:last-child {
  border-bottom: none;
}

.deposit-v2-history-icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent);
  color: var(--muted-foreground);
  font-size: 0.875rem;
}

.deposit-v2-history-method {
  font-weight: 500;
  color: var(--foreground);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deposit-v2-history-date {
  color: var(--muted-foreground);
  font-size: 0.8125rem;
  white-space: nowrap;
}

.deposit-v2-history-amount {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--foreground);
}

.deposit-v2-history-status {
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.25rem 0.5rem;
  border-radius: 9999px;
  text-transform: uppercase;
  letter-spacing: 0.025em;
}

.deposit-v2-history-status--completed {
  background: hsl(142 71% 45% / 0.1);
  color: hsl(142 71% 30%);
}

.deposit-v2-history-status--pending {
  background: hsl(38 92% 50% / 0.1);
  color: hsl(38 92% 35%);
}

.deposit-v2-history-status--failed {
  background: hsl(0 84% 60% / 0.1);
  color: hsl(0 84% 45%);
}

.deposit-v2-history-expand {
  display: block;
  width: 100%;
  margin-top: 1rem;
  padding: 0.625rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--foreground);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease;
}

.deposit-v2-history-expand:hover {
  background: var(--accent);
}

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

/* === D10 collapse + D9 filter rules ===
 * Default collapse: rows beyond position 10 hidden when [data-collapsed].
 * Filter Completed: hide failed + pending regardless of position.
 * Filter Failed: hide completed + pending regardless of position.
 *
 * AC2.5 footgun fix (Slice 2 Concern #4): under filter-failed, REVERSE
 * the collapse rule so failed rows beyond position 10 become visible
 * even while [data-collapsed] is still set. Without this, a buyer
 * with 20 completed transactions + 5 failed transactions at positions
 * 12-16 would click "Failed" and see an empty list. The reversal uses
 * `display: grid` to match the default `display: grid` on the row
 * (NOT `list-item` — the parent <ul> uses list-style: none and the
 * rows are grid containers).
 */

.deposit-v2-history-list[data-collapsed] .deposit-v2-history-row:nth-child(n+11) {
  display: none;
}

body.activity-filter-completed .deposit-v2-history-row[data-status='failed'],
body.activity-filter-completed .deposit-v2-history-row[data-status='pending'] {
  display: none;
}

body.activity-filter-failed .deposit-v2-history-row[data-status='completed'],
body.activity-filter-failed .deposit-v2-history-row[data-status='pending'] {
  display: none;
}

body.activity-filter-failed .deposit-v2-history-list[data-collapsed] .deposit-v2-history-row[data-status='failed']:nth-child(n+11) {
  display: grid;
}

/* Slice 2 polish 2026-05-04: symmetric reversal for COMPLETED filter.
 * Bug surfaced post-flag-flip: admin's first 10 rows were all
 * pending/failed; Completed filter hid them all (correct), but
 * completed rows in positions 11+ stayed hidden under [data-collapsed]
 * with no reversal — empty list under Completed. Mirror the failed
 * reversal exactly. AC2.5 generalized: filtering by status X must
 * reveal X-rows beyond first 10, regardless of which filter active. */
body.activity-filter-completed .deposit-v2-history-list[data-collapsed] .deposit-v2-history-row[data-status='completed']:nth-child(n+11) {
  display: grid;
}

/* Slice 2 polish iter-3 2026-05-04: desktop 2-column layout (form
 * left, activity right). Mobile keeps single-column flow (existing
 * @media (max-width: 991px) below). On ≥992px the container becomes
 * a 2-col grid via explicit grid-template-areas:
 *   ┌─────────┬─────────┐
 *   │  alert  │  alert  │  optional banner; 0-height when absent
 *   ├─────────┼─────────┤
 *   │  form   │ history │  form fills left column with AVAILABLE
 *   │         │         │  balance INSIDE its top sub-header;
 *   └─────────┴─────────┘  RECENT ACTIVITY fills right column.
 *
 * Both columns start at the same Y position (top of grid, just below
 * the navbar) so the whole content view aligns with the NEZHNA
 * navbar logo per user feedback "выравнивание по логотипу всей
 * вьюшки". AVAILABLE balance was moved INTO the form card at the
 * top (was a separate grid item in iter-2; before that a spanning
 * row in iter-1) per "перенести available в форму чтобы не занимать
 * место" — frees up the right column for activity, and balance lives
 * inside the form's information hierarchy where amount + receipt
 * compute against it. Balance is also still visible in the navbar
 * Funds widget so its prominence is not lost.
 *
 * row-gap intentionally absent: when the alert area has no children
 * (common case) an explicit row-gap between alert track and the
 * form/history track creates unwanted top space. Use explicit
 * margin-bottom on the alert instead.
 *
 * History resets margin-top + padding-top + border-top: those are
 * "below the form" affordances on mobile (where history stacks under
 * form) but make no sense when history is a column-mate sitting
 * side-by-side with the form on desktop. */
@media (min-width: 992px) {
  .deposit-v2-container {
    max-width: 1080px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "alert  alert"
      "form   history";
    column-gap: 3rem;
    align-items: start;
  }

  .deposit-v2-alert {
    grid-area: alert;
    margin-bottom: 1.5rem;
  }

  #payment-form-v2 {
    grid-area: form;
    min-width: 0;
  }

  .deposit-v2-history {
    grid-area: history;
    margin-top: 0;
    padding-top: 0;
    border-top: none;
    min-width: 0;
  }
}

/* Mobile responsive — match Slice 1 sticky-bar context. */
@media (max-width: 991px) {
  .deposit-v2-history {
    /* Slice 2 Concern #5: clear sticky submit-bar overlap on mobile.
       Sticky submit-bar at z-index 50 sits at bottom: 0; without bottom
       padding here, the last activity row sits under the bar. */
    padding-bottom: calc(60px + env(safe-area-inset-bottom));
  }

  .deposit-v2-history-row {
    grid-template-columns: 28px 1fr auto auto;
    gap: 0.5rem;
    font-size: 0.875rem;
  }

  /* Hide separate date cell on mobile to fit the narrower layout —
     date moves visually behind the method line via overflow elision. */
  .deposit-v2-history-row .deposit-v2-history-date {
    display: none;
  }
}
/* ════════════════════════ END deposit-page-rework Slice 2 ═══════════ */
