/* Back office enhancements (static/backoffice/backoffice.js) */

/* Resizable columns */
#result_list thead th, .inline-group .tabular thead th { position: relative; }
.col-grip {
  position: absolute; top: 0; right: -3px; bottom: 0; width: 7px; z-index: 2;
  cursor: col-resize; touch-action: none;
}
.col-grip:hover, .col-grip:active { background: var(--primary); opacity: .45; }
table.cols-fixed { table-layout: fixed; }
table.cols-fixed th { box-sizing: border-box; }
table.cols-fixed td, table.cols-fixed th { overflow: hidden; text-overflow: ellipsis; }
table.cols-fixed td input:not([type=checkbox]), table.cols-fixed td select,
table.cols-fixed td textarea, table.cols-fixed .select2-container {
  max-width: 100%; box-sizing: border-box;
}

/* Delete line: a button that asks; a removed line stays in view, struck out, until Save */
.delete-line {
  border: 1px solid var(--border-color); background: var(--body-bg); color: var(--body-quiet-color);
  border-radius: 4px; padding: 1px 6px; font-size: 13px; line-height: 1.3; cursor: pointer;
}
.delete-line:hover, .delete-line:focus-visible { border-color: var(--error-fg); color: var(--error-fg); }
.line-removed > td:not(.delete), .inline-related.line-removed > fieldset {
  opacity: .45; text-decoration: line-through; pointer-events: none;
}
.line-removed .delete-line { color: var(--link-fg); }
.inline-related.line-removed > h3 { text-decoration: line-through; }

/* Duplicate line */
.inline-group .tabular .dup-cell { width: 3em; text-align: center; }
table.cols-fixed .dup-cell { overflow: visible; text-overflow: clip; }
.dup-line {
  border: 1px solid var(--border-color); background: var(--body-bg); color: var(--link-fg);
  border-radius: 4px; padding: 1px 6px; font-size: 14px; line-height: 1.3; cursor: pointer;
}
.dup-line:hover, .dup-line:focus-visible { border-color: var(--primary); background: var(--selected-row); }
.inline-group .tabular .drag-cell { width: 2em; text-align: center; padding-left: 4px; padding-right: 0; }
table.cols-fixed .drag-cell { overflow: visible; text-overflow: clip; }
.drag-line {
  border: 0; background: none; color: var(--body-quiet-color); font-size: 16px; line-height: 1;
  padding: 2px 4px; border-radius: 4px; cursor: grab; touch-action: none;
}
.drag-line:hover, .drag-line:focus-visible { color: var(--primary); background: var(--selected-row); }
.drag-line:active { cursor: grabbing; }
.inline-group tr.dragging td { background: var(--selected-row); opacity: .7; }
.inline-group h2 .line-tools { float: right; display: flex; align-items: center; gap: 8px; margin: -3px 0 -3px 8px; }
.inline-group h2 .reorder-lines {
  padding: 2px 10px; border-radius: 4px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .5); background: transparent; color: var(--header-link-color);
  font: inherit; font-size: 12px; text-transform: none; letter-spacing: normal;
}
.inline-group h2 .reorder-lines:hover, .inline-group h2 .reorder-lines:focus-visible {
  background: rgba(255, 255, 255, .15); border-color: #fff;
}
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* Buttons above lists (templates/admin/actions.html) and records (admin/change_form.html).
   "button.button" and "a.button" outrank Django's own rules for the Go button, which load
   after this file. */
#changelist .actions, .record-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
}
.record-actions { margin: 0 0 14px; }
.record-actions form { display: contents; }

/* A record's toolbar (templates/admin/change_form.html): the record's actions, Discuss and
   Tasks in one row, pinned to the top of the window while the page scrolls.
   It spans the content area's padding so it reads as a bar, not a floating strip. */
#content { --bar-gutter: 40px; }
@media (max-width: 1024px) { #content { --bar-gutter: 20px; } }
@media (max-width: 767px) { #content { --bar-gutter: 15px; } }
.record-bar {
  position: sticky; top: 0; z-index: 30;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: -10px calc(-1 * var(--bar-gutter)) 16px; padding: 10px var(--bar-gutter);
  background: var(--body-bg); border-bottom: 1px solid var(--hairline-color);
  box-shadow: 0 6px 12px -10px rgba(0, 0, 0, 0.35);
}
/* Under the header, which the text size (My settings) doesn't scale though the page does. */
@media (min-width: 768px) { .record-bar { top: calc(var(--header-h, 0px) * var(--text-unzoom, 1)); } }
.record-bar .record-bar-actions { display: contents; }
:is(.record-bar, .record-foot) .button, .record-bar .closelink {
  display: inline-flex; align-items: center; box-sizing: border-box; height: auto;
  min-height: 2rem; margin: 0; padding: 6px 12px; font-size: 0.8125rem; line-height: 1;
  border-radius: 4px; text-decoration: none; cursor: pointer;
}
:is(.record-bar, .record-foot) .button {
  border: 1px solid var(--border-color); background: var(--body-bg); color: var(--body-fg);
  box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
}
:is(.record-bar, .record-foot) .button:hover, :is(.record-bar, .record-foot) .button:focus { border-color: var(--body-quiet-color); }
/* The record's next step (Place order, Receive…) beside Save, filled; the rest outlined. */
.record-bar .button.primary-action { border-color: var(--button-bg); background: var(--button-bg); color: var(--button-fg);
  font-weight: 600; box-shadow: none; }
.record-bar .button.primary-action:hover, .record-bar .button.primary-action:focus { background: var(--button-hover-bg); }
.record-bar-actions:has(.primary-action) + .record-more .record-more-items > :first-child { margin-left: 10px; }  /* a gap after the main steps */
/* The rest of the record's actions (admin/change_form.html): in the row on a computer; on a
   phone, under Actions, a menu that drops down from the bar (backoffice.js 14). */
.record-more, .record-more-items { display: contents; }
.record-more-toggle { display: none !important; }
@media (max-width: 720px), (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
  .record-more { display: block; position: relative; margin-left: auto; }
  .record-more:not(:has(.record-more-items > *)) { display: none; }
  .record-bar .record-more-toggle { display: inline-flex !important; gap: 6px; }
  .record-more-toggle::after { content: ""; width: 7px; height: 7px; margin: -3px 2px 0 2px;
                               border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg); }
  .record-more.open .record-more-toggle::after { margin-top: 3px; transform: rotate(-135deg); }
  .record-more-items { display: none; }
  .record-more.open .record-more-items {
    display: flex; flex-direction: column; gap: 2px; position: absolute; z-index: 40; top: calc(100% + 6px); right: 0;
    min-width: 13rem; max-width: calc(100vw - 2 * var(--bar-gutter, 15px)); padding: 6px; box-sizing: border-box;
    background: var(--body-bg); border: 1px solid var(--border-color); border-radius: 8px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .22); }
  .record-bar .record-more-items > .button { justify-content: flex-start; width: 100%; min-height: 44px; margin: 0 !important;
                                             padding: 0 12px; border: 0; box-shadow: none; background: none;
                                             font-size: 15px; text-align: left; }
  .record-bar .record-more-items > .button:hover { background: var(--darkened-bg); }
}
.record-bar .closelink { border: 1px solid var(--border-color); color: var(--body-fg); background: var(--close-button-bg, var(--darkened-bg)); }
@media (max-width: 767px) {
  .record-bar { gap: 6px; }
  .record-bar .record-bar-actions .button { margin-left: 0 !important; }
}
#changelist .actions button.button, #changelist .actions a.button, .record-actions .button {
  display: inline-flex; align-items: center; box-sizing: border-box; height: auto;
  min-height: 1.75rem; margin: 0; padding: 4px 10px; font-size: 0.8125rem; line-height: 1;
  border: 1px solid var(--border-color); border-radius: 4px; background: var(--body-bg);
  box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; color: var(--body-fg);
  text-decoration: none; cursor: pointer;
}
#changelist .actions button.button:hover, #changelist .actions button.button:focus,
#changelist .actions a.button:hover, #changelist .actions a.button:focus,
.record-actions .button:hover, .record-actions .button:focus {
  border-color: var(--body-quiet-color);
}
#changelist .actions a.add, #changelist .actions a.add:hover, #changelist .actions a.add:focus {
  border-color: var(--button-bg); background: var(--button-bg); box-shadow: none;
  color: var(--button-fg); font-weight: 600;
}
#changelist .actions a.add:hover, #changelist .actions a.add:focus {
  background: var(--button-hover-bg);
}
#changelist .actions a.add::before { content: "+"; margin-right: 5px; font-weight: 600; }
#changelist .actions button.delete { color: var(--error-fg); }
#changelist .actions button.delete:hover, #changelist .actions button.delete:focus {
  border-color: var(--error-fg);
}

/* Search boxes (product, partner, account...) fill their column in line tables, so resizing
   the column resizes the box. Select2 writes a fixed pixel width inline, hence !important. */
.inline-group .tabular td .related-widget-wrapper { width: 100%; }
.inline-group .tabular td .select2-container { width: 100% !important; min-width: 14em; max-width: 26em; }
.inline-group .tabular table.cols-fixed td .select2-container { min-width: 0; max-width: none; }
/* Other boxes fill their column too, from a sensible least width, so a table of lines fits the
   page instead of each box keeping Django's fixed width (310px for a vendor's SKU). */
.inline-group .tabular td input[type=text], .inline-group .tabular td textarea {
  width: 100%; min-width: 7em; box-sizing: border-box; }
.inline-group .tabular td textarea { min-width: 12em; }
.inline-group .tabular td input[type=number] { width: 6.5em; box-sizing: border-box; }
.inline-group .tabular td select[multiple] { height: auto; min-height: 0; }  /* sized to its choices: backoffice.js 15 */

/* Two-column record screens (SplitLayoutMixin, templates/admin/split_change_form.html):
   details left, related lists right, a draggable splitter between (backoffice.js, 7).
   Stacked on narrow screens. */
.split-layout { display: grid; gap: 0 28px; align-items: start; }
/* A column may be narrower than its widest dropdown (as wide as its longest choice), which then
   fits the column: so a larger text size (My settings) never makes a phone scroll sideways. */
.split-layout > * { min-width: 0; }
.split-layout select { max-width: 100%; }
#content fieldset { min-width: 0; }  /* browsers make a fieldset as wide as its fields want */
.split-handle { display: none; }
@media (min-width: 1100px) {
  .split-layout { grid-template-columns: minmax(300px, var(--split, 45%)) 20px minmax(380px, 1fr); gap: 0 4px; }
  .split-handle { display: block; align-self: stretch; position: relative; cursor: col-resize; touch-action: none; }
  .split-handle::after {
    content: ""; position: absolute; top: 0; bottom: 0; left: 9px; width: 2px;
    background: var(--hairline-color, #ddd); border-radius: 2px;
  }
  .split-handle:hover::after, .split-handle:focus-visible::after, .split-handle.dragging::after {
    left: 8px; width: 4px; background: var(--primary, #417690);
  }
  .split-handle:focus-visible { outline: none; }
  body.split-resizing { cursor: col-resize; user-select: none; }
  /* The details column: each label beside its value (as on one-column screens), fields filling
     the rest of the row; paired fields one under the other. Only when the column is dragged
     narrow do labels go above their fields (the container query below). */
  .split-left { container: details / inline-size; }
  .split-left .aligned .form-row { padding: 8px 10px; }
  /* Labels line up with the text inside the box beside them; a read-only value shares their baseline. */
  .split-left .aligned .flex-container { align-items: flex-start; }
  .split-left .aligned .flex-container > label:not(.vCheckboxLabel) { flex: none; width: 150px; min-width: 150px;
                                                                     padding-top: 7px; }
  .split-left .aligned .flex-container:has(> .readonly) { align-items: baseline; }
  .split-left .aligned .flex-container:has(> .readonly) > label { padding-top: 0; }
  .split-left .aligned .readonly { margin-left: 0 !important; }
  .split-left form .aligned div.help, .split-left .aligned div.help, .split-left .aligned ul.errorlist { margin-left: 160px; padding-left: 0; }
  .split-left .aligned .flex-container > input:not([type=checkbox]):not(.vDateField):not(.vTimeField),
  .split-left .aligned .flex-container > textarea, .split-left .aligned .flex-container > .related-widget-wrapper,
  .split-left .aligned .flex-container > select { flex: 1 1 auto; min-width: 0; }
  .split-left input[type=text], .split-left input[type=email], .split-left input[type=url],
  .split-left input[type=tel], .split-left input[type=number], .split-left textarea { width: 100%; box-sizing: border-box; }
  .split-left select, .split-left .select2-container { max-width: 100%; }
  .split-left .form-multiline { flex-direction: column; gap: 10px; }
  /* Paired fields stack here, so the second's label takes the label column like any other. */
  .split-left .aligned .form-multiline > div + div > .fieldBox > label:not(.vCheckboxLabel) {
    width: 150px; min-width: 150px; padding-left: 0;
  }
  .split-left .form-multiline > div { margin-right: 0; width: 100%; }
  .split-layout input.vDateField, .split-layout input.vTimeField { width: 10em; }
  @container details (max-width: 459px) {
    .split-left .aligned .flex-container { display: block; }
    .split-left .aligned label { float: none; width: auto; display: block; padding: 0 0 4px; }
    .split-left .aligned .checkbox-row label, .split-left .aligned label.vCheckboxLabel { display: inline; padding: 0 0 0 4px; }
    .split-left .aligned .help, .split-left .aligned div.help, .split-left .aligned ul.errorlist { margin-left: 0; }
  }
}
/* Two fields on one line (one-column screens): the second's label hugs its field instead of
   taking a whole label column, so the pair reads as one row. */
@media (min-width: 768px) {
  .aligned .form-multiline > div + div > .fieldBox > label:not(.vCheckboxLabel) { width: auto; min-width: 0;
                                                                                padding-left: 6px; }
}
/* Narrow screens: Django sizes each row to the screen (100vw - 30px), which overflows once the
   text size (My settings) scales the page: the row's own width instead. Phones lay records out
   in static/backoffice/phone.css: labels above their fields, each section a card. */
@media (max-width: 767px) {
  #content .aligned .form-row > div { width: auto; max-width: 100%; }  /* after responsive.css */
  .aligned .form-multiline { flex-flow: column; gap: 12px; }
}
/* Side panels: compact related lists in the right-hand column. */
.side-panel .form-row { padding: 0; border: 0; }
.side-panel .flex-container { display: block; }
.side-panel .form-row label, .aligned.side-panel label { display: none; }
.side-panel .readonly { margin-left: 0 !important; padding: 0; width: 100%; }
.side-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.side-table th { text-align: left; font-weight: 600; white-space: nowrap; }
.side-table th, .side-table td { padding: 6px 10px; border-bottom: 1px solid var(--hairline-color, #eee); vertical-align: top; }
.side-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.side-table .quiet { color: var(--body-quiet-color); }
.side-more, .side-empty { margin: 8px 10px; font-size: 13px; }
.side-empty { color: var(--body-quiet-color, #666); }

/* The process bar above a record in the sales process (templates/admin/_process_bar.html). */
.process-bar { margin: 0 0 12px; overflow-x: auto; }
.process-bar ol { display: flex; gap: 0; margin: 0; padding: 0; list-style: none; min-width: max-content; }
.process-step { list-style: none; position: relative; display: flex; flex-direction: column; gap: 2px; min-width: 120px;
  padding: 6px 22px 6px 14px; background: var(--darkened-bg); font-size: 12px; line-height: 1.35;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%, 10px 50%); }
.process-step:first-child { clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%); }
.process-step + .process-step { margin-left: -6px; padding-left: 20px; }
.process-label { font-size: 12px; color: var(--body-quiet-color); font-weight: 500; }
.process-step.current { background: var(--button-bg); color: var(--button-fg, #fff); }  /* white on it reads */
.process-step.current .process-label, .process-step.current small, .process-step.current a { color: inherit; }
.process-item { white-space: nowrap; }
.process-item.this { font-weight: 600; }
.process-item small { color: var(--body-quiet-color); }
.process-none { color: var(--body-quiet-color); }
.process-more { font-size: 11px; }

/* A product's picture, first in its right-hand column: medium size, the original on click. */
.product-image .field-image_preview label { display: none; }
.product-image .field-image_preview .readonly { margin-left: 0 !important; padding: 0; }
.product-image .field-image_preview img { display: block; max-width: 100%; max-height: 340px; width: auto;
  border-radius: 8px; border: 1px solid var(--hairline-color); background: #fff; }
.product-image-none { display: block; padding: 40px 0; text-align: center; color: var(--body-quiet-color);
  border: 1px dashed var(--hairline-color); border-radius: 8px; }
.product-image .field-image .help { font-size: 11px; }

/* "＋ New customer" at the foot of a customer search, and its form (quick_add.js) */
.quick-add-foot {
  display: block; width: 100%; padding: 8px 10px; text-align: left; cursor: pointer;
  background: var(--darkened-bg); color: var(--link-fg); border: 0; border-top: 1px solid var(--hairline-color);
  font: inherit;
}
.quick-add-foot:hover { background: var(--selected-row); }
dialog.quick-add {
  width: min(380px, calc(100vw - 32px)); padding: 20px; border: 1px solid var(--border-color);
  border-radius: 6px; background: var(--body-bg); color: var(--body-fg);
}
dialog.quick-add::backdrop { background: rgba(0, 0, 0, .35); }
dialog.quick-add h2 { margin: 0 0 12px; font-size: 1.1rem; }
dialog.quick-add label { display: block; margin-bottom: 10px; font-weight: 600; }
dialog.quick-add input { display: block; width: 100%; box-sizing: border-box; margin-top: 4px; font-weight: normal; }
.quick-add-error { color: var(--error-fg); margin: 0 0 10px; }
.quick-add-error button { margin-left: 4px; }
.quick-add-buttons { display: flex; gap: 8px; margin-top: 14px; }
dialog.quick-add .button { padding: 8px 14px; cursor: pointer; }
dialog.quick-add .button:not(.default) {  /* outlined, as the record bar's secondary steps */
  border: 1px solid var(--border-color); background: var(--body-bg); color: var(--body-fg);
}
dialog.quick-add .button.default { font-weight: 600; }

/* "Show done and cancelled" in a list's filters (admin_utils.hide_finished) */
.filter-checkbox a, .filter-checkbox label { display: flex; align-items: center; gap: 6px; }
.filter-checkbox input { margin: 0; pointer-events: none; }
.filter-checkbox label { color: var(--body-quiet-color); }

/* Search everything: Home's search box and its results (apps/web/search.py) */
.site-search { max-width: 980px; margin: 0 auto 8px; }
.site-search-bar { display: flex; align-items: center; gap: 8px; border: 1px solid var(--border-color);
  border-radius: 10px; padding: 6px 6px 6px 12px; background: var(--body-bg); }
.site-search-bar:focus-within { border-color: var(--primary); }
.site-search-bar svg { width: 20px; height: 20px; color: var(--body-quiet-color); flex: none; }
.site-search-bar input[type=search] { flex: 1; min-width: 0; border: 0; padding: 8px 4px; font-size: 1rem;
  background: transparent; color: var(--body-fg); outline: none; }
.site-search-bar .button { padding: 9px 16px; }
.site-search-advanced { margin-top: 8px; }
.site-search-advanced summary { cursor: pointer; color: var(--link-fg); font-size: .9rem; }
.site-search-tools { margin: 10px 0 4px; }
.site-search-tools button { background: none; border: 0; color: var(--link-fg); cursor: pointer; padding: 0 8px 0 0; font: inherit; font-size: .85rem; }
.site-search-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 4px 24px; }
.site-search-groups fieldset { border: 0; margin: 0; padding: 6px 0; }
.site-search-groups legend { font-size: 12px;
  color: var(--body-quiet-color); font-weight: 500; padding: 0; margin-bottom: 4px; }
.switch { display: flex; align-items: center; gap: 8px; padding: 4px 0; cursor: pointer; font-size: .9rem; }
.switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.switch-track { position: relative; width: 30px; height: 17px; border-radius: 9px; background: var(--border-color);
  flex: none; transition: background .15s; }
.switch-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px;
  border-radius: 50%; background: #fff; transition: transform .15s; }
.switch input:checked + .switch-track { background: var(--primary); }
.switch input:checked + .switch-track::after { transform: translateX(13px); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--primary); outline-offset: 2px; }
.site-search-empty { max-width: 980px; margin: 24px auto; color: var(--body-quiet-color); }
.site-search-results { max-width: 980px; margin: 22px auto 0; }
.site-search-results h2 { display: flex; align-items: center; gap: 8px; font-size: 1rem; margin: 0 0 8px;
  background: none; color: var(--body-fg); padding: 0; }
.site-search-results h2 svg { width: 20px; height: 20px; color: var(--secondary); }
.site-search-results h2 .count { color: var(--body-quiet-color); font-weight: 600; font-size: .85rem; }
.site-search-results ul { list-style: none; margin: 0; padding: 0; border: 1px solid var(--hairline-color); border-radius: 10px; overflow: hidden; }
.site-search-results li { border-top: 1px solid var(--hairline-color); padding: 0; list-style: none; }
.site-search-results li:first-child { border-top: 0; }
.site-search-results li a { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; padding: 10px 14px; color: var(--body-fg); }
.site-search-results li a:hover { background: var(--selected-row); }
.site-search-results li span { color: var(--body-quiet-color); font-size: .88rem; }
.site-search-results li .snippet { flex-basis: 100%; }
.site-search-results .more { margin: 6px 2px 0; font-size: .9rem; }
.process-map .site-search { margin-top: 14px; }
.site-search-finished { margin: 10px 0 2px; font-weight: 600; }
.site-search-finished small { font-weight: normal; color: var(--body-quiet-color); }

/* Create vendor bill: what to bill (purchasing/purchaseorder/bill.html) */
.bill-choice { margin: 12px 0 18px; min-width: min(640px, 100%); }
.bill-choice th, .bill-choice td { padding: 8px 12px; }
.bill-choice .num { text-align: right; font-variant-numeric: tabular-nums; }
.side-note { margin: 6px 0 0; color: var(--body-quiet-color); font-size: .85rem; }

/* A quantity with its unit, switchable (apps/catalog/units.py, static/js/uom-qty.js) */
.uom-qty { white-space: nowrap; font-variant-numeric: tabular-nums; }
.uom-qty select.uom-pick { padding: 1px 2px; font-size: .85em; margin-left: 2px; max-width: 9em; }
.uom-show { margin: 0 0 6px; font-size: .85rem; color: var(--body-quiet-color); }
.uom-show select { font-size: .85rem; }

/* History and Delete, out of the way at the bottom of a record (admin/change_form.html) */
.record-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; margin: 28px 0 8px; }
.record-foot .record-delete { font-size: .85rem; color: var(--body-quiet-color); }
.record-foot .record-delete:hover { color: var(--delete-button-bg, #ba2121); }

/* Save floats at the bottom middle of the screen once something on the record changed, and on
   a new record (backoffice.js 9); on a phone, just above the tab bar. Its size doesn't follow
   the text size (My settings), like the round + on lists. */
.save-float {
  position: fixed; z-index: 850; left: 50%; bottom: calc(var(--tabbar-space, 0px) + 20px);
  transform: translate(-50%, 12px); opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .15s, transform .15s, visibility 0s .15s; zoom: var(--text-unzoom, 1);
}
.save-float.shown { transform: translate(-50%, 0); opacity: 1; visibility: visible; pointer-events: auto;
                    transition: opacity .15s, transform .15s; }
.save-float .submit-row { display: flex; gap: 8px; margin: 0; padding: 0; border: 0; background: none;
                          box-shadow: none; overflow: visible; }
.save-float .submit-row:empty { display: none; }
.save-float .submit-row input[type=submit] {
  float: none; height: auto; min-height: 46px; margin: 0; padding: 0 34px; border: 0; border-radius: 999px;
  background: var(--fab-bg, #2f5d50); color: var(--fab-fg, #fff); font-size: 15px; font-weight: 600;
  letter-spacing: 0; text-transform: none; box-shadow: 0 6px 18px rgba(0, 0, 0, .28); cursor: pointer;
}
.save-float .submit-row input[type=submit]:is(:hover, :focus) { background: var(--fab-bg, #2f5d50); filter: brightness(1.1); }
.save-float .submit-row input[type=submit]:active { transform: scale(.97); }
.save-float .submit-row input[name="_saveasnew"] { background: var(--body-bg); color: var(--body-fg);
                                                   box-shadow: 0 6px 18px rgba(0, 0, 0, .2), inset 0 0 0 1px var(--border-color); }
#content:has(.save-float.shown) { padding-bottom: 90px; }  /* the last of the record clears it */

/* Merge… (admin/core/partner/merge.html) and Possible duplicates */
.merge-pick { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 12px 0; }
.merge-pick .select2-container { min-width: min(420px, 100%); }
.merge-likely { color: var(--body-quiet-color); }
.side-list { margin: 0; padding-left: 18px; }
.side-list li { margin: 4px 0; list-style: disc; }
.merge-confirm { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; }


/* Products list: on hand under the reorder minimum */
.stock-low { color: #a15c00; font-weight: 600; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .stock-low { color: #f0b44c; } }
html[data-theme="dark"] .stock-low { color: #f0b44c; }

/* ---- Titles, breadcrumbs and section headings: one style on every page (derp.css matches it) ---- */
#content h1 { margin: 0 0 16px; font-size: 22px; font-weight: 600; letter-spacing: -.01em; color: var(--body-fg); }
/* A record's page: its number over its name, the page's title (admin/change_form.html), in mono
   like the label on a part bin. */
#content .record-kind { margin: 0 0 2px; font-family: var(--font-family-monospace); font-size: 12px;
                        font-weight: 500; color: var(--body-quiet-color); }
#content .record-kind .record-status { font-family: var(--font-family-primary); }
#content h1.record-name { margin-bottom: 12px; }
/* The lane a page belongs to leads its breadcrumbs, as a label (a lane isn't a page). */
div.breadcrumbs .crumb-section { opacity: .75; }
/* Section headings inside a page are quiet text on a hairline; only the header is a coloured bar. */
/* (#content outranks Django's forms.css, which record pages load after this file.) */
.module h2, .module caption, .inline-group h2,
#content fieldset .fieldset-heading, #content fieldset .inline-heading, #content :not(.inline-related) .collapse summary {
  padding: 12px 10px 8px; background: none; color: var(--body-fg); font-size: 13px; font-weight: 600;
  letter-spacing: 0; text-transform: none; border: 0; border-bottom: 1px solid var(--hairline-color);
}
.inline-group h2 .reorder-lines { border-color: var(--border-color); color: var(--link-fg); }
.inline-group h2 .reorder-lines:hover, .inline-group h2 .reorder-lines:focus-visible {
  background: var(--selected-row); border-color: var(--primary);
}
@media (max-width: 767px) {
  /* "Lane › This list" only repeats the title below it: phones skip it (records keep theirs). */
  div.breadcrumbs:has(> .crumb-section:first-child + [aria-current]:last-child) { display: none; }
}

/* ---- Type: one short scale, used the same way on every screen ----
   page title 22 · section headings 16 · values 14 · labels 13 (grey, all alike; required ones
   marked *) · column headings and small overlines 12, in sentence case. Weights 400 to 600.
   Help text is behind an ⓘ. */
#content fieldset .fieldset-heading, #content .module h2, #content .inline-group h2, #content .module caption,
.split-right .fieldset-heading {
  font-size: 16px; font-weight: 600; letter-spacing: 0;
}
#content .aligned label, #content .form-row label, #content .aligned label.required {
  font-size: 13px; font-weight: 500; color: var(--body-quiet-color);
}
#content .aligned label.required:not(.vCheckboxLabel)::after, #content .aligned .required-mark {
  content: "*"; display: inline; height: auto; margin-left: 2px; color: var(--link-fg); font-weight: 600;
  vertical-align: baseline;
}
#content .aligned label.required:has(.required-mark)::after { content: none; }  /* help.js put it before the ⓘ */
/* A tick box's label is as wide as its words (Django gives every label a fixed width). */
#content .aligned .vCheckboxLabel { width: auto; min-width: 0; }
#content .aligned .vCheckboxLabel, #content .form-row .vCheckboxLabel { font-size: 14px; color: var(--body-fg); font-weight: 400; }
#content input[type=text], #content input[type=number], #content input[type=email], #content input[type=url],
#content input[type=tel], #content input[type=password], #content input[type=search], #content input.vDateField,
#content input.vTimeField, #content select, #content textarea, #content .select2-container .select2-selection__rendered,
#content .aligned .readonly, #content .inline-group td, #content .side-table td, #content #result_list td {
  font-size: 14px; font-weight: 400;
}
#content .inline-group thead th, #content .side-table th, #content #result_list thead th, #content thead th {
  font-size: 12px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--body-quiet-color);
}
/* Django's other capitals: the filter sidebar, captions, small headings and its own buttons. */
#changelist-filter h2, #content h5, .object-tools a:link, .object-tools a:visited {
  text-transform: none; letter-spacing: 0;
}
/* Figures line up digit under digit. */
#content td, #content .readonly, .side-table td { font-variant-numeric: tabular-nums; }
/* The toolbar's buttons: filled for the next step, not shouting. */
:is(.record-bar, .record-foot) .button { text-transform: none; letter-spacing: 0; font-size: 13px; }
.record-bar .button.primary-action { font-weight: 600; }
:is(.record-bar, .record-foot) .button:not(.primary-action) { font-weight: 500; }
/* The line's own name Django prints over each row of a line table only repeats the row, so it's
   left out, unless it holds the line's own link (a ticket's Change): then a quiet caption. */
#content .inline-group td.original p { font-size: 11px; font-weight: 400; color: var(--body-quiet-color); }
.inline-group .tabular td.original p:not(:has(a)) { display: none; }
.inline-group .tabular tr.has_original:not(:has(td.original a)) td { padding-top: 8px; }

/* A list's actions (Accept order, Create invoice…) and its "1 of 4 selected" show once a row is
   ticked (admin/actions.html, backoffice.js): until then the row holds only Add and its links. */
#changelist:not(.has-selection) .actions .bulk { display: none; }

/* A list's filters (admin/change_list.html, admin/filter.html), as on Tasks: a row of dropdowns
   under the search, each showing what's picked; on a phone the row opens from a Filters button
   beside the search, which counts those set (backoffice.js). */
.list-toolbar { display: flex; align-items: center; gap: 8px; }
.list-toolbar #toolbar { flex: 1; min-width: 0; margin-bottom: 0; }
.list-filters-toggle { display: none; }
.list-filters { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 10px 0 14px; }
.list-filter { position: relative; }
.list-filter > summary, .list-filter-check > :is(a, label) {
  display: inline-flex; align-items: center; gap: 6px; box-sizing: border-box; min-height: 30px; padding: 4px 12px;
  border: 1px solid var(--border-color); border-radius: 999px; background: var(--body-bg); color: var(--body-fg);
  font-size: 13px; font-weight: 500; line-height: 1.2; white-space: nowrap; cursor: pointer; list-style: none; text-decoration: none; }
.list-filter > summary::-webkit-details-marker { display: none; }
.list-filter > summary::after { content: "▾"; margin-left: 2px; color: var(--body-quiet-color); font-size: .8em; }
.list-filter > summary:hover, .list-filter[open] > summary, .list-filter-check > a:hover { border-color: var(--body-quiet-color); }
.list-filter.active > summary, .list-filter-check.active > a { border-color: var(--primary); background: var(--selected-row); }
.list-filter > summary b { font-weight: 600; }
.list-filter-check input { margin: 0; }
.list-filter > ul { position: absolute; z-index: 50; top: calc(100% + 4px); left: 0; min-width: 200px; max-height: min(60vh, 420px);
  overflow-y: auto; margin: 0; padding: 6px; list-style: none; background: var(--body-bg); border: 1px solid var(--hairline-color);
  border-radius: 10px; box-shadow: 0 10px 28px rgba(0, 0, 0, .16); }
.list-filter li { margin: 0; padding: 0; list-style: none; }
.list-filter li a { display: flex; justify-content: space-between; gap: 12px; padding: 7px 10px; border-radius: 6px;
  color: var(--body-fg); font-size: 13.5px; text-decoration: none; white-space: nowrap; }
.list-filter li a:hover, .list-filter li a:focus-visible { background: var(--darkened-bg); color: var(--body-fg); }
.list-filter li.selected a { color: var(--link-fg); font-weight: 600; }
.list-filter li.selected a::after { content: "✓"; }
.list-filters-link { font-size: 12.5px; white-space: nowrap; }
.list-filters-link.viewlink, .list-filters-link.hidelink { padding-left: 0; background: none; }  /* no blue eye */
@media (max-width: 720px), (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
  .list-filters-toggle { display: inline-flex; flex: none; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px;
    border: 1px solid var(--border-color); border-radius: 8px; background: var(--body-bg); color: var(--body-fg);
    font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; }
  .list-filters-toggle[aria-expanded="true"] { border-color: var(--primary); background: var(--selected-row); }
  .list-filters-count { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px; box-sizing: border-box;
    border-radius: 999px; background: var(--primary); color: #fff; font-size: 12px; }
  .list-filters { display: none; }
  #changelist.filters-open .list-filters { display: flex; }
  /* each choice list opens the width of the screen, under the row */
  .list-filter { position: static; }
  .list-filter > ul { left: 0; right: 0; min-width: 0; max-height: 55vh; }
  .list-filter > summary, .list-filter-check > :is(a, label) { min-height: 38px; padding: 6px 14px; font-size: 14px; }
  .list-filter li a { padding: 12px; font-size: 15px; }
}

/* ---- Record screens: less to scroll past before the lines ---- */

/* A record's status, read-only, beside its number (admin/change_form.html, CompactRecordMixin). */
#content .record-kind .record-status {
  display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 999px; vertical-align: 1px;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0; text-transform: none;
  background: #e3effa; color: #1d4f7c;
}
#content .record-kind .record-status-new { background: #eceeef; color: #4a5056; }
#content .record-kind .record-status-done { background: #e2f1ea; color: #2f5d50; }
#content .record-kind .record-status-ended { background: #eeeeee; color: #6b6b6b; text-decoration: line-through; }
#content .record-kind .record-status-short { background: #fbf1d9; color: #7a5a12; }  /* an order short of parts */

/* A purchase order line's status (purchasing/admin.py, line_progress): how far it's got. */
.line-state { display: inline-block; padding: 1px 8px; border-radius: 10px; line-height: 1.45;
              background: #eceeef; color: #4a5056; }
.line-state-part { background: #fbf1d9; color: #7a5a12; }
.line-state-done { background: #e2f1ea; color: #2f5d50; }
.line-state-over { background: #e3effa; color: #1d4f7c; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :is(.record-status, .line-state) { filter: brightness(.85) saturate(1.1); }
}
:root[data-theme="dark"] :is(.record-status, .line-state) { filter: brightness(.85) saturate(1.1); }

/* Line tables sort by a column (backoffice.js 15): its heading says which way. */
.inline-group .tabular thead th.sortable { cursor: pointer; user-select: none; }
.inline-group .tabular thead th.sortable:hover { color: var(--body-fg); }
.inline-group .tabular thead th.sortable:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.inline-group .tabular thead th.sorted-up::after, .inline-group .tabular thead th.sorted-down::after {
  content: "▲"; margin-left: 4px; font-size: 9px; color: var(--link-fg);
}
.inline-group .tabular thead th.sorted-down::after { content: "▼"; }
.inline-group h2 .line-sort { display: none; }

/* The fields that say what a record is, over its lines (lines_first): side by side, as many to
   a row as fit; a long text box takes the whole row. */
@media (min-width: 768px) {
  .record-head fieldset.aligned { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
                                  column-gap: 24px; align-items: start; }
  .record-head fieldset.aligned > :not(.form-row) { grid-column: 1 / -1; }
  .record-head .form-row:has(textarea), .record-head .form-row.errors { grid-column: 1 / -1; }
  .record-head .aligned .flex-container { align-items: baseline; }
  .record-head .aligned .flex-container > label:not(.vCheckboxLabel) { flex: none; width: 140px; min-width: 140px; }
  .record-head .aligned .flex-container > :is(input:not([type=checkbox]), select, .related-widget-wrapper) {
    flex: 1 1 auto; min-width: 0; }
  .record-head .aligned .readonly { margin-left: 0 !important; }
  .record-head form .aligned div.help, .record-head .aligned div.help { margin-left: 150px; padding-left: 0; }
}
body.change-form #content-main :is(fieldset.module, .inline-group) { margin-bottom: 18px; }
.record-head fieldset.module { margin-bottom: 6px; }

/* Text boxes as tall as what's in them: three lines when empty (a line's, two), scrolling past
   about twenty (backoffice.js 16 where the browser can't). A Markdown editor keeps its own size. */
#content .aligned textarea:not(.kb-editor textarea), #content .inline-group textarea {
  field-sizing: content; min-height: 4.6em; max-height: 26em; }
#content textarea.fits-text { min-height: 4.6em; max-height: 26em; overflow-y: auto; resize: vertical; }
#content .inline-group .tabular textarea { min-height: 2.6em; }

/* On a phone each line of a line table is a card: its product or name across the top, the
   rest under their column names, as many to a row as fit; delete and duplicate in the corner.
   The table's Sort menu sorts it (backoffice.js 15). */
@media (max-width: 720px), (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
  .inline-group { overflow: visible; }
  .inline-group .tabular :is(table, tbody) { display: block; width: auto !important; }
  .inline-group .tabular thead { display: none; }
  .inline-group h2 .line-sort { display: block; min-width: 0; padding: 3px 6px; font-size: 13px; font-weight: 500; }
  /* Its title, then Sort and Reorder at the right; under the title when a long one ("Vendor
     prices") leaves no room. (Floated, they hung below it and squeezed the table aside.) */
  .inline-group h2:has(.line-tools) { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
  .inline-group h2 .line-tools { float: none; margin: 0 0 0 auto; min-width: 0; max-width: 100%; }
  .inline-group .tabular table { clear: both; }
  .inline-group .tabular tr.form-row:not(.empty-form) {
    position: relative; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 96px), 1fr));
    grid-auto-flow: row dense; gap: 8px 12px; padding: 10px; border-bottom: 1px solid var(--hairline-color);
  }
  .inline-group .tabular tr.form-row:nth-child(odd):not(.empty-form) { background: var(--darkened-bg); }
  .inline-group .tabular tr.form-row > td { display: block; padding: 0 !important; border: 0; min-width: 0;
                                            width: auto !important; overflow: visible; }
  .inline-group .tabular tr.form-row > td.hidden, .inline-group .tabular tr.form-row > td.drag-cell,
  .inline-group .tabular tr.form-row > td.original:not(:has(a)) { display: none; }
  .inline-group .tabular tr.form-row > td.line-wide { grid-column: span 2; }
  .inline-group .tabular tr.form-row > :is(td.line-lead, td.original, td:has(textarea), td.field-status) {
    grid-column: 1 / -1; }
  /* the product, then its status (how much has come), then the rest */
  .inline-group .tabular tr.form-row > td.line-lead { order: -2; padding-right: 84px !important; font-weight: 600; }
  .inline-group .tabular tr.form-row > td.field-status { order: -1; }
  .inline-group .tabular tr.form-row > td[data-label]::before {
    content: attr(data-label); display: block; margin-bottom: 2px; font-size: 12px; font-weight: 500;
    color: var(--body-quiet-color);
  }
  .inline-group .tabular tr.form-row > td.line-lead::before { content: none; }
  .inline-group .tabular tr.form-row > td p { margin: 0; padding: 0; }
  .inline-group .tabular tr.form-row > :is(td.delete, td.dup-cell) { position: absolute; top: 10px; width: auto !important; }
  .inline-group .tabular tr.form-row > td.delete { right: 10px; }
  .inline-group .tabular tr.form-row > td.dup-cell { right: 50px; }
  .inline-group .tabular tr.form-row > td.delete:empty { display: none; }
  .inline-group .tabular tr.form-row :is(input:not([type=checkbox]), select, textarea, .select2-container,
                                         .related-widget-wrapper) { width: 100% !important; min-width: 0 !important;
                                                                    max-width: 100%; box-sizing: border-box; }
  .inline-group .tabular tr:is(.add-row, .row-form-errors), .inline-group .tabular tr:is(.add-row, .row-form-errors) > td {
    display: block; }
}

/* ---- Django's own pictures in derp's colours ---- */
/* The date and time pickers' icons are blue pictures: drawn in the link colour instead. */
#content .datetimeshortcuts .date-icon, #content .datetimeshortcuts .clock-icon { background: var(--link-fg); }
#content .datetimeshortcuts .date-icon {
  -webkit-mask: url("../admin/img/icon-calendar.ac7aea671bea.svg") 0 0 / 24px auto no-repeat;
  mask: url("../admin/img/icon-calendar.ac7aea671bea.svg") 0 0 / 24px auto no-repeat; }
#content .datetimeshortcuts .clock-icon {
  -webkit-mask: url("../admin/img/icon-clock.e1d4dfac3f2b.svg") 0 0 / 24px auto no-repeat;
  mask: url("../admin/img/icon-clock.e1d4dfac3f2b.svg") 0 0 / 24px auto no-repeat; }
#content .datetimeshortcuts a:is(:hover, :focus) :is(.date-icon, .clock-icon) { background: var(--link-hover-color); }
/* In a list, "no" is the quiet case: a grey cross, not a red one on every row. */
#result_list img[src$="icon-no.svg"] { filter: grayscale(1); opacity: .45; }
/* A list's columns of figures (backoffice.js, initFigureColumns). */
#result_list .figure { text-align: right; }
#result_list th.figure .text, #result_list th.figure .sortoptions { float: none; }

/* ---- Bills of materials: List | Map (admin/mrp/bom/change_list.html, mrp/maps.py) ---- */
/* The switch sits beside the title, as Tasks' does; the map's boxes and lines are Tasks' map's
   (tasks/tasks.css), coloured here by what each BOM is. */
#content .list-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin: 0 0 16px; }
#content .list-head h1 { margin: 0; }
.view-switch { display: inline-flex; border: 1px solid var(--border-color); border-radius: 8px; overflow: hidden; }
.view-switch a { padding: 4px 14px; font-size: 13px; color: var(--body-fg); background: var(--body-bg);
                 text-decoration: none; }
.view-switch a + a { border-left: 1px solid var(--border-color); }
.view-switch a.active { background: var(--button-bg); color: var(--button-fg, #fff); }
.view-switch a:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
#bom-map-arrow path { fill: #8fa79e; }
.bom-map .bom-made .stripe, .bom-map .bom-made .state, .bom-key.bom-made { fill: #23875a; background: #23875a; }
.bom-map .bom-bought .stripe, .bom-map .bom-bought .state, .bom-key.bom-bought { fill: #2a6aa3; background: #2a6aa3; }
.bom-map .bom-kit .stripe, .bom-map .bom-kit .state, .bom-key.bom-kit { fill: #b07d12; background: #b07d12; }
.bom-map .bom-inactive .stripe, .bom-map .bom-inactive .state, .bom-key.bom-inactive { fill: #8a8a8a; background: #8a8a8a; }
.bom-map .bom-kit .box { stroke-dasharray: 6 4; }  /* never built on its own: its parts go straight in */
.bom-map .bom-inactive .title { fill: var(--body-quiet-color); }
.bom-key { display: inline-block; width: 10px; height: 10px; border-radius: 3px; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .bom-map :is(.stripe, .state) { filter: brightness(1.35); } }
:root[data-theme="dark"] .bom-map :is(.stripe, .state) { filter: brightness(1.35); }
@media (max-width: 767px) { .view-switch a { padding: 9px 18px; font-size: 14px; } }
