@charset "UTF-8";
/* ==========================================================================
  Hanken Grotesk
  --------------------------------------------------------------------------
  Purpose:
  Registers the portal's text face. Both files are variable fonts covering
  weight 100-900, so one file per style replaces the nine static weights a
  family would otherwise need. Licensed under the SIL Open Font License;
  OFL.txt ships next to the font files.

  ovasso.com sets Overused Grotesk. Hanken Grotesk stays until that face is
  confirmed as licensed for the portal: it is the nearest grotesk already
  here, so swapping it later is one token in _theme-overwrites.scss.
  ========================================================================== */
@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("../fonts/hanken-grotesk/HankenGrotesk-VariableFont_wght.ttf") format("truetype-variations");
}
@font-face {
  font-family: "Hanken Grotesk";
  font-style: italic;
  font-display: swap;
  font-weight: 100 900;
  src: url("../fonts/hanken-grotesk/HankenGrotesk-Italic-VariableFont_wght.ttf") format("truetype-variations");
}
/* ==========================================================================
   Primo icon font
   --------------------------------------------------------------------------
   Purpose:
   Registers the custom Primo icon font used by all .primo-* icon classes.
   When updating the icon font files, the codepoints below should be checked
   and updated as well.
   ========================================================================== */
@font-face {
  font-family: "primo-ivons";
  font-style: normal;
  font-display: block;
  font-weight: normal;
  src: url("../fonts/primo-ivons.ttf?dnyf2") format("truetype"), url("../fonts/primo-ivons.woff?dnyf2") format("woff"), url("../fonts/primo-ivons.svg?dnyf2#primo-ivons") format("svg");
}
/* ==========================================================================
   Primo icon base class
   --------------------------------------------------------------------------
   Purpose:
   Applies the custom Primo icon font to the icon classes, primo-icon-*. The
   !important prevents browser extensions or global font rules from replacing the
   icon font. Scoped to primo-icon-, not primo-: the message boxes carry
   primo-dialog, and a wider match set their titles in the icon font, which has
   no letters, so the browser fell back to a serif.
   ========================================================================== */
[class^=primo-icon-],
[class*=" primo-icon-"] {
  font-family: "primo-ivons" !important;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  line-height: 1;
  text-transform: none;
  speak: never;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ==========================================================================
   Primo icon codepoints
   --------------------------------------------------------------------------
   Purpose:
   Maps each Primo icon class to the correct glyph inside the custom icon
   font. These values must stay in sync with the generated icon font files.
   ========================================================================== */
.primo-icon-storage::before {
  content: "\e900";
}

.primo-icon-activity::before {
  content: "\e901";
}

.primo-icon-add::before {
  content: "\e902";
}

.primo-icon-add-time::before {
  content: "\e903";
}

.primo-icon-brand::before {
  content: "\e904";
}

.primo-icon-calendar::before {
  content: "\e905";
}

.primo-icon-category::before {
  content: "\e906";
}

.primo-icon-close::before {
  content: "\e907";
}

.primo-icon-components::before {
  content: "\e908";
}

.primo-icon-confirm::before {
  content: "\e909";
}

.primo-icon-contact::before {
  content: "\e90a";
}

.primo-icon-copy::before {
  content: "\e90b";
}

.primo-icon-customers::before {
  content: "\e90c";
}

.primo-icon-dashboard::before {
  content: "\e90d";
}

.primo-icon-delete::before {
  content: "\e90e";
}

.primo-icon-doc-add::before {
  content: "\e90f";
}

.primo-icon-dropdown::before {
  content: "\e910";
}

.primo-icon-edit::before {
  content: "\e911";
}

.primo-icon-equipment::before {
  content: "\e912";
}

.primo-icon-filter::before {
  content: "\e913";
}

.primo-icon-filter-2::before {
  content: "\e914";
}

.primo-icon-gear::before {
  content: "\e915";
}

.primo-icon-gear-2::before {
  content: "\e916";
}

.primo-icon-gear-2-square::before {
  content: "\e917";
}

.primo-icon-hidemenu::before {
  content: "\e918";
}

.primo-icon-invoice::before {
  content: "\e919";
}

.primo-icon-locationpin::before {
  content: "\e91a";
}

.primo-icon-mail::before {
  content: "\e91b";
}

.primo-icon-messages::before {
  content: "\e91c";
}

.primo-icon-notification::before {
  content: "\e91d";
}

.primo-icon-phone::before {
  content: "\e91e";
}

.primo-icon-product::before {
  content: "\e91f";
}

.primo-icon-production-orders::before {
  content: "\e920";
}

.primo-icon-project-2::before {
  content: "\e921";
}

.primo-icon-purchaseorders::before {
  content: "\e922";
}

.primo-icon-quotation::before {
  content: "\e923";
}

.primo-icon-resource::before {
  content: "\e924";
}

.primo-icon-salesorders::before {
  content: "\e925";
}

.primo-icon-search::before {
  content: "\e926";
}

.primo-icon-shipment::before {
  content: "\e927";
}

.primo-icon-stats::before {
  content: "\e928";
}

.primo-icon-sub-category::before {
  content: "\e929";
}

.primo-icon-suppliers::before {
  content: "\e92a";
}

.primo-icon-support::before {
  content: "\e92b";
}

.primo-icon-textsize::before {
  content: "\e92c";
}

.primo-icon-units::before {
  content: "\e92d";
}

.primo-icon-upload::before {
  content: "\e92e";
}

.primo-icon-view-doc::before {
  content: "\e92f";
}

.primo-icon-warehouse::before {
  content: "\e930";
}

.primo-icon-warning::before {
  content: "\e931";
}

.primo-icon-workorder::before {
  content: "\e932";
}

.primo-icon-work-order-template::before {
  content: "\e933";
}

:root {
  /* Ovasso brand palette, read from the terracotta and warm grey scales of the ovasso.com stylesheet until
     an official brand book arrives. Terracotta is the action colour, its darker steps carry ink on light
     surfaces, warm grey is the page wash. See docs/frontend/design-spec.md section 1. */
  /* Terracotta 700, one step darker than the 600 the site paints its buttons with: white text on 600 is
     3.7:1 and fails AA at label size, on 700 it is 5.2:1. */
  --primo-primary: #a75830;
  --primo-primary-rgb: 167, 88, 48;
  --primo-primary-dark: #874524;
  /* Terracotta 50 from the brand scale: the lightest step of the action colour, for a hover that stays in the
     family instead of borrowing a grey. */
  --primo-primary-50: #faf0eb;
  /* Terracotta is a dark surface, so anything sitting on --primo-primary carries white ink. */
  --primo-primary-fg: #ffffff;
  --primo-accent: #874524;
  --primo-accent-rgb: 135, 69, 36;
  --primo-accent-dark: #663218;
  --primo-secondary: #ece9e3;
  --primo-text-primary: #000000;
  --primo-text-secondary: #7e7e7e;
  /* Bootstrap's .text-primary / .border-primary are ink on white, so they follow the accent rather
     than the action colour; .btn-primary picks up --primo-primary on its own in _buttons.scss. */
  --bs-primary: var(--primo-accent);
  --bs-danger-rgb: rgb(232, 17, 35);
  --dxbl-fl-item-spacing-x: 1.25rem;
  --dxbl-fl-item-spacing-y: 0.35rem;
  --grid-out-of-stock: #ff121273;
  --grid-out-of-stock-hover: #ff1212b8;
  --grid-produce-from-components: #ffa70073;
  --grid-produce-from-components-hover: #ffa700b8;
  --primo-icon-muted: #9c9c9c;
  --primo-icon-muted-dark: #565656;
  --primo-primary-brand: #24241e;
  --primo-icon-accent: #c86b3c;
  --primo-messagebox-btn-primary: var(--primo-primary);
  --primo-messagebox-btn-secondary-text: #343a40;
  --primo-messagebox-btn-secondary-border: #495057;
  /* Shell chrome: the sidebar is the brand black with warm grey labels, and the active item is the
     next warm grey step up with the primary rail on its left edge. */
  --primo-sidebar-bg: #24241e;
  /* White, the same as the icons beside it. A warm grey caption next to a white icon read as two different
     states on a row that only has one; which row is open is said by the rail and the fill, not by dimming
     every other label. */
  --primo-sidebar-label: #ffffff;
  --primo-sidebar-item-active-bg: #3e3d32;
  --primo-status-grey: #b9b9b9;
  --primo-status-success: #25b315;
  --primo-status-success-rgb: 37, 179, 21;
  --primo-status-danger: #c92600;
  --primo-status-warning: #ffa700;
  --primo-status-info: #1560bd;
  --primo-status-dark-blue: #191970;
  --primo-status-yellow: #f6dd29;
  --primo-status-red: #e50000;
  --primo-status-dark-red: #720004;
  --primo-kpi-danger-accent: #e15759;
  --primo-kpi-positive: #28a745;
  --primo-kpi-negative: #dc3545;
  --primo-grid-row-invalid: #e93142;
  /* The rail on a selected grid row. It marks where you are, so it takes the brand terracotta at full
     strength: a rail carries no text, so the contrast that keeps the buttons on 700 does not bind it. */
  --primo-grid-selection: #c86b3c;
  --primo-border: #d6d6d6;
  --primo-border-strong: #8f8f8f;
  --primo-border-muted: #b7b7b7;
  --primo-border-panel: #e4e6eb;
  --primo-border-section: #eceef1;
  --primo-border-faint: #f0f1f3;
  --primo-border-input: #ced4da;
  --primo-surface-muted: #eeeeee;
  --primo-surface-subtle: #f6f5f3;
  --primo-surface-page: #ece9e3;
  --primo-surface-icon-bg: #ececec;
  --primo-text-heading: #2f3437;
  --primo-text-dark: #333333;
  --primo-text-muted: #6c757d;
  --primo-text-subtle: #6f6f6f;
  --primo-popover-text: #303030;
  /* Conditional messages (NoticeBanner): a tinted surface with dark, readable text - the same three
     states everywhere, so a warning in a popup reads the same as a warning on a page. */
  --primo-notice-info-bg: #cff4fc;
  --primo-notice-info-border: #b6effb;
  --primo-notice-info-fg: #055160;
  --primo-notice-warning-bg: #fff3cd;
  --primo-notice-warning-border: #ffecb5;
  --primo-notice-warning-fg: #664d03;
  --primo-notice-error-bg: #f8d7da;
  --primo-notice-error-border: #f5c2c7;
  --primo-notice-error-fg: #842029;
  /* Stock pills on the dealer assortment (design spec §1): orderable = green, low stock = amber (the warning
     triad), not orderable = grey. Surface / border / ink per state. */
  --primo-stock-available-bg: #e4f7e1;
  --primo-stock-available-border: #bfeab8;
  --primo-stock-available-fg: #116a0a;
  --primo-stock-limited-bg: #fff3cd;
  --primo-stock-limited-border: #ffecb5;
  --primo-stock-limited-fg: #664d03;
  --primo-stock-unavailable-bg: #eeeeee;
  --primo-stock-unavailable-border: #d6d6d6;
  --primo-stock-unavailable-fg: #6c757d;
}

/* ==========================================================================
   Fluid container reset
   --------------------------------------------------------------------------
   Purpose:
   Removes default Bootstrap container padding so the page content can align
   flush with the surrounding Primo layout.
   ========================================================================== */
.container-fluid {
  padding: 0 !important;
}

/* ==========================================================================
   Badge base styling
   --------------------------------------------------------------------------
   Purpose:
   Defines compact badge sizing, spacing and border radius for status labels
   and small inline indicators.
   ========================================================================== */
.badge {
  padding: 0.4em 0.65em 0.35em;
  color: inherit;
  font-size: 11px;
  font-weight: 400;
  line-height: 1;
  vertical-align: middle;
  border-radius: 5px;
}

/* ==========================================================================
   Badge color variants
   --------------------------------------------------------------------------
   Purpose:
   Provides Primo-specific badge color variants for primary, secondary,
   success, danger, warning, info, light and dark states.
   ========================================================================== */
.badge-primary {
  color: var(--primo-primary-fg) !important;
  background-color: var(--primo-primary) !important;
}

.badge-secondary {
  color: #000 !important;
  background-color: var(--primo-status-grey) !important;
}

.badge-success {
  color: #fff !important;
  background-color: var(--primo-status-success) !important;
}

.badge-danger {
  color: #fff !important;
  background-color: var(--primo-status-danger) !important;
}

.badge-warning {
  color: #000 !important;
  background-color: var(--primo-status-warning) !important;
}

.badge-info {
  color: #fff !important;
  background-color: var(--primo-status-info) !important;
}

.badge-light {
  color: #000 !important;
  background-color: var(--primo-secondary) !important;
}

.badge-dark {
  color: #fff !important;
  background-color: var(--primo-status-dark-blue) !important;
}

/* ==========================================================================
  Primo theme overwrite variables
  --------------------------------------------------------------------------
  Purpose:
  List of CSS variables that overwrite the default Fluent Theme variables to match
  Primo design. These are defined as CSS variables here because they are used frequently across the application and defining them as CSS variables
  allows for easier maintenance and potential dynamic theming in the future.
  ========================================================================== */
:root {
  --primo-font-family: "Hanken Grotesk", "Helvetica Neue", Arial, sans-serif;
  /* Ovasso sets its headings in the same grotesk as its text, so the display line has no face of its own -
     see docs/frontend/design-spec.md, deviation 1. */
  --primo-font-display: var(--primo-font-family);
}

/* ==========================================================================
   Theme variables overwrite
   --------------------------------------------------------------------------
   Purpose:
   List of theme variables that are overwritten to match Primo design.
   ========================================================================== */
:root {
  --bs-primary-rgb: var(--primo-accent-rgb);
  --dxbl-text-font-family: var(--primo-font-family) !important;
  --dxbl-grid-font-family: var(--primo-font-family) !important;
  --dxds-font-family-sans-serif: var(--primo-font-family) !important;
  --bs-link-color: var(--primo-accent);
  /* Bootstrap 5.3 colours a link from the -rgb variables, so without them the theme's blue stays. */
  --bs-link-color-rgb: var(--primo-accent-rgb);
  --bs-link-hover-color: var(--primo-accent);
  --bs-link-hover-color-rgb: var(--primo-accent-rgb);
  --bs-btn-bg: var(--primo-primary-brand);
  --dxds-color-content-highlight-rest: var(--primo-primary-brand);
}

/* ==========================================================================
  Primo Fluent Grid Layer
  --------------------------------------------------------------------------
  Purpose:
  Adds Primo-specific behavior and layout on top of the DevExpress Fluent
  theme. This file should not replace the Fluent theme; it should be loaded
  after it through ThemeFluentProperties.AddFilePaths(...).
  ========================================================================== */
/* ==========================================================================
   Local CSS variables
   --------------------------------------------------------------------------
   Purpose:
   Centralizes Primo colors and fallbacks used by the grid overrides.
   Existing app variables such as --primo-primary and --primo-secondary are respected.
   ========================================================================== */
:root {
  --primo-grid-primary: var(--primo-accent);
  --primo-grid-secondary: var(--primo-secondary, #f1f1f1);
  --primo-grid-out-of-stock: var(--grid-out-of-stock, #fff3cd);
  --primo-grid-out-of-stock-hover: var(--grid-out-of-stock-hover, #ffe69c);
  --primo-grid-produce-from-components: var(--grid-produce-from-components, #fff3cd);
  --primo-grid-produce-from-components-hover: var(--grid-produce-from-components-hover, #ffe69c);
  --primo-grid-danger: var(--primo-grid-row-invalid);
  --primo-grid-validation-danger: var(--primo-status-danger);
  --primo-grid-detail-border: var(--primo-border-muted);
  --primo-grid-edit-form-padding: 1.25rem;
  --primo-grid-command-button-padding: 5px;
  --primo-grid-header-indent-radius: 20px;
}

/* ==========================================================================
   Old Primo grid visual parity layer
   --------------------------------------------------------------------------
   Purpose:
   Restores the most visible differences between the old Office White based
   Primo grid and the new Fluent grid.
   ========================================================================== */
:root {
  --primo-grid-primary: var(--primo-accent);
  --primo-grid-secondary: var(--primo-secondary, #f1f1f1);
  --primo-grid-header-bg: var(--primo-surface-muted);
  --primo-grid-border: var(--primo-border);
  --primo-grid-border-strong: var(--primo-border-strong);
  --primo-grid-icon-color: var(--primo-icon-accent);
  --primo-grid-text-muted: var(--primo-text-subtle);
}

/* ==========================================================================
   Reusable helpers
   --------------------------------------------------------------------------
   Purpose:
   Keeps repeated border, button and row behavior consistent and easier to
   adjust when DevExpress changes small Fluent details.
   ========================================================================== */
/* ==========================================================================
   Main DxGrid behavior
   --------------------------------------------------------------------------
   Purpose:
   Removes the old heavy theme border, restores row cursor behavior, controls
   table layout, and keeps cell content compact and single-line.
   ========================================================================== */
.dxbl-grid {
  border: none;
}
.dxbl-grid tr td {
  cursor: pointer;
}
.dxbl-grid tr td.dxbl-grid-edit-form {
  cursor: default;
}
.dxbl-grid .dxbl-grid-table {
  border-collapse: collapse;
}
.dxbl-grid .dxbl-grid-table td {
  width: 1rem;
  overflow: hidden;
  white-space: nowrap;
}
.dxbl-grid .dxbl-grid-table th.searchbox-open {
  width: 30rem;
}

/* ==========================================================================
   Grid top panel and search area
   --------------------------------------------------------------------------
   Purpose:
   Restores the Primo full-width toolbar/search layout inside the DxGrid
   top panel.
   ========================================================================== */
.dxbl-grid .dxbl-grid-top-panel {
  border: none;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container {
  width: 100%;
  margin-left: 0;
  padding: 15px 0 0.5rem;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .input-group {
  display: flex;
  align-items: center;
  flex-wrap: nowrap !important;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .input-group i {
  margin-right: 0.5rem;
  font-size: 0.85rem;
  color: var(--primo-text-muted);
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .input-group .grid-search {
  border: none;
  padding-left: 0;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .input-group .grid-search .dxbl-text-edit-input,
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .input-group .grid-search input.form-control,
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .input-group .grid-search input {
  padding-left: 0 !important;
  padding-inline-start: 0 !important;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .grid-button {
  white-space: nowrap;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container .grid-button span:not(.dxbl-image) {
  text-decoration: none;
}
.dxbl-grid .dxbl-grid-top-panel .dxbl-grid-search-box-container ::deep .dbl-text-edit:has(:focus)::after {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* ==========================================================================
   Grid body rows
   --------------------------------------------------------------------------
   Purpose:
   Restores Primo row hover, selection, border and spacing behavior while
   still using Fluent as the base grid style.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table > tbody > tr:hover, .dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-selected-row {
  background-color: var(--primo-grid-secondary);
}
.dxbl-grid .dxbl-grid-table > tbody > tr:hover.workplan-out-of-stock, .dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-selected-row.workplan-out-of-stock {
  background-color: var(--primo-grid-out-of-stock-hover);
}
.dxbl-grid .dxbl-grid-table > tbody > tr:hover.workplan-produce-from-components, .dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-selected-row.workplan-produce-from-components {
  background-color: var(--primo-grid-produce-from-components-hover);
}
.dxbl-grid .dxbl-grid-table > tbody > tr:hover td, .dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-selected-row td {
  color: var(--dxbl-grid-color, #000) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.workplan-out-of-stock {
  background-color: var(--primo-grid-out-of-stock);
}
.dxbl-grid .dxbl-grid-table > tbody > tr.workplan-produce-from-components {
  background-color: var(--primo-grid-produce-from-components);
}
.dxbl-grid .dxbl-grid-table > tbody > tr.invalid-row {
  color: #fff;
  background-color: var(--primo-grid-danger) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr td.invalid-cell {
  box-shadow: inset 0 0 0 2px var(--bs-danger) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr td {
  border-left-width: 0;
  border-bottom-width: 0;
  border-top-width: 1px;
  border-image: none !important;
  border-top-color: var(--primo-grid-secondary);
  border-bottom: 1px solid var(--primo-grid-secondary);
}
.dxbl-grid .dxbl-grid-table > tbody > tr td:first-child {
  position: relative;
  border: none;
  overflow: visible;
  border-top-width: 1px;
  border-top-color: var(--primo-grid-secondary);
  border-bottom: 1px solid var(--primo-grid-secondary);
}
.dxbl-grid .dxbl-grid-table > tbody > tr td:last-child {
  position: relative;
  border: none;
  overflow: visible;
  border-top-width: 1px;
  border-top-color: var(--primo-grid-secondary);
  border-bottom: 1px solid var(--primo-grid-secondary);
}
.dxbl-grid .dxbl-grid-table > tbody > tr td:first-child {
  overflow: hidden;
}
.dxbl-grid .dxbl-grid-table > tbody > tr:nth-last-child(2) td:first-child::before, .dxbl-grid .dxbl-grid-table > tbody > tr:nth-last-child(2) td:last-child::before {
  content: none;
}

/* ==========================================================================
   Focused row that is also selected
   --------------------------------------------------------------------------
   Purpose:
   The block below deliberately skips a selected row, which left the theme's
   full-strength accent for a row that is selected *and* focused. Next to the
   plain row, the hover/focus tint and the selection tint that is a fourth row
   colour in one grid, and the text on it is barely readable. Keep the
   selection tint and let the accent bar carry the focus.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row.dxbl-grid-selected-row {
  background-color: var(--dxbl-grid-selection-bg) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row.dxbl-grid-selected-row > td {
  color: var(--dxbl-grid-color, #000) !important;
  background-color: transparent !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row.dxbl-grid-selected-row > td::before {
  background-color: transparent !important;
  border-color: transparent !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row.dxbl-grid-selected-row > td.dxbl-grid-fixed-cell {
  background-color: var(--dxbl-grid-selection-bg) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row.dxbl-grid-selected-row > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--primo-grid-selection);
}

/* ==========================================================================
   Keyboard focused row
   --------------------------------------------------------------------------
   Purpose:
   Keyboard Up/Down navigation highlights the focused row. The default theme
   accent is far too bright and hides the command-column icons, so tone it down
   to a subtle tint, clear the cell overlay, and mark the row with a thin accent
   bar. Excludes the selected row so an explicit selection keeps its own style.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) {
  background-color: var(--primo-grid-secondary) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) > td {
  color: var(--dxbl-grid-color, #000) !important;
  background-color: transparent !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) > td::before {
  background-color: transparent !important;
  border-color: transparent !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) {
  /* A fixed column is sticky, so the columns it covers scroll underneath it. Clearing the cell
     background above leaves it transparent, and on a horizontally scrolled grid the text of
     those columns then reads straight through the command icons. Repeat the row
     tint here so the sticky cells stay opaque. */
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) > td.dxbl-grid-fixed-cell {
  background-color: var(--primo-grid-secondary) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) {
  /* Gotcha: the grey focus tint above is !important and outranks the plain row status classes,
     so a focused out-of-stock row rendered as an ordinary grey row and read as "in stock"
     (#123056). Repeat the status colours here, in their hover shade so the focus still shows. */
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row).workplan-out-of-stock {
  background-color: var(--primo-grid-out-of-stock-hover) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row).workplan-out-of-stock > td.dxbl-grid-fixed-cell {
  background-color: var(--primo-grid-out-of-stock-hover) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row).workplan-produce-from-components {
  background-color: var(--primo-grid-produce-from-components-hover) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row).workplan-produce-from-components > td.dxbl-grid-fixed-cell {
  background-color: var(--primo-grid-produce-from-components-hover) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) {
  /* The detail expand button does not inherit the cell colour: the theme drives it through
     --dxbl-btn-color, and for a focused row it sets that to the near-white "content on a dark
     surface" token because it assumes the bright accent background we tone down above. On the
     subtle tint that leaves a light-grey chevron on a light-grey row, which reads as missing. */
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) .dxbl-grid-expand-button {
  /* The theme's own focused-row rule carries a higher specificity than this one, so the
     custom properties need !important to stick; the button paints itself with them. */
  --dxbl-btn-color: var(--dxbl-grid-color, #000) !important;
  --dxbl-btn-hover-color: var(--dxbl-grid-color, #000) !important;
  color: var(--dxbl-grid-color, #000) !important;
}
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-selected-row) > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--primo-grid-selection);
}

/* ==========================================================================
   Focused row check box cell
   --------------------------------------------------------------------------
   Purpose:
   A Boolean column renders its cell as a display-view check box that takes its
   border and its tick color from theme variables. On the focused row the theme
   repoints both at its "on surface" colors - white - because its own focused
   row is filled with the accent color. The block above tints that row light
   grey instead, so the resting colors have to be handed back here.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-touch-selection):not(.dxbl-grid-touch-selection-edge) .dxbl-checkbox.dxbl-checkbox-display-view-checked,
.dxbl-grid .dxbl-grid-table > tbody > tr.dxbl-grid-focused-row:not(.dxbl-grid-touch-selection):not(.dxbl-grid-touch-selection-edge) .dxbl-checkbox.dxbl-checkbox-display-view-indeterminate {
  --dxbl-checkbox-primary-checked-check-element-bg: var(--dxds-color-content-primary-compound-rest);
  --dxbl-checkbox-primary-checked-readonly-check-element-border: var(--dxds-color-border-neutral-default-disabled);
}

/* ==========================================================================
   Edit form row
   --------------------------------------------------------------------------
   Purpose:
   Restores the Primo inline edit area: secondary background, generous
   padding and clear validation-message styling.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table > tbody > tr td.dxbl-grid-edit-form {
  padding: var(--primo-grid-edit-form-padding);
  background: var(--primo-grid-secondary);
  border-bottom: 2px solid #fff;
}
.dxbl-grid .dxbl-grid-table > tbody > tr td.dxbl-grid-edit-form::before {
  bottom: -4px;
  width: calc(100% - 2.5rem);
}

/* ==========================================================================
   Inline edit cell alignment
   --------------------------------------------------------------------------
   Purpose:
   A column with TextAlignment="GridTextAlignment.Right" renders its cells as
   td.dxbl-align-right, and DevExpress keeps that class on the cell in inline
   edit mode. Its own auto-generated editor repeats the class on the <input>,
   but an editor supplied through DataColumnCellEditTemplate does not, so its
   text falls back to the left and amounts visibly jump while a row is edited.
   Re-align the editor input for every right-aligned edit cell. Keyed on the
   cell (data-edit-cell), so filter-row editors and left-aligned columns such
   as text and drop-down fields are untouched.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table td[data-edit-cell].dxbl-align-right .dxbl-text-edit-input {
  text-align: end;
}

/* ==========================================================================
   Read-only grid variants
   --------------------------------------------------------------------------
   Purpose:
   Supports popup/embedded read-only grids with constrained dimensions and a
   stronger selected-row style.
   ========================================================================== */
.readonly-grid {
  width: 1000px;
  max-width: 50dvw;
  height: 400px;
  max-height: 50dvh;
  padding: 10px;
}
.readonly-grid .dxbl-grid {
  max-height: 90%;
}

/* ==========================================================================
   Scroll and virtualization helpers
   --------------------------------------------------------------------------
   Purpose:
   Fixes phantom 1px scrolling caused by sub-pixel rounding in non-virtual
   grids and constrains virtual scrolling grids.
   ========================================================================== */
.dxbl-grid:not(.virtual-scrolling-grid):not(.nested-virtual-scrolling-grid) > .dxbl-scroll-viewer > .dxbl-scroll-viewer-content > .dxbl-grid-table {
  contain: paint;
}

.nested-virtual-scrolling-grid {
  max-height: 300px;
}

.virtual-scrolling-grid {
  height: calc(100dvh - 220px);
}

.gridlayout-content:has(.virtual-scrolling-grid) {
  overflow-y: hidden;
}

/* ==========================================================================
   Grid header and filter row
   --------------------------------------------------------------------------
   Purpose:
   The old grid had a clear grey header band. Fluent is much flatter by
   default, so we explicitly restore the old header/filter visual separation.

   Adds a Bootstrap Icons search icon to input editors inside the DevExpress
   Grid filter row, matching the old Primo filter styling.

   Removes borders from filter row editors and adds padding to keep the target cell
   ========================================================================== */
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row {
  background-color: var(--primo-grid-header-bg);
  border-bottom: 0;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row > th,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row > th.dxbl-grid-header,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row > th.dxbl-grid-fixed-cell:not(.dxbl-grid-empty-cell) {
  background-color: var(--primo-grid-header-bg);
  border-color: white;
  color: #000;
  font-weight: 600;
  padding-top: 0.55rem;
  padding-bottom: 0.55rem;
  border-width: 2px;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row > th > .dxbl-grid-header-content > span,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row > th.dxbl-grid-header > .dxbl-grid-header-content > span,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-header-row > th.dxbl-grid-fixed-cell:not(.dxbl-grid-empty-cell) > .dxbl-grid-header-content > span {
  white-space: nowrap;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row {
  background-color: #fff;
  border-bottom: 2px solid var(--primo-grid-border-strong);
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row .filter-type-container > .element-container {
  flex-grow: 1;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-input-editor::after {
  content: "\f3e1" !important;
  color: var(--primo-icon-muted);
  font-family: bootstrap-icons;
  background: transparent !important;
  display: flex;
  align-items: center;
  margin-right: 0.75rem;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-date-time-edit,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-date-edit {
  border: none;
  width: 100%;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-date-time-edit button,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-date-edit button {
  border: none;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-date-time-edit::after,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-date-edit::after {
  display: none !important;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-spinedit {
  border: none;
  width: calc(100% + 15px);
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-spinedit::after {
  display: none !important;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-spinedit {
  /* Decrease padding so the targetted border on the TD is not interrupted by this inputs border */
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row dxbl-spinedit input {
  padding: 0 1.25rem !important;
}
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row > td,
.dxbl-grid .dxbl-grid-table > thead .dxbl-grid-filter-row > th {
  background-color: #fff;
  border-color: white;
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
}

/* ==========================================================================
   Command/action icons
   --------------------------------------------------------------------------
   Purpose:
   The old grid used orange action icons. Fluent text buttons default darker,
   so command buttons are recolored back to Primo orange.
   ========================================================================== */
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary {
  color: var(--primo-grid-icon-color);
  background: transparent;
  border: 0;
  box-shadow: none;
}
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn .dxbl-image,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn i,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn [class^=primo-],
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn [class*=" primo-"],
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text .dxbl-image,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text i,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text [class^=primo-],
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text [class*=" primo-"],
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary .dxbl-image,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary i,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary [class^=primo-],
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary [class*=" primo-"] {
  color: var(--primo-grid-icon-color);
}
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn:hover,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text:hover,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary:hover {
  background-color: var(--primo-primary);
}
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn:hover span.dxbl-image,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text:hover span.dxbl-image,
.dxbl-grid .dxbl-grid-command-cell .dxbl-btn.dxbl-btn-text-primary:hover span.dxbl-image {
  color: var(--primo-primary-fg) !important;
}
.dxbl-grid {
  /* The Small/Large cell padding override in _layout.scss widens
     --dxbl-grid-text-cell-padding-x to 1.25rem, and the Fluent theme derives
     the command button horizontal padding from that same variable. The
     action buttons then outgrow the fixed command column width and the last
     icons wrap onto a hidden second line and disappear. Re-pin a compact
     padding on command cells and forbid wrapping so every action icon stays
     visible at all text sizes. */
}
.dxbl-grid.dxbl-sm .dxbl-grid-command-cell, .dxbl-grid.dxbl-lg .dxbl-grid-command-cell {
  --dxbl-grid-text-cell-padding-x: 0.25rem;
  white-space: nowrap;
}

/* ==========================================================================
   Grid editable status cell
   --------------------------------------------------------------------------
   Purpose:
   Updates the cursor for editable status cells to indicate they are clickable and editable,
   while keeping non-editable status cells with the default cursor.
   This is important for user experience, as it provides a visual cue that the status can be interacted with and changed, which is especially relevant if the status cell uses a custom template that may not have other obvious interactive elements.
   ========================================================================== */
.grid-cell-editable {
  cursor: text !important;
}

/* ==========================================================================
   Inline grid action icon
   --------------------------------------------------------------------------
   Purpose:
   Keeps inline action icons compact, clickable and aligned inside grid cells.
   ========================================================================== */
.grid-inline-action {
  display: inline-flex;
  height: 1.2rem;
  padding: 0 5px;
  margin: 0;
  cursor: pointer !important;
}

/* ==========================================================================
   Grid edited/interactive cell states
   --------------------------------------------------------------------------
   Purpose:
   Highlights modified grid cells and applies pointer cursors to editable
   grid cells.
   ========================================================================== */
.grid-modified-cell {
  background-color: rgba(var(--bs-primary-rgb), 0.15) !important;
}

.grid-cell-editable {
  cursor: pointer !important;
}

/* ==========================================================================
   Grid cell link
   --------------------------------------------------------------------------
   Purpose:
   Provides link-style visual feedback for clickable cell content that
   navigates to a detail page. Shows underline on hover and pointer cursor.
   ========================================================================== */
.grid-cell-link {
  display: block;
  width: 100%;
  height: 100%;
  margin: -0.5rem;
  padding: 0.5rem;
  color: var(--bs-primary);
  text-decoration: none;
  cursor: pointer;
}
.grid-cell-link:hover {
  text-decoration: underline;
  color: var(--bs-primary);
}

/* ==========================================================================
   Grid empty cell fix
   --------------------------------------------------------------------------
   Purpose:
   Sets the empty cells width to 0 to prevent them from taking space.
   Without this fix there would be a row which can't be interacted with and serves no purpose
   ========================================================================== */
.dxbl-grid-empty-cell {
  width: 0 !important;
}

/* ==========================================================================
   Greyed-out grid styling
   --------------------------------------------------------------------------
   Purpose:
   Gives a grid the same background as the grid header and visually greys out
   the body cells. This is useful for grids that should remain visible but look
   inactive, disabled, or read-only.
   ========================================================================== */
.dxbl-grid.greyed-out .dxbl-grid-table {
  background-color: var(--primo-grid-header-bg);
  border-collapse: separate;
}
.dxbl-grid.greyed-out .dxbl-grid-table .dxbl-grid-header {
  border: none;
  border-radius: 0 !important;
}
.dxbl-grid.greyed-out .dxbl-grid-table tbody {
  background-color: var(--primo-grid-header-bg);
}
.dxbl-grid.greyed-out .dxbl-grid-table tbody td {
  background-color: var(--primo-secondary) !important;
  border-radius: 0 !important;
}

/* ==========================================================================
   Grid detail cell
   --------------------------------------------------------------------------
   Purpose:
   Adds a dashed left border and compact padding to detail/expand rows.
   ========================================================================== */
.dxbl-grid .dxbl-grid-table .dxbl-grid-detail-cell {
  padding: 4px 16px;
  border-left: 2px dashed #b7b7b7;
}

/* ==========================================================================
   Grid toolbar dropdown — active option
   --------------------------------------------------------------------------
   Purpose:
   Makes the currently selected option in the grid toolbar submenus
   (text size, edit mode, virtual scrolling) clearly stand out — bold and
   in the Primo brand color, instead of relying on the check icon alone.
   ========================================================================== */
.grid-buttongroup-button.active {
  font-weight: 600 !important;
  color: var(--primo-grid-primary) !important;
}
.grid-buttongroup-button.active .dxbl-image,
.grid-buttongroup-button.active i {
  color: var(--primo-grid-primary) !important;
}

/* ==========================================================================
   Options menu — on/off toggles
   --------------------------------------------------------------------------
   Purpose:
   The on/off options in the Gantt and swimlane view-options menus carry their
   state in the toggle icon alone (the item text stays unhighlighted), so the
   icon itself is colored: brand color when on, muted when off. Only the icons
   marked with these classes represent state - a plain `bi-toggle-*` icon on an
   either/or option (Show / Hide) is decorative and stays neutral.
   ========================================================================== */
.grid-buttongroup-button .option-toggle-on {
  color: var(--primo-grid-primary) !important;
}
.grid-buttongroup-button .option-toggle-off {
  color: var(--primo-grid-text-muted) !important;
}

/* ==========================================================================
   Grid panel
   --------------------------------------------------------------------------
   Purpose:
   An overview carries no frame: on a white page the head tint and the row lines
   are enough to hold it together, and a box around it only added a line that
   nothing else on the screen repeats.
   ========================================================================== */
.dxbl-grid {
  border: 0;
  border-radius: 0;
  background-color: #fff;
}

/* The row of page actions above an overview sits off the panel rather than on its edge. */
.container-fluid > .row + .row {
  margin-top: 0.75rem;
}

/* The search box lives inside the panel, so its icon takes the panel's own inset instead of starting on
   the border. */
.input-group > .primo-icon-search {
  margin-left: 0.75rem;
}

/* ==========================================================================
  Header navigation
  --------------------------------------------------------------------------
  Purpose:
  Removes extra padding from the DevExpress menu title and keeps the header
  menu items aligned to the right in a single horizontal row.
  ========================================================================== */
.header-navbar.dxbl-menu-horizontal .dxbl-menu-title {
  padding: 0;
}
.header-navbar .dxbl-menu-item-list {
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-end;
}

/* The running language in the header's language drop-down. Global rather than scoped to the header: DevExpress
   renders the drop-down in a popup outside the header's markup, where its scoped styles never reach. */
.header-language-active button {
  font-weight: 600;
}

/* The flag in front of each language, at the 4:3 of the flag files rather than their own 640 x 480; the hairline
   keeps a white field (France) from running into the menu's background. */
.header-language-option .dxbl-image {
  width: 1.333em;
  height: 1em;
  object-fit: cover;
  border-radius: 2px;
  box-shadow: 0 0 0 1px var(--primo-border);
}

/* ==========================================================================
   Main grid layout
   --------------------------------------------------------------------------
   Purpose:
   Ensures the main DevExpress GridLayout fills the available page height while
   preserving the desired horizontal spacing between grid columns.
   Additionally, it hides horizontal overflow on grid layout items to prevent
   unwanted horizontal scrollbars when content exceeds the available width, while
   preserving vertical scrolling for content that exceeds the available height.
   ========================================================================== */
.main-grid {
  /* Scope overflow handling to the content area only. Targeting every grid item (the bare
     .dxbl-gridlayout-item) also clipped the sidebar and header, cutting off the navigation menu. */
}
.main-grid .dxbl-gridlayout-item.content-layout-item {
  overflow-x: hidden;
  overflow-y: auto;
}
.main-grid .dx-gridlayout-root {
  height: auto;
  min-height: 100%;
  grid-column-gap: 1.25rem !important;
}

/* ==========================================================================
   Nested DevExpress FormLayout groups
   --------------------------------------------------------------------------
   Purpose:
   Adjusts nested form layout groups so they look cleaner inside edit/detail
   forms: fixed label width, hidden nested group headers, compact dropdown/edit
   buttons, and Primo primary coloring for editor icons.
   ========================================================================== */
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col label {
  min-width: 190px;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col {
  margin-top: 0;
  margin-bottom: 0;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-group-header {
  display: none;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col svg .dxbl-image {
  color: red;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit > .dxbl-btn > svg.dxbl-image,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit > .dxbl-btn-group > .dxbl-btn > svg.dxbl-image,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit > .dxbl-btn-group-vertical > .dxbl-btn.dxbl-btn > svg.dxbl-image {
  opacity: 1;
  color: var(--primo-accent);
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit > .dxbl-btn > svg.dxbl-image,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit > .dxbl-btn-group > .dxbl-btn:not(.dxbl-edit-btn-dropdown, .dxbl-btn-outline-secondary) > svg.dxbl-image,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit > .dxbl-btn-group-vertical > .dxbl-btn.dxbl-btn:not(.dxbl-edit-btn-dropdown, .dxbl-btn-outline-secondary) > svg.dxbl-image {
  color: var(--primo-primary-fg);
  background-color: var(--primo-primary);
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit.dxbl-disabled > .dxbl-btn-group-vertical > .dxbl-btn,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-text-edit.dxbl-disabled > .dxbl-btn-group-right > .dxbl-btn {
  display: none;
}

/* ==========================================================================
   DevExpress tabs
   --------------------------------------------------------------------------
   Purpose:
   Keeps the active tab aligned with the Primo visual style: active text
   inherits the current theme color and uses a slightly stronger font weight.
   ========================================================================== */
.dxbl-tabs > .dxbl-scroll-viewer > .dxbl-scroll-viewer-content > ul > li > .dxbl-tabs-item:not(.dxbl-tabs-tmpl):not(.dxbl-disabled):not(:disabled).dxbl-active {
  font-weight: 600;
}
.dxbl-tabs > .dxbl-scroll-viewer > .dxbl-scroll-viewer-content > ul > li > .dxbl-tabs-item:not(.dxbl-tabs-tmpl):not(.dxbl-disabled):not(:disabled).dxbl-active .dxbl-text {
  color: inherit;
}
.dxbl-tabs > ul > li > .dxbl-tabs-item:not(.dxbl-tabs-tmpl):not(.dxbl-disabled):not(:disabled).dxbl-active {
  font-weight: 600;
}
.dxbl-tabs > ul > li > .dxbl-tabs-item:not(.dxbl-tabs-tmpl):not(.dxbl-disabled):not(:disabled).dxbl-active .dxbl-text {
  color: inherit;
}

/* ==========================================================================
   Detail page tab and action bar
   --------------------------------------------------------------------------
   Purpose:
   Lets the action buttons drop below the tabs once the row runs out of room,
   instead of overflowing the page. The tabs themselves wrap first, so this
   only kicks in on narrow screens or tab rows with many buttons.
   ========================================================================== */
/* A plain tab bar: one hairline under the row, with the page's own action sitting at its right end. Nothing
   is framed on this page, so the tabs are not a lid on a box either. */
.tabs-container {
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  padding: 0 0 0.15rem;
  border-bottom: 1px solid var(--primo-border-section);
  background-color: #fff;
}

/* ==========================================================================
   DevExpress grid size variants
   --------------------------------------------------------------------------
   Purpose:
   Overrides DevExpress grid cell padding for small and large grid variants so
   both sizes keep the same Primo spacing.
   ========================================================================== */
.dxbl-grid.dxbl-sm, .dxbl-grid.dxbl-lg {
  --dxbl-grid-text-cell-padding-x: 1.25rem;
  --dxbl-grid-text-cell-padding-y: 0.5rem;
}

/* ==========================================================================
   Disabled editor buttons
   --------------------------------------------------------------------------
   Purpose:
   Hides disabled custom editor buttons inside text editor button groups, while
   keeping clear buttons and icon-only buttons visible.
   ========================================================================== */
.dxbl-text-edit > .dxbl-btn-group > .dxbl-btn:not(.dxbl-btn.dxbl-edit-btn-clear, .dxbl-btn.dxbl-btn-icon).dxbl-disabled, .dxbl-text-edit > .dxbl-btn-group > .dxbl-btn:not(.dxbl-btn.dxbl-edit-btn-clear, .dxbl-btn.dxbl-btn-icon):disabled {
  display: none;
}

/* ==========================================================================
   GridLayout row spacing
   --------------------------------------------------------------------------
   Purpose:
   Adds a fixed 10px vertical gap between rows in DevExpress GridLayout
   instances that opt in with the grid-layout-row-gap-10 class.
   ========================================================================== */
.grid-layout-row-gap-10 dxbl-grid-layout-root {
  row-gap: 10px;
}

/* ==========================================================================
  Bootstrap primary button background
  --------------------------------------------------------------------------
  Purpose:
  Overrides Bootstrap's primary button background variable. This affects
  buttons such as <button class="btn btn-primary">...</button>.
  ========================================================================== */
.btn.btn-primary {
  --bs-btn-bg: var(--primo-primary);
  --bs-btn-border-color: var(--primo-primary);
  --bs-btn-color: var(--primo-primary-fg);
  --bs-btn-hover-color: var(--primo-primary-fg);
  --bs-btn-active-color: var(--primo-primary-fg);
  --bs-btn-hover-bg: var(--primo-primary-dark);
  --bs-btn-hover-border-color: var(--primo-primary-dark);
  --bs-btn-active-bg: var(--primo-primary-dark);
  --bs-btn-active-border-color: var(--primo-primary-dark);
}

/* ==========================================================================
   DevExpress primary button
   --------------------------------------------------------------------------
   Purpose:
   The primary action is the brand terracotta with white ink (design spec
   section 1). The DevExpress theme accent stays the colour set in App.razor,
   because that accent also drives selection, focus and active states, which the
   spec assigns to the accent rather than to the action colour - so only the
   primary button is repainted here.
   ========================================================================== */
.dxbl-btn.dxbl-btn-primary {
  --dxbl-btn-bg: var(--primo-primary);
  --dxbl-btn-primary-bg: var(--primo-primary);
  --dxbl-btn-border-color: var(--primo-primary);
  --dxbl-btn-color: var(--primo-primary-fg);
  --dxbl-btn-primary-color: var(--primo-primary-fg);
  --dxbl-btn-hover-bg: var(--primo-primary-dark);
  --dxbl-btn-hover-border-color: var(--primo-primary-dark);
  --dxbl-btn-hover-color: var(--primo-primary-fg);
  --dxbl-btn-active-bg: var(--primo-primary-dark);
  --dxbl-btn-active-border-color: var(--primo-primary-dark);
  --dxbl-btn-active-color: var(--primo-primary-fg);
  color: var(--primo-primary-fg);
}
.dxbl-btn.dxbl-btn-primary.dxbl-disabled, .dxbl-btn.dxbl-btn-primary:disabled {
  --dxbl-btn-bg: var(--primo-surface-muted);
  --dxbl-btn-border-color: var(--primo-surface-muted);
  --dxbl-btn-color: var(--primo-text-muted);
  color: var(--primo-text-muted);
  opacity: 1;
}

/* ==========================================================================
   Standalone text-primary button color
   --------------------------------------------------------------------------
   Purpose:
   Applies the Primo accent colour to standalone DevExpress text-primary
   buttons, such as icon/action buttons that are not part of a button group.
   ========================================================================== */
.dxbl-btn.dxbl-btn-text-primary.dxbl-btn-standalone {
  color: var(--primo-accent);
}

/* ==========================================================================
   Main button sizing
   --------------------------------------------------------------------------
   Purpose:
   Normalizes the height and padding for primary, secondary and outline
   Secondary DevExpress buttons so normal buttons visually match split buttons.
   Split buttons are left with smaller padding to accommodate the dropdown arrow without increasing the overall button size.

   Excluded:
   Form field buttons such as dropdown or the clear button
   ========================================================================== */
.dxbl-btn.dxbl-btn-primary:not(.dxbl-edit-btn-dropdown):not(.dxbl-edit-btn-clear):not(.dxbl-spin-btn-inc):not(.dxbl-spin-btn-dec), .dxbl-btn.dxbl-btn-secondary:not(.dxbl-edit-btn-dropdown):not(.dxbl-edit-btn-clear):not(.dxbl-spin-btn-inc):not(.dxbl-spin-btn-dec), .dxbl-btn.dxbl-btn-outline-secondary:not(.dxbl-edit-btn-dropdown):not(.dxbl-edit-btn-clear):not(.dxbl-spin-btn-inc):not(.dxbl-spin-btn-dec) {
  height: 2.65em;
  padding: 1rem;
  white-space: nowrap;
}
.dxbl-btn.dxbl-btn-split-dropdown {
  padding: 0.5rem;
}

/* ==========================================================================
   Secondary button styling
   --------------------------------------------------------------------------
   Purpose:
   Keeps secondary DevExpress buttons flat and neutral: black border, no shadow,
   and white background when active.
   ========================================================================== */
.dxbl-btn.dxbl-btn-secondary {
  --dxbl-btn-border-color: black;
  --dxbl-btn-hover-border-color: black;
  --dxbl-btn-active-bg: #ffffff;
  box-shadow: none;
}

/* ==========================================================================
   Link button underline spacing
   --------------------------------------------------------------------------
   Purpose:
   Improves readability for DevExpress link-style buttons by adding a small
   offset between the text and underline.
   ========================================================================== */
.dxbl-btn.dxbl-btn-link span:not(.dxbl-image), .dxbl-btn.dxbl-btn-outline-link span:not(.dxbl-image), .dxbl-btn.dxbl-btn-text-link span:not(.dxbl-image) {
  text-underline-offset: 2px;
}

/* ==========================================================================
   DevExpress SplitButton dropdown menu
   --------------------------------------------------------------------------
   Purpose:
   Makes SplitButton dropdown menu text darker and removes the large empty
   space around a small menu item list.
   ========================================================================== */
.dxbl-dropdown .dxbl-listbox,
.dxbl-dropdown .dxbl-menu,
.dxbl-dropdown .dxbl-menu-item-list,
.dxbl-popup .dxbl-listbox,
.dxbl-popup .dxbl-menu,
.dxbl-popup .dxbl-menu-item-list {
  min-width: max-content;
  width: max-content;
}
.dxbl-dropdown .dxbl-listbox-item,
.dxbl-dropdown .dxbl-menu-item,
.dxbl-popup .dxbl-listbox-item,
.dxbl-popup .dxbl-menu-item {
  min-height: 32px;
  padding: 6px 14px;
  color: #000;
}
.dxbl-dropdown .dxbl-listbox-item .dxbl-text,
.dxbl-dropdown .dxbl-menu-item .dxbl-text,
.dxbl-popup .dxbl-listbox-item .dxbl-text,
.dxbl-popup .dxbl-menu-item .dxbl-text {
  color: #000;
}

/* ==========================================================================
   DevExpress dropdown minimum width
   --------------------------------------------------------------------------
   Purpose:
   Sets a reasonable minimum width for DevExpress dropdowns sub buttons,
   ensure they have less unused space.
   ========================================================================== */
.dxbl-dropdown > .dxbl-dropdown-dialog,
.dxbl-itemlist-dropdown > .dxbl-dropdown-dialog {
  --dxbl-dropdown-min-width: 10rem;
}

/* ==========================================================================
   DevExpress SplitButton dropdown popup content
   --------------------------------------------------------------------------
   Purpose:
   Reduces unnecessary white space inside the popup/dropdown container itself.
   ========================================================================== */
.dxbl-popup-content,
.dxbl-dropdown-body,
.dxbl-dropdown-content {
  padding: 0;
}
.dxbl-popup-content .dxbl-listbox,
.dxbl-popup-content .dxbl-menu,
.dxbl-dropdown-body .dxbl-listbox,
.dxbl-dropdown-body .dxbl-menu,
.dxbl-dropdown-content .dxbl-listbox,
.dxbl-dropdown-content .dxbl-menu {
  margin: 0;
  padding: 0;
}

/* ==========================================================================
   Dropdown item contrast
   --------------------------------------------------------------------------
   Purpose:
   The theme draws a dropdown item in a grey that sits at roughly 2:1 on white,
   and fades a disabled one further still. Both are brought back to readable
   ink; a disabled item is told apart by the cursor and by not responding, not
   by being too pale to read.
   ========================================================================== */
.dxbl-listbox-item,
.dxbl-menu-item {
  --dxbl-listbox-item-color: var(--primo-text-heading);
  --dxbl-menu-item-color: var(--primo-text-heading);
  color: var(--primo-text-heading) !important;
}
.dxbl-listbox-item .dxbl-text,
.dxbl-menu-item .dxbl-text {
  color: var(--primo-text-heading) !important;
}
.dxbl-listbox-item.dxbl-disabled, .dxbl-listbox-item:disabled,
.dxbl-menu-item.dxbl-disabled,
.dxbl-menu-item:disabled {
  opacity: 1;
  color: var(--primo-text-muted) !important;
}
.dxbl-listbox-item.dxbl-disabled .dxbl-text, .dxbl-listbox-item:disabled .dxbl-text,
.dxbl-menu-item.dxbl-disabled .dxbl-text,
.dxbl-menu-item:disabled .dxbl-text {
  color: var(--primo-text-muted) !important;
  opacity: 1;
}

/* ==========================================================================
  Disabled form field behavior
  --------------------------------------------------------------------------
  Purpose:
  Keeps all disabled DevExpress form fields readable and clearly non-editable.
  This removes the faded disabled look, keeps text black, and applies a
  not-allowed cursor to text boxes, dropdowns, combo boxes, date edits,
  spin edits, memo fields, tag boxes and checkboxes.
  ========================================================================== */
.dxbl-fl .dxbl-text-edit.dxbl-disabled, .dxbl-fl .dxbl-text-edit:disabled,
.dxbl-fl .dxbl-combobox.dxbl-disabled,
.dxbl-fl .dxbl-combobox:disabled,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled,
.dxbl-fl .dxbl-dropdown-box:disabled,
.dxbl-fl .dxbl-date-edit.dxbl-disabled,
.dxbl-fl .dxbl-date-edit:disabled,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled,
.dxbl-fl .dxbl-date-time-edit:disabled,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled,
.dxbl-fl .dxbl-spin-edit:disabled,
.dxbl-fl .dxbl-memo.dxbl-disabled,
.dxbl-fl .dxbl-memo:disabled,
.dxbl-fl .dxbl-tag-box.dxbl-disabled,
.dxbl-fl .dxbl-tag-box:disabled,
.dxbl-fl .dxbl-checkbox.dxbl-disabled,
.dxbl-fl .dxbl-checkbox:disabled {
  --dxbl-text-edit-disabled-opacity: 1;
  --dxbl-disabled-opacity: 1;
  color: #000;
  cursor: not-allowed;
  opacity: 1;
}
.dxbl-fl .dxbl-text-edit.dxbl-disabled *, .dxbl-fl .dxbl-text-edit:disabled *,
.dxbl-fl .dxbl-combobox.dxbl-disabled *,
.dxbl-fl .dxbl-combobox:disabled *,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled *,
.dxbl-fl .dxbl-dropdown-box:disabled *,
.dxbl-fl .dxbl-date-edit.dxbl-disabled *,
.dxbl-fl .dxbl-date-edit:disabled *,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled *,
.dxbl-fl .dxbl-date-time-edit:disabled *,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled *,
.dxbl-fl .dxbl-spin-edit:disabled *,
.dxbl-fl .dxbl-memo.dxbl-disabled *,
.dxbl-fl .dxbl-memo:disabled *,
.dxbl-fl .dxbl-tag-box.dxbl-disabled *,
.dxbl-fl .dxbl-tag-box:disabled *,
.dxbl-fl .dxbl-checkbox.dxbl-disabled *,
.dxbl-fl .dxbl-checkbox:disabled * {
  color: #000;
  cursor: not-allowed;
  opacity: 1;
}
.dxbl-fl .dxbl-text-edit.dxbl-disabled input,
.dxbl-fl .dxbl-text-edit.dxbl-disabled textarea,
.dxbl-fl .dxbl-text-edit.dxbl-disabled button,
.dxbl-fl .dxbl-text-edit.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-text-edit.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-text-edit.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-text-edit.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-text-edit.dxbl-disabled .dxbl-image, .dxbl-fl .dxbl-text-edit:disabled input,
.dxbl-fl .dxbl-text-edit:disabled textarea,
.dxbl-fl .dxbl-text-edit:disabled button,
.dxbl-fl .dxbl-text-edit:disabled .dxbl-text,
.dxbl-fl .dxbl-text-edit:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-text-edit:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-text-edit:disabled .dxbl-btn,
.dxbl-fl .dxbl-text-edit:disabled .dxbl-image,
.dxbl-fl .dxbl-combobox.dxbl-disabled input,
.dxbl-fl .dxbl-combobox.dxbl-disabled textarea,
.dxbl-fl .dxbl-combobox.dxbl-disabled button,
.dxbl-fl .dxbl-combobox.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-combobox.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-combobox.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-combobox.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-combobox.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-combobox:disabled input,
.dxbl-fl .dxbl-combobox:disabled textarea,
.dxbl-fl .dxbl-combobox:disabled button,
.dxbl-fl .dxbl-combobox:disabled .dxbl-text,
.dxbl-fl .dxbl-combobox:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-combobox:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-combobox:disabled .dxbl-btn,
.dxbl-fl .dxbl-combobox:disabled .dxbl-image,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled input,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled textarea,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled button,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-dropdown-box:disabled input,
.dxbl-fl .dxbl-dropdown-box:disabled textarea,
.dxbl-fl .dxbl-dropdown-box:disabled button,
.dxbl-fl .dxbl-dropdown-box:disabled .dxbl-text,
.dxbl-fl .dxbl-dropdown-box:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-dropdown-box:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-dropdown-box:disabled .dxbl-btn,
.dxbl-fl .dxbl-dropdown-box:disabled .dxbl-image,
.dxbl-fl .dxbl-date-edit.dxbl-disabled input,
.dxbl-fl .dxbl-date-edit.dxbl-disabled textarea,
.dxbl-fl .dxbl-date-edit.dxbl-disabled button,
.dxbl-fl .dxbl-date-edit.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-date-edit.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-date-edit.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-date-edit.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-date-edit.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-date-edit:disabled input,
.dxbl-fl .dxbl-date-edit:disabled textarea,
.dxbl-fl .dxbl-date-edit:disabled button,
.dxbl-fl .dxbl-date-edit:disabled .dxbl-text,
.dxbl-fl .dxbl-date-edit:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-date-edit:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-date-edit:disabled .dxbl-btn,
.dxbl-fl .dxbl-date-edit:disabled .dxbl-image,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled input,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled textarea,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled button,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-date-time-edit:disabled input,
.dxbl-fl .dxbl-date-time-edit:disabled textarea,
.dxbl-fl .dxbl-date-time-edit:disabled button,
.dxbl-fl .dxbl-date-time-edit:disabled .dxbl-text,
.dxbl-fl .dxbl-date-time-edit:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-date-time-edit:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-date-time-edit:disabled .dxbl-btn,
.dxbl-fl .dxbl-date-time-edit:disabled .dxbl-image,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled input,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled textarea,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled button,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-spin-edit:disabled input,
.dxbl-fl .dxbl-spin-edit:disabled textarea,
.dxbl-fl .dxbl-spin-edit:disabled button,
.dxbl-fl .dxbl-spin-edit:disabled .dxbl-text,
.dxbl-fl .dxbl-spin-edit:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-spin-edit:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-spin-edit:disabled .dxbl-btn,
.dxbl-fl .dxbl-spin-edit:disabled .dxbl-image,
.dxbl-fl .dxbl-memo.dxbl-disabled input,
.dxbl-fl .dxbl-memo.dxbl-disabled textarea,
.dxbl-fl .dxbl-memo.dxbl-disabled button,
.dxbl-fl .dxbl-memo.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-memo.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-memo.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-memo.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-memo.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-memo:disabled input,
.dxbl-fl .dxbl-memo:disabled textarea,
.dxbl-fl .dxbl-memo:disabled button,
.dxbl-fl .dxbl-memo:disabled .dxbl-text,
.dxbl-fl .dxbl-memo:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-memo:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-memo:disabled .dxbl-btn,
.dxbl-fl .dxbl-memo:disabled .dxbl-image,
.dxbl-fl .dxbl-tag-box.dxbl-disabled input,
.dxbl-fl .dxbl-tag-box.dxbl-disabled textarea,
.dxbl-fl .dxbl-tag-box.dxbl-disabled button,
.dxbl-fl .dxbl-tag-box.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-tag-box.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-tag-box.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-tag-box.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-tag-box.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-tag-box:disabled input,
.dxbl-fl .dxbl-tag-box:disabled textarea,
.dxbl-fl .dxbl-tag-box:disabled button,
.dxbl-fl .dxbl-tag-box:disabled .dxbl-text,
.dxbl-fl .dxbl-tag-box:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-tag-box:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-tag-box:disabled .dxbl-btn,
.dxbl-fl .dxbl-tag-box:disabled .dxbl-image,
.dxbl-fl .dxbl-checkbox.dxbl-disabled input,
.dxbl-fl .dxbl-checkbox.dxbl-disabled textarea,
.dxbl-fl .dxbl-checkbox.dxbl-disabled button,
.dxbl-fl .dxbl-checkbox.dxbl-disabled .dxbl-text,
.dxbl-fl .dxbl-checkbox.dxbl-disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-checkbox.dxbl-disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-checkbox.dxbl-disabled .dxbl-btn,
.dxbl-fl .dxbl-checkbox.dxbl-disabled .dxbl-image,
.dxbl-fl .dxbl-checkbox:disabled input,
.dxbl-fl .dxbl-checkbox:disabled textarea,
.dxbl-fl .dxbl-checkbox:disabled button,
.dxbl-fl .dxbl-checkbox:disabled .dxbl-text,
.dxbl-fl .dxbl-checkbox:disabled .dxbl-text-edit-input,
.dxbl-fl .dxbl-checkbox:disabled .dxbl-text-edit-template,
.dxbl-fl .dxbl-checkbox:disabled .dxbl-btn,
.dxbl-fl .dxbl-checkbox:disabled .dxbl-image {
  color: #000;
  cursor: not-allowed;
  opacity: 1;
}
.dxbl-fl .dxbl-text-edit.dxbl-disabled svg, .dxbl-fl .dxbl-text-edit:disabled svg,
.dxbl-fl .dxbl-combobox.dxbl-disabled svg,
.dxbl-fl .dxbl-combobox:disabled svg,
.dxbl-fl .dxbl-dropdown-box.dxbl-disabled svg,
.dxbl-fl .dxbl-dropdown-box:disabled svg,
.dxbl-fl .dxbl-date-edit.dxbl-disabled svg,
.dxbl-fl .dxbl-date-edit:disabled svg,
.dxbl-fl .dxbl-date-time-edit.dxbl-disabled svg,
.dxbl-fl .dxbl-date-time-edit:disabled svg,
.dxbl-fl .dxbl-spin-edit.dxbl-disabled svg,
.dxbl-fl .dxbl-spin-edit:disabled svg,
.dxbl-fl .dxbl-memo.dxbl-disabled svg,
.dxbl-fl .dxbl-memo:disabled svg,
.dxbl-fl .dxbl-tag-box.dxbl-disabled svg,
.dxbl-fl .dxbl-tag-box:disabled svg,
.dxbl-fl .dxbl-checkbox.dxbl-disabled svg,
.dxbl-fl .dxbl-checkbox:disabled svg {
  color: var(--primo-icon-muted);
  fill: var(--primo-icon-muted);
}

/* ==========================================================================
   DevExpress group headers and bodies
   --------------------------------------------------------------------------
   Purpose:
   Makes group headers more compact and bold, and reduces group body padding
   for denser Primo form layouts.
   ========================================================================== */
.dxbl-group > .dxbl-group-header {
  padding: 4px 8px 0;
}
.dxbl-group > .dxbl-group-header > .dxbl-text {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5rem;
  margin-top: 0.5rem;
  margin-left: 0.65rem;
}

.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body > .dxbl-group-body-content {
  padding: 8px 15px;
}

/* ==========================================================================
   FormLayout group spacing
   --------------------------------------------------------------------------
   Purpose:
   Reduces the default vertical spacing between FormLayout groups for a denser
   Primo form layout.
   ========================================================================== */
.dxbl-fl .dxbl-fl-gd,
.dxbl-fl .dxbl-fl-gt {
  margin-bottom: calc(var(--dxbl-fl-group-spacing-y) * 0.1);
}

/* ==========================================================================
   Checkbox alignment
   --------------------------------------------------------------------------
   Purpose:
   Vertically centers DevExpress checkbox content.
   ========================================================================== */
.dxbl-checkbox {
  padding-left: 0;
  align-items: center;
}
.dxbl-checkbox > .dxbl-checkbox-check-element {
  width: 1.125rem;
  height: 1.125rem;
}
.dxbl-checkbox.dxbl-checkbox-unchecked > .dxbl-checkbox-check-element {
  background: white;
  border: 2px solid rgba(118, 118, 118, 0.3);
}
.dxbl-checkbox.dxbl-checkbox-checked.dxbl-readonly > .dxbl-checkbox-check-element {
  background: white;
  border: 2px solid rgba(118, 118, 118, 0.3);
}
.dxbl-checkbox.dxbl-checkbox-checked.dxbl-disabled > .dxbl-checkbox-check-element {
  background-color: black;
  opacity: 0.3;
}

/* ==========================================================================
   FormLayout captions
   --------------------------------------------------------------------------
   Purpose:
   Adds a small top margin to columns and gives form captions a medium font
   weight with compact vertical padding.
   ========================================================================== */
.dxbl-col {
  margin-top: 0.5rem;
}

.dxbl-fl:not(.dxbl-fl-calc) .dxbl-fl-item > .dxbl-fl-cpt {
  padding: 1px 0;
  font-weight: 500;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col label {
  padding: 1px 0;
  font-weight: 500;
}

/* ==========================================================================
   Grid edit form caption clipping (Large text size)
   --------------------------------------------------------------------------
   Purpose:
   Prevents form captions from being clipped at the top inside grid edit forms.
   The DevExpress FormLayout (.dxbl-fl) sets overflow:hidden. Its first .dxbl-row
   uses a fixed negative top margin (in px) to offset the row gutter, but our
   .dxbl-col top margin is rem-based (see "FormLayout captions" above), so it
   scales down with the Large text size and no longer fully cancels that pull.
   The first caption row then sits above the FormLayout content box and its top
   gets cut off, dropping the top of words like "Naam" and "Omschrijving".
   Zeroing the first row's negative margin in Large mode (.dxbl-lg) keeps the
   row inside the clipping box without changing Normal/Small layouts.
   ========================================================================== */
.dxbl-grid-edit-form .dxbl-fl {
  padding: 1.25rem 1.5rem 1rem;
  border-radius: 4px;
}
.dxbl-grid-edit-form .dxbl-fl.dxbl-lg > .dxbl-row:first-child {
  margin-top: 0;
}

/* ==========================================================================
   Editor input padding
   --------------------------------------------------------------------------
   Purpose:
   Normalizes left padding for text editors and TagBox tags so editor content
   aligns consistently across controls.
   ========================================================================== */
.dxbl-tag-box > .dxbl-tag {
  padding-left: 8px;
}

.dxbl-text-edit > .dxbl-text-edit-template,
.dxbl-text-edit > .dxbl-text-edit-input,
.dxbl-text-edit > textarea {
  padding-left: 8px;
}
.dxbl-text-edit > .dxbl-text-edit-template .dxbl-text-edit-input {
  padding-left: 8px;
}

/* ==========================================================================
   Validation messages
   --------------------------------------------------------------------------
   Purpose:
   Styles validation errors consistently and renders grouped validation
   messages as a custom bullet list without relying on native list styling.
   ========================================================================== */
.validation-message {
  color: var(--bs-danger-rgb);
}

.validation-error-group {
  padding-left: 1rem;
  margin-top: 0;
  margin-bottom: 1rem;
  list-style-type: none;
}
.validation-error-group .validation-message {
  position: relative;
  padding-left: 1rem;
  color: var(--bs-danger-rgb);
}
.validation-error-group .validation-message::before {
  content: "•";
  position: absolute;
  top: -0.3rem;
  left: -0.05rem;
  font-size: 1.4rem;
}

/* ==========================================================================
   Editor validation status spacing
   --------------------------------------------------------------------------
   Purpose:
   Adds spacing before the DevExpress validation icon/status element.
   ========================================================================== */
.dxbl-edit-validation-status {
  padding-left: 6px !important;
}

/* ==========================================================================
   FormLayout group card background
   --------------------------------------------------------------------------
   Purpose:
   Restores the old Primo FormLayout group styling that existed in the
   A group sits on the panel that holds the form rather than in a tinted box of
   its own: no fill, no corner, no border - the caption line and the space around
   it are what tell one group from the next. Only the inner padding stays.
   ========================================================================== */
.dxbl-fl .dxbl-fl-group > .dxbl-group,
.dxbl-fl .dxbl-fl-group > dxbl-group-control,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group {
  overflow: hidden;
  color: #000;
  background-color: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-header,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-header,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-header {
  color: #000;
  background-color: transparent;
  border: 0;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group > .dxbl-group > dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > dxbl-group-body {
  background-color: transparent;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > .dxbl-group > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > .dxbl-group > dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > dxbl-group-body > dxbl-group-body-content {
  padding: 0;
  background-color: transparent;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group .dxbl-group-body-content {
  background-color: transparent;
}

/* ==========================================================================
   FormLayout group spacing
   --------------------------------------------------------------------------
   Purpose:
   Recreates the old spacing between grouped form sections without adding a
   large gap inside the grey group card itself.
   ========================================================================== */
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd, .dxbl-fl .dxbl-fl-group.dxbl-fl-gt {
  margin: 10px 0 0;
}

/* ==========================================================================
   FormLayout group outer spacing
   --------------------------------------------------------------------------
   Purpose:
   Adds spacing between FormLayout groups while keeping enough room at the top
   of each grey group so labels are not clipped by the rounded container.
   ========================================================================== */
.dxbl-fl > .dxbl-fl-gd,
.dxbl-fl > .dxbl-fl-gt {
  margin: 10px 0 0;
}

/* ==========================================================================
   Nested FormLayout groups
   --------------------------------------------------------------------------
   Purpose:
   Prevents nested groups from creating a second grey rounded card inside an
   existing grey group. This keeps nested groups visually flat and compact.
   ========================================================================== */
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col {
  margin-top: 0.5rem;
  margin-bottom: 0;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group {
  background-color: transparent;
  border: 0;
  border-radius: 0;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > .dxbl-group-header,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > .dxbl-group-header,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > .dxbl-group-header {
  display: none;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > dxbl-group-body,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > dxbl-group-body,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > dxbl-group-body {
  background-color: transparent;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group > dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control > dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group > dxbl-group-body > dxbl-group-body-content {
  padding: 0;
  background-color: transparent;
}
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > .dxbl-group .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-group-control .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group.dxbl-fl-gd.dxbl-col .dxbl-fl-group.dxbl-fl-gd.dxbl-col > dxbl-form-layout-group .dxbl-group-body-content {
  background-color: transparent;
}

/* ==========================================================================
   CustomForm nested subgroups
   --------------------------------------------------------------------------
   Purpose:
   The "Nested FormLayout groups" rule above hides the header of every nested
   group and zeroes its padding. CustomForm intentionally nests one level of
   captioned subgroups (e.g. Afdichtingen > Bakboord / Midden / Stuurboord), so
   re-show those subgroup captions and restore a little top padding so the
   subgroup header and its first field row are not clipped. The header caption
   text also loses its default left margin so it aligns with the field captions
   below it. Scoped to .customform-layout so other forms keep the flat
   nested-group behaviour.
   ========================================================================== */
.customform-layout .customform-subgroup > .dxbl-group > .dxbl-group-header,
.customform-layout .customform-subgroup > .dxbl-group > dxbl-group-header,
.customform-layout .customform-subgroup > dxbl-group-control > .dxbl-group-header,
.customform-layout .customform-subgroup > dxbl-group-control > dxbl-group-header,
.customform-layout .customform-subgroup > dxbl-form-layout-group > .dxbl-group-header,
.customform-layout .customform-subgroup > dxbl-form-layout-group > dxbl-group-header, .customform-layout .customform-subgroup > .dxbl-group-header,
.customform-layout .customform-subgroup > dxbl-group-header {
  display: flex !important;
  margin-bottom: 0.75rem;
  padding-left: 0;
}
.customform-layout .customform-subgroup > .dxbl-group > .dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > .dxbl-group > .dxbl-group-body > dxbl-group-body-content,
.customform-layout .customform-subgroup > .dxbl-group > dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > .dxbl-group > dxbl-group-body > dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-group-control > .dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-group-control > .dxbl-group-body > dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-group-control > dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-group-control > dxbl-group-body > dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-form-layout-group > .dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-form-layout-group > .dxbl-group-body > dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-form-layout-group > dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-form-layout-group > dxbl-group-body > dxbl-group-body-content, .customform-layout .customform-subgroup > .dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > .dxbl-group-body > dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-group-body > .dxbl-group-body-content,
.customform-layout .customform-subgroup > dxbl-group-body > dxbl-group-body-content {
  padding-top: 0.75rem;
}
.customform-layout .customform-subgroup .dxbl-group > .dxbl-group-header > .dxbl-text {
  margin-left: 0;
}

/* ==========================================================================
   CustomForm static label field
   --------------------------------------------------------------------------
   Purpose:
   A 'Label' field type renders static text with no editor. The item keeps a
   (blank) caption row and gives the text the same height as a text editor so
   it lines up row-by-row with input fields placed in an adjacent column.
   ========================================================================== */
.customform-field-label {
  display: flex;
  align-items: center;
  min-height: 2.25rem;
  font-weight: 500;
}

/* ==========================================================================
   FormLayout group inner padding
   --------------------------------------------------------------------------
   Purpose:
   Restores the old Primo spacing inside FormLayout groups. Without this,
   the Fluent theme places labels and editors too close to the rounded group
   edges, causing the form to look cramped and sometimes visually clipped.
   ========================================================================== */
.dxbl-fl .dxbl-fl-group > .dxbl-group,
.dxbl-fl .dxbl-fl-group > dxbl-group-control,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group {
  padding: 0;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group > .dxbl-group > dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-body,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > dxbl-group-body {
  padding: 0;
  background-color: transparent;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > .dxbl-group > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > .dxbl-group > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > .dxbl-group > dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control > dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > .dxbl-group-body > dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > dxbl-group-body > .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group > dxbl-group-body > dxbl-group-body-content {
  padding: 0;
  background-color: transparent;
}
.dxbl-fl .dxbl-fl-group > .dxbl-group .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-group-control .dxbl-group-body-content,
.dxbl-fl .dxbl-fl-group > dxbl-form-layout-group .dxbl-group-body-content {
  padding: 0;
  background-color: transparent;
}

/* ==========================================================================
   White form background variant
   --------------------------------------------------------------------------
   Purpose:
   Forces selected forms back to a white background when they should not use
   the default grey Primo FormLayout group styling.
   ========================================================================== */
.form-background-white {
  background: #fff !important;
}
.form-background-white .dxbl-fl-group,
.form-background-white .dxbl-group,
.form-background-white dxbl-group-control,
.form-background-white dxbl-form-layout-group,
.form-background-white .dxbl-group-header,
.form-background-white .dxbl-group-body,
.form-background-white .dxbl-group-body-content {
  background: #fff !important;
}

/* ==========================================================================
   Readonly and disabled editor background
   --------------------------------------------------------------------------
   Purpose:
   Keeps readonly and disabled DevExpress text editors visually white instead
   of greyed out.
   ========================================================================== */
.dxbl-text-edit.dxbl-disabled, .dxbl-text-edit.dxbl-readonly {
  background: #fff;
}

/* ==========================================================================
   Readonly and disabled text editor lock icon
   --------------------------------------------------------------------------
   Purpose:
   Adds a centered Bootstrap Icons lock indicator to disabled/readonly
   DevExpress text editors. The icon is positioned absolutely so it stays
   vertically centered regardless of editor height.
   ========================================================================== */
.dxbl-text-edit.dxbl-disabled, .dxbl-text-edit.dxbl-readonly {
  position: relative;
}
.dxbl-text-edit.dxbl-disabled::after, .dxbl-text-edit.dxbl-readonly::after {
  content: "\f47a" !important;
  position: absolute !important;
  top: 50%;
  right: 8px;
  bottom: auto;
  left: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  clip-path: none;
  transform: translateY(-50%);
  color: var(--primo-icon-muted);
  font-family: bootstrap-icons;
  font-size: 0.85rem;
  line-height: 1;
  background: transparent !important;
  pointer-events: none;
}
.dxbl-text-edit.dxbl-disabled .dxbl-text-edit-input, .dxbl-text-edit.dxbl-readonly .dxbl-text-edit-input {
  padding-right: 1.75rem;
}

/* ==========================================================================
   Disabled checkbox lock icon
   --------------------------------------------------------------------------
   Purpose:
   Adds a Bootstrap Icons lock indicator to disabled checkboxes, using a
   slightly different color because checkbox rendering differs from text edits.
   ========================================================================== */
.dxbl-checkbox.dxbl-disabled::after {
  content: "\f47a" !important;
  position: relative !important;
  color: var(--primo-icon-muted-dark);
  font-family: bootstrap-icons;
  background: transparent !important;
  margin-left: 0.25rem;
}

/* ==========================================================================
   Full-height FormLayout group
   --------------------------------------------------------------------------
   Purpose:
   Forces specific FormLayout groups to fill the available row height.
   ========================================================================== */
.group-height-100 dxbl-group-control {
  height: 100%;
}

/* ==========================================================================
   Form group header decoration reset
   --------------------------------------------------------------------------
   Purpose:
   Removes the dark grey pseudo-element/header bar from DevExpress group
   headers.
   ========================================================================== */
.dxbl-group > .dxbl-group-header::before {
  background-color: transparent !important;
}

/* ==========================================================================
   TimeEdit footer customization
   --------------------------------------------------------------------------
   Purpose:
   Hides the "Now" button in TimeEdit dropdown footers for controls that opt in
   with the timeedit-hide-now class.
   ========================================================================== */
.timeedit-hide-now .dxbl-edit-dropdown-footer > button:first-child {
  display: none;
}

/* ==========================================================================
   Calendar and DateEdit dropdown footer buttons
   --------------------------------------------------------------------------
   Purpose:
   Styles DateEdit/Calendar footer buttons so Apply is primary and Today/Close
   are secondary.
   ========================================================================== */
.dxbl-edit-dropdown-footer > .dxbl-btn:nth-child(2) {
  --dxbl-btn-bg: var(--primo-primary) !important;
  --dxbl-btn-border-color: var(--primo-primary) !important;
  --dxbl-btn-hover-bg: var(--primo-primary) !important;
  --dxbl-btn-hover-border-color: var(--primo-primary) !important;
  --dxbl-btn-active-bg: var(--primo-primary) !important;
  --dxbl-btn-active-border-color: var(--primo-primary) !important;
  --dxbl-btn-color: var(--primo-primary-fg) !important;
  color: var(--primo-primary-fg) !important;
}
.dxbl-edit-dropdown-footer > .dxbl-btn:nth-child(1), .dxbl-edit-dropdown-footer > .dxbl-btn:nth-child(3) {
  --dxbl-btn-bg: #ffffff !important;
  --dxbl-btn-border-color: black !important;
  --dxbl-btn-hover-bg: #ffffff !important;
  --dxbl-btn-hover-border-color: black !important;
  --dxbl-btn-active-bg: #ffffff !important;
  --dxbl-btn-color: black !important;
  color: black !important;
}

/* ==========================================================================
   Calendar fixed width
   --------------------------------------------------------------------------
   Purpose:
   Prevents calendar dropdown width changes caused by different month-name
   lengths.
   ========================================================================== */
.dxbl-calendar {
  width: 325px;
}

/* ==========================================================================
   List box height adjustment
   --------------------------------------------------------------------------
   Purpose:
   Sets list boxes to fill the available height of their container, preventing
   awkward empty space when list content is short.
   ========================================================================== */
.dxbl-list-box {
  height: 100%;
}

/* ==========================================================================
   Editor clear button icon contrast
   --------------------------------------------------------------------------
   Purpose:
   Makes the clear/dismiss icon inside DevExpress editors more visible by
   forcing the SVG to a consistent size, circular shape, and white fill/stroke
   color on a filled primary-colour disc. Covers every editor host that exposes
   a clear button so the icon styling stays consistent across the app.

   The primary-colour background lives HERE (not only in the FormLayout rule in
   layout/_layout.scss) because the white fill/stroke is invisible on any white
   surface without it. Editors outside a DxFormLayout - toolbar / filter drop-
   downs such as the Gantt and Capacity planning filters - previously showed a
   white cross on a white field (an invisible clear button users hit by
   accident). Applying the disc globally gives every clear button the same
   white-cross-on-orange look the form editors already had.
   ========================================================================== */
dxbl-tag-box button.dxbl-edit-btn-clear svg.dxbl-image,
dxbl-date-edit button.dxbl-edit-btn-clear svg.dxbl-image,
dxbl-dropdown-box button.dxbl-edit-btn-clear svg.dxbl-image,
dxbl-combo-box button.dxbl-edit-btn-clear svg.dxbl-image,
dxbl-text-box button.dxbl-edit-btn-clear svg.dxbl-image,
dxbl-spin-edit button.dxbl-edit-btn-clear svg.dxbl-image {
  width: 1rem !important;
  height: 1rem !important;
  border-radius: 50%;
  background-color: var(--primo-primary);
  fill: #fff !important;
  stroke: #fff !important;
  stroke-width: 0 !important;
  stroke-linecap: round;
}

/* ==========================================================================
   Input placeholder visibility for disabled editors
   --------------------------------------------------------------------------
   Purpose:
   Hides the placeholder text for disabled input fields
   ========================================================================== */
input:disabled::placeholder {
  color: transparent !important;
}

/* ==========================================================================
   Input required indicator
   --------------------------------------------------------------------------
   Purpose:
   Adds a red mark to the end of form labels for required fields. This is a simple visual
   Helper to easily see what fields are required
   ========================================================================== */
.required-caption:after {
  content: "*";
  color: red;
}

/* ==========================================================================
   Tagbox pill styling
   --------------------------------------------------------------------------
   Purpose:
   Reduces the paddings to the sides and font weight
   ========================================================================== */
dxbl-tag-box .dxbl-tag .dxbl-tag-text {
  font-weight: 400;
  padding-left: 0.125rem !important;
  padding-right: 0.125rem !important;
}

/* ==========================================================================
   Detail form panel
   --------------------------------------------------------------------------
   Purpose:
   A detail form stands on the page itself with no frame, and labels each column
   group with a small letterspaced capital line over a
   hairline, the way A3 draws BEDRIJFSGEGEVENS and CONTACT & INSTELLINGEN. The
   groups are told apart by that caption and by the space around them, not by a
   second box inside the panel.
   ========================================================================== */
.dxbl-fl {
  padding: 1.25rem 0 1rem;
  border: 0;
  background-color: #fff;
}
.dxbl-fl .dxbl-group-header {
  margin-top: 0.75rem;
  margin-bottom: 0.65rem;
  padding-left: 0;
  padding-right: 0;
  padding-bottom: 0.35rem;
  /* The theme indents the caption text inside the header by half a line, which left it standing right of
     the labels under it however the group was nested. The header box was already flush; this is what was
     pushing the words. */
}
.dxbl-fl .dxbl-group-header .dxbl-text {
  margin-left: 0;
}
.dxbl-fl .dxbl-group-header {
  border-bottom: 1px solid var(--primo-border-section);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primo-text-muted);
}
.dxbl-fl {
  /* A group only has to be as tall as its own fields: the tinted boxes that once made two columns look
     ragged are gone, so stretching them to match leaves an empty stretch of panel instead. */
}
.dxbl-fl .group-height-100 dxbl-group-control {
  height: auto;
}

/* ==========================================================================
   Tab hint
   --------------------------------------------------------------------------
   Purpose:
   A quiet line that explains the state of the section it stands in - not a
   banner across the page, which shouts for something the form below already
   makes obvious.
   ========================================================================== */
.tab-hint {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  color: var(--primo-text-muted);
}

/* ==========================================================================
   Modal vertical alignment
   --------------------------------------------------------------------------
   Purpose:
   Centers modal dialogs vertically inside the modal root container.
   ========================================================================== */
.dxbl-modal > .dxbl-modal-root {
  align-content: center;
}

/* ==========================================================================
   Modal footer button spacing
   --------------------------------------------------------------------------
   Purpose:
   Adds consistent spacing between action buttons in modal footers.
   ========================================================================== */
.dxbl-modal-footer button {
  margin-left: 0.5em;
}

/* ==========================================================================
   Modal close button radius
   --------------------------------------------------------------------------
   Purpose:
   Prevents an oval hover/active shape on the popup close button by forcing a
   small border radius.
   ========================================================================== */
.dxbl-modal > .dxbl-modal-root > .dxbl-popup > .dxbl-modal-content > .dxbl-modal-header .dxbl-popup-header-button {
  --dxbl-btn-border-radius: 5%;
}

/* ==========================================================================
   Modal border reset
   --------------------------------------------------------------------------
   Purpose:
   Removes the default border around DevExpress modal content.
   ========================================================================== */
.dxbl-modal-content {
  border: 0 !important;
}

/* ==========================================================================
   Scrollable popups by default
   --------------------------------------------------------------------------
   Purpose:
   A DevExpress popup grows to fit its content, so a tall one (send document,
   bill of materials, line selection, ...) runs off the bottom of a laptop
   screen and its footer buttons become unreachable without zooming the
   browser out.

   DxPopupBase.Scrollable already solves this, but it defaults to false and
   would have to be repeated on every popup in the app. These two declarations
   are exactly what that property applies (.dxbl-popup-scrollable in the
   DevExpress theme); stating them here without the opt-in class makes a
   scrollable popup the default, new popups included. The body itself already
   carries overflow-y: auto from the theme, so capping the content is what
   actually turns the overflow into a scrollbar; the 3.5rem is the popup's own
   --dxbl-popup-margin, top plus bottom.

   Excluded: drop-down, toolbar and side-panel popups, which reuse the same
   modal markup but bring their own sizing and inner scroll containers, and the
   scheduler appointment form, which renders its own body element and is capped
   in _appointment.scss.

   Per popup opt-out: Scrollable is DevExpress's own switch, so set an explicit
   Height/MaxHeight on the popup rather than fighting this rule.
   ========================================================================== */
.dxbl-modal > .dxbl-modal-root > .dxbl-popup:not(.dxbl-edit-dropdown, .dxbl-btn-dropdown-modal, .dxbl-toolbar-dropdown-modal, .dxbl-toolbar-dialog, .dxbl-toolbar-bottom-sheet, .dxbl-sidepanel-dialog, .dxbl-apt-edit-dialog) > .dxbl-modal-content {
  max-height: calc(100vh - 3.5rem);
  overflow-y: hidden;
}
.dxbl-modal > .dxbl-modal-root > .dxbl-popup:not(.dxbl-edit-dropdown, .dxbl-btn-dropdown-modal, .dxbl-toolbar-dropdown-modal, .dxbl-toolbar-dialog, .dxbl-toolbar-bottom-sheet, .dxbl-sidepanel-dialog, .dxbl-apt-edit-dialog) > .dxbl-modal-content > .dxbl-modal-body {
  overflow-y: auto;
}

/* ==========================================================================
   Create Orders popup scrollbar gutter
   --------------------------------------------------------------------------
   Purpose:
   Reserves the vertical scrollbar gutter inside the Create Orders popup body,
   so content no longer shifts sideways when toggling options makes the
   scrollbar appear or disappear.
   ========================================================================== */
.create-orders-popup .dxbl-modal-body {
  scrollbar-gutter: stable;
}

/* ==========================================================================
   Dialog message line breaks
   --------------------------------------------------------------------------
   Purpose:
   Keeps the line breaks of a dialog message. The DevExpress message box renders
   its text as text, so a message that carries several lines (an exception plus
   its inner exception) needs pre-line to show them as lines - writing a break
   tag in the message instead would end up on screen as literal characters
   (#122555).
   ========================================================================== */
.primo-dialog .dxbl-modal-body {
  white-space: pre-line;
}

/* ==========================================================================
   Send document popup layout
   --------------------------------------------------------------------------
   Purpose:
   Keeps the send button of SendDocumentPopup pinned at the bottom of the popup
   and lets the active tab scroll instead. Without it a tall Details tab pushes
   the button below the fold of the popup body, where it is only reachable by
   scrolling the popup itself - and it comes back into view when the user
   switches to a shorter tab, which is how the bug was reported.

   Why global and not the component's scoped stylesheet:
   the popup body (DxPopup BodyCssClass), the form (EditForm) and the button
   (DxButton) are all rendered by CHILD components, so Blazor never stamps this
   component's scope attribute on them and a scoped selector cannot match them.
   ========================================================================== */
.send-popup-body {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.send-popup-form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  overflow: hidden;
}

.send-popup-tab-content {
  flex: 1 1 0%;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.send-popup-form .send-popup-submit {
  flex: 0 0 auto !important;
}

/* ==========================================================================
  Popover and appointment dialog headers
  --------------------------------------------------------------------------
  Purpose:
  Applies the Primo primary header styling for popovers and scheduler
  appointment edit dialogs.
  ========================================================================== */
.popover-body {
  color: var(--primo-popover-text);
}

.popover-header,
.dxbl-apt-edit-dialog-header {
  background: var(--primo-primary) !important;
}
.popover-header > div,
.popover-header > .dxbl-btn,
.popover-header > .dxbl-sc-dialog-title,
.popover-header > .dxbl-btn-tool,
.dxbl-apt-edit-dialog-header > div,
.dxbl-apt-edit-dialog-header > .dxbl-btn,
.dxbl-apt-edit-dialog-header > .dxbl-sc-dialog-title,
.dxbl-apt-edit-dialog-header > .dxbl-btn-tool {
  color: var(--primo-primary-fg) !important;
}
.popover-header .dxbl-btn.dxbl-btn-tool:hover,
.dxbl-apt-edit-dialog-header .dxbl-btn.dxbl-btn-tool:hover {
  color: var(--primo-primary-fg) !important;
  background: var(--primo-primary-dark) !important;
  background-color: var(--primo-primary-dark) !important;
  border-color: var(--primo-primary-dark) !important;
}

/* ==========================================================================
  Message box footer buttons
  --------------------------------------------------------------------------
  Purpose:
  Restores Primo-specific colors for message box primary and secondary
  buttons where DevExpress variables are not enough.
  ========================================================================== */
.dxbl-message-box-footer .dxbl-message-box-footer-primary-button {
  color: #fff !important;
  background-color: var(--primo-messagebox-btn-primary) !important;
}
.dxbl-message-box-footer .dxbl-message-box-footer-primary-button:hover {
  color: #fff !important;
  background-color: var(--primo-primary-dark) !important;
  border-color: var(--primo-primary-dark) !important;
}
.dxbl-message-box-footer .dxbl-message-box-footer-secondary-button {
  color: var(--primo-messagebox-btn-secondary-text) !important;
  border-color: var(--primo-messagebox-btn-secondary-border) !important;
}
.dxbl-message-box-footer .dxbl-message-box-footer-secondary-button:hover {
  color: var(--primo-messagebox-btn-secondary-text) !important;
  background-color: var(--primo-surface-subtle) !important;
  border-color: var(--primo-messagebox-btn-secondary-border) !important;
}

/* ==========================================================================
  Status indicator base
  --------------------------------------------------------------------------
  Purpose:
  Defines the shared visual shape for status indicators: a small inline
  circular marker that aligns with surrounding text and leaves space before
  the status label.
  ========================================================================== */
.status-indicator {
  display: inline-block;
  position: relative;
  width: 14px;
  height: 14px;
  margin-right: 8px;
  border-radius: 10px;
  font-style: normal;
  text-align: center;
  vertical-align: middle;
}

/* ==========================================================================
   Hidden status indicator
   --------------------------------------------------------------------------
   Purpose:
   Hides the status indicator completely when no visible status marker should
   be shown.
   ========================================================================== */
.status-none {
  display: none;
}

/* ==========================================================================
   Status wrapper
   --------------------------------------------------------------------------
   Purpose:
   Removes default paragraph spacing around status content so indicators and
   labels align cleanly inside compact layouts such as grids.
   ========================================================================== */
.status-wrapper {
  margin: 0;
}

/* ==========================================================================
   Filled status color variants
   --------------------------------------------------------------------------
   Purpose:
   Provides reusable background and text color combinations for status
   indicators that need a colored circular marker.
   ========================================================================== */
.status-black {
  color: #fff;
  background-color: #000;
}

.status-grey {
  color: #000;
  background-color: var(--primo-status-grey);
}

.status-green {
  color: #fff;
  background-color: var(--primo-status-success);
}

.status-orange {
  color: #000;
  background-color: var(--primo-primary-brand);
}

/* The design spec's warning status (#FFA700); ticket status Awaiting customer. */
.status-warning {
  color: #000;
  background-color: var(--primo-status-warning);
}

.status-yellow {
  color: #000;
  background-color: var(--primo-status-yellow);
}

.status-red {
  color: #fff;
  background-color: var(--primo-status-red);
}

.status-dark-red {
  color: #fff;
  background-color: var(--primo-status-dark-red);
}

.status-light-blue {
  color: #fff;
  background-color: var(--primo-status-info);
}

.status-blue {
  color: #fff;
  background-color: var(--primo-status-dark-blue);
}

/* ==========================================================================
   Text-only status color variants
   --------------------------------------------------------------------------
   Purpose:
   Provides reusable text color classes for statuses where only the text should
   be colored and no filled circular marker is needed.
   ========================================================================== */
.status-orange-color {
  color: var(--primo-primary-brand);
}

.status-red-color {
  color: red;
}

/* ==========================================================================
   Readonly status positioning
   --------------------------------------------------------------------------
   Purpose:
   Places the tabs status wrapper in the same position as the edit form status wrapper, so the
   status indicator and label are consistently located across the application regardless of the context.
   ========================================================================== */
.tabs-container .status-wrapper {
  padding: 1rem 1rem 1.25rem 1rem;
  height: 2.65em;
}

/* ==========================================================================
  Detail page tabs
  --------------------------------------------------------------------------
  Purpose:
  The open tab reads in ink with the action colour ruled under it. The theme's
  own accent chain wins on specificity, so the two declarations that matter are
  forced.
  ========================================================================== */
.dxbl-tabs .dxbl-tabs-item {
  /* The theme reaches these from a five-deep selector chain of its own, so an ordinary rule loses on
     specificity. Copying that chain would tie this to DevExpress' internal markup, which changes between
     releases; !important keeps the override to the two declarations that matter. */
}
.dxbl-tabs .dxbl-tabs-item.dxbl-active {
  color: var(--primo-text-heading) !important;
  font-weight: 600;
  /* The rule under the open tab is the action colour, the same as every other mark that says where
     you are. */
}
.dxbl-tabs .dxbl-tabs-item.dxbl-active::after {
  background-color: var(--primo-primary) !important;
}

/* ==========================================================================
  Main text behavior
  --------------------------------------------------------------------------
  Purpose:
  Overwrites the default text settings of the Fluent Theme to match
  Primo design. This is required because the old theme set the font
  ========================================================================== */
html,
body {
  font-family: var(--primo-font-family);
  font-size: var(--primo-font-size);
  line-height: var(--primo-line-height);
}
html .bi::before, html [class*=" bi-"]::before,
body .bi::before,
body [class*=" bi-"]::before {
  line-height: inherit;
}

/* ==========================================================================
   Status text styling
   --------------------------------------------------------------------------
   Purpose:
   Highlights warning and danger text with stronger font weight and status
   colors. Also styles urgent Bootstrap icons so they stand out slightly more
   and have spacing before the text.
   ========================================================================== */
.text-danger {
  font-weight: 600;
  color: #C92600 !important;
}

.text-warning {
  font-weight: 600;
  color: #ffa700 !important;
}

.urgent {
  font-weight: 600;
  color: #C92600 !important;
}
.urgent.bi::before {
  margin-right: 5px;
  font-size: 1.2em;
}

/* ==========================================================================
   Detail page title
   --------------------------------------------------------------------------
   Purpose:
   A detail title names its context before the record - "Dealers / HUSS B.V." -
   with the quiet word first and the record carrying the weight. The spans are
   written by the page rather than by PageHeader, so they cannot be styled from
   that component's scoped sheet.
   ========================================================================== */
.page-title-context {
  font-size: 0.8em;
  font-weight: 400;
  color: var(--primo-text-muted);
}
.page-title-context::after {
  content: "/";
  margin-left: 0.4rem;
  color: var(--primo-border);
}

.page-title-name {
  font-weight: 600;
  color: var(--primo-text-heading);
}

/* ==========================================================================
   File dropzone container
   --------------------------------------------------------------------------
   Purpose:
   Styles the upload dropzone as a fixed-height dashed area with centered
   content, making it visually clear where files can be dropped or selected.
   ========================================================================== */
.file-dropzone {
  display: flex;
  height: 230px;
  margin-top: 20px !important;
  padding: 0 !important;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  border-width: 3px !important;
  border-style: dashed !important;
}
.file-dropzone svg {
  width: 42px;
  height: 42px;
}

/* ==========================================================================
   Placeholder upload image wrapper
   --------------------------------------------------------------------------
   Purpose:
   Centers a placeholder image inside the upload area and keeps the image
   height constrained relative to the viewport width.
   ========================================================================== */
.placeholder-img-upload-wrapper {
  position: relative;
  display: flex;
  height: 15vw;
  align-items: center;
  justify-content: center;
}
.placeholder-img-upload-wrapper img {
  height: 100%;
}

/* ==========================================================================
   Upload button overlay
   --------------------------------------------------------------------------
   Purpose:
   Positions upload buttons above the placeholder image and centers them within
   the upload area. Adds spacing before primary DevExpress buttons.
   ========================================================================== */
.upload-button-wrapper {
  position: absolute;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.upload-button-wrapper .dxbl-btn.dxbl-btn-primary {
  margin-left: 5px;
}

/* ==========================================================================
   Hidden upload panel
   --------------------------------------------------------------------------
   Purpose:
   Hides the DevExpress Upload panel for upload controls that opt in with the
   hide-upload class. This is useful when the upload control is used behind a
   custom dropzone or custom upload UI and the default cancel/progress panel
   should not be visible.
   ========================================================================== */
.hide-upload .dxbl-upload-container .dxbl-upload-panel {
  display: none !important;
}

/* ==========================================================================
  Primary flyout header
  --------------------------------------------------------------------------
  Purpose:
  Applies the Primo primary color to flyout headers that opt in with the
  background-color-primary class.
  ========================================================================== */
.dxbl-flyout-header.background-color-primary {
  background-color: var(--primo-primary) !important;
  color: var(--primo-primary-fg) !important;
}

/* ==========================================================================
   Custom flyout header
   --------------------------------------------------------------------------
   Purpose:
   Styles custom flyout headers with compact padding, white text, a title area
   and right-aligned action buttons.
   ========================================================================== */
.flyout-header {
  padding: 4.6875px 11.25px 4.6875px 5.25px;
  font-weight: 400;
  color: #fff;
  align-content: center;
}
.flyout-header .header-title {
  font-size: 18px;
}
.flyout-header .header-buttons {
  display: flex;
  float: right;
  align-items: center;
  font-size: 13px;
}
.flyout-header .header-buttons .header-close {
  cursor: pointer;
}

/* ==========================================================================
   Flyout button row
   --------------------------------------------------------------------------
   Purpose:
   Aligns flyout footer buttons to the right with consistent spacing and a top
   separator line.
   ========================================================================== */
.flyout-button-row {
  display: flex;
  width: 100%;
  gap: 10px;
  justify-content: flex-end;
  padding-top: 10px;
  border-top: 1px solid var(--primo-text-secondary);
}

/* ==========================================================================
  Dashboard card container
  --------------------------------------------------------------------------
  Purpose:
  Provides a clean white card surface for dashboard widgets, including rounded
  corners, subtle shadow and consistent inner spacing.
  ========================================================================== */
.dashboard-card {
  padding: 1rem;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* ==========================================================================
   KPI widget layout
   --------------------------------------------------------------------------
   Purpose:
   Arranges the KPI widget content vertically so the header and KPI cards stack
   cleanly.
   ========================================================================== */
.kpi-widget {
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   KPI header
   --------------------------------------------------------------------------
   Purpose:
   Adds spacing between the KPI title/header area and the KPI card list below.
   ========================================================================== */
.kpi-header {
  margin-bottom: 0.75rem;
}

/* ==========================================================================
   KPI title
   --------------------------------------------------------------------------
   Purpose:
   Styles the KPI section title with a slightly larger, semibold appearance
   while removing default heading margin.
   ========================================================================== */
.kpi-title {
  margin: 0;
  color: var(--bs-body-color);
  font-size: 1.1rem;
  font-weight: 600;
}

/* ==========================================================================
   KPI card collection
   --------------------------------------------------------------------------
   Purpose:
   Displays KPI cards in a responsive wrapping row with consistent spacing
   between cards.
   ========================================================================== */
.kpi-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-content: flex-start;
}

/* ==========================================================================
   KPI inner card
   --------------------------------------------------------------------------
   Purpose:
   Styles each individual KPI value card with flexible sizing, compact padding,
   a subtle background and a left status border.
   ========================================================================== */
.kpi-inner-card {
  display: flex;
  flex: 1 1 140px;
  flex-direction: column;
  justify-content: center;
  min-width: 140px;
  max-width: 260px;
  padding: 0.75rem 1rem;
  background: var(--bs-tertiary-bg);
  border-left: 4px solid;
  border-radius: 0.375rem;
}
.kpi-inner-card.kpi-inner-card-danger {
  border-left-color: var(--primo-kpi-danger-accent) !important;
}

/* ==========================================================================
   KPI amount
   --------------------------------------------------------------------------
   Purpose:
   Emphasizes the primary KPI value and provides positive/negative color
   variants for financial or performance indicators.
   ========================================================================== */
.kpi-amount {
  color: var(--bs-body-color);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.2;
}
.kpi-amount.kpi-positive {
  color: var(--primo-kpi-positive);
}
.kpi-amount.kpi-negative {
  color: var(--primo-kpi-negative);
}

/* ==========================================================================
   KPI label
   --------------------------------------------------------------------------
   Purpose:
   Styles the descriptive label below a KPI value with smaller, muted text.
   ========================================================================== */
.kpi-label {
  margin-top: 0.25rem;
  color: var(--bs-secondary-color);
  font-size: 0.85rem;
  font-weight: 500;
}

/* ==========================================================================
   Empty KPI state
   --------------------------------------------------------------------------
   Purpose:
   Displays a muted empty-state message when no KPI data is available.
   ========================================================================== */
.kpi-empty {
  color: var(--bs-secondary-color);
  font-size: 1.25rem;
}

.drawer-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  background: #fff;
}

.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 20px;
  background: linear-gradient(135deg, var(--primo-surface-subtle) 0%, #fff 100%);
  border-bottom: 1px solid var(--primo-border-panel);
  flex-shrink: 0;
  min-width: 0;
}

.drawer-header-icon {
  font-size: 1.4rem;
  color: var(--primo-primary-brand);
}

.drawer-header-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--primo-text-heading);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.drawer-header-title i {
  font-size: 0.65rem;
  color: var(--primo-text-muted);
  vertical-align: middle;
  margin: 0 2px;
}

.drawer-close-btn {
  flex-shrink: 0;
  margin-left: auto;
  align-self: center;
}

.drawer-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px 20px;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
.drawer-body .table td:first-child {
  width: 40%;
}

.gridlayout-content:has(> .page-drawer) {
  display: flex;
  flex-direction: column;
}

.gridlayout-content > .page-drawer {
  flex: 1 0 auto;
}

.drawer-shadow .dxbl-drawer-panel {
  box-shadow: -6px 0 20px rgba(0, 0, 0, 0.12), -2px 0 6px rgba(0, 0, 0, 0.06);
  border-left: 1px solid var(--primo-border-panel);
}

.drawer-history {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--primo-border-section);
}

.drawer-history-list {
  max-height: 300px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}

.drawer-history-item {
  padding: 8px 0;
  border-bottom: 1px solid var(--primo-border-faint);
}
.drawer-history-item:last-child {
  border-bottom: none;
}

.drawer-history-date {
  font-size: 0.75rem;
  color: var(--primo-text-muted);
  margin-bottom: 2px;
}

.drawer-history-event {
  font-size: 0.85rem;
  color: var(--primo-text-dark);
  line-height: 1.4;
}

.drop-down-button-container {
  position: relative;
  height: 2.65em;
  min-width: 75px;
}
.drop-down-button-container .dxbl-btn {
  height: 100% !important;
  padding: unset !important;
}
.drop-down-button-container .dxbl-btn .status-wrapper .status-text {
  padding-right: 0.25rem;
}
.drop-down-button-container .drop-down-button-items {
  z-index: 9999;
  position: absolute;
  width: fit-content;
  min-width: 100%;
  background-color: white;
  /* Reset default styling for a unordered list */
  list-style-type: none;
  padding: 0;
  margin: 2px 0 0;
  border: 1px solid var(--primo-border-input);
  border-radius: 0.125rem;
}
.drop-down-button-container .drop-down-button-items.align-right {
  right: 0;
}
.drop-down-button-container .drop-down-button-items[data-is-visible] {
  display: none;
}
.drop-down-button-container .drop-down-button-items[data-is-visible=true] {
  display: block;
}
.drop-down-button-container .drop-down-button-items .drop-down-button-item {
  cursor: pointer;
  white-space: nowrap;
  padding: 0.5rem 1.25rem;
  background-color: #ffffff;
}
.drop-down-button-container .drop-down-button-items .drop-down-button-item:hover {
  background-color: var(--primo-secondary);
}

/* ==========================================================================
  Placeholder picker
  --------------------------------------------------------------------------
  Purpose:
  Styles the two halves of the insert-placeholder UI: the button that sits
  inside a PlaceholderTextBox editor, and the PlaceholderDropDown list it
  shares with the SimpleHtmlEditor toolbar button. The drop-down is rendered
  in a body-level portal, so it cannot be reached from either component's
  scoped stylesheet and lives here instead.
  ========================================================================== */
.placeholder-text-box {
  width: 100%;
  /* Keep the button's label on one line and compact; the editor shrinks the input to fit it. */
}
.placeholder-text-box .placeholder-text-box-button {
  white-space: nowrap;
  padding: 0 0.5rem;
  font-size: 0.9em;
  color: var(--primo-text-muted);
}
.placeholder-text-box .placeholder-text-box-button:hover {
  color: var(--primo-primary-brand);
}

/* The SimpleHtmlEditor's menu hangs off an empty marker covering the whole toolbar strip rather than off the
   DevExpress toolbar button itself: the button is DevExpress' markup, so whether its CssClass reaches the rendered
   element is not ours to rely on, and a PositionTarget that matches nothing leaves the menu unplaced. The marker
   spans the strip, so the menu drops out of the toolbar's left edge and stays inside the popup it lives in. */
.simple-html-editor {
  position: relative;
}
.simple-html-editor .simple-html-editor-placeholder-anchor {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* The Fluent toolbar strip's height; the menu drops from just below it. */
  height: 2.5rem;
  pointer-events: none;
}

.placeholder-drop-down {
  /* Sized by its longest group name rather than by a guessed pixel width, which either cut the labels off or
     left a gap in front of the chevrons. !important because DevExpress writes the popup width inline. */
  width: max-content !important;
  min-width: 11rem;
  max-width: 22rem;
}
.placeholder-drop-down .placeholder-drop-down-body {
  display: flex;
  flex-direction: column;
  padding: 0.25rem;
}
.placeholder-drop-down .placeholder-drop-down-search {
  margin-bottom: 0.25rem;
}
.placeholder-drop-down {
  /* The scroll sits on this wrapper rather than on the menu: a height limit on the menu itself makes DevExpress
     render its own scroll arrows on top of the scrollbar and clip the first item. The search box stays outside
     it, so it holds still while the list moves under it. */
}
.placeholder-drop-down .placeholder-drop-down-scroll {
  max-height: 16rem;
  overflow-y: auto;
}
.placeholder-drop-down .placeholder-drop-down-menu {
  border: none;
  background: transparent;
}

/* Compact rows at the body font size, matching the toolbar dropdown this menu replaced. SizeMode.Small was tried
   for this and shrank the type along with the rows, so the tightening happens on the padding alone. The submenu
   popup renders body-level, so it carries the same rules through its own class rather than through the
   drop-down's. */
.placeholder-drop-down .dxbl-menu-item,
.placeholder-drop-down-submenu .dxbl-menu-item {
  min-height: 0 !important;
  padding: 0.15rem 0.5rem !important;
}
.placeholder-drop-down .dxbl-menu-item-list,
.placeholder-drop-down-submenu .dxbl-menu-item-list {
  padding: 0.15rem 0 !important;
}
.placeholder-drop-down,
.placeholder-drop-down-submenu {
  /* DevExpress renders every menu item as an anchor and the app paints links brand-orange. A placeholder is not
     a link, so the item takes the body text colour and weight back. */
}
.placeholder-drop-down .dxbl-menu-item,
.placeholder-drop-down .dxbl-menu-item a,
.placeholder-drop-down .dxbl-menu-item-text,
.placeholder-drop-down-submenu .dxbl-menu-item,
.placeholder-drop-down-submenu .dxbl-menu-item a,
.placeholder-drop-down-submenu .dxbl-menu-item-text {
  color: var(--primo-text-primary);
  font-weight: 400;
  text-decoration: none;
}

.placeholder-drop-down-submenu {
  width: max-content !important;
  max-width: 22rem;
  max-height: 16rem;
  overflow-y: auto;
}

/* ==========================================================================
  Login
  --------------------------------------------------------------------------
  Purpose:
  Styles the editors and the reveal ("eye") button inside the login card. Both
  are DevExpress' own markup, so they carry no scoped-CSS attribute and cannot
  be reached from Login.razor.scss - they have to live in the global sheet, the
  same as the PlaceholderTextBox button next door.
  ========================================================================== */
.login-input-container {
  /* The design board draws the sign-in fields as outlined boxes, where the Fluent editors are underlined by
     default. Scoped here to the login card so the rest of the application keeps the theme's own editors. */
}
.login-input-container .dxbl-text-edit {
  border: 1px solid var(--primo-border);
  border-radius: 2px;
}
.login-input-container {
  /* Sized down to an inline icon. The global .dxbl-btn rule in _buttons.scss gives every primary / secondary /
     outline-secondary button height: 2.65em and padding: 1rem, and its :not() list excludes only DevExpress' own
     built-in editor buttons (dropdown, clear, spin) - a custom <Buttons> entry falls straight through it. Left
     alone that inflates the password box to 45px against the 39px email box above it. The !important is what beats
     that rule's six-class specificity without widening the global exclusion list, which would restyle every custom
     editor button in the app. */
}
.login-input-container .login-password-toggle {
  height: auto !important;
  padding: 0 0.5rem !important;
  color: var(--primo-text-muted);
}
.login-input-container .login-password-toggle:hover {
  color: var(--primo-primary-brand);
}

/* ==========================================================================
   Authentication card
   --------------------------------------------------------------------------
   Purpose:
   The four authentication pages share one card: an optional eyebrow over a
   display title and a muted subtitle, labelled fields, a full-width action and
   a secondary link under it. They are separate components, so scoped styles
   cannot be shared between them - these classes live here instead of being
   copied into four .razor.scss files.
   ========================================================================== */
.auth-intro {
  margin-bottom: 1.5rem;
  text-align: center;
}

.auth-eyebrow {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primo-accent);
}

.auth-title {
  /* The display line runs on --primo-font-display, the text face, the way ovasso.com sets its headings -
     see docs/frontend/design-spec.md, deviation 1. */
  margin: 0;
  font-family: var(--primo-font-display);
  font-size: 2rem;
  font-weight: 400;
  letter-spacing: 0.01em;
  color: var(--primo-primary-brand);
}

.auth-subtitle {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
  color: var(--primo-text-muted);
}

.auth-field {
  margin-bottom: 1rem;
}
.auth-field:last-of-type {
  margin-bottom: 0;
}

.auth-field-label {
  display: block;
  margin-bottom: 0.25rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--primo-text-heading);
}

.auth-actions {
  width: 100%;
  margin-top: 1.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.auth-secondary-link {
  display: inline-block;
  margin-top: 1rem;
  font-size: 0.85rem;
  color: var(--primo-accent);
  text-decoration: none;
}
.auth-secondary-link:hover {
  text-decoration: underline;
}

.auth-note {
  margin: 1.25rem 0 0;
  font-size: 0.75rem;
  text-align: center;
  color: var(--primo-text-muted);
}

/* The editors on every authentication page are outlined boxes, where the Fluent editors are underlined by
   default. Scoped to the card so the rest of the application keeps the theme's own editors. */
.auth-fields .dxbl-text-edit {
  border: 1px solid var(--primo-border);
  border-radius: 2px;
}

.events-container {
  margin-top: 15px;
  overflow-y: auto;
  height: 450px;
  padding: 0 0 15px 15px;
}
.events-container h1 {
  font-size: 1em;
  font-weight: bold;
}
.events-container .navigation-event, .events-container .historic-event {
  margin-bottom: 12px;
}
.events-container .navigation-event label, .events-container .historic-event label {
  font-size: 0.875em;
  font-weight: 600;
  display: block;
}
.events-container .navigation-event span, .events-container .historic-event span {
  font-size: 0.875em;
}
.events-container .navigation-event .dxbl-btn {
  padding: 0;
  text-align: left;
}
.events-container .navigation-event .dxbl-btn span {
  font-size: 0.875rem;
  color: black;
}
.events-container .navigation-event .dxbl-btn > .dxbl-image {
  background: var(--primo-surface-icon-bg);
  border-radius: 20px;
  padding: 10px;
  height: 2.5em;
  width: 3em;
}

/* ==========================================================================
  Keyboard shortcut keys
  --------------------------------------------------------------------------
  Purpose:
  Renders shortcut chords as physical keycaps instead of Bootstrap's dark
  inline <kbd>. Used by the header hint that opens the shortcut help overlay
  (the bi-keyboard glyph was unreadable at menu icon size) and by the chord
  column inside that overlay.
  ========================================================================== */
.keycap-group {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  white-space: nowrap;
}

.keycap {
  display: inline-block;
  min-width: 1.8em;
  padding: 0.15em 0.5em;
  font-family: inherit;
  font-size: 0.9em;
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
  color: var(--primo-text-dark);
  background: linear-gradient(#ffffff, var(--primo-surface-icon-bg));
  border: 1px solid var(--primo-border-muted);
  border-radius: 0.375rem;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 2px 0 rgba(0, 0, 0, 0.12);
}

/* Header hint: scaled down and flattened so the caps sit level with the 16px menu icons. */
.keycap-sm {
  min-width: 1.4em;
  padding: 0.05em 0.35em;
  font-size: 0.75em;
  line-height: 1.3;
  color: var(--primo-text-muted);
  border-color: var(--primo-border);
  border-radius: 0.25rem;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}

/* Fixed width so the chord column in the help overlay stays aligned. */
.shortcut-help-key {
  min-width: 7.5rem;
}

/* ==========================================================================
   Dealer assortment - shared pieces
   --------------------------------------------------------------------------
   Purpose:
   The stock pill, the price line and the quantity editor appear on the product
   card, in the list row and in the quick-look drawer. Global because scoped
   CSS never reaches the markup a DevExpress component renders (grid cells,
   the drawer body), and because the three surfaces must read identically.
   ========================================================================== */
.catalog-stock-pill {
  display: inline-block;
  padding: 0.125rem 0.625rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
}

.catalog-stock-pill-available {
  background-color: var(--primo-stock-available-bg);
  border-color: var(--primo-stock-available-border);
  color: var(--primo-stock-available-fg);
}

.catalog-stock-pill-limited {
  background-color: var(--primo-stock-limited-bg);
  border-color: var(--primo-stock-limited-border);
  color: var(--primo-stock-limited-fg);
}

.catalog-stock-pill-unavailable {
  background-color: var(--primo-stock-unavailable-bg);
  border-color: var(--primo-stock-unavailable-border);
  color: var(--primo-stock-unavailable-fg);
}

.catalog-price {
  display: flex;
  align-items: baseline;
  gap: 0.375rem;
}

.catalog-price-amount {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--primo-text-heading);
}

.catalog-price-suffix {
  font-size: 0.75rem;
  color: var(--primo-text-secondary);
}

.catalog-quantity {
  width: 6rem;
  flex-shrink: 0;
}

.catalog-add {
  white-space: nowrap;
}

/* The icon-only add button in the list rows: a glyph at text size is easy to miss in a 48px row. */
.catalog-cart .dxbl-image {
  font-size: 1.5rem;
}

html, body, #app {
  height: 100%;
  width: 100%;
}

/* Prevent text selection during drag */
.no-select,
.no-select * {
  user-select: none !important;
  -webkit-user-select: none !important;
  -ms-user-select: none !important;
  -moz-user-select: none !important;
}

@media (max-width: 576px) {
  html, body {
    font-size: 11px;
    --bs-body-font-size: 11px;
  }
}
@media (min-width: 576px) {
  html, body {
    font-size: 12px;
    --bs-body-font-size: 12px;
  }
}
@media (min-width: 768px) {
  html, body {
    font-size: 13px;
    --bs-body-font-size: 13px;
  }
}
body.density-dealer {
  font-size: 15px;
  --bs-body-font-size: 15px;
}

@media (max-width: 767.98px) {
  body.density-dealer {
    font-size: 14px;
    --bs-body-font-size: 14px;
  }
}
/*# sourceMappingURL=app.css.map */
