/* ======================================================================
   dt_ui.css — THE FINISH LAYER

   One stylesheet, loaded last by all three applications (storefront, admin
   panel, sales terminal), that does three things and nothing else:

     1. TYPE      a proper display/text pairing instead of one weight of one
                  face doing every job, and figures that line up in a column
                  of money because they are tabular.
     2. COLOUR    a single restrained neutral ramp. The old screens mixed
                  Bootstrap greys, Tailwind slates and a few hand-picked
                  hexes; they are close enough to look like a mistake rather
                  than a decision.
     3. SPACING   a rhythm. Padding was set per component as each was built,
                  so cards, tables and form rows all breathed differently.

   WHAT IT DELIBERATELY DOES NOT TOUCH

   Anything inside [id^="print_"]. Those are the A4 documents - invoice,
   estimate, delivery note - which are printed on paper and must keep the
   exact layout, size and colour they already have. Every rule below is
   written so it cannot reach inside them.
   ====================================================================== */

/* ---------------------------------------------------------------- TYPE */
:root {
    --dt-font-text: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --dt-font-head: 'Plus Jakarta Sans', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --dt-font-num:  'Inter', ui-monospace, 'SF Mono', sans-serif;

    /* A spacing scale, so padding is chosen from a set rather than typed. */
    --dt-s1: 4px;  --dt-s2: 8px;  --dt-s3: 12px;
    --dt-s4: 16px; --dt-s5: 24px; --dt-s6: 32px;

    /* One neutral ramp for all three applications. */
    --dt-ink:    #0f172a;
    --dt-body:   #334155;
    --dt-quiet:  #64748b;
    --dt-faint:  #94a3b8;
    --dt-rule:   #e2e8f0;
    --dt-rule-2: #f1f5f9;
}

body {
    font-family: var(--dt-font-text);
    /* Real typographic niceties the browser leaves off by default: proper
       kerning, common ligatures, and contextual alternates. */
    font-feature-settings: 'kern' 1, 'liga' 1, 'calt' 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    letter-spacing: -0.005em;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--dt-font-head);
    font-weight: 700;
    letter-spacing: -0.021em;   /* large type needs to be pulled in */
    line-height: 1.22;
}
h1, .h1, .display-4, .display-5, .display-6 { letter-spacing: -0.03em; }

/* Money and quantities line up in a column only if the digits are all the
   same width. This is the single biggest readability win on a shop. */
.dt-num, .price, .amount, td.text-end, th.text-end,
.table td.text-end, .table th.text-end {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

/* Small print earns its keep by being legible, not merely small. */
small, .small { line-height: 1.5; }
.text-muted { color: var(--dt-quiet) !important; }

/* ------------------------------------------------------------- SPACING */
/* Cards were padded between 12px and 32px depending on when each was
   written. One value, from the scale, applied where nothing overrides it. */
.card > .card-body:not([class*="p-"]) { padding: var(--dt-s5); }
.card > .card-header:not([class*="p-"]),
.card > .card-footer:not([class*="p-"]) { padding: var(--dt-s3) var(--dt-s5); }

/* Table cells: roomier vertically, aligned to the middle, so a row with a
   thumbnail and a row without do not sit at different heights. */
.table > :not(caption) > * > * { padding: 11px 14px; vertical-align: middle; }
.table > thead > tr > th {
    font-family: var(--dt-font-head);
    font-size: 11px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase;
    color: var(--dt-quiet); white-space: nowrap;
}
.table > :not(:first-child) { border-top-width: 1px; }

/* Form rhythm: a label sits close to its field, and fields sit apart. */
.form-label, label.form-label { margin-bottom: 6px; font-weight: 600; letter-spacing: .01em; }
.form-control, .form-select { padding: 9px 13px; }
.form-text { margin-top: 5px; }
.input-group-text { padding: 9px 13px; }

/* Buttons: the label is the shape, so it needs air either side of it. */
.btn { font-weight: 600; letter-spacing: .005em; }
.btn:not(.btn-sm):not(.btn-lg):not([class*="p-"]) { padding: 8px 16px; }
.btn-sm { padding: 5px 11px; }
.btn i + span, .btn i:not(:only-child) { margin-right: 2px; }

/* Modals and alerts, to the same scale. */
.modal-header:not([class*="p-"]) { padding: var(--dt-s4) var(--dt-s5); }
.modal-body:not([class*="p-"])   { padding: var(--dt-s5); }
.modal-footer:not([class*="p-"]) { padding: var(--dt-s3) var(--dt-s5); }
.alert:not([class*="p-"])        { padding: var(--dt-s3) var(--dt-s4); }

/* ------------------------------------------------------ MODAL SIZE
   A modal is sized by the screen, never by what is inside it. Bootstrap's
   modal-lg and modal-xl are fixed pixel widths, so on a laptop the order
   and document modals ran wider than the window and the sides were cut
   off; tall ones pushed their buttons below the fold. Each size now keeps
   its intended width but stops at the viewport, and the body scrolls
   inside the frame so the header and the footer buttons stay put.

   Fullscreen modals are left alone - they are already asking for the
   whole screen, which is the one case where filling it is correct.
   ------------------------------------------------------------------ */
/* Below 576px the sales portal already presents a modal as a sheet across
   the whole screen, so only the height is touched there. */
@media (min-width: 576px) {
    .modal-dialog:not([class*="modal-fullscreen"]) {
        max-width: min(500px, calc(100vw - 2rem));
        margin-left: auto;
        margin-right: auto;
    }
    .modal-dialog.modal-sm:not([class*="modal-fullscreen"]) { max-width: min(300px,  calc(100vw - 2rem)); }
    .modal-dialog.modal-lg:not([class*="modal-fullscreen"]) { max-width: min(800px,  calc(100vw - 2rem)); }
    .modal-dialog.modal-xl:not([class*="modal-fullscreen"]) { max-width: min(1140px, calc(100vw - 2rem)); }
}
.modal-dialog:not([class*="modal-fullscreen"]) > .modal-content {
    max-height: calc(100vh - 2rem);
}
.modal-dialog:not([class*="modal-fullscreen"]) > .modal-content > .modal-body {
    overflow-y: auto;
    overflow-x: hidden;
}

/* Nav tabs stop looking like buttons that failed to render. */
.nav-tabs .nav-link { font-weight: 600; letter-spacing: .01em; }

/* ----------------------------------------------- ONE TAB STRIP, EVERYWHERE
   Every modal that grew tabs grew its own colours with them. The order
   modal's tabs were blue pills, the product modal's were grey underlines,
   the sales portal's were dark chips - three answers to the same question,
   sitting side by side in one product.

   The strip is defined once, here, in terms of the theme's own variables
   rather than fixed hexes, so light and dark are both correct and a portal
   that changes its accent changes its tabs with it.

   Only the strip is touched. The tabbed panes below it - which on the
   order modal are the A4 documents themselves - are reached by nothing
   here, so the printed invoice is exactly as it was.
   -------------------------------------------------------------------- */
.modal .nav-tabs,
.modal .nav-pills {
    --dt-tab-ink:    var(--bs-secondary-color, var(--dt-quiet));
    --dt-tab-on:     var(--bs-primary, #0d6efd);
    --dt-tab-rule:   var(--bs-border-color, var(--dt-rule));
    border-bottom: 1px solid var(--dt-tab-rule);
    flex-wrap: wrap;
    /* NO gap. The separation between tabs comes from the padding on the link
       below, which lives INSIDE the tab and therefore costs the strip nothing.
       A gap does cost it: a two-up strip whose tabs are each w-50 - which is
       how the storefront's Login / Register dialog is built - then measures
       100% plus the gap, and flex-wrap does exactly what it is asked to and
       drops Register onto a line of its own. */
}
.modal .nav-tabs .nav-link,
.modal .nav-pills .nav-link {
    color: var(--dt-tab-ink);
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: 10px 14px;
    white-space: nowrap;
}
.modal .nav-tabs .nav-link:hover,
.modal .nav-pills .nav-link:hover {
    color: var(--dt-tab-on);
    background: transparent;
    border-bottom-color: var(--dt-tab-rule);
}
.modal .nav-tabs .nav-link.active,
.modal .nav-tabs .nav-item.show .nav-link,
.modal .nav-pills .nav-link.active {
    color: var(--dt-tab-on);
    background: transparent;
    border-bottom-color: var(--dt-tab-on);
}
.modal .nav-tabs .nav-link:focus-visible,
.modal .nav-pills .nav-link:focus-visible {
    outline: 2px solid var(--dt-tab-on);
    outline-offset: -2px;
    box-shadow: none;
}

/* ------------------------------------------------------ THE PAYMENT SLIP
   A receipt for one payment is a document, so it prints on the same white
   sheet the invoice does - but on screen it lives in a modal, and a long
   reference or a tall logo used to push the figures out of the frame.
   Nothing here changes what goes on paper; it only keeps the sheet inside
   the window it is being read in.
   -------------------------------------------------------------------- */
/* White paper, dark ink, whatever the screen theme is - the same rule the rest
   of the printed documents follow. The markup asks for it with .bg-white, but
   both portals redefine that class for dark mode, so it is stated outright
   here rather than left to a utility that another stylesheet has re-aimed. */
#print_due_slip { background: #ffffff; color: #212529; overflow-x: auto; }
#print_due_slip img { max-height: 34px; max-width: 190px; object-fit: contain; }
#print_due_slip table { width: 100%; }
#print_due_slip td, #print_due_slip th { overflow-wrap: anywhere; word-break: break-word; }
@media (max-width: 575.98px) {
    #print_due_slip { padding: 12px !important; font-size: 13px; }
    #print_due_slip img { max-height: 26px; max-width: 140px; }
}

/* -------------------------------------------- THE RECEIPT AS A SECOND COLUMN
   The due's own receipt is an offcanvas rather than a second modal, so there
   is no second backdrop to be left behind when one of the two is closed.

   On a wide screen it takes a column on the right and the invoice slides left
   to make room, which is what the client asked for: the receipt beside the
   document it settles, not covering it. On a phone there is no room for two
   columns, so it takes the screen and the invoice waits underneath.
   -------------------------------------------------------------------- */
.dt-due-canvas {
    --dt-due-w: 520px;
    width: var(--dt-due-w);
    max-width: 100vw;
    z-index: 1058;                 /* above a modal (1055), below a toast */
    display: flex;
    flex-direction: column;
}
.dt-due-canvas .offcanvas-body { flex: 1 1 auto; overflow-y: auto; }
.dt-due-canvas-foot { flex: 0 0 auto; background: inherit; }

@media (max-width: 767.98px) {
    /* One column at a time. The receipt is a document and needs the width
       more than the invoice behind it does, which is not being read yet. */
    .dt-due-canvas { --dt-due-w: 100vw; }
    .dt-due-canvas .offcanvas-body { padding: var(--dt-s3) !important; }
    .dt-due-canvas #print_due_slip { padding: 12px !important; font-size: 13px; }
    .dt-due-canvas #print_due_slip img { max-height: 26px; max-width: 140px; }
}

/* The invoice steps aside rather than being covered. Only on a screen wide
   enough for two columns, and only while the panel is actually open - the
   class goes on <body> when it shows and comes off when it hides. */
@media (min-width: 992px) {
    body.dt-due-open .modal-dialog {
        transform: translateX(-260px);
        transition: transform .3s ease;
    }
    .modal-dialog { transition: transform .3s ease; }
}

/* ------------------------------------------------ ANYTHING BUT THE PRINT
   Everything above is written not to reach the A4 documents, but a rule
   inherited through <body> still would. This puts the paper back exactly
   as it was: its own metrics, its own colour, its own typeface.
   -------------------------------------------------------------------- */
[id^="print_"],
[id^="print_"] * {
    font-family: 'Inter', Arial, Helvetica, sans-serif !important;
    letter-spacing: normal !important;
}
[id^="print_"] h1, [id^="print_"] h2, [id^="print_"] h3,
[id^="print_"] h4, [id^="print_"] h5, [id^="print_"] h6 { letter-spacing: normal !important; }
[id^="print_"] .table > :not(caption) > * > * { padding: 6px 8px !important; vertical-align: top !important; }
[id^="print_"] .table > thead > tr > th {
    font-size: inherit !important; text-transform: none !important;
    letter-spacing: normal !important;
}
[id^="print_"] .card > .card-body { padding: inherit !important; }

/* ---------------------------------------------- DOCUMENT TABLE HEADINGS
   A column heading used to be told `color: inherit`, which meant it took
   the colour of the sheet it sits on - #212529 on a white page. That is
   right for an ordinary heading and wrong for the dark strip the invoice
   uses for its item header: dark text on a dark bar, which is what was
   being reported as headings you cannot read. Every heading is now told
   its own colour outright, the same colour in dark mode as in light,
   because the sheet is printed either way.

   The doubled attribute selector is deliberate. This file loads after
   both dashboards, but the portals carry `[data-theme="dark"] [id^="print_"]
   .table th` rules that are one class-level heavier than a plain
   `[id^="print_"] .table ...`; repeating the attribute puts these level
   with them and lets source order decide, so there is one place that
   settles what colour a heading is.
   -------------------------------------------------------------------- */
[id^="print_"][id^="print_"] {
    color-scheme: light;
    --bs-body-color: #212529;
    --bs-body-bg: #ffffff;
    --bs-emphasis-color: #212529;
    --bs-emphasis-color-rgb: 33, 37, 41;
    --bs-heading-color: inherit;
    --bs-border-color: #dee2e6;
}
[id^="print_"][id^="print_"] .table {
    --bs-table-color: #212529;
    --bs-table-bg: #ffffff;
    --bs-table-border-color: #dee2e6;
    --bs-table-striped-color: #212529;
    --bs-table-striped-bg: rgba(0, 0, 0, .05);
}
/* The ordinary heading: dark on the white sheet. */
[id^="print_"][id^="print_"] .table > thead > tr > th,
[id^="print_"][id^="print_"] .table > thead > tr > td {
    color: #212529 !important;
    background-color: #ffffff !important;
}
[id^="print_"][id^="print_"] .table > thead.bg-light > tr > th,
[id^="print_"][id^="print_"] .table > thead > tr.table-light > th,
[id^="print_"][id^="print_"] .table > thead > tr.table-light > td,
[id^="print_"][id^="print_"] .table.table-light > thead > tr > th {
    color: #212529 !important;
    background-color: #f1f3f5 !important;
}
/* The invoice item header is a dark strip in both themes - white on it. */
[id^="print_"][id^="print_"] .table > thead > tr.table-dark > th,
[id^="print_"][id^="print_"] .table > thead > tr.table-dark > td,
[id^="print_"][id^="print_"] .table.table-dark > thead > tr > th,
[id^="print_"][id^="print_"] tr.table-dark > th,
[id^="print_"][id^="print_"] tr.table-dark > td {
    color: #ffffff !important;
    background-color: #212529 !important;
    border-color: #373b3e !important;
}
[id^="print_"][id^="print_"] .table > tbody > tr > th,
[id^="print_"][id^="print_"] .table > tbody > tr > td,
[id^="print_"][id^="print_"] .table > tfoot > tr > th,
[id^="print_"][id^="print_"] .table > tfoot > tr > td {
    color: #212529;
    background-color: transparent;
}

@media print {
    /* Belt and braces: on paper, nothing from this file applies at all. */
    body { letter-spacing: normal; }
}

/* ==================================================================== */
/*  DOCUMENT PAGES                                                      */
/*                                                                      */
/*  The invoice, the estimate and the order each have a page of their   */
/*  own now rather than a modal. Two things matter here: the sheet has  */
/*  to read like paper on screen, and the edit affordance has to be     */
/*  obvious without being loud - a figure you may change should look    */
/*  changeable when Edit is on, and exactly like a printed figure when  */
/*  it is off.                                                          */
/* ==================================================================== */
.dt-dp-bar {
    top: 0;
    z-index: 1010;
    background: var(--bs-body-bg, #fff);
    border-bottom: 1px solid var(--bs-border-color, #e2e8f0);
}
.dt-dp-sheet {
    /* Paper, whatever the screen theme is - the same rule every other
       printed document in this codebase follows. */
    background: #ffffff !important;
    color: #212529 !important;
    max-width: 1000px;
    margin-left: auto;
    margin-right: auto;
}
@media (max-width: 767.98px) {
    .dt-dp-sheet { padding: 1.25rem !important; }
}

/* A value that can be edited, while editing is off: no decoration at all. */
.dt-ed { display: inline-block; }

/* While editing is on: a dotted underline and a pointer, so it reads as
   "click me" without turning the invoice into a form. */
.dt-dp-editing .dt-ed {
    cursor: pointer;
    border-bottom: 1px dashed #0d6efd;
    padding: 0 2px;
    border-radius: 3px;
}
.dt-dp-editing .dt-ed:hover { background: rgba(13, 110, 253, .08); }
.dt-dp-editing .dt-ed.dt-ed-open { border-bottom-color: transparent; background: transparent; }

/* The per-line delete button and the image-upload camera overlay are staff
   controls, not part of the document itself - they should only appear once
   Edit is actually switched on, the same as every editable field above.
   Having permission to edit is not the same thing as currently editing;
   these were rendering unconditionally on permission alone. */
.dt-doc-line-del,
.dt-doc-img-edit { display: none !important; }
.dt-dp-editing .dt-doc-line-del { display: inline-flex !important; }
.dt-dp-editing .dt-doc-img-edit { display: block !important; }

/* The box that replaces the text. Sized to the cell it sits in rather than
   to a fixed width, so a table does not jump when one opens. */
.dt-ed input.dt-ed-in,
.dt-ed textarea.dt-ed-in {
    width: 100%;
    min-width: 70px;
    padding: 2px 6px;
    font: inherit;
    color: #212529;
    background: #fffbe6;
    border: 1px solid #f59e0b;
    border-radius: 4px;
}
.dt-ed textarea.dt-ed-in { min-height: 62px; }
.dt-ed.dt-ed-dirty input.dt-ed-in,
.dt-ed.dt-ed-dirty textarea.dt-ed-in { background: #fff3cd; border-color: #d97706; }
td .dt-ed, th .dt-ed { display: block; }

/* Nothing above belongs on paper. */
@media print {
    .dt-dp-bar { display: none !important; }
    .dt-dp-sheet { border: 0 !important; box-shadow: none !important; max-width: none; }
    .dt-ed { border: 0 !important; background: none !important; }
}

/* ----------------------------------------------------------------------
   THE SMALL VAT SWITCH

   It sits in the strip that stays in view while the cart scrolls, beside
   the item count and the running total, so the answer to "is there tax on
   this?" is never off screen. It is styled here rather than with Bootstrap
   button classes because it has to read as a quiet setting next to those
   chips, not as two more things to press.
   ---------------------------------------------------------------------- */
.dt-vat-mini { flex: 0 0 auto; }
.dt-vat-mini .dt-vat-pick {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .2px;
    padding: 2px 9px;
    border: 1px solid var(--line, #dee2e6);
    background: var(--surface, #fff);
    color: var(--muted, #6c757d);
    line-height: 1.5;
}
.dt-vat-mini .dt-vat-pick:first-child  { border-radius: 999px 0 0 999px; }
.dt-vat-mini .dt-vat-pick:last-child   { border-radius: 0 999px 999px 0; margin-left: -1px; }
.dt-vat-mini .dt-vat-pick:hover        { color: var(--text, #212529); }
.dt-vat-mini .dt-vat-pick.active {
    background: var(--pri, #4f46e5);
    border-color: var(--pri, #4f46e5);
    color: #fff;
    z-index: 1;
}

/* The custom-item box is now a form of six fields rather than three, so its
   description reads as a description and not as a second name box. */
.dt-cu-box textarea.dt-cu-desc { min-height: 46px; resize: vertical; }

/* ----------------------------------------------------------------------
   FILTER FORMS

   A dropdown in a filter form applies itself the moment it changes, so the
   Apply button is only ever needed for the boxes people type into. It is
   marked while there is something typed but not yet applied, because a
   button that looks identical whether or not it has work to do is a button
   people stop believing in.
   ---------------------------------------------------------------------- */
.dt-filter-dirty {
    animation: dtFilterNudge 1.4s ease-in-out 2;
}
@keyframes dtFilterNudge {
    0%, 100% { transform: none; }
    40%      { transform: translateY(-2px); }
    70%      { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .dt-filter-dirty { animation: none; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25); }
}

/* ======================================================================
   ONE STACKING SCALE

   Layer numbers were being invented at each call site - 3, 5, 10, 1019,
   1020, 1025, 1030, 1035, 1040, 1048 - and the only way to know whether a
   new one was safe was to grep for all the others. That is how a floating
   button ends up over the menu that is supposed to have covered it.

   These are the only numbers any of it should use. They are var()s so a
   layer can be moved once, here, and everything that names it follows.
   The values leave Bootstrap's own scale alone: dropdown 1000, sticky
   1020, fixed 1030, offcanvas 1045, modal 1055, popover 1070, tooltip
   1080 - ours sit BETWEEN those rather than fighting them.
   ====================================================================== */
:root {
    --dt-z-raised:     1;      /* lifted off the page, still inside its card  */
    --dt-z-pinned:     3;      /* a heading pinned inside a scrolling card    */
    --dt-z-column:     1020;   /* a whole column pinned on a phone            */
    --dt-z-bottomnav:  1025;   /* the bottom bar on a phone                   */
    --dt-z-topbar:     1030;   /* the bar across the top of the page          */
    --dt-z-backdrop:   1035;   /* the dimming behind the menu                 */
    --dt-z-sidebar:    1040;   /* the menu itself, above its own backdrop     */
    --dt-z-float:      1042;   /* a floating action pill: above the page,     */
                               /* BELOW the menu and its backdrop, because a  */
                               /* button floating over a dimmed screen is the */
                               /* clearest way to say the dimming is a lie    */
    --dt-z-offcanvas:  1045;
    --dt-z-modal:      1055;
    --dt-z-duecanvas:  1058;   /* the payments panel, beside an open document */
    --dt-z-toast:      1090;   /* above everything: it reports on all of it   */
}

/* A card that pins itself does NOT need a z-index of its own, and giving it
   one is actively harmful: any positioned element inside it - a dropdown, a
   date picker, a tooltip - is then sealed into that layer and cannot rise
   above anything outside the card, however high a number it asks for. The
   cart column is the one that bit; it is unset here rather than at the call
   site so the reason travels with the rule. */
#posWrap #cartColumn > form,
#cartColumn > form { z-index: auto; }


/* ======================================================================
   THE SEARCHABLE PICKERS

   Select2 sizes its dropdown from the control it is attached to and hangs
   it off the end of the document. Where the options are long - a product
   name, its code, its price and its stock all on one line - the panel came
   out wider than the window, and a panel wider than the window gives the
   WHOLE PAGE a horizontal scrollbar. The Book Order screen picked up a
   sideways scroll the moment Advanced Find was opened, and the list inside
   it had a second scrollbar of its own.

   Nothing here changes what the picker does. It is only told that it may
   not be wider than the window it is drawn in, and that a long option
   should wrap rather than run off the side.
   ====================================================================== */
.select2-container .select2-dropdown,
.select2-container--open .select2-dropdown {
    max-width: calc(100vw - 24px);
    box-sizing: border-box;
}
.select2-container .select2-results__options {
    overflow-x: hidden;
}
.select2-container .select2-results__option {
    /* A product whose name and code will not fit takes a second line. That
       is a better answer than a scrollbar the user has to find and drag
       before they can read what they are picking. */
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
}
/* The control itself, likewise: it lives in a card and must not push it. */
.select2-container { max-width: 100%; }
.select2-container .select2-selection__rendered { overflow-wrap: anywhere; }

/* ----------------------------------------------------------------------
   ADDING A LINE, WHERE THE LINE WILL GO

   This panel used to sit above the whole document, a screen away from the
   table the line it adds will appear in. It now sits directly under the
   last row, so the form and its result are in the same place - and it
   reads as part of the table rather than as a separate thing floating
   over the page.
   ---------------------------------------------------------------------- */
.dt-dp-sheet .dt-dp-add {
    margin: -6px 0 18px;
    padding: 14px 16px 10px;
    border: 1px dashed rgba(13, 110, 253, .38);
    border-top: 0;
    border-radius: 0 0 12px 12px;
    background: rgba(13, 110, 253, .045);
}
.dt-dp-sheet .dt-dp-add .dt-cu-box > summary { color: #0d6efd; }
.dt-dp-sheet .dt-dp-adds:not(:empty) {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(13, 110, 253, .28);
}

/* ======================================================================
   THE BAR ALONG THE BOTTOM

   On a phone the things people reach for most are at the top of the page,
   behind a menu button, at the end of a scroll. Every shopping app in the
   world has answered this the same way: a fixed row of five along the
   bottom, thumb height, always there.

   Defined once here and used by the storefront and the admin panel, so
   the two cannot drift apart the way the tab strips did. The sales portal
   already had its own; this is deliberately built to match it, down to the
   raised circle in the middle for the one action that matters most.
   ====================================================================== */
.dt-botnav {
    display: none;
    position: fixed; bottom: 0; left: 0; right: 0;
    z-index: var(--dt-z-bottomnav, 1025);
    background: var(--dt-botnav-bg, rgba(255, 255, 255, .94));
    backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
    border-top: 1px solid var(--dt-botnav-line, rgba(2, 8, 23, .10));
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
    box-shadow: 0 -8px 30px rgba(2, 8, 23, .10);
}
.dt-botnav .dt-bn {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px;
    text-align: center; text-decoration: none;
    color: var(--dt-botnav-ink, #64748b);
    font-size: 10px; font-weight: 700; letter-spacing: .01em;
    padding: 5px 2px 3px; border: 0; background: transparent; border-radius: 14px;
    min-height: 48px;
    transition: color .18s ease, transform .18s ease;
}
.dt-botnav .dt-bn i { font-size: 18px; line-height: 1; transition: transform .18s ease; }
.dt-botnav .dt-bn span { display: block; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dt-botnav .dt-bn.active { color: var(--dt-botnav-on, #4f46e5); }
.dt-botnav .dt-bn.active i { transform: translateY(-2px); }
.dt-botnav .dt-bn:active { transform: scale(.93); }

/* The one action worth raising out of the row. */
.dt-botnav .dt-bn-cta { flex: 0 0 66px; margin-top: -26px; }
.dt-botnav .dt-bn-cta .dt-bn-circle {
    width: 50px; height: 50px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--dt-botnav-on, #4f46e5); color: #fff;
    box-shadow: 0 8px 20px rgba(79, 70, 229, .40);
    margin-bottom: 2px;
}
.dt-botnav .dt-bn-cta .dt-bn-circle i { font-size: 19px; }

/* A count on a tab - basket, wishlist - sits on the icon, not beside it. */
.dt-botnav .dt-bn-count {
    position: absolute; transform: translate(14px, -8px);
    min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: 99px; background: #ef4444; color: #fff;
    font-size: 9.5px; line-height: 16px; font-weight: 800;
}
.dt-botnav .dt-bn-count:empty,
.dt-botnav .dt-bn-count[data-zero="1"] { display: none; }

@media (max-width: 991.98px) {
    .dt-botnav { display: flex; align-items: flex-end; }
    /* Room for it, so the last thing on the page is never underneath it. */
    body.dt-has-botnav { padding-bottom: 74px; }
}
@media print { .dt-botnav { display: none !important; } }

[data-theme="dark"] .dt-botnav,
[data-bs-theme="dark"] .dt-botnav {
    --dt-botnav-bg: rgba(15, 23, 42, .94);
    --dt-botnav-line: rgba(255, 255, 255, .10);
    --dt-botnav-ink: #94a3b8;
}

/* ----------------------------------------------------------------------
   THE THUMBNAIL IN ADVANCED FIND

   The admin panel sized this with `#posWrap .qf-img`. Select2 hangs its
   dropdown off the END OF THE DOCUMENT, not off the control it belongs to,
   so the panel is never inside #posWrap and that rule never matched a
   single one of these images. A product photo then rendered at whatever
   size the file happened to be - one row of the list swallowing the whole
   panel, which is exactly what the client's screenshot shows.

   So the rule is written UNSCOPED, here, where it applies wherever the
   dropdown ends up. The height is pinned as well as the width: a rule that
   sets only the width lets a tall photo stretch the row instead, which
   looks like a different bug and is the same one.
   ---------------------------------------------------------------------- */
.qf-img {
    width: 50px;
    height: 50px;
    min-width: 50px;
    object-fit: cover;
    border-radius: 9px;
    margin-right: 10px;
    flex-shrink: 0;
    border: 1px solid var(--dt-rule, #e2e8f0);
    background: var(--dt-quiet-bg, #f1f5f9);
}
