/* ============================================
   Component Styles - Buttons, Forms, Cards, Tables, etc.
   ============================================ */

/* ============================================
   Buttons
   ============================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-2) var(--spacing-4);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1.5;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  user-select: none;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  transition: all var(--transition-base);
  min-height: 40px;
  touch-action: manipulation; /* Better touch handling */
}

.btn:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 1px var(--bg-primary);
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
}

/* Primary Button */
.btn-primary {
  color: var(--text-inverse);
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}

.btn-primary:hover:not(:disabled) {
  background-color: var(--color-gray-900);
  border-color: var(--color-gray-900);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.btn-primary:active:not(:disabled) {
  background-color: var(--color-gray-800);
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

/* Success (Save) Button — PO deck v3 S4: every Spara button is green (design green family,
   same family as the Aktiv badge). */
.btn-success {
  color: var(--text-inverse);
  background-color: var(--color-success);
  border-color: var(--color-success);
}

.btn-success:hover:not(:disabled) {
  background-color: var(--color-success-light);
  border-color: var(--color-success-light);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.btn-success:active:not(:disabled) {
  background-color: var(--color-success-dark);
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

/* Accent (blue) button — PO deck v3 S4: the Tillval button is blue. Reuses the portal's
   existing accent blue (see AssortmentFab). */
.btn-accent {
  color: #fff;
  background-color: #0d6efd;
  border-color: #0d6efd;
}

.btn-accent:hover:not(:disabled) {
  background-color: #0b5ed7;
  border-color: #0b5ed7;
  color: #fff;
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.btn-accent:active:not(:disabled) {
  background-color: #0a58ca;
  color: #fff;
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

/* Secondary Button */
.btn-outline-secondary {
  color: var(--text-secondary);
  background-color: transparent;
  border-color: var(--border-color);
}

.btn-outline-secondary:hover:not(:disabled) {
  background-color: var(--bg-tertiary);
  border-color: var(--color-gray-400);
  color: var(--text-primary);
}

/* Outline Primary */
.btn-outline-primary {
  color: var(--color-primary);
  background-color: transparent;
  border-color: var(--color-primary);
}

.btn-outline-primary:hover:not(:disabled) {
  background-color: var(--color-primary);
  color: var(--text-inverse);
  border-color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}

/* Danger Button */
.btn-danger, .btn-outline-danger {
  color: var(--color-danger);
  background-color: transparent;
  border-color: var(--color-danger);
}

.btn-danger {
  background-color: var(--color-danger);
  color: var(--text-inverse);
}

.btn-danger:hover:not(:disabled) {
  background-color: var(--color-danger-dark);
  border-color: var(--color-danger-dark);
}

.btn-outline-danger:hover:not(:disabled) {
  background-color: var(--color-danger);
  color: var(--text-inverse);
}

/* Success Button */
.btn-outline-success {
  color: var(--color-success);
  background-color: transparent;
  border-color: var(--color-success);
}

.btn-outline-success:hover:not(:disabled) {
  background-color: var(--color-success);
  color: var(--text-inverse);
}

/* Button Sizes */
.btn-sm {
  padding: var(--spacing-1) var(--spacing-3);
  font-size: var(--font-size-xs);
  min-height: 32px;
}

@media (max-width: 576px) {
  .btn {
    min-height: 44px; /* Minimum touch target */
  }

  .btn-sm {
    min-height: 36px;
  }
}

.btn-lg {
  padding: var(--spacing-3) var(--spacing-6);
  font-size: var(--font-size-base);
  min-height: 48px;
}

/* Button with Icon */
.btn i {
  font-size: 1em;
  line-height: 1;
}

.btn i.bi {
  margin-right: var(--spacing-2);
}

.btn i:last-child {
  margin-right: 0;
  margin-left: var(--spacing-2);
}

.btn i:only-child {
  margin: 0;
}

/* Link Button */
.btn-link {
  color: var(--color-primary);
  background-color: transparent;
  border: none;
  padding: var(--spacing-1) var(--spacing-2);
  text-decoration: none;
}

.btn-link:hover:not(:disabled) {
  color: var(--color-gray-800);
  text-decoration: underline;
  background-color: transparent;
}

/* ============================================
   Forms
   ============================================ */
.form-label {
  display: block;
  margin-bottom: var(--spacing-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
}

.form-control,
.form-select {
  display: block;
  width: 100%;
  padding: var(--spacing-2) var(--spacing-3);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-normal);
  color: var(--text-primary);
  background-color: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-control:focus,
.form-select:focus {
  color: var(--text-primary);
  background-color: var(--bg-primary);
  border-color: var(--color-primary);
  outline: 0;
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1);
}

.form-control:focus-visible,
.form-select:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-color: var(--color-primary);
}

.form-control::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

.form-control:disabled {
  background-color: var(--bg-tertiary);
  opacity: 0.6;
  cursor: not-allowed;
}

/* Input Groups */
.input-group {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  width: 100%;
}

.input-group-text {
  display: flex;
  align-items: center;
  padding: var(--spacing-2) var(--spacing-3);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-normal);
  color: var(--text-secondary);
  text-align: center;
  white-space: nowrap;
  background-color: var(--bg-tertiary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md) 0 0 var(--radius-md);
}

.input-group .form-control {
  border-left: none;
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.input-group:focus-within .input-group-text,
.input-group:focus-within .form-control {
  border-color: var(--color-primary);
}

/* Validation */
.validation-message {
  display: block;
  margin-top: var(--spacing-1);
  font-size: var(--font-size-sm);
  color: var(--color-danger);
}

.valid.modified:not([type=checkbox]) {
  outline: 2px solid var(--color-success);
  outline-offset: -2px;
}

.invalid {
  border-color: var(--color-danger) !important;
}

/* Checkboxes & Radios */
.form-check-input {
  width: 1.125em;
  height: 1.125em;
  margin-top: 0.125em;
  vertical-align: top;
  background-color: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.form-check-input:checked {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}

.form-check-input:focus {
  border-color: var(--color-primary);
  outline: 0;
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1);
}

/* ============================================
   Cards
   ============================================ */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  word-wrap: break-word;
  background-color: var(--bg-primary);
  background-clip: border-box;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), transform var(--transition-base);
}

.card:hover {
  box-shadow: var(--shadow-md);
}

.card-header {
  padding: var(--spacing-4) var(--spacing-6);
  margin-bottom: 0;
  background-color: var(--bg-primary);
  border-bottom: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.card-header:first-child {
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.card-header h5 {
  margin: 0;
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.card-body {
  flex: 1 1 auto;
  padding: var(--spacing-6);
}

.card-footer {
  padding: var(--spacing-4) var(--spacing-6);
  background-color: var(--bg-primary);
  border-top: 1px solid var(--border-color-light);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/* Card with Shadow */
.card.shadow-sm {
  box-shadow: var(--shadow-sm);
}

.card.border-0 {
  border: none;
}

/* Clickable Category Cards */
.category-card-clickable {
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}

.category-card-clickable:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.category-card-clickable:active {
  transform: translateY(0);
  box-shadow: var(--shadow-md);
}

.category-card-clickable:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ============================================
   Tables
   ============================================ */
.table {
  width: 100%;
  margin-bottom: 0;
  color: var(--text-primary);
  vertical-align: top;
  border-color: var(--border-color);
}

.table > :not(caption) > * > * {
  padding: var(--spacing-3) var(--spacing-4);
  background-color: transparent;
  border-bottom-width: 1px;
  box-shadow: inset 0 0 0 9999px transparent;
}

.table > thead {
  vertical-align: bottom;
}

.table > thead > tr > th {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  background-color: var(--bg-tertiary);
  border-bottom: 2px solid var(--border-color);
  padding: var(--spacing-4);
}

.table > tbody > tr {
  transition: background-color var(--transition-fast);
}

.table > tbody > tr:hover {
  background-color: var(--bg-tertiary);
}

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

.table-hover > tbody > tr:hover > * {
  background-color: var(--bg-tertiary);
  color: var(--text-primary);
}

/* Sortable Columns */
.sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
}

.sortable:hover {
  background-color: var(--bg-secondary) !important;
}

.sortable i {
  margin-left: var(--spacing-2);
  opacity: 0.5;
  transition: opacity var(--transition-fast);
}

.sortable:hover i {
  opacity: 1;
}

/* ============================================
   Badges
   ============================================ */
.badge {
  display: inline-block;
  padding: 0.25em 0.6em;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  vertical-align: baseline;
  border-radius: var(--radius-base);
}

/* ------------------------------------------------------------------------------------------
   Background utilities, re-pointed at the design-system palette but kept OPACITY-AWARE.

   These used to be flat `background-color: var(--color-x) !important`. That looked harmless and
   was not: Bootstrap paints `rgba(var(--bs-x-rgb), var(--bs-bg-opacity))`, so overriding with a
   flat hex made every `.bg-opacity-*` class in the portal inert. Thirty-six sites asking for a
   10% or 25% TINT were painted at 100%, which is what turned the SuperAdmin stat cards into
   solid black / dark-green / olive blocks, made the icon circles solid black, and rendered
   `.text-primary` (#000000) on `.bg-primary` (#000000) - contrast 1.00:1, an invisible value.

   `--bs-bg-opacity: 1` is the default here exactly as in Bootstrap, so a bare `.bg-success`
   badge is unchanged; only the combinations that ALSO carry `.bg-opacity-*` start tinting again.
   ------------------------------------------------------------------------------------------ */
.bg-primary {
  background-color: rgba(var(--color-primary-rgb), var(--bs-bg-opacity, 1)) !important;
  color: var(--text-inverse) !important;
}

.text-primary {
  color: var(--color-primary) !important;
}

.bg-secondary {
  background-color: rgba(var(--color-secondary-rgb), var(--bs-bg-opacity, 1)) !important;
  color: var(--text-inverse) !important;
}

.bg-success {
  background-color: rgba(var(--color-success-rgb), var(--bs-bg-opacity, 1)) !important;
  color: var(--text-inverse) !important;
}

.bg-warning {
  background-color: rgba(var(--color-warning-rgb), var(--bs-bg-opacity, 1)) !important;
  color: var(--text-inverse) !important;
}

.bg-danger {
  background-color: rgba(var(--color-danger-rgb), var(--bs-bg-opacity, 1)) !important;
  color: var(--text-inverse) !important;
}

.bg-info {
  background-color: rgba(var(--color-info-rgb), var(--bs-bg-opacity, 1)) !important;
  color: var(--text-inverse) !important;
}

/* A `bg-opacity-*` modifier means the surface is a light TINT of the colour, not the solid
   colour. The white text the solid variants need would then be invisible on it, so let those
   elements inherit the page's own text colour and keep whatever `.text-*` class they carry.
   Without this the fix above would trade a black-on-black value for a white-on-near-white one. */
.bg-primary[class*="bg-opacity-"],
.bg-secondary[class*="bg-opacity-"],
.bg-success[class*="bg-opacity-"],
.bg-warning[class*="bg-opacity-"],
.bg-danger[class*="bg-opacity-"],
.bg-info[class*="bg-opacity-"] {
  color: inherit !important;
}

/* ------------------------------------------------------------------------------------------
   The stat-card icon tile.

   This is defined here, once, on purpose. It previously lived in four separate `.razor.css`
   files at two different sizes (56px/--radius-lg on the two dashboards, 48px/12px on the two
   Fortnox tools pages), and `Pages/Admin/ZReportTools.razor` used the class while shipping no
   scoped stylesheet at all - so on that page the tile had no size, no flex and no centring.
   A global rule reaches every page including that one, which is the whole point.
   ------------------------------------------------------------------------------------------ */
.stat-icon {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  flex-shrink: 0;
}

/* The tile carries the colour (`.text-*` beside `.bg-* .bg-opacity-*`); the glyph follows it.
   Never force a literal colour here - that is what made the icons white on a 10% tint. */
.stat-icon i {
  color: inherit;
}

/* Subtle Badges */
.bg-success-subtle {
  background-color: var(--color-success-bg) !important;
  color: var(--color-success-dark) !important;
}

.bg-warning-subtle {
  background-color: var(--color-warning-bg) !important;
  color: var(--color-warning-dark) !important;
}

.bg-danger-subtle {
  background-color: var(--color-danger-bg) !important;
  color: var(--color-danger-dark) !important;
}

.bg-info-subtle {
  background-color: var(--color-info-bg) !important;
  color: var(--color-info-dark) !important;
}

.bg-primary-subtle {
  background-color: var(--color-primary-50) !important;
  color: var(--color-primary-700) !important;
}

/* Ensure icons in stat cards are properly colored */
.stat-icon i,
.bg-primary-subtle i,
.bg-info-subtle i {
  color: inherit;
}

/* Navigation menu icons - ensure they're white */
.nav-menu .nav-link i.bi-receipt {
  color: var(--text-sidebar) !important;
}

/* Make receipt icon white */
.bi-receipt,
i.bi-receipt {
  color: #ffffff;
}

/* Override for navigation menu to use sidebar text color */
.nav-menu .nav-link i.bi-receipt {
  color: var(--text-sidebar) !important;
}

/* Override for stat cards if needed */
.stat-icon i.bi-receipt,
.bg-primary-subtle i.bi-receipt,
.bg-info-subtle i.bi-receipt {
  color: #ffffff !important;
}

/* Ensure all navigation icons are white */
.nav-menu .nav-link i {
  color: var(--text-sidebar) !important;
}

/* Specific icon overrides to ensure white */
.nav-menu .nav-link i.bi-building {
  color: #ffffff !important;
}

.nav-menu .nav-link i.bi-receipt {
  color: #ffffff !important;
}

/* ============================================
   Modals
   ============================================ */
.modal {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-modal);
  display: none;
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  outline: 0;
}

.modal.show {
  /* PO deck v3.0 S8: no align-items/justify-content here. Flex-centering the fixed,
     overflow-y:auto .modal container puts a taller-than-viewport dialog's top edge OUTSIDE the
     reachable scroll area (scrollable overflow only extends block-end), so a long receipt could
     never be scrolled to its first rows. Auto margins on the dialog center it when it fits and
     resolve to 0 when it is taller — anchoring it to the top so everything is reachable. */
  display: flex !important;
  padding: var(--spacing-4);
  background: var(--bg-overlay);
  backdrop-filter: blur(4px);
  animation: fadeIn var(--transition-base);
  cursor: pointer;
}

.modal.show .modal-dialog {
  cursor: default;
  margin: auto;
}

.modal-dialog {
  position: relative;
  width: auto;
  margin: var(--spacing-4);
  pointer-events: none;
  max-width: 500px;
  animation: slideDown var(--transition-slow);
}

.modal-dialog-centered {
  display: flex;
  align-items: center;
  min-height: calc(100% - var(--spacing-8));
}

.modal-dialog-centered::before {
  display: block;
  height: calc(100vh - var(--spacing-8));
  content: "";
}

.modal-lg {
  max-width: 800px;
}

.modal-xxl {
  max-width: 1400px;
}

.modal-content {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  pointer-events: auto;
  background-color: var(--bg-primary);
  background-clip: padding-box;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-2xl);
  outline: 0;
}

.modal-header {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: space-between;
  padding: var(--spacing-5) var(--spacing-6);
  border-bottom: 1px solid var(--border-color-light);
  border-top-left-radius: var(--radius-xl);
  border-top-right-radius: var(--radius-xl);
}

.modal-header.bg-danger {
  background-color: var(--color-danger);
  color: var(--text-inverse);
  border-bottom-color: var(--color-danger-dark);
}

.modal-title {
  margin: 0;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.modal-header.bg-danger .modal-title {
  color: var(--text-inverse);
}

/* bg-primary is black in this design system, so the default black .modal-title was
   invisible against it. Same treatment as .bg-danger above. */
.modal-header.bg-primary .modal-title {
  color: var(--text-inverse);
}

.btn-close {
  box-sizing: content-box;
  width: 1em;
  height: 1em;
  padding: 0.25em;
  color: var(--text-primary);
  background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;
  border: 0;
  border-radius: var(--radius-base);
  opacity: 0.5;
  cursor: pointer;
  transition: opacity var(--transition-fast), background-color var(--transition-fast);
}

.btn-close:hover {
  opacity: 1;
  background-color: var(--bg-tertiary);
}

.btn-close-white {
  filter: invert(1) grayscale(100%) brightness(200%);
}

.modal-body {
  position: relative;
  flex: 1 1 auto;
  padding: var(--spacing-6);
}

.modal-footer {
  display: flex;
  flex-wrap: wrap;
  flex-shrink: 0;
  align-items: center;
  justify-content: flex-end;
  padding: var(--spacing-4) var(--spacing-6);
  border-top: 1px solid var(--border-color-light);
  border-bottom-right-radius: var(--radius-xl);
  border-bottom-left-radius: var(--radius-xl);
  gap: var(--spacing-2);
}

/* Modal Animations */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ============================================
   Alerts
   ============================================ */
.alert {
  position: relative;
  padding: var(--spacing-4);
  margin-bottom: var(--spacing-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
}

.alert-danger {
  color: var(--color-danger-dark);
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger);
}

.alert-warning {
  color: var(--color-warning-dark);
  background-color: var(--color-warning-bg);
  border-color: var(--color-warning);
}

.alert-info {
  color: var(--color-info-dark);
  background-color: var(--color-info-bg);
  border-color: var(--color-info);
}

/* ============================================
   Dropdowns
   ============================================ */
.dropdown-menu {
  position: absolute;
  z-index: var(--z-dropdown);
  display: none;
  min-width: 10rem;
  padding: var(--spacing-2) 0;
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--text-primary);
  text-align: left;
  list-style: none;
  background-color: var(--bg-primary);
  background-clip: padding-box;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

.dropdown-menu.show {
  display: block;
  animation: fadeIn var(--transition-fast);
}

.dropdown-item {
  display: block;
  width: 100%;
  padding: var(--spacing-2) var(--spacing-4);
  clear: both;
  font-weight: var(--font-weight-normal);
  color: var(--text-primary);
  text-align: inherit;
  text-decoration: none;
  white-space: nowrap;
  background-color: transparent;
  border: 0;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.dropdown-item:hover,
.dropdown-item:focus {
  color: var(--text-primary);
  background-color: var(--bg-tertiary);
}

.dropdown-item.active,
.dropdown-item:active {
  color: var(--text-inverse);
  background-color: var(--color-primary);
  font-weight: var(--font-weight-medium);
}

.dropdown-item.text-danger {
  color: var(--color-danger) !important;
}

.dropdown-item.text-danger:hover {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-dark) !important;
}

.dropdown-item.text-warning {
  color: var(--color-warning) !important;
}

.dropdown-item.text-warning:hover {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-dark) !important;
}

.dropdown-divider {
  height: 0;
  margin: var(--spacing-2) 0;
  overflow: hidden;
  border-top: 1px solid var(--border-color-light);
}

.dropdown-toggle::after {
  display: inline-block;
  margin-left: var(--spacing-2);
  vertical-align: 0.255em;
  content: "";
  border-top: 0.3em solid;
  border-right: 0.3em solid transparent;
  border-bottom: 0;
  border-left: 0.3em solid transparent;
}

/* ============================================
   Pagination
   ============================================ */
.pagination {
  display: flex;
  padding-left: 0;
  list-style: none;
  gap: var(--spacing-1);
}

.page-link {
  position: relative;
  display: block;
  padding: var(--spacing-2) var(--spacing-3);
  color: var(--color-primary);
  text-decoration: none;
  background-color: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  transition: all var(--transition-fast);
}

.page-link:hover {
  z-index: 2;
  color: var(--color-gray-900);
  background-color: var(--bg-tertiary);
  border-color: var(--border-color-dark);
}

.page-item.active .page-link {
  z-index: 3;
  color: var(--text-inverse);
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}

.page-item.disabled .page-link {
  color: var(--text-muted);
  pointer-events: none;
  cursor: auto;
  background-color: var(--bg-tertiary);
  border-color: var(--border-color);
}

/* ============================================
   Progress Bars
   ============================================ */
.progress {
  display: flex;
  height: 0.5rem;
  overflow: hidden;
  background-color: var(--bg-tertiary);
  border-radius: var(--radius-full);
}

.progress-bar {
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
  color: var(--text-inverse);
  text-align: center;
  white-space: nowrap;
  background-color: var(--color-primary);
  transition: width var(--transition-slow) ease;
}

.progress-bar.bg-primary { background-color: var(--color-primary); }
.progress-bar.bg-success { background-color: var(--color-success); }
.progress-bar.bg-info { background-color: var(--color-info); }
.progress-bar.bg-warning { background-color: var(--color-warning); }
.progress-bar.bg-danger { background-color: var(--color-danger); }

/* ============================================
   Spinners
   ============================================ */
.spinner-border {
  display: inline-block;
  width: 2rem;
  height: 2rem;
  vertical-align: text-bottom;
  border: 0.25em solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spinner-border 0.75s linear infinite;
}

.spinner-border-sm {
  width: 1rem;
  height: 1rem;
  border-width: 0.2em;
}

@keyframes spinner-border {
  to { transform: rotate(360deg); }
}

.spinner-border.text-primary {
  color: var(--color-primary);
}

/* ============================================
   Skeleton Loading
   ============================================ */

/* Base skeleton styles */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

/* Skeleton shimmer animation */
@keyframes skeleton-shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* Skeleton pulse animation (alternative) */
@keyframes skeleton-pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

.skeleton-pulse {
  background-color: var(--color-gray-200);
  animation: skeleton-pulse 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

/* Skeleton text - for text placeholders */
.skeleton-text {
  display: inline-block;
  height: 1em;
  min-width: 60px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
  vertical-align: middle;
}

.skeleton-text.skeleton-text-sm {
  height: 0.75em;
}

.skeleton-text.skeleton-text-lg {
  height: 1.25em;
}

/* Skeleton text width variations */
.skeleton-text.w-25 { width: 25%; min-width: 40px; }
.skeleton-text.w-50 { width: 50%; min-width: 60px; }
.skeleton-text.w-75 { width: 75%; min-width: 80px; }
.skeleton-text.w-100 { width: 100%; }

/* Skeleton avatar - for profile pictures/icons */
.skeleton-avatar {
  display: inline-block;
  width: 40px;
  height: 40px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.skeleton-avatar.skeleton-avatar-sm {
  width: 32px;
  height: 32px;
}

.skeleton-avatar.skeleton-avatar-lg {
  width: 48px;
  height: 48px;
}

.skeleton-avatar.skeleton-avatar-xl {
  width: 64px;
  height: 64px;
}

/* Skeleton avatar square variant (for product images) */
.skeleton-avatar.skeleton-avatar-square {
  border-radius: var(--radius-md);
}

/* Skeleton badge - for status badges/tags */
.skeleton-badge {
  display: inline-block;
  width: 60px;
  height: 20px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-base);
  vertical-align: middle;
}

.skeleton-badge.skeleton-badge-sm {
  width: 40px;
  height: 16px;
}

.skeleton-badge.skeleton-badge-lg {
  width: 80px;
  height: 24px;
}

/* Skeleton row - for table rows */
.skeleton-row {
  display: flex;
  align-items: center;
  padding: var(--spacing-3) var(--spacing-4);
  border-bottom: 1px solid var(--border-color-light);
  gap: var(--spacing-4);
}

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

/* Skeleton cell - for table cells */
.skeleton-cell {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}

.skeleton-cell.skeleton-cell-stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-1);
}

/* Skeleton button - for action buttons */
.skeleton-button {
  display: inline-block;
  width: 70px;
  height: 32px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-md);
}

.skeleton-button.skeleton-button-sm {
  width: 50px;
  height: 28px;
}

/* Skeleton table container */
.skeleton-table {
  width: 100%;
}

.skeleton-table-header {
  display: flex;
  align-items: center;
  padding: var(--spacing-4);
  background-color: var(--bg-tertiary);
  border-bottom: 2px solid var(--border-color);
  gap: var(--spacing-4);
}

.skeleton-table-header .skeleton-text {
  background: linear-gradient(
    90deg,
    var(--color-gray-300) 0%,
    var(--color-gray-200) 50%,
    var(--color-gray-300) 100%
  );
  background-size: 200% 100%;
  height: 0.75em;
}

.skeleton-table-body {
  background-color: var(--bg-primary);
}

/* Skeleton card - for card layouts */
.skeleton-card {
  padding: var(--spacing-4);
  background-color: var(--bg-primary);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
}

.skeleton-card-image {
  width: 100%;
  height: 120px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-md);
  margin-bottom: var(--spacing-3);
}

/* Skeleton icon placeholder */
.skeleton-icon {
  display: inline-block;
  width: 20px;
  height: 20px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
  vertical-align: middle;
}

.skeleton-icon.skeleton-icon-circle {
  border-radius: var(--radius-full);
}

/* Status dot skeleton */
.skeleton-status-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-full);
}

/* Skeleton checkbox placeholder */
.skeleton-checkbox {
  display: inline-block;
  width: 18px;
  height: 18px;
  background: linear-gradient(
    90deg,
    var(--color-gray-200) 0%,
    var(--color-gray-100) 50%,
    var(--color-gray-200) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

/* Reduce motion for accessibility */
@media (prefers-reduced-motion: reduce) {
  .skeleton,
  .skeleton-text,
  .skeleton-avatar,
  .skeleton-badge,
  .skeleton-button,
  .skeleton-card-image,
  .skeleton-icon,
  .skeleton-status-dot,
  .skeleton-checkbox,
  .skeleton-table-header .skeleton-text {
    animation: none;
    background: var(--color-gray-200);
  }

  .skeleton-pulse {
    animation: none;
  }
}

/* ============================================================================
   SORTIMENT SHARED COMPONENTS AND LAYOUT PRIMITIVES
   Plan: SORTIMENT-PARITY-PLAN.md, UI-1 .. UI-10.

   Everything below is ADDITIVE and uses only the existing design-system.css custom properties.
   Class names are new on purpose - none of them collide with the page-scoped <style> block in
   Pages/Company/Assortment/Index.razor, so the decomposition can adopt them one component at a
   time.
   ============================================================================ */

/* ============================================
   UI-1 - Toast notifications
   Rendered by Components/Shared/ToastHost.razor, fed by IToastService.
   ============================================ */
.gp-toast-region {
  position: fixed;
  top: var(--spacing-4);
  right: var(--spacing-4);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
  width: min(var(--toast-width), calc(100vw - var(--spacing-8)));
  pointer-events: none;
}

.gp-toast {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-3);
  padding: var(--spacing-3) var(--spacing-4);
  border: 1px solid var(--border-color);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--bg-primary);
  box-shadow: var(--shadow-lg);
  pointer-events: auto;
  animation: gp-toast-in var(--transition-base) both;
}

@keyframes gp-toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.gp-toast--success { border-left-color: var(--color-success); }
.gp-toast--info    { border-left-color: var(--color-info); }
.gp-toast--warning { border-left-color: var(--color-warning); }
.gp-toast--error   { border-left-color: var(--color-danger); }

.gp-toast-icon {
  flex-shrink: 0;
  font-size: var(--font-size-lg);
  line-height: var(--line-height-tight);
  margin-top: 2px;
}

.gp-toast--success .gp-toast-icon { color: var(--color-success); }
.gp-toast--info    .gp-toast-icon { color: var(--color-info); }
.gp-toast--warning .gp-toast-icon { color: var(--color-warning); }
.gp-toast--error   .gp-toast-icon { color: var(--color-danger); }

.gp-toast-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}

.gp-toast-title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.gp-toast-message {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.gp-toast-close {
  flex-shrink: 0;
  padding: var(--spacing-1);
  border: none;
  background: transparent;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  line-height: 1;
}

.gp-toast-close:hover { color: var(--text-primary); }

.gp-toast-close:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* ============================================
   UI-6 - Confirmation dialog
   ============================================ */
.confirm-dialog-message {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
}

.confirm-dialog-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--spacing-2);
  width: 100%;
  flex-wrap: wrap;
}

/* ============================================
   Shared image uploader (A4 / B19)
   ============================================ */
.image-uploader {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
}

.image-uploader-preview {
  position: relative;
  width: 120px;
  height: 120px;
  border: 1px dashed var(--border-color-dark);
  border-radius: var(--radius-md);
  background: var(--bg-tertiary);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.image-uploader-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-uploader-placeholder {
  color: var(--text-muted);
  font-size: var(--font-size-3xl);
}

.image-uploader-remove {
  position: absolute;
  top: var(--spacing-1);
  right: var(--spacing-1);
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-full);
  background: var(--bg-overlay);
  color: var(--text-inverse);
  font-size: var(--font-size-xs);
  cursor: pointer;
}

.image-uploader-remove:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color-inverse);
  outline-offset: var(--focus-ring-offset);
}

.image-uploader-busy {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.7);
}

.image-uploader-hint {
  font-size: var(--font-size-xs);
  color: var(--text-muted);
}

.image-uploader-error {
  font-size: var(--font-size-sm);
  color: var(--color-danger);
}

/* ============================================
   B13 - Money input
   LEFT aligned, and it must stay that way (PO ticket 2026-07-30: "all values with amount entered
   in the portal should be displayed on the left side and not the right"). B13 originally shipped
   this right aligned to match the money COLUMNS in tables, but an amount you TYPE is not a column
   you read: live production leaves txtProductPrice at the browser default
   (old-backend/possystemn/Views/Assortment/Article.cshtml:235 - .sub_elements sets no text-align),
   so right aligning it was a parity break. Read-only money cells (.numeric-cell) stay right aligned.
   Tabular figures are kept so digits stop jittering while typing.
   ============================================ */
.price-input-field {
  text-align: left;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* ============================================
   A6 / B22 - Tillval picker
   ============================================ */
.ingredient-picker {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-3);
}

.ingredient-picker-toolbar {
  display: flex;
  gap: var(--spacing-2);
  flex-wrap: wrap;
}

.ingredient-picker-search { flex: 1 1 220px; }

.ingredient-picker-selected {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  flex-wrap: wrap;
  padding: var(--spacing-2) var(--spacing-3);
  background: var(--bg-tertiary);
  border-radius: var(--radius-md);
  min-height: 44px;
}

.ingredient-picker-selected-label {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
}

.ingredient-picker-empty {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}

.ingredient-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.ingredient-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1);
  padding: 2px var(--spacing-1) 2px var(--spacing-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full);
  background: var(--bg-primary);
  font-size: var(--font-size-sm);
}

.ingredient-chip-name { color: var(--text-primary); }

.ingredient-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  line-height: 1;
}

.ingredient-chip-remove:hover:not(:disabled) {
  background: var(--color-danger-bg);
  color: var(--color-danger);
}

.ingredient-chip-remove:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 1px;
}

.ingredient-picker-table-scroll {
  max-height: 320px;
  overflow-y: auto;
  overflow-x: auto;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.ingredient-picker-table {
  margin-bottom: 0;
  min-width: 480px;
}

.ingredient-picker-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-tertiary);
}

.ingredient-picker-table tbody tr.is-selected { background: var(--color-primary-50); }

.ingredient-picker-name {
  margin: 0;
  cursor: pointer;
}

/* ============================================
   UI-5 - Skeleton rows (in-place loading placeholder)
   ============================================ */
/* Table mode: distinct class names, because the pre-existing .skeleton-row/.skeleton-cell are
   display:flex and would drop a real <tr>/<td> out of the table layout. */
tr.skeleton-table-row > td.skeleton-table-cell {
  padding: var(--spacing-3) var(--spacing-4);
  vertical-align: middle;
}

/* Div mode: for card and list layouts. */
.skeleton-rows {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-3);
  padding: var(--spacing-3);
}

.skeleton-rows-line {
  display: flex;
  align-items: center;
  gap: var(--spacing-4);
}

.skeleton-rows-line .skeleton-text { margin: 0; }

/* ============================================
   UI-2 - Sticky category rail, sticky table header, horizontal grid scroll
   The BODY must never scroll sideways: the overflow lives on .assortment-grid-scroll.
   ============================================ */
.assortment-rail {
  position: sticky;
  top: 0;
  align-self: flex-start;
  flex: 0 0 var(--rail-width);
  width: var(--rail-width);
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.assortment-rail-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--bg-primary);
  padding: var(--spacing-2) var(--spacing-3);
  border-bottom: 1px solid var(--border-color);
}

.assortment-grid-scroll {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overflow-y: auto;
  overscroll-behavior-x: contain;
}

.assortment-grid-table {
  width: 100%;
  min-width: 720px;
  margin-bottom: 0;
  border-collapse: separate;
  border-spacing: 0;
}

.assortment-grid-table thead th {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--bg-tertiary);
  box-shadow: inset 0 -1px 0 var(--border-color);
}

/* ============================================
   UI-3 - Drag affordances
   The handle is the ONLY drag surface, so selecting text in a row never starts a drag. The
   up/down buttons are the keyboard and touch path and must always be reachable.
   ============================================ */
.drag-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: grab;
  border-radius: var(--radius-sm);
  touch-action: none;
}

.drag-handle:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.drag-handle:active { cursor: grabbing; }

.drag-handle:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.is-dragging {
  opacity: var(--drag-ghost-opacity);
}

/* Drop indicator: a line on the edge the dragged item will land against. */
.drop-target-before {
  box-shadow: inset 0 var(--drop-indicator-width) 0 0 var(--drop-indicator-color);
}

.drop-target-after {
  box-shadow: inset 0 calc(var(--drop-indicator-width) * -1) 0 0 var(--drop-indicator-color);
}

.reorder-buttons {
  display: inline-flex;
  flex-direction: column;
  gap: 1px;
}

.reorder-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 16px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--font-size-xs);
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.reorder-btn:hover:not(:disabled) { color: var(--text-primary); background: var(--bg-tertiary); }
.reorder-btn:disabled { opacity: 0.35; cursor: not-allowed; }

.reorder-btn:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 1px;
}

/* ============================================
   UI-4 - Row density, tabular figures, prices, stock badge
   ============================================ */
.row-density-compact > tbody > tr > td,
.row-density-compact > thead > tr > th {
  height: var(--row-height-compact);
  padding-top: var(--spacing-1);
  padding-bottom: var(--spacing-1);
  vertical-align: middle;
}

/* Any numeric cell: right aligned, tabular figures so columns of money line up. */
.numeric-cell {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  white-space: nowrap;
}

.price-current {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  font-weight: var(--font-weight-semibold);
}

/* A discounted row shows the original struck through and the active price in the danger tone.
   The percentage chip carries the same information in text (UI-10). */
.price-original {
  text-decoration: line-through;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  margin-right: var(--spacing-2);
}

.price-discounted { color: var(--color-danger); }

.discount-chip {
  display: inline-block;
  margin-left: var(--spacing-2);
  padding: 0 var(--spacing-2);
  border-radius: var(--radius-full);
  background: var(--color-danger-bg);
  color: var(--color-danger-dark);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

.stock-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1);
  padding: 2px var(--spacing-2);
  border-radius: var(--radius-full);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

.stock-badge--zero { background: var(--stock-zero-bg); color: var(--stock-zero-text); }
.stock-badge--low  { background: var(--stock-low-bg);  color: var(--stock-low-text); }
.stock-badge--ok   { background: var(--stock-ok-bg);   color: var(--stock-ok-text); }

/* Variant rows sit under their article, indented and marked with a left rule. */
.variant-row > td:first-child {
  padding-left: var(--variant-indent);
  border-left: var(--variant-rule-width) solid var(--border-color-dark);
}

.variant-row > td {
  background: var(--bg-secondary);
  font-size: var(--font-size-sm);
}

/* ============================================
   UI-9 - Responsive
   Under 900px the rail becomes a horizontal chip scroller; the grid drops its optional columns
   (margin, discount, dates) before anything else.
   ============================================ */
.category-chip-scroller {
  display: flex;
  gap: var(--spacing-2);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding: var(--spacing-2) var(--spacing-3);
  scrollbar-width: thin;
}

.category-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-2);
  height: var(--rail-chip-height);
  padding: 0 var(--spacing-4);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full);
  background: var(--bg-primary);
  color: var(--text-primary);
  font-size: var(--font-size-sm);
  white-space: nowrap;
  cursor: pointer;
}

.category-chip.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--text-inverse);
}

.category-chip:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

@media (max-width: 899.98px) {
  /* The rail stops being a column and scrolls sideways instead. */
  .assortment-rail {
    position: static;
    flex: 1 1 auto;
    width: 100%;
    max-height: none;
    overflow-y: visible;
  }

  .assortment-rail.rail-as-chips {
    display: flex;
    gap: var(--spacing-2);
    overflow-x: auto;
    padding: var(--spacing-2) var(--spacing-3);
  }

  .assortment-rail.rail-as-chips .assortment-rail-header { display: none; }

  /* First columns to go: margin, discount and the two discount dates. */
  .col-optional { display: none; }
}

@media (max-width: 599.98px) {
  .col-optional-2 { display: none; }

  .gp-toast-region {
    top: auto;
    bottom: var(--spacing-3);
    left: var(--spacing-3);
    right: var(--spacing-3);
    width: auto;
  }
}

/* Opt-in full-screen modal on small screens. Applied per dialog rather than to every
   .modal-dialog in the portal, so pages outside the sortiment area keep their current layout. */
@media (max-width: 575.98px) {
  .modal-dialog.modal-dialog-mobile-full,
  .modal-dialog.confirm-dialog {
    width: 100%;
    max-width: none;
    height: 100%;
    margin: 0;
  }

  .modal-dialog.modal-dialog-mobile-full .modal-content,
  .modal-dialog.confirm-dialog .modal-content {
    height: 100%;
    border: 0;
    border-radius: 0;
  }

  .modal-dialog.modal-dialog-mobile-full .modal-body,
  .modal-dialog.confirm-dialog .modal-body {
    overflow-y: auto;
  }
}

/* ============================================
   Reduced motion (UI-10)
   ============================================ */
@media (prefers-reduced-motion: reduce) {
  .gp-toast { animation: none; }
}
