/* ============================================================================
   KOOMI POS — GLOBAL DESIGN SYSTEM
   ============================================================================

   THIS IS THE SINGLE SOURCE OF TRUTH FOR THE APPLICATION'S LOOK.

   Change a value in the token block below and it updates everywhere:
   every button, input, dropdown, card, table, modal, badge and page shell
   in the whole POS. Nothing else in the app should hardcode a colour,
   a radius, a shadow or a control height.

   ---------------------------------------------------------------------------
   WHY THIS FILE EXISTS
   ---------------------------------------------------------------------------
   The app had grown four competing token namespaces, each with a different
   idea of what "primary" meant:

       --ui-*      in style.css          primary #1d4ed8   (indigo)
       --koomi-*   in view-consistency   primary #3498db   (sky)
       --kp-*      in koomi-theme.css    primary #ff7a00   (orange, dead file)
       raw hex     #3497d3 x359 in style.css, plus ad-hoc hexes in 15 views

   So a button, a breadcrumb link and a pagination pill on the same screen
   could each be a different blue. This file collapses all four namespaces
   onto one canonical `--k-*` set: the legacy names are re-declared here as
   aliases, so every rule already written against them inherits the correct
   value without needing to be touched.

   LOAD ORDER MATTERS: this file is loaded LAST (see layout/partials/head),
   after style.css and the other koomi-*.css files, so both its token
   re-declarations and its component rules win the cascade.
   ============================================================================ */

/* ============================================================================
   1. TOKENS — the only place values are defined
   ============================================================================ */

:root {
    /* ── Brand ──────────────────────────────────────────────────────────── */
    --k-primary:            #2563eb;
    --k-primary-strong:     #1d4ed8;
    --k-primary-darker:     #1e40af;
    --k-primary-soft:       #eff6ff;
    --k-primary-border:     #bfdbfe;
    --k-primary-rgb:        37, 99, 235;

    /* ── Semantic ───────────────────────────────────────────────────────── */
    --k-success:            #059669;
    --k-success-strong:     #047857;
    --k-success-soft:       #ecfdf5;
    --k-success-border:     #a7f3d0;

    --k-danger:             #dc2626;
    --k-danger-strong:      #b91c1c;
    --k-danger-soft:        #fef2f2;
    --k-danger-border:      #fecaca;

    --k-warning:            #d97706;
    --k-warning-strong:     #b45309;
    --k-warning-soft:       #fffbeb;
    --k-warning-border:     #fde68a;

    --k-info:               #0891b2;
    --k-info-strong:        #0e7490;
    --k-info-soft:          #ecfeff;
    --k-info-border:        #a5f3fc;

    /* ── Neutrals / surfaces ────────────────────────────────────────────── */
    --k-bg:                 #f5f7fb;   /* page background            */
    --k-surface:            #ffffff;   /* cards, modals, table body  */
    --k-surface-soft:       #f8fafc;   /* table head, inset panels   */
    --k-surface-hover:      #f1f5f9;

    --k-border:             #e5e9f0;   /* default hairline           */
    --k-border-strong:      #d3dae5;   /* input borders              */
    --k-border-focus:       var(--k-primary);

    /* ── Text ───────────────────────────────────────────────────────────── */
    --k-text:               #0f172a;   /* headings, primary copy     */
    --k-text-body:          #334155;   /* body copy                  */
    --k-text-muted:         #64748b;   /* labels, help text          */
    --k-text-soft:          #94a3b8;   /* placeholders, icons        */
    --k-text-invert:        #ffffff;

    /* ── Typography ─────────────────────────────────────────────────────── */
    --k-font: "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    --k-fs-page-title:      22px;   /* page <h1>                     */
    --k-fs-section-title:   15px;   /* card / form section heading   */
    --k-fs-base:            14px;   /* inputs, buttons, body         */
    --k-fs-table:           13.5px;
    --k-fs-table-head:      12.5px;
    --k-fs-label:           13px;
    --k-fs-help:            12px;
    --k-fs-badge:           11.5px;

    --k-fw-normal:          500;
    --k-fw-medium:          600;
    --k-fw-bold:            700;

    /* ── Spacing scale ──────────────────────────────────────────────────── */
    --k-space-1:            4px;
    --k-space-2:            8px;
    --k-space-3:            12px;
    --k-space-4:            16px;
    --k-space-5:            20px;
    --k-space-6:            24px;
    --k-space-8:            32px;

    --k-page-pad:           24px;   /* .content padding              */
    --k-card-pad:           20px;   /* card body padding             */
    --k-field-gap:          16px;   /* vertical gap between fields   */

    /* ── Radii ──────────────────────────────────────────────────────────── */
    --k-radius-sm:          8px;    /* badges, small chips           */
    --k-radius:             10px;   /* inputs, buttons               */
    --k-radius-lg:          14px;   /* cards, modals, table frame    */
    --k-radius-pill:        999px;

    /* ── Shadows ────────────────────────────────────────────────────────── */
    --k-shadow-xs:          0 1px 2px rgba(15, 23, 42, .05);
    --k-shadow-sm:          0 2px 8px rgba(15, 23, 42, .05);
    --k-shadow:             0 4px 16px rgba(15, 23, 42, .07);
    --k-shadow-lg:          0 12px 32px rgba(15, 23, 42, .10);
    --k-shadow-focus:       0 0 0 3px rgba(var(--k-primary-rgb), .15);

    /* ── Control sizing — ONE height for every input, select and button ─── */
    --k-control-h:          42px;
    --k-control-h-sm:       34px;
    --k-control-h-lg:       48px;
    --k-control-pad-x:      13px;

    /* ── Motion ─────────────────────────────────────────────────────────── */
    --k-transition:         150ms ease;

    /* ── Layering — keeps dropdowns above sticky headers and inside modals ─ */
    --k-z-dropdown:         1060;
    --k-z-modal:            1055;
    --k-z-toast:            1080;
}

/* ---------------------------------------------------------------------------
   1b. LEGACY NAMESPACE ALIASES
   Every historical token now resolves to a canonical one. This is what makes
   the pre-existing rules in style.css / koomi-tables.css / view-consistency
   agree with each other without editing hundreds of declarations.
   --------------------------------------------------------------------------- */
:root {
    /* style.css "modern UI" layer */
    --ui-bg:            var(--k-bg);
    --ui-surface:       var(--k-surface);
    --ui-surface-soft:  var(--k-surface-soft);
    --ui-border:        var(--k-border);
    --ui-text:          var(--k-text);
    --ui-muted:         var(--k-text-muted);
    --ui-primary:       var(--k-primary);
    --ui-primary-strong:var(--k-primary-strong);
    --ui-primary-soft:  var(--k-primary-soft);
    --ui-success:       var(--k-success);
    --ui-warning:       var(--k-warning);
    --ui-danger:        var(--k-danger);
    --ui-radius-xl:     var(--k-radius-lg);
    --ui-radius-lg:     var(--k-radius-lg);
    --ui-radius-md:     var(--k-radius);
    --ui-shadow:        var(--k-shadow);
    --ui-shadow-soft:   var(--k-shadow-sm);

    /* koomi-view-consistency.css */
    --koomi-card-radius: var(--k-radius-lg);
    --koomi-border:      var(--k-border);
    --koomi-muted:       var(--k-text-muted);
    --koomi-title:       var(--k-text);
    --koomi-bg-soft:     var(--k-surface-soft);
    --koomi-primary:     var(--k-primary);
    --koomi-danger:      var(--k-danger);

    /* koomi-tables.css */
    --koomi-tbl-border:  var(--k-border);
    --koomi-tbl-line:    var(--k-surface-hover);
    --koomi-tbl-head-bg: var(--k-surface-soft);
    --koomi-tbl-head-fg: var(--k-text);
    --koomi-tbl-fg:      var(--k-text-body);
    --koomi-tbl-muted:   var(--k-text-muted);
    --koomi-tbl-hover:   var(--k-primary-soft);
    --koomi-tbl-radius:  var(--k-radius-lg);

    /* koomi-theme.css (retired file — aliases kept so any stray rule agrees) */
    --kp-primary:     var(--k-primary);
    --kp-secondary:   var(--k-text);
    --kp-success:     var(--k-success);
    --kp-warning:     var(--k-warning);
    --kp-danger:      var(--k-danger);
    --kp-info:        var(--k-info);
    --kp-body-bg:     var(--k-bg);
    --kp-card-bg:     var(--k-surface);
    --kp-border:      var(--k-border);
    --kp-text:        var(--k-text);
    --kp-text-muted:  var(--k-text-muted);
    --kp-radius-sm:   var(--k-radius-sm);
    --kp-radius-md:   var(--k-radius);
    --kp-radius-lg:   var(--k-radius-lg);

    /* Bootstrap 5 — so native components (pagination, close, form-check,
       validation, spinners) match without per-component overrides. */
    --bs-primary:       var(--k-primary);
    --bs-primary-rgb:   var(--k-primary-rgb);
    --bs-danger:        var(--k-danger);
    --bs-success:       var(--k-success);
    --bs-warning:       var(--k-warning);
    --bs-info:          var(--k-info);
    --bs-body-color:    var(--k-text-body);
    --bs-body-bg:       var(--k-bg);
    --bs-border-color:  var(--k-border);
    --bs-border-radius: var(--k-radius);
    --bs-link-color:    var(--k-primary);
    --bs-link-hover-color: var(--k-primary-strong);
}

/* ============================================================================
   2. BASE / TYPOGRAPHY
   ============================================================================ */

body {
    font-family: var(--k-font);
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-body);
    background: var(--k-bg);
    -webkit-font-smoothing: antialiased;
}

.page-wrapper .content {
    padding: var(--k-page-pad);
}

/* One heading scale. Page titles come from x-page-header, section titles from
   x-ui.card / x-ui.form-section — nothing else should set these sizes. */
.page-wrapper .content h1,
.page-wrapper .content h2,
.page-wrapper .content h3,
.page-wrapper .content h4,
.page-wrapper .content h5,
.page-wrapper .content h6 {
    color: var(--k-text);
    font-weight: var(--k-fw-bold);
    letter-spacing: -.01em;
    margin-top: 0;
}

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

a { color: var(--k-primary); text-decoration: none; }
a:hover { color: var(--k-primary-strong); }

/* Numeric columns and money read as columns, not ragged text. */
.k-numeric,
.koomi-money-input,
.k-money { font-variant-numeric: tabular-nums; }

/* ============================================================================
   3. PAGE HEADER + BREADCRUMB
   ============================================================================ */

.page-header,
.koomi-auto-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--k-space-4);
    padding: 0;
    margin: 0 0 var(--k-space-5);
    background: transparent;
    border: 0;
    box-shadow: none;
    /* The header's own stacking context, sitting above the page content.
       A panel opened from a header button (Purchase Order → Documents) is a child
       of this header, while every card below it is position:relative and later in
       the document — without this the cards painted straight over the open panel
       and it was only visible in the gutter between the columns. */
    position: relative;
    z-index: 30;
}

/* An open header panel goes above everything else the header holds. */
.page-header .dropdown-menu,
.koomi-auto-page-header .dropdown-menu {
    z-index: var(--k-z-dropdown);
}

.page-header .page-title h1,
.page-header .page-title h4 {
    font-size: var(--k-fs-page-title);
    font-weight: var(--k-fw-bold);
    color: var(--k-text);
    margin: 0 0 var(--k-space-1);
    line-height: 1.25;
}

.page-header .page-title h6,
.page-header .page-title .k-page-subtitle {
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-muted);
    margin: 0;
}

.page-header .page-btn {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--k-space-2);
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
}

.page-header .breadcrumb,
.koomi-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    background: transparent;
    padding: 0;
    margin: 0;
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
}

.page-header .breadcrumb a { color: var(--k-primary); }
.page-header .breadcrumb a:hover { text-decoration: underline; }
.page-header .breadcrumb .active,
.page-header .breadcrumb .breadcrumb-item.active { color: var(--k-text-muted); }

.page-header .breadcrumb-item + .breadcrumb-item::before {
    content: "/";
    color: var(--k-text-soft);
    padding: 0 var(--k-space-2);
}

/* ============================================================================
   4. CARDS
   ============================================================================ */

.page-wrapper .content .card,
.koomi-unified-card,
.koomi-form-card,
.koomi-show-card,
.k-card {
    background: var(--k-surface);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius-lg);
    box-shadow: var(--k-shadow-sm);
    margin-bottom: var(--k-space-5);
}

.page-wrapper .content .card > .card-header,
.koomi-card-header,
.k-card > .k-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--k-space-3);
    background: var(--k-surface);
    border-bottom: 1px solid var(--k-border);
    border-radius: var(--k-radius-lg) var(--k-radius-lg) 0 0;
    padding: var(--k-space-4) var(--k-card-pad);
    min-height: 0;
}

/* One section-title treatment. Icons inherit the title colour rather than each
   page picking its own — that was the multicolour emoji problem. */
.page-wrapper .content .card > .card-header .card-title,
.k-card-title {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
    font-size: var(--k-fs-section-title);
    font-weight: var(--k-fw-bold);
    color: var(--k-text);
    margin: 0;
    line-height: 1.3;
}

/* Section-heading icons always follow the brand.
   Pages used to colour their own: the Add Product screen alone had a blue
   "Basic Information", a red "Item Image", a green "Costs" and a grey
   "Settings". Scoping to headings inside a card header means the .text-*
   utilities keep working everywhere else (a green profit figure, a red
   negative balance) — only section icons are normalised. */
.k-card-title > i,
.k-card-title > svg,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header .card-title > i,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h1 > i,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h2 > i,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h3 > i,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h4 > i,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h5 > i,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h6 > i,
.koomi-card-header h6 > i {
    color: var(--k-primary) !important;
    font-size: 1em;
    opacity: .9;
}

/* A card header's heading uses the section-title scale whatever tag it was
   written with (pages variously used h5, h6 and .card-title). */
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h5,
.page-wrapper:not(.koomi-bespoke) .content .card > .card-header h6,
.koomi-card-header h6 {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
    font-size: var(--k-fs-section-title);
    font-weight: var(--k-fw-bold);
    color: var(--k-text);
    margin: 0;
}

.k-card-subtitle {
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-muted);
    margin: 2px 0 0;
}

.page-wrapper .content .card > .card-body,
.k-card > .k-card-body { padding: var(--k-card-pad); }

.page-wrapper .content .card > .card-footer,
.k-card > .k-card-footer {
    background: var(--k-surface-soft);
    border-top: 1px solid var(--k-border);
    border-radius: 0 0 var(--k-radius-lg) var(--k-radius-lg);
    padding: var(--k-space-3) var(--k-card-pad);
}

/* ============================================================================
   5. BUTTONS
   ============================================================================
   Historically the same action was written five different ways:
       .btn-added .btn-submit .btn-primary .btn-outline-primary .page-btn a
   They are all mapped onto the same primary treatment here, so a page that has
   not been migrated yet still renders the correct button.
   ============================================================================ */

.btn,
.page-wrapper .content .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--k-space-2);
    min-height: var(--k-control-h);
    min-width: 0;
    padding: 0 var(--k-space-4);
    border: 1px solid transparent;
    border-radius: var(--k-radius) !important;
    font-family: var(--k-font);
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-medium);
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--k-transition), border-color var(--k-transition),
                color var(--k-transition), box-shadow var(--k-transition);
}

.btn:focus-visible,
.page-wrapper .content .btn:focus-visible {
    outline: none;
    box-shadow: var(--k-shadow-focus);
}

/* Icons inside buttons never need per-page margin utilities. */
.btn > i,
.btn > svg,
.btn > img { flex: 0 0 auto; font-size: 1em; width: auto; height: 1em; }
.btn > img { height: 14px; width: 14px; }

/* Kill the theme's lift-on-hover + gradient: it made buttons feel different
   depending on which stylesheet block last touched them. */
.btn:hover,
.btn-added:hover,
.btn-submit:hover,
.btn-cancel:hover { transform: none; }

/* ── Primary ────────────────────────────────────────────────────────────── */
.btn-primary,
.btn-submit,
.btn-added,
.k-btn-primary,
.page-header .page-btn > a.btn-added {
    background: var(--k-primary) !important;
    background-image: none !important;
    border-color: var(--k-primary) !important;
    color: var(--k-text-invert) !important;
    box-shadow: none !important;
}

.btn-primary:hover,
.btn-submit:hover,
.btn-added:hover,
.k-btn-primary:hover,
.btn-primary:focus,
.btn-submit:focus,
.btn-added:focus {
    background: var(--k-primary-strong) !important;
    border-color: var(--k-primary-strong) !important;
    color: var(--k-text-invert) !important;
}

/* ── Secondary (Cancel / Back / Close) ──────────────────────────────────── */
.btn-secondary,
.btn-cancel,
.btn-light,
.btn-white,
.btn-outline-secondary,
.btn-outline-light,
.btn-filter,
.btn-filters,
.k-btn-secondary {
    background: var(--k-surface) !important;
    background-image: none !important;
    border: 1px solid var(--k-border-strong) !important;
    color: var(--k-text-body) !important;
    box-shadow: none !important;
}

.btn-secondary:hover,
.btn-cancel:hover,
.btn-light:hover,
.btn-white:hover,
.btn-outline-secondary:hover,
.btn-outline-light:hover,
.btn-filter:hover,
.btn-filters:hover,
.k-btn-secondary:hover {
    background: var(--k-surface-hover) !important;
    border-color: var(--k-border-strong) !important;
    color: var(--k-text) !important;
}

/* ── Danger ─────────────────────────────────────────────────────────────── */
.btn-danger,
.k-btn-danger {
    background: var(--k-danger) !important;
    border-color: var(--k-danger) !important;
    color: var(--k-text-invert) !important;
}
.btn-danger:hover,
.k-btn-danger:hover {
    background: var(--k-danger-strong) !important;
    border-color: var(--k-danger-strong) !important;
}

.btn-outline-danger,
.k-btn-danger-soft {
    background: var(--k-surface) !important;
    border: 1px solid var(--k-danger-border) !important;
    color: var(--k-danger) !important;
}
.btn-outline-danger:hover,
.k-btn-danger-soft:hover {
    background: var(--k-danger-soft) !important;
    border-color: var(--k-danger) !important;
    color: var(--k-danger-strong) !important;
}

/* ── Success ────────────────────────────────────────────────────────────── */
.btn-success,
.k-btn-success {
    background: var(--k-success) !important;
    border-color: var(--k-success) !important;
    color: var(--k-text-invert) !important;
}
.btn-success:hover,
.k-btn-success:hover {
    background: var(--k-success-strong) !important;
    border-color: var(--k-success-strong) !important;
}

.btn-outline-success {
    background: var(--k-surface) !important;
    border: 1px solid var(--k-success-border) !important;
    color: var(--k-success) !important;
}
.btn-outline-success:hover {
    background: var(--k-success-soft) !important;
    border-color: var(--k-success) !important;
}

/* ── Warning ────────────────────────────────────────────────────────────── */
.btn-warning,
.k-btn-warning {
    background: var(--k-warning) !important;
    border-color: var(--k-warning) !important;
    color: var(--k-text-invert) !important;
}
.btn-warning:hover,
.k-btn-warning:hover {
    background: var(--k-warning-strong) !important;
    border-color: var(--k-warning-strong) !important;
}

/* ── Outline primary / tertiary ─────────────────────────────────────────── */
.btn-outline-primary,
.k-btn-tertiary {
    background: var(--k-surface) !important;
    border: 1px solid var(--k-primary-border) !important;
    color: var(--k-primary) !important;
}
.btn-outline-primary:hover,
.k-btn-tertiary:hover {
    background: var(--k-primary-soft) !important;
    border-color: var(--k-primary) !important;
    color: var(--k-primary-strong) !important;
}

/* Selected state for a .btn-check toggle group (People -> Business Role, and any
   other one). Bootstrap's own `.btn-check:checked + .btn-outline-primary` rule
   carries no !important, so the outline treatment above was overriding it and
   every option in the group rendered as though nothing was picked. The :hover
   pairing matters for the same reason - without it, pointing at the chosen
   option made it look unchosen again. */
.btn-check:checked + .btn-outline-primary,
.btn-check:checked + .btn-outline-primary:hover,
.btn-check:checked + .btn-outline-primary:focus,
.btn-check:active + .btn-outline-primary {
    background: var(--k-primary) !important;
    border-color: var(--k-primary) !important;
    color: var(--k-text-invert) !important;
}

.btn-check:focus-visible + .btn-outline-primary {
    box-shadow: var(--k-shadow-focus);
}

/* ── Link / ghost ───────────────────────────────────────────────────────── */
.btn-link,
.k-btn-ghost {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--k-primary) !important;
    padding-inline: var(--k-space-2);
}
.btn-link:hover,
.k-btn-ghost:hover {
    background: var(--k-primary-soft) !important;
    color: var(--k-primary-strong) !important;
}

/* ── Sizes ──────────────────────────────────────────────────────────────── */
.btn-sm,
.k-btn-sm {
    min-height: var(--k-control-h-sm) !important;
    padding: 0 var(--k-space-3) !important;
    font-size: 13px !important;
    border-radius: var(--k-radius-sm) !important;
}

.btn-lg,
.k-btn-lg {
    min-height: var(--k-control-h-lg) !important;
    padding: 0 var(--k-space-5) !important;
    font-size: 15px !important;
}

.btn.w-100, .btn.btn-block { width: 100%; }

/* ── Icon-only button ───────────────────────────────────────────────────── */
.k-btn-icon {
    width: var(--k-control-h);
    height: var(--k-control-h);
    min-height: var(--k-control-h);
    padding: 0 !important;
    flex: 0 0 auto;
}
.k-btn-icon.btn-sm {
    width: var(--k-control-h-sm);
    height: var(--k-control-h-sm);
    min-height: var(--k-control-h-sm);
}
.k-btn-icon > i { font-size: 15px; }

/* ── Disabled ───────────────────────────────────────────────────────────── */
.btn:disabled,
.btn.disabled,
.koomi-real-submit:disabled {
    opacity: .55;
    cursor: not-allowed;
    box-shadow: none !important;
}

/* ── Button group / form action row ─────────────────────────────────────── */
.k-btn-row,
.koomi-form-actions {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
    flex-wrap: wrap;
}
/* Save/Cancel sit right on desktop, full width and stacked on phones. */
.k-btn-row-end,
.koomi-form-actions { justify-content: flex-end; }

/* ============================================================================
   6. FORMS — labels, controls, help, validation
   ============================================================================ */

.form-group,
.k-field { margin-bottom: var(--k-field-gap); }

label,
.form-label,
.k-label {
    display: block;
    font-size: var(--k-fs-label);
    font-weight: var(--k-fw-medium);
    color: var(--k-text-body);
    margin-bottom: 6px;
    line-height: 1.4;
}

/* One required marker everywhere. */
.k-required,
label .manitory,
.form-label .manitory {
    color: var(--k-danger);
    margin-left: 2px;
    font-weight: var(--k-fw-bold);
}

/* ── The control: identical height for input, select, textarea, select2 ─── */
.form-control,
.form-select,
.k-input,
select.form-control,
textarea.form-control,
input[type="text"].form-control,
input[type="email"].form-control,
input[type="password"].form-control,
input[type="number"].form-control,
input[type="tel"].form-control,
input[type="url"].form-control,
input[type="search"].form-control,
input[type="date"].form-control,
input[type="datetime-local"].form-control,
input[type="time"].form-control {
    min-height: var(--k-control-h);
    height: auto;
    padding: 9px var(--k-control-pad-x);
    background-color: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    font-family: var(--k-font);
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-normal);
    color: var(--k-text);
    box-shadow: none;
    transition: border-color var(--k-transition), box-shadow var(--k-transition);
}

textarea.form-control,
.k-textarea {
    min-height: 96px;
    padding-block: 10px;
    line-height: 1.55;
    resize: vertical;
}

.form-control::placeholder,
.k-input::placeholder { color: var(--k-text-soft); font-weight: var(--k-fw-normal); }

.form-control:focus,
.form-select:focus,
.k-input:focus {
    background-color: var(--k-surface);
    border-color: var(--k-border-focus);
    box-shadow: var(--k-shadow-focus);
    outline: none;
    color: var(--k-text);
}

.form-control:disabled,
.form-control[readonly],
.form-select:disabled {
    background-color: var(--k-surface-soft);
    color: var(--k-text-muted);
    cursor: not-allowed;
    border-color: var(--k-border);
}

/* Native select chevron — one arrow, not the browser's default per platform. */
.form-select,
select.form-control:not([multiple]):not([size]) {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 36px;
}

/* Date/time inputs: the native picker indicator is styled to match. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
    opacity: .55;
    cursor: pointer;
}
input[type="date"]:hover::-webkit-calendar-picker-indicator { opacity: .9; }

/* ── Input with a leading (and optional trailing) icon ──────────────────── */
/* Used by the filter bar, the header search and every page-level search box,
   so the icon inset is defined once instead of per screen. NOTE: the base
   .form-control rule above sets `padding` as a shorthand, so any icon inset
   has to be re-applied after it — that is why these live here. */
.k-input-icon,
.koomi-filter-search {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

/* The inset has to out-specify the base .form-control block above, which lists
   `input[type="text"].form-control` — element + class + attribute = 0,2,1. A
   plain `.k-input-icon > .form-control` is only 0,2,0 and therefore LOSES to it
   no matter how late it appears, which is why an icon input kept the default
   13px padding and the glyph sat on the value. Naming the element here matches
   that weight, and being later in the file wins the tie. Bootstrap's
   .form-control-sm (the filter bar's search box) is covered the same way. */
.k-input-icon > input.form-control,
.k-input-icon > textarea.form-control,
.k-input-icon > .form-control,
.koomi-list-filters .koomi-filter-search > .form-control,
.k-filter-bar .koomi-filter-search > .form-control,
.koomi-filter-search > .form-control.form-control-sm,
.koomi-filter-search > .form-control { padding-left: 36px; }

/* A trailing control (the clear ×) needs room on the right. */
.k-input-icon:has(.k-input-icon-trailing) > input.form-control,
.k-input-icon:has(.k-input-icon-trailing) > .form-control,
.koomi-list-filters .koomi-filter-search > .form-control,
.koomi-filter-search > .form-control { padding-right: 32px; }

.k-input-icon-leading,
.koomi-filter-search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--k-text-soft);
    font-size: 13px;
    line-height: 1;
    pointer-events: none;
}

/* When the field sits under a label the icon centres on the input, not the pair. */
.k-input-icon:has(> label) .k-input-icon-leading,
.koomi-filter-search:has(> label) .koomi-filter-search-icon { top: auto; bottom: 14px; transform: none; }

.k-input-icon-trailing,
.koomi-filter-search-clear {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--k-text-soft);
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
}
.k-input-icon-trailing:hover,
.koomi-filter-search-clear:hover { background: var(--k-surface-hover); color: var(--k-text-body); }

/* ── Help text ──────────────────────────────────────────────────────────── */
.form-text,
.k-help,
.k-hint {
    display: block;
    margin-top: 5px;
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-muted);
    line-height: 1.45;
}

/* ── Validation ─────────────────────────────────────────────────────────── */
.form-control.is-invalid,
.form-select.is-invalid,
.k-input.is-invalid,
.was-validated .form-control:invalid {
    border-color: var(--k-danger);
    background-image: none;
    padding-right: var(--k-control-pad-x);
}

.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
    box-shadow: 0 0 0 3px rgba(220, 38, 38, .15);
    border-color: var(--k-danger);
}

/* Screens outside the design system (sign in, sign up, legacy markup) use bare
   <input> elements rather than .form-control, so the invalid state is bound to the
   class itself as well — every field flagged reads the same wherever it lives. */
input.is-invalid,
select.is-invalid,
textarea.is-invalid {
    border-color: var(--k-danger) !important;
}

input.is-invalid:focus,
select.is-invalid:focus,
textarea.is-invalid:focus {
    box-shadow: 0 0 0 3px rgba(220, 38, 38, .15) !important;
    border-color: var(--k-danger) !important;
}

/* select2 hides the real <select> and draws its own box; koomi-validation.js marks
   the container so the two never disagree about whether the field is in error. */
.select2-container.is-invalid .select2-selection {
    border-color: var(--k-danger) !important;
}

.invalid-feedback,
.k-error {
    display: block;
    margin-top: 5px;
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
    color: var(--k-danger);
}

.form-control.is-valid,
.form-select.is-valid { border-color: var(--k-success); background-image: none; }

.valid-feedback { color: var(--k-success); font-size: var(--k-fs-help); }

/* ── Input group (currency prefix, unit suffix, search icon) ────────────── */
.input-group > .form-control,
.input-group > .form-select { min-height: var(--k-control-h); }

.input-group-text,
.k-input-addon {
    min-height: var(--k-control-h);
    padding: 0 var(--k-control-pad-x);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    color: var(--k-text-muted);
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-medium);
    display: inline-flex;
    align-items: center;
}

.input-group > :not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-group > :not(:last-child)  { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.input-group:focus-within .input-group-text { border-color: var(--k-border-focus); }

/* ── Checkbox / radio ───────────────────────────────────────────────────── */
.form-check { min-height: auto; margin-bottom: var(--k-space-2); padding-left: 1.75em; }

.form-check-input {
    width: 18px;
    height: 18px;
    margin-top: .12em;
    background-color: var(--k-surface);
    border: 1.5px solid var(--k-border-strong);
    cursor: pointer;
    transition: background-color var(--k-transition), border-color var(--k-transition);
}

/* The negative margin belongs to the .form-check layout (it pulls the box back
   into the label's indent) and must NOT apply to a bare checkbox — a "select
   all" box in a table header has no .form-check wrapper, so the pull dragged it
   out of its cell and it got clipped by the table. */
.form-check > .form-check-input { margin-left: -1.75em; }
.form-check-input[type="checkbox"] { border-radius: 5px; }
.form-check-input[type="radio"]    { border-radius: 50%; }

.form-check-input:checked {
    background-color: var(--k-primary);
    border-color: var(--k-primary);
}
.form-check-input:focus-visible { box-shadow: var(--k-shadow-focus); border-color: var(--k-primary); }
.form-check-input:disabled { opacity: .55; cursor: not-allowed; }

.form-check-label {
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-body);
    cursor: pointer;
    margin-bottom: 0;
}

/* ── Switch / toggle ────────────────────────────────────────────────────── */
.form-switch { padding-left: 3.1em; }
.form-switch .form-check-input,
.koomi-switch .form-check-input {
    width: 42px;
    height: 24px;
    margin-left: -3.1em;
    border-radius: var(--k-radius-pill);
    background-color: var(--k-border-strong);
    border-color: var(--k-border-strong);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");
    background-position: left center;
    cursor: pointer;
}
.form-switch .form-check-input:checked,
.koomi-switch .form-check-input:checked {
    background-color: var(--k-primary);
    border-color: var(--k-primary);
    background-position: right center;
}

/* ── File input ─────────────────────────────────────────────────────────── */
input[type="file"].form-control,
.k-file {
    padding: 0;
    min-height: var(--k-control-h);
    overflow: hidden;
    display: flex;
    align-items: center;
}

input[type="file"].form-control::file-selector-button,
.k-file::file-selector-button {
    height: 100%;
    min-height: calc(var(--k-control-h) - 2px);
    margin: 0 var(--k-control-pad-x) 0 0;
    padding: 0 var(--k-space-4);
    background: var(--k-surface-soft);
    border: 0;
    border-right: 1px solid var(--k-border-strong);
    color: var(--k-text-body);
    font-family: var(--k-font);
    font-size: 13px;
    font-weight: var(--k-fw-medium);
    cursor: pointer;
    transition: background var(--k-transition);
}
input[type="file"].form-control::file-selector-button:hover { background: var(--k-surface-hover); }

/* ── Image / file dropzone ──────────────────────────────────────────────── */
.k-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--k-space-2);
    min-height: 160px;
    padding: var(--k-space-6);
    background: var(--k-surface-soft);
    border: 1.5px dashed var(--k-border-strong);
    border-radius: var(--k-radius-lg);
    color: var(--k-text-muted);
    font-size: var(--k-fs-help);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--k-transition), background var(--k-transition);
}
.k-dropzone:hover,
.k-dropzone.is-dragover {
    border-color: var(--k-primary);
    background: var(--k-primary-soft);
    color: var(--k-primary-strong);
}
/* The upload glyph follows the brand instead of the theme's stray orange. */
.k-dropzone i,
.k-dropzone .fa-cloud-arrow-up,
.k-dropzone svg { font-size: 26px; color: var(--k-primary); }
.k-dropzone img.k-dropzone-preview {
    max-width: 100%;
    max-height: 190px;
    border-radius: var(--k-radius);
    object-fit: contain;
}

/* ── Product image dropzone ─────────────────────────────────────────────── */
/* The Add/Edit Product screen ships its own uploader because its JS swaps the
   preview, the hint text and a clear button (#product-image-*). The markup and
   those hooks are unchanged — only its 100-line inline <style> block, which
   hardcoded its own greys and blues, moved here onto the shared tokens. */
/* Basic Information: the fields take the width, the thumbnail sits at the end.
   It collapses to a full-width block on a narrow screen, above nothing — the
   fields are what matters there. */
.k-basic-layout {
    display: flex;
    align-items: flex-start;
    gap: var(--k-space-4);
}

.k-basic-fields { flex: 1 1 auto; min-width: 0; }

.k-basic-image {
    flex: 0 0 170px;
    width: 170px;
}

@media (max-width: 767.98px) {
    .k-basic-layout { flex-direction: column; }
    .k-basic-image { flex: 1 1 auto; width: 100%; }
}

.koomi-image-drop {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    /* A thumbnail, not a panel. It used to grow to fill a card stretched to the height
       of the whole Basic Information block, so an image took over the screen. */
    height: 150px;
    flex: 0 0 auto;
    padding: var(--k-space-4);
    background: var(--k-surface-soft);
    border: 1.5px dashed var(--k-border-strong);
    border-radius: var(--k-radius-lg);
    text-align: center;
    overflow: hidden;
    cursor: pointer;
    transition: border-color var(--k-transition), background var(--k-transition);
}
.koomi-image-drop:hover { border-color: var(--k-primary); background: var(--k-primary-soft); }
.koomi-image-drop i { color: var(--k-primary); }

.koomi-image-clear {
    position: absolute;
    top: var(--k-space-2);
    right: var(--k-space-2);
    z-index: 3;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--k-radius-sm);
    background: rgba(15, 23, 42, .6);
    color: var(--k-text-invert);
    font-size: 13px;
    cursor: pointer;
}
.koomi-image-clear:hover { background: var(--k-danger); }

.koomi-image-preview { max-height: 84px; max-width: 100%; object-fit: contain; }

/* Empty state: the placeholder graphic is assets/img/icons/upload.svg, which is
   orange and was the one off-brand splash of colour left on the product form.
   The <i> glyph and the hint text below already say "upload", so the stray
   artwork is hidden until there is a real photo to show. The <img> itself is
   kept in the DOM because the page JS swaps its src. */
.koomi-image-drop:not(.has-image) .koomi-image-preview { display: none; }

.koomi-image-drop.has-image {
    padding: 0;
    background: var(--k-surface);
    border-style: solid;
    border-color: var(--k-border);
}
.koomi-image-drop.has-image .koomi-image-preview.is-photo {
    width: 100%;
    height: 100%;
    max-height: none;
    object-fit: cover;
}

.koomi-image-hint { margin-top: var(--k-space-2); font-size: var(--k-fs-help); color: var(--k-text-muted); }
.koomi-image-drop.has-image .koomi-image-hint {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    margin: 0;
    padding: var(--k-space-2);
    background: rgba(15, 23, 42, .55);
    color: var(--k-text-invert);
    font-weight: var(--k-fw-medium);
}

/* ── Form sections + grid ───────────────────────────────────────────────── */
.k-form-section + .k-form-section { margin-top: var(--k-space-5); }

.k-form-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--k-space-3);
    flex-wrap: wrap;
    margin-bottom: var(--k-space-4);
    padding-bottom: var(--k-space-3);
    border-bottom: 1px solid var(--k-border);
}

/* A form grid that keeps field widths equal across every create/edit screen. */
.k-form-grid {
    display: grid;
    grid-template-columns: repeat(var(--k-cols, 3), minmax(0, 1fr));
    gap: var(--k-space-4) var(--k-space-4);
}
.k-form-grid > .k-col-2 { grid-column: span 2; }
.k-form-grid > .k-col-full { grid-column: 1 / -1; }
.k-form-grid .form-group,
.k-form-grid .k-field { margin-bottom: 0; }

/* A row of switches, under a .k-form-grid rather than inside it.

   A switch carries its own label to the right of the control and none above it, so
   dropped into a grid cell it aligns with the neighbouring fields' LABELS while their
   inputs sit lower — the row looks misaligned even though nothing is wrong with it.
   Kept apart, the switches line up with each other and are separated from the fields
   above by a rule, which is also how they read: settings rather than values. */
.k-switch-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--k-space-3) var(--k-space-6);
    align-items: flex-start;
    margin-top: var(--k-space-4);
    padding-top: var(--k-space-4);
    border-top: 1px solid var(--k-border);
}

/* Each switch is as wide as it needs to be, so two never stretch to half the card. */
.k-switch-row > .form-group { flex: 0 1 auto; margin-bottom: 0; max-width: 22rem; }
.k-switch-row .form-check { margin-bottom: 0; }
.k-switch-row .form-check-label { font-weight: var(--k-fw-medium); }

/* Standard form width so long forms do not stretch to 4K widths. */
.k-form-narrow { max-width: 760px; }

/* Legacy standard form: keep row/col forms visually aligned with the grid. */
.koomi-standard-form .form-group { margin-bottom: var(--k-field-gap); }

.koomi-form-error-summary {
    display: none;
    margin-bottom: var(--k-space-4);
    padding: var(--k-space-3) var(--k-space-4);
    background: var(--k-danger-soft);
    border: 1px solid var(--k-danger-border);
    border-radius: var(--k-radius);
    color: var(--k-danger-strong);
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
}
.koomi-standard-form.is-invalid-submit .koomi-form-error-summary { display: block; }

/* ============================================================================
   7. DROPDOWNS — select2 skinned to look exactly like a native control
   ============================================================================
   Every <select> in the app is upgraded to a searchable select2 by
   assets/js/script.js (window.koomiInitSelects). These rules make the
   select2 rendering pixel-match .form-control so a searchable dropdown and a
   plain input sitting side by side line up.
   ============================================================================ */

.select2-container { width: 100% !important; }

/* ── Closed state, single select ────────────────────────────────────────── */
.select2-container--default .select2-selection--single,
.select2-container .select2-selection--single {
    display: flex;
    align-items: center;
    min-height: var(--k-control-h);
    height: var(--k-control-h);
    padding: 0 36px 0 var(--k-control-pad-x);
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    transition: border-color var(--k-transition), box-shadow var(--k-transition);
}

.select2-container--default .select2-selection--single .select2-selection__rendered {
    /* The selection box above is a flex row, so this has to be told to fill it.
       Left to shrink-wrap the value, the clear button that select2 floats to its
       right edge ended up hard against the text - "Lebanon x" - instead of over
       at the end of the control. min-width:0 keeps the ellipsis working. */
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    line-height: 1.4;
    color: var(--k-text);
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-normal);
}

.select2-container--default .select2-selection--single .select2-selection__placeholder {
    color: var(--k-text-soft);
    font-weight: var(--k-fw-normal);
}

/* One chevron, drawn the same way as the native select's. */
.select2-container--default .select2-selection--single .select2-selection__arrow {
    top: 0;
    right: 10px;
    width: 20px;
    height: 100%;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E") no-repeat center;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b { display: none; }

/* The × that clears a selection. */
.select2-container--default .select2-selection--single .select2-selection__clear {
    float: right;
    padding: 0;
    margin-right: 6px;
    line-height: inherit;
    color: var(--k-text-soft);
    font-size: 18px;
    font-weight: var(--k-fw-normal);
}
.select2-container--default .select2-selection--single .select2-selection__clear:hover { color: var(--k-danger); }

/* ── Closed state, multi select ─────────────────────────────────────────── */
.select2-container--default .select2-selection--multiple {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
    min-height: var(--k-control-h);
    padding: 5px 8px;
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong) !important;
    border-radius: var(--k-radius);
    transition: border-color var(--k-transition), box-shadow var(--k-transition);
}

.select2-container--default .select2-selection--multiple .select2-selection__rendered {
    display: contents;
    padding: 0;
    margin: 0;
}

/* Selected values read as chips, not as the plugin's default grey boxes. */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
    display: inline-flex;
    align-items: center;
    flex-direction: row-reverse;
    gap: 6px;
    margin: 0;
    padding: 4px 10px;
    background: var(--k-primary-soft);
    border: 1px solid var(--k-primary-border);
    border-radius: var(--k-radius-sm);
    color: var(--k-primary-strong);
    font-size: 12.5px;
    font-weight: var(--k-fw-medium);
    line-height: 1.4;
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
    order: 2;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--k-primary);
    font-size: 15px;
    font-weight: var(--k-fw-bold);
    line-height: 1;
    cursor: pointer;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
    background: transparent;
    color: var(--k-danger);
}

.select2-container--default .select2-selection--multiple .select2-search--inline {
    display: inline-flex;
    align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-search__field {
    margin: 0;
    height: 26px;
    font-family: var(--k-font);
    font-size: var(--k-fs-base);
    color: var(--k-text);
}
.select2-container--default .select2-selection--multiple .select2-search__field::placeholder {
    color: var(--k-text-soft);
}

/* ── Focus / open ───────────────────────────────────────────────────────── */
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
    border-color: var(--k-border-focus) !important;
    box-shadow: var(--k-shadow-focus);
}

/* ── The dropdown panel ─────────────────────────────────────────────────── */
.select2-container--default .select2-dropdown {
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    box-shadow: var(--k-shadow-lg);
    overflow: hidden;
    z-index: var(--k-z-dropdown);
}

/* Only a select2 that is OPEN may lift itself above the page.
   A blanket z-index on .select2-container raises every closed control too, and
   since Bootstrap's .modal sits at 1055, each dropdown on the page underneath
   then painted ON TOP of an open dialog — which is what hid the left half of
   the variation picker's header behind the "Purchase Currency" field. */
.select2-container--open { z-index: var(--k-z-dropdown); }

/* One search field, one height, on every dropdown in the app. */
.select2-container--default .select2-search--dropdown { padding: var(--k-space-2); border-bottom: 1px solid var(--k-border); }
.select2-container--default .select2-search--dropdown .select2-search__field {
    min-height: var(--k-control-h-sm);
    padding: 6px 10px;
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius-sm);
    font-family: var(--k-font);
    font-size: 13px;
    color: var(--k-text);
    outline: none;
}
.select2-container--default .select2-search--dropdown .select2-search__field:focus {
    border-color: var(--k-primary);
    background: var(--k-surface);
}

/* Consistent panel height for long lists — no dropdown is 3 rows on one page
   and 30 on another. */
.select2-container--default .select2-results > .select2-results__options {
    max-height: 260px;
    overscroll-behavior: contain;
}

.select2-container--default .select2-results__option {
    padding: 9px var(--k-space-3);
    font-size: 13.5px;
    font-weight: var(--k-fw-normal);
    color: var(--k-text-body);
    line-height: 1.4;
}

.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted {
    background: var(--k-primary-soft) !important;
    color: var(--k-primary-strong) !important;
}

.select2-container--default .select2-results__option[aria-selected="true"],
.select2-container--default .select2-results__option--selected {
    background: var(--k-surface-hover);
    color: var(--k-text);
    font-weight: var(--k-fw-medium);
}

.select2-container--default .select2-results__option[aria-disabled="true"] {
    color: var(--k-text-soft);
    cursor: not-allowed;
}

.select2-container--default .select2-results__message,
.select2-container--default .select2-results__option.loading-results {
    padding: var(--k-space-4);
    color: var(--k-text-muted);
    font-size: 13px;
    text-align: center;
}

/* Disabled select2 matches a disabled input. */
.select2-container--disabled .select2-selection--single,
.select2-container--default.select2-container--disabled .select2-selection--single,
.select2-container--default.select2-container--disabled .select2-selection--multiple {
    background: var(--k-surface-soft) !important;
    color: var(--k-text-muted);
    cursor: not-allowed;
}

/* Invalid select2 (server-side validation) gets the same red as an input. */
.is-invalid + .select2-container .select2-selection--single,
.is-invalid + .select2-container .select2-selection--multiple {
    border-color: var(--k-danger) !important;
}

/* Inside a modal the panel must clear the backdrop — again only while open, so
   a closed control never stacks above the dialog it lives in. */
.modal .select2-container--open,
.modal .select2-dropdown { z-index: calc(var(--k-z-modal) + 20); }

/* Select-all / clear-all bar used by the multi-select component. */
.k-select-bulk {
    display: flex;
    align-items: center;
    gap: var(--k-space-3);
    margin-top: 6px;
}
.k-select-bulk button {
    background: none;
    border: 0;
    padding: 0;
    color: var(--k-primary);
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
    cursor: pointer;
}
.k-select-bulk button:hover { text-decoration: underline; color: var(--k-primary-strong); }
.k-select-bulk .k-select-count { margin-left: auto; color: var(--k-text-muted); font-size: var(--k-fs-help); }

/* ============================================================================
   8. TABLES  (frame + head + rows live in koomi-tables.css, which now reads
   its values from the tokens above; these rules cover the chrome around it)
   ============================================================================ */

/* Toolbar above a table: add button, export icons, search. */
.k-table-toolbar,
.table-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--k-space-3);
    margin-bottom: var(--k-space-4);
}
.k-table-toolbar-actions {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
    flex-wrap: wrap;
    margin-left: auto;
}

/* Export buttons were raw coloured images (green/red/grey) — now uniform. */
.k-export-btn,
.export-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--k-control-h);
    height: var(--k-control-h);
    padding: 0;
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    color: var(--k-text-muted);
    cursor: pointer;
    transition: all var(--k-transition);
}
.k-export-btn:hover,
.export-btn:hover {
    background: var(--k-primary-soft);
    border-color: var(--k-primary);
    color: var(--k-primary);
}
/* The export icons ship as full-colour PNG/SVG (green Excel, red PDF, grey
   printer). Desaturating them makes the row read as one set of controls; the
   hover state tints the whole button instead. */
.k-export-btn img,
.export-btn img {
    width: 16px;
    height: 16px;
    filter: grayscale(1);
    opacity: .55;
    transition: filter var(--k-transition), opacity var(--k-transition);
}
.k-export-btn:hover img,
.export-btn:hover img { filter: grayscale(0); opacity: 1; }
.k-export-btn i { font-size: 15px; }

/* Filter bar */
.koomi-list-filters,
.k-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--k-space-2) var(--k-space-3);
    padding: var(--k-space-3);
    margin-bottom: var(--k-space-4);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
}
.koomi-filter-label,
.k-filter-label {
    font-size: 11.5px;
    font-weight: var(--k-fw-medium);
    color: var(--k-text-muted);
    margin: 0 0 3px;
    text-transform: none;
    letter-spacing: 0;
}
.koomi-filter-field,
.k-filter-field { display: flex; flex-direction: column; min-width: 150px; }
/* Every control in the filter bar shares the table-toolbar height. */
.koomi-list-filters .form-control,
.koomi-list-filters .form-select,
.koomi-list-filters .select2-selection--single,
.k-filter-bar .form-control,
.k-filter-bar .form-select { min-height: var(--k-control-h-sm); height: var(--k-control-h-sm); padding-block: 4px; font-size: 13px; }
.koomi-list-filters .btn,
.k-filter-bar .btn { min-height: var(--k-control-h-sm); padding-inline: var(--k-space-3); font-size: 13px; }
.koomi-filter-actions { display: flex; gap: var(--k-space-2); align-items: flex-end; }

/* DataTables length/info chrome.
   style.css injects `content: "Show  per page :"` before this label while
   DataTables itself renders "Show _MENU_ entries" — together they read
   "Show per page : Show 10 entries". The pseudo-element is dropped here and
   the wording is set once in x-data-table's `language.lengthMenu`. */
.dataTables_length label::before { content: none !important; }

.dataTables_wrapper .dataTables_length label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-muted);
}

.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
    font-size: var(--k-fs-help);
    color: var(--k-text-muted);
}
.dataTables_wrapper .dataTables_length select {
    min-height: var(--k-control-h-sm);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius-sm);
    padding: 3px 26px 3px 10px;
    margin-inline: 6px;
    font-size: 13px;
}

/* ── Pagination — one pill style for DataTables and Laravel paginator ───── */
.dataTables_wrapper .dataTables_paginate .paginate_button,
.page-wrapper .content .pagination .page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 10px !important;
    margin-left: 4px;
    background: var(--k-surface) !important;
    border: 1px solid var(--k-border) !important;
    border-radius: var(--k-radius-sm) !important;
    color: var(--k-text-body) !important;
    font-size: 13px;
    font-weight: var(--k-fw-medium);
    box-shadow: none !important;
}

.dataTables_wrapper .dataTables_paginate .paginate_button:hover,
.page-wrapper .content .pagination .page-link:hover {
    background: var(--k-primary-soft) !important;
    border-color: var(--k-primary-border) !important;
    color: var(--k-primary-strong) !important;
}

.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover,
.page-wrapper .content .pagination .page-item.active .page-link {
    background: var(--k-primary) !important;
    border-color: var(--k-primary) !important;
    color: var(--k-text-invert) !important;
}

.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,
.page-wrapper .content .pagination .page-item.disabled .page-link {
    background: var(--k-surface) !important;
    border-color: var(--k-border) !important;
    color: var(--k-text-soft) !important;
    cursor: not-allowed;
}

/* Row action menu (three dots) */
.table-action-dropdown .table-action-btn,
.k-action-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    min-height: 32px;
    padding: 0 !important;
    background: transparent !important;
    border: 1px solid transparent !important;
    border-radius: var(--k-radius-sm) !important;
    color: var(--k-text-muted) !important;
    box-shadow: none !important;
}
.table-action-dropdown .table-action-btn:hover,
.table-action-dropdown .table-action-btn[aria-expanded="true"],
.k-action-btn:hover {
    background: var(--k-surface-hover) !important;
    border-color: var(--k-border) !important;
    color: var(--k-text) !important;
}
.table-action-dropdown .action-dots { font-size: 18px; line-height: 1; }

/* A wide table scrolls sideways inside its own frame. Note that this alone makes the
   browser compute overflow-y as `auto` as well, so an open row menu would be cut off at
   the bottom edge — CSS cannot undo that without giving up the horizontal scroll.
   The menu is therefore moved out to <body> while it is open; see the dropdown portal in
   layout/partials/footer-scripts.blade.php and .koomi-dropdown-portal in koomi-tables.css.
   Please fix clipped menus there rather than adding another per-table override here. */
.page-wrapper .content .table-responsive { overflow-x: auto; }

/* ── Bootstrap dropdown menus (row actions, header menus) ───────────────── */
.dropdown-menu {
    padding: 6px;
    background: var(--k-surface);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
    box-shadow: var(--k-shadow-lg);
    font-size: 13.5px;
    min-width: 180px;
    z-index: var(--k-z-dropdown);
}
.dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--k-radius-sm);
    background: transparent;
    color: var(--k-text-body);
    font-size: 13.5px;
    font-weight: var(--k-fw-normal);
    text-align: left;
    cursor: pointer;
}
.dropdown-item:hover,
.dropdown-item:focus { background: var(--k-surface-hover); color: var(--k-text); }
.dropdown-item.text-danger { color: var(--k-danger) !important; }
.dropdown-item.text-danger:hover { background: var(--k-danger-soft); }
.dropdown-item img { width: 15px; height: 15px; opacity: .7; }
.dropdown-item.active,
.dropdown-item:active { background: var(--k-primary-soft); color: var(--k-primary-strong); }
.dropdown-divider { margin: 5px 2px; border-color: var(--k-border); }
.dropdown-menu form { margin: 0; }

/* Clickable row affordance */
.koomi-clickable-row { cursor: pointer; }
.dt-name-link { color: var(--k-primary); font-weight: var(--k-fw-medium); }
.dt-name-link:hover { text-decoration: underline; color: var(--k-primary-strong); }

/* ============================================================================
   9. BADGES / STATUS PILLS
   ============================================================================ */

.badge,
.badges,
.k-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border: 1px solid transparent;
    border-radius: var(--k-radius-pill);
    font-size: var(--k-fs-badge);
    font-weight: var(--k-fw-medium);
    line-height: 1.5;
    white-space: nowrap;
}

.k-badge-neutral { background: var(--k-surface-hover); border-color: var(--k-border); color: var(--k-text-muted); }
.k-badge-primary { background: var(--k-primary-soft); border-color: var(--k-primary-border); color: var(--k-primary-strong); }
.k-badge-success,
.badges.bg-lightgreen,
.badge.bg-success   { background: var(--k-success-soft) !important; border-color: var(--k-success-border); color: var(--k-success-strong) !important; }
.k-badge-danger,
.badges.bg-lightred,
.badge.bg-danger    { background: var(--k-danger-soft) !important;  border-color: var(--k-danger-border);  color: var(--k-danger-strong) !important; }
.k-badge-warning,
.badges.bg-lightyellow,
.badge.bg-warning   { background: var(--k-warning-soft) !important; border-color: var(--k-warning-border); color: var(--k-warning-strong) !important; }
.k-badge-info,
.badges.bg-lightblue,
.badge.bg-info      { background: var(--k-info-soft) !important;    border-color: var(--k-info-border);    color: var(--k-info-strong) !important; }
.badge.bg-secondary,
.badges.bg-lightgrey { background: var(--k-surface-hover) !important; border-color: var(--k-border); color: var(--k-text-muted) !important; }

/* A dot in front of a status reads faster than colour alone. */
.k-badge-dot::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}

/* ============================================================================
   10. ALERTS / TOASTS
   ============================================================================ */

.alert {
    display: flex;
    align-items: flex-start;
    gap: var(--k-space-3);
    padding: var(--k-space-3) var(--k-space-4);
    margin-bottom: var(--k-space-4);
    border: 1px solid transparent;
    border-radius: var(--k-radius);
    font-size: 13.5px;
    font-weight: var(--k-fw-normal);
}
.alert > i { font-size: 15px; margin-top: 1px; flex: 0 0 auto; }
.alert .btn-close { margin-left: auto; padding: 0; font-size: 11px; }

.alert-success { background: var(--k-success-soft); border-color: var(--k-success-border); color: var(--k-success-strong); }
.alert-danger  { background: var(--k-danger-soft);  border-color: var(--k-danger-border);  color: var(--k-danger-strong); }
.alert-warning { background: var(--k-warning-soft); border-color: var(--k-warning-border); color: var(--k-warning-strong); }
.alert-info    { background: var(--k-info-soft);    border-color: var(--k-info-border);    color: var(--k-info-strong); }
.alert ul { margin-bottom: 0; }

/* Toastr — matched to the alert palette so a flash and an inline alert agree. */
#toast-container > div {
    padding: var(--k-space-3) var(--k-space-4) var(--k-space-3) 48px;
    border-radius: var(--k-radius);
    box-shadow: var(--k-shadow-lg) !important;
    font-family: var(--k-font);
    font-size: 13.5px;
    font-weight: var(--k-fw-normal);
    opacity: 1;
}
#toast-container > .toast-success { background-color: var(--k-success) !important; }
#toast-container > .toast-error   { background-color: var(--k-danger) !important; }
#toast-container > .toast-warning { background-color: var(--k-warning) !important; }
#toast-container > .toast-info    { background-color: var(--k-info) !important; }
.toast-title { font-weight: var(--k-fw-bold); }

/* ============================================================================
   11. MODALS
   ============================================================================ */

.modal-content {
    background: var(--k-surface);
    border: 0;
    border-radius: var(--k-radius-lg);
    box-shadow: var(--k-shadow-lg);
}

.modal-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--k-space-3);
    padding: var(--k-space-4) var(--k-space-5);
    border-bottom: 1px solid var(--k-border);
    border-radius: var(--k-radius-lg) var(--k-radius-lg) 0 0;
}

/* A long title must WRAP, never overflow the header.
   A flex item defaults to min-width:auto, so a header whose title is a long
   product name ("Select Variations — G Green Lion Interlaken True Wireless
   Earbuds - White") could not shrink, overflowed the .modal-content, and got
   clipped — losing the first words of the title. Letting the title block
   shrink and wrap fixes it for every modal at once. */
.modal-header > *:first-child { flex: 1 1 auto; min-width: 0; }

.modal-title {
    font-size: var(--k-fs-section-title);
    font-weight: var(--k-fw-bold);
    color: var(--k-text);
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* The close button keeps its size and stays inside the header. */
.modal-header .btn-close { flex: 0 0 auto; margin: 0; align-self: flex-start; }
.modal-body   { padding: var(--k-space-5); }

/* ── Modal sizing ───────────────────────────────────────────────────────────
   Bootstrap's defaults are narrow for what this app puts in a modal: the variation
   picker alone carries a search box and a six-column table, and at 500px the price
   fields end up shoulder to shoulder. Every step up is widened, and each is capped
   against the viewport so a wide modal still fits a laptop screen.

   These override Bootstrap's own max-widths, which are set inside its
   `@media (min-width: 576px)` block — hence the matching media query here. */
@media (min-width: 576px) {
    .modal-dialog                 { max-width: min(720px, calc(100vw - 3rem)); }
    .modal-dialog.modal-sm        { max-width: min(420px, calc(100vw - 3rem)); }
}

@media (min-width: 992px) {
    .modal-dialog.modal-lg        { max-width: min(980px, calc(100vw - 4rem)); }
}

@media (min-width: 1200px) {
    .modal-dialog.modal-xl        { max-width: min(1360px, calc(100vw - 4rem)); }
}

/* Vertical room. A short modal should not feel squeezed, and a tall one should be
   allowed most of the screen before it starts scrolling inside itself. */
@media (min-width: 576px) {
    .modal-dialog { margin: 1.25rem auto; }
    .modal-body   { min-height: 90px; }

    .modal-dialog-scrollable       { height: calc(100% - 2.5rem); }
    .modal-dialog-scrollable .modal-content { max-height: 100%; }

    /* A centered modal is capped so its own header and footer stay on screen. */
    .modal-dialog-centered .modal-content { max-height: calc(100vh - 2.5rem); }
    .modal-dialog-centered .modal-body    { overflow-y: auto; }
}
.modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--k-space-2);
    padding: var(--k-space-3) var(--k-space-5);
    background: var(--k-surface-soft);
    border-top: 1px solid var(--k-border);
    border-radius: 0 0 var(--k-radius-lg) var(--k-radius-lg);
}
.modal-footer > * { margin: 0; }
.modal-backdrop.show { opacity: .45; }

.btn-close {
    width: 30px;
    height: 30px;
    min-height: 30px;
    padding: 0;
    border-radius: var(--k-radius-sm);
    opacity: .5;
    transition: all var(--k-transition);
}
.btn-close:hover { opacity: 1; background-color: var(--k-surface-hover); }

/* A modal never runs off a small screen. */
@media (max-width: 575.98px) {
    .modal-dialog { margin: var(--k-space-3); max-width: calc(100% - var(--k-space-6)); }
    .modal-body   { padding: var(--k-space-4); max-height: 70vh; overflow-y: auto; }
    .modal-footer { padding: var(--k-space-3) var(--k-space-4); }
    .modal-footer .btn { flex: 1 1 auto; }
}

/* ── IMEI lists ─────────────────────────────────────────────────────────────
   A purchase line can carry dozens of IMEIs. They fold away behind a count so the
   order still reads as a list of lines, and open on a click when somebody needs to
   check a unit. <details> rather than a script: no JS to load, nothing to re-bind
   after a redraw, and it keeps working if the page's JS fails. */
.koomi-imeis > summary {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--k-space-1);
    font-size: var(--k-fs-help);
    color: var(--k-text-muted);
    list-style: none;
    user-select: none;
    padding: 2px 0;
}

/* The browser's default triangle is replaced with one that matches the app. */
.koomi-imeis > summary::-webkit-details-marker { display: none; }

.koomi-imeis > summary::before {
    content: '▸';
    display: inline-block;
    transition: transform var(--k-transition);
    font-size: .9em;
}

.koomi-imeis[open] > summary::before { transform: rotate(90deg); }
.koomi-imeis > summary:hover { color: var(--k-text); }

/* The IMEIs sit on their own row under the line they belong to, so the line keeps
   its own height and the numbers do not push the quantity and price apart. */
.koomi-imei-row > td {
    background: var(--k-surface-soft);
    border-top: 0;
    padding-top: var(--k-space-2);
    padding-bottom: var(--k-space-2);
}

.koomi-imei-tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--k-space-1);
    margin-top: var(--k-space-2);
}

/* One tag per unit. Monospace so a column of digits is comparable at a glance —
   which is the whole reason anybody reads an IMEI. */
.koomi-imei-tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px;
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius-pill, 999px);
    background: var(--k-surface);
    font-family: var(--k-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
    font-size: var(--k-fs-help);
    line-height: 1.6;
    white-space: nowrap;
}

/* A unit that has left stock — sold, returned — is still part of what this order
   brought in, but it is not on the shelf, so it reads as spent rather than current. */
.koomi-imei-tag.is-gone {
    background: var(--k-surface-soft);
    color: var(--k-text-muted);
    border-style: dashed;
}

/* Typed on the order but not received yet: a promise, not a unit. */
.koomi-imei-tag.is-pending {
    border-style: dashed;
    color: var(--k-text-muted);
}

.koomi-imei-tag-alt,
.koomi-imei-tag-status {
    color: var(--k-text-muted);
    font-size: .92em;
}

.koomi-imei-tag-status {
    text-transform: uppercase;
    letter-spacing: .02em;
    font-size: .8em;
}

/* A printed order shows its IMEIs whether or not anybody opened them on screen. */
@media print {
    .koomi-imeis > summary::before { content: ''; }
    .koomi-imei-tag { border-color: #999; }
}

/* SweetAlert — same radius/typography as our own modals. */
.swal2-popup {
    border-radius: var(--k-radius-lg) !important;
    font-family: var(--k-font) !important;
}
.swal2-title { font-size: 18px !important; font-weight: var(--k-fw-bold) !important; color: var(--k-text) !important; }
.swal2-html-container { font-size: 14px !important; color: var(--k-text-muted) !important; }
.swal2-styled.swal2-confirm {
    background: var(--k-primary) !important;
    border-radius: var(--k-radius) !important;
    font-weight: var(--k-fw-medium) !important;
    box-shadow: none !important;
}
.swal2-styled.swal2-cancel {
    background: var(--k-surface) !important;
    border: 1px solid var(--k-border-strong) !important;
    color: var(--k-text-body) !important;
    border-radius: var(--k-radius) !important;
    font-weight: var(--k-fw-medium) !important;
}
.swal2-styled.swal2-deny { background: var(--k-danger) !important; border-radius: var(--k-radius) !important; }

/* ============================================================================
   12. TABS
   ============================================================================ */

.nav-tabs {
    gap: var(--k-space-1);
    border-bottom: 1px solid var(--k-border);
    margin-bottom: var(--k-space-4);
    flex-wrap: nowrap;
    /* Many tabs scroll sideways rather than wrapping into a second row.
       overflow-y must stay hidden or the horizontal scroller also paints a
       vertical scrollbar next to the tab strip. */
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}
.nav-tabs::-webkit-scrollbar { height: 0; width: 0; }
.nav-tabs .nav-link {
    padding: 10px var(--k-space-4);
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--k-text-muted);
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-medium);
    white-space: nowrap;
    transition: color var(--k-transition), border-color var(--k-transition);
}
.nav-tabs .nav-link:hover { color: var(--k-text); border-bottom-color: var(--k-border-strong); }
.nav-tabs .nav-link.active {
    background: transparent;
    color: var(--k-primary);
    border-bottom-color: var(--k-primary);
}
.nav-tabs .nav-link .badge { margin-left: 6px; }

/* Pill tabs (sub-navigation) */
.nav-pills { gap: var(--k-space-1); }
.nav-pills .nav-link {
    padding: 7px var(--k-space-3);
    border-radius: var(--k-radius-sm);
    color: var(--k-text-muted);
    font-size: 13.5px;
    font-weight: var(--k-fw-medium);
}
.nav-pills .nav-link.active { background: var(--k-primary); color: var(--k-text-invert); }

/* ============================================================================
   13. EMPTY / LOADING STATES
   ============================================================================ */

.k-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--k-space-2);
    padding: var(--k-space-8) var(--k-space-4);
    text-align: center;
    color: var(--k-text-muted);
}
.k-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin-bottom: var(--k-space-2);
    background: var(--k-surface-hover);
    border-radius: 50%;
    color: var(--k-text-soft);
    font-size: 22px;
}
.k-empty-title { font-size: 15px; font-weight: var(--k-fw-bold); color: var(--k-text); margin: 0; }
.k-empty-text  { font-size: 13.5px; color: var(--k-text-muted); margin: 0; max-width: 420px; }
.k-empty .btn  { margin-top: var(--k-space-3); }

/* Table empty cell reuses the same treatment. */
.page-wrapper .content .table td.dataTables_empty,
.koomi-table-empty {
    padding: var(--k-space-8) var(--k-space-4) !important;
    text-align: center;
    color: var(--k-text-muted);
    font-size: 13.5px;
    font-weight: var(--k-fw-normal);
}

/* Spinner */
.k-spinner {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid var(--k-primary-border);
    border-top-color: var(--k-primary);
    border-radius: 50%;
    animation: k-spin .7s linear infinite;
    vertical-align: -3px;
}
.k-spinner-lg { width: 32px; height: 32px; border-width: 3px; }
@keyframes k-spin { to { transform: rotate(360deg); } }

.k-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--k-space-3);
    padding: var(--k-space-8) var(--k-space-4);
    color: var(--k-text-muted);
    font-size: 13.5px;
}

/* Skeleton placeholder */
.k-skeleton {
    background: linear-gradient(90deg, var(--k-surface-hover) 25%, var(--k-border) 37%, var(--k-surface-hover) 63%);
    background-size: 400% 100%;
    border-radius: var(--k-radius-sm);
    animation: k-shimmer 1.4s ease infinite;
    min-height: 14px;
}
@keyframes k-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* A button that is mid-submit shows its own spinner. */
.btn.is-loading { position: relative; color: transparent !important; pointer-events: none; }
.btn.is-loading::after {
    content: "";
    position: absolute;
    width: 16px;
    height: 16px;
    border: 2px solid rgba(255, 255, 255, .45);
    border-top-color: #fff;
    border-radius: 50%;
    animation: k-spin .7s linear infinite;
}

/* ============================================================================
   14. TOOLTIPS / POPOVERS
   ============================================================================ */

.tooltip-inner {
    padding: 6px 10px;
    background: var(--k-text);
    border-radius: var(--k-radius-sm);
    font-family: var(--k-font);
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-normal);
    max-width: 240px;
}
.tooltip .tooltip-arrow::before { border-top-color: var(--k-text); border-bottom-color: var(--k-text); }
.popover {
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
    box-shadow: var(--k-shadow-lg);
    font-family: var(--k-font);
}
.popover-header { background: var(--k-surface-soft); border-bottom-color: var(--k-border); font-size: 13.5px; font-weight: var(--k-fw-bold); }
.popover-body { font-size: 13px; color: var(--k-text-body); }

/* ============================================================================
   15. READ-ONLY / DETAIL (show) PAGES
   ============================================================================ */

.koomi-readonly-field,
.k-detail-field {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-height: 62px;
    padding: 10px var(--k-space-3);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
}
.koomi-readonly-field span,
.k-detail-label {
    font-size: 11px;
    font-weight: var(--k-fw-medium);
    color: var(--k-text-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.koomi-readonly-field strong,
.k-detail-value {
    font-size: 13.5px;
    font-weight: var(--k-fw-medium);
    color: var(--k-text);
    word-break: break-word;
}

.k-detail-grid {
    display: grid;
    grid-template-columns: repeat(var(--k-cols, 3), minmax(0, 1fr));
    gap: var(--k-space-3);
}

/* Summary tiles */
.koomi-stat-tile-value,
.k-stat-value {
    font-size: 24px;
    font-weight: var(--k-fw-bold);
    color: var(--k-text);
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.koomi-stat-tile-label,
.k-stat-label { margin-top: 4px; font-size: var(--k-fs-help); font-weight: var(--k-fw-medium); color: var(--k-text-muted); }
.koomi-stat-tile-hint { margin-top: 2px; font-size: 11.5px; color: var(--k-text-soft); }

/* ============================================================================
   15b. AUTHENTICATION SCREENS
   ============================================================================
   Sign in / sign up / forgot / reset render outside .page-wrapper, using the
   theme's .login-* markup, so none of the rules above reached them: the login
   button stayed the old theme sky-blue while every button inside the app was
   the brand blue. These rules put the auth screens on the same tokens without
   changing their markup (the eye-toggle and layout JS keep working).
   ============================================================================ */

.account-page { background: var(--k-bg); }

.login-userheading h3 {
    font-size: 24px;
    font-weight: var(--k-fw-bold);
    color: var(--k-text);
}
.login-userheading h4 {
    font-size: var(--k-fs-base);
    font-weight: var(--k-fw-normal);
    color: var(--k-text-muted);
}

.form-login label,
.login-userset label {
    font-size: var(--k-fs-label);
    font-weight: var(--k-fw-medium);
    color: var(--k-text-body);
    margin-bottom: 6px;
}

/* The auth inputs are bare <input>s (no .form-control), so they are matched by
   position rather than by class. */
.form-login input,
.form-addons input,
.pass-group input,
.login-userset input[type="text"],
.login-userset input[type="email"],
.login-userset input[type="password"] {
    width: 100%;
    min-height: var(--k-control-h-lg);
    padding: 10px 42px 10px var(--k-control-pad-x);
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    font-family: var(--k-font);
    font-size: var(--k-fs-base);
    color: var(--k-text);
    transition: border-color var(--k-transition), box-shadow var(--k-transition);
}

.form-login input:focus,
.pass-group input:focus,
.form-addons input:focus {
    border-color: var(--k-border-focus);
    box-shadow: var(--k-shadow-focus);
    outline: none;
}

/* The trailing mail / eye glyphs. */
.form-addons img,
.pass-group .toggle-password {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--k-text-soft);
    cursor: pointer;
}
.form-addons, .pass-group { position: relative; }

.btn-login {
    width: 100%;
    min-height: var(--k-control-h-lg);
    background: var(--k-primary) !important;
    border-color: var(--k-primary) !important;
    border-radius: var(--k-radius) !important;
    color: var(--k-text-invert) !important;
    font-size: 15px;
    font-weight: var(--k-fw-medium);
}
.btn-login:hover {
    background: var(--k-primary-strong) !important;
    border-color: var(--k-primary-strong) !important;
}

.alreadyuser h4,
.signinform h4 { font-size: var(--k-fs-help); color: var(--k-text-muted); font-weight: var(--k-fw-normal); }
.hover-a { color: var(--k-primary); font-weight: var(--k-fw-medium); }
.hover-a:hover { color: var(--k-primary-strong); text-decoration: underline; }

/* Nothing in the auth column may exceed the column itself. The theme sizes the
   form pane at 40% and the artwork at 60%, and on a phone the panes are flex
   children whose default min-width:auto lets a full-width input push the layout
   wider than the screen. */
.login-wrapper { display: flex; max-width: 100%; }
.login-wrapper .login-content { min-width: 0; max-width: 100%; }
.login-wrapper .login-content .login-userset { min-width: 0; max-width: 100%; }
.form-login,
.form-addons,
.pass-group { max-width: 100%; }
.form-login input,
.form-addons input,
.pass-group input { max-width: 100%; }

@media (max-width: 991.98px) {
    /* The marketing artwork is decoration; the form gets the whole screen. */
    .login-wrapper .login-img { display: none; }
    .login-wrapper .login-content { width: 100%; flex: 1 1 100%; padding: var(--k-space-6); }
}

/* ============================================================================
   16. RESPONSIVE
   ============================================================================
   Goals: no horizontal page scroll at any width, dropdowns and action menus
   stay reachable, tables scroll inside their own frame, buttons never overlap.
   ============================================================================ */

/* Nothing may push the document sideways. */
html, body { max-width: 100%; overflow-x: hidden; }
.page-wrapper .content > .row { margin-inline: 0; }
img, svg, video, canvas { max-width: 100%; height: auto; }

/* Wide content scrolls inside its own container, never the page. */
.table-responsive,
.k-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ── Large desktop ──────────────────────────────────────────────────────── */
@media (min-width: 1600px) {
    .page-wrapper .content { padding: var(--k-space-8); }
    /* Content stays readable instead of stretching across an ultrawide. */
    .page-wrapper .content > .k-container { max-width: 1600px; margin-inline: auto; }
}

/* ── Laptop / small desktop ─────────────────────────────────────────────── */
@media (max-width: 1399.98px) {
    .k-form-grid { --k-cols: 3; }
}

/* ── Tablet ─────────────────────────────────────────────────────────────── */
@media (max-width: 991.98px) {
    :root { --k-page-pad: 18px; --k-card-pad: 16px; }

    /* !important is load-bearing here: a section declares its desktop column
       count as an inline `style="--k-cols: 3"`, and an inline custom property
       beats a stylesheet one. Without it the grids would never collapse and
       a 4-column form would still be 4 columns on a phone. */
    .k-form-grid,
    .k-detail-grid { --k-cols: 2 !important; }

    .page-header { gap: var(--k-space-3); }
    .page-header .page-title h1,
    .page-header .page-title h4 { font-size: 19px; }
    /* Breadcrumb is redundant with the title on narrow screens. */
    .page-header .breadcrumb { display: none !important; }

    .koomi-list-filters,
    .k-filter-bar { gap: var(--k-space-2); }
    .koomi-filter-field,
    .k-filter-field { flex: 1 1 180px; min-width: 140px; }
}

/* ── Mobile ─────────────────────────────────────────────────────────────── */
@media (max-width: 767.98px) {
    :root { --k-page-pad: 14px; --k-card-pad: 14px; --k-field-gap: 14px; }

    .k-form-grid,
    .k-detail-grid { --k-cols: 1 !important; }
    /* A "two cells wide" field cannot span 2 of 1 column. */
    .k-form-grid > .k-col-2 { grid-column: span 1; }

    .page-header { flex-direction: column; align-items: stretch; }
    .page-header .page-btn { width: 100%; }
    /* The page's main action becomes a full-width tap target. */
    .page-header .page-btn > .btn,
    .page-header .page-btn > a.btn { flex: 1 1 auto; justify-content: center; }

    /* Save/Cancel stack rather than shrinking into unreadable pills. */
    .koomi-form-actions,
    .k-btn-row { flex-direction: column-reverse; align-items: stretch; }
    .koomi-form-actions .btn,
    .k-btn-row .btn { width: 100%; }

    .k-table-toolbar { flex-direction: column; align-items: stretch; }
    .k-table-toolbar-actions { margin-left: 0; justify-content: flex-start; }

    /* The filter bar stacks. Each field must also reset its flex shorthand:
       `flex: 1 1 14rem` sets the basis along the MAIN axis, so once the bar
       becomes a column that 14rem is a 224px-tall field, which is what put
       large empty gaps between the search box and each dropdown. */
    .koomi-list-filters,
    .k-filter-bar { flex-direction: column; align-items: stretch; }
    .koomi-filter-field,
    .koomi-filter-search,
    .k-filter-field {
        flex: 0 0 auto;
        width: 100%;
        min-width: 0;
        justify-content: flex-start;
    }
    .koomi-filter-actions { width: 100%; }
    .koomi-filter-actions .btn { flex: 1 1 auto; }

    /* DataTables footer chrome stacks instead of colliding. */
    .dataTables_wrapper .dataTables_info,
    .dataTables_wrapper .dataTables_paginate { float: none !important; text-align: center; width: 100%; }
    .dataTables_wrapper .dataTables_paginate { margin-top: var(--k-space-3); }

    /* An action menu near the right edge opens inward, not off-screen. */
    .dropdown-menu-end { right: 0; left: auto; }
    .dropdown-menu { max-width: calc(100vw - 24px); }

    .nav-tabs .nav-link { padding: 9px var(--k-space-3); font-size: 13.5px; }
}

/* ── Very small phones ──────────────────────────────────────────────────── */
@media (max-width: 400px) {
    :root { --k-page-pad: 10px; }
    .page-header .page-title h1,
    .page-header .page-title h4 { font-size: 17px; }
}

/* ── Touch targets ──────────────────────────────────────────────────────── */
@media (hover: none) and (pointer: coarse) {
    .btn, .form-control, .form-select { min-height: 44px; }
    .table-action-dropdown .table-action-btn { width: 38px; height: 38px; }
}

/* ── Print ──────────────────────────────────────────────────────────────── */
@media print {
    .page-header .page-btn,
    .k-table-toolbar,
    .koomi-list-filters,
    .dataTables_wrapper .dataTables_paginate,
    .dataTables_wrapper .dataTables_length,
    .sidebar, .header { display: none !important; }
    .page-wrapper .content .card { box-shadow: none; border-color: #ddd; }
}

/* ============================================================================
   17. ACCESSIBILITY
   ============================================================================ */

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid var(--k-primary);
    outline-offset: 2px;
}

.k-visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

/* ============================================================================
   18. VARIANT BUILDER  (Add / Edit Product)
   ============================================================================
   Moved here verbatim from a 313-line inline <style> block in
   resources/views/product/_form.blade.php. Its hardcoded greys, blues and
   greens are now the shared tokens, so the variant grid follows the rest of
   the app when the palette changes. Class names are unchanged — the variant
   builder JS in that view still drives them.
   ============================================================================ */

.koomi-variant-panel {
    border: 1px solid var(--k-border);
    border-radius: 12px;
    background: var(--k-surface);
    overflow: hidden;
}

.koomi-variant-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .7rem 1rem;
    background: var(--k-surface-soft);
    border-bottom: 1px solid var(--k-border);
    flex-wrap: wrap;
}

.koomi-step-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0;
    font-weight: 600;
    font-size: .9rem;
    color: var(--k-text);
}

.koomi-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--k-primary-soft);
    color: var(--k-primary);
    font-size: .72rem;
    font-weight: 700;
    flex-shrink: 0;
}

.koomi-variant-note {
    font-size: .74rem;
    color: var(--k-text-muted);
}

.koomi-variant-note .koomi-note-lock {
    color: var(--k-text-soft);
}

/* Shown while the options above have moved on from the rows below. */
.koomi-variant-stale {
    display: inline-flex;
    align-items: center;
    margin-top: .35rem;
    padding: .2rem .5rem;
    border: 1px solid var(--k-warning-border);
    border-radius: 999px;
    background: var(--k-warning-soft);
    color: var(--k-warning-strong);
    font-size: .72rem;
    font-weight: 600;
}

.koomi-variant-stale.d-none {
    display: none;
}

.koomi-variant-body {
    padding: 1rem;
}

.koomi-variant-body .dimension-row:not(:last-child) {
    padding-bottom: .65rem;
    border-bottom: 1px dashed var(--k-border);
}

.koomi-variant-table {
    min-width: 860px;
}

/* Order is read-only: the rows follow the options, so it is a number, not a field. */
.koomi-variant-order {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    font-size: .78rem;
    font-weight: 600;
    color: var(--k-text-soft);
    font-variant-numeric: tabular-nums;
}

.koomi-variant-subhead {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
    color: var(--k-text-soft);
}

/* The SKU sits under the name as a quiet sub-line, not a column of its own. */
.koomi-standard-form .koomi-variant-table .form-control.koomi-variant-sku {
    margin-top: .15rem;
    min-height: 24px;
    /* Matches the name input's horizontal padding so the two line up. */
    padding: .1rem .75rem;
    font-size: .72rem;
    color: var(--k-text-soft);
    background: transparent;
    border-color: transparent;
    border-radius: 6px;
}

.koomi-standard-form .koomi-variant-table .form-control.koomi-variant-sku:hover {
    border-color: var(--k-border);
}

.koomi-standard-form .koomi-variant-table .form-control.koomi-variant-sku:focus {
    background: var(--k-surface);
    border-color: var(--k-border-strong);
    color: var(--k-text-body);
}

.koomi-variant-table>thead>tr>th {
    /* Same cell padding as the body, so a header label sits over its own column. */
    padding: .4rem .5rem !important;
}

.koomi-variant-table thead th {
    background: var(--k-surface-soft);
    border-bottom: 1px solid var(--k-border);
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--k-text-muted);
    font-weight: 700;
    white-space: nowrap;
}

.koomi-variant-table th,
.koomi-variant-table td {
    padding: .4rem .5rem;
    vertical-align: middle;
}

/* The name cell is two lines tall (name + SKU), so centring would push every
   other field down past it. Cells hang from the top instead, and everything that
   is not a full-height input is given the input's height so the first line of
   every column sits on the same baseline.

   !important is load-bearing here: koomi-tables.css dresses every .table inside
   .content as a list row (12px cells, middle-aligned) from a five-class selector
   this file cannot outrank. The variant table is a dense editor grid, not a list. */
.koomi-variant-table>tbody>tr>td {
    padding: .4rem .5rem !important;
    vertical-align: top !important;
}

.koomi-variant-table tbody td>.koomi-variant-order,
.koomi-variant-table tbody td>.koomi-file-btn,
.koomi-variant-table tbody td>.koomi-lock-pill,
.koomi-variant-table tbody td>.btn {
    height: 34px;
}

.koomi-variant-table tbody td>.koomi-lock-pill {
    width: 34px;
}

.koomi-standard-form .koomi-variant-table .form-control {
    min-height: 34px;
    font-size: .85rem;
    border-radius: 8px;
}

.koomi-variant-table input[type=file].form-control,
.koomi-variant-table input[type=file].form-control-sm {
    font-size: .78rem;
    padding: .3rem .4rem;
}

.koomi-variant-table .locked-variant-row>td {
    background: var(--k-surface);
}

.koomi-variant-table .btn-outline-danger.btn-sm {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    padding: 0;
}

/* Saved variations get a quiet lock chip instead of a heavy grey badge. */
.koomi-lock-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: var(--k-surface-hover);
    border: 1px solid var(--k-border);
    color: var(--k-text-soft);
    font-size: .72rem;
    cursor: help;
}

/* Same chip, sized to sit where the row's delete button would be. */
.koomi-lock-pill-wide {
    width: 100%;
    height: 38px;
}

.locked-dimension-row .select2-container--disabled .select2-selection--single {
    background: var(--k-surface-soft);
    cursor: not-allowed;
}

/* ── Options multi-select: chips that match the builder ───────── */
.dimension-row .select2-container {
    width: 100% !important;
}

/* Height matched to the Type select next to it. Border colour and
   radius are left to the theme so both fields look identical. */
.dimension-row .select2-container--default .select2-selection--multiple {
    min-height: 38px;
    padding: 0 .4rem;
}

.dimension-row .select2-container--default .select2-selection--multiple .select2-selection__rendered {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem;
    margin: 0;
    padding: 0;
    min-height: 36px;
    line-height: 1;
}

.dimension-row .select2-container--default .select2-selection--multiple .select2-selection__choice {
    display: inline-flex;
    flex-direction: row-reverse;
    align-items: center;
    gap: .35rem;
    margin: 0;
    padding: .1rem .45rem .1rem .55rem;
    border: 1px solid var(--k-primary-border);
    border-radius: 999px;
    background: var(--k-primary-soft);
    color: var(--k-primary-strong);
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.5;
}

.dimension-row .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
    float: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--k-primary-border);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1;
}

.dimension-row .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
    color: var(--k-primary-strong);
    background: transparent;
}

/* Locked options can't be removed. The theme forces one text colour on
   every chip, so the green says !important to come through. */
.dimension-row .select2-selection__choice.is-locked {
    background: var(--k-success-soft);
    border-color: var(--k-success-border);
    color: var(--k-success-strong) !important;
    padding-right: .55rem;
    cursor: not-allowed;
}

.dimension-row .select2-selection__choice.is-locked .select2-selection__choice__remove {
    display: none;
}

.dimension-row .select2-container--default .select2-search--inline {
    display: flex;
    align-items: center;
}

.dimension-row .select2-container--default .select2-search--inline .select2-search__field {
    margin: 0;
    height: 22px;
    line-height: 22px;
    font-size: .8rem;
}

.dimension-row .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
    margin: 0;
    color: var(--k-text-soft);
    font-size: .82rem;
}

.koomi-file-btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    max-width: 100%;
    padding: .3rem .55rem;
    border: 1px solid var(--k-border-strong);
    border-radius: 8px;
    background: var(--k-surface);
    cursor: pointer;
    font-size: .8rem;
    color: var(--k-text-body);
    line-height: 1;
}

.koomi-file-btn:hover {
    border-color: var(--k-text-soft);
    background: var(--k-surface-soft);
}

.koomi-file-btn.has-file {
    border-color: var(--k-success);
    color: var(--k-success-strong);
    background: var(--k-success-soft);
}

.koomi-file-btn i {
    font-size: .9rem;
}

/* Icon-only picker for the variation rows — the thumbnail is the label. */
.koomi-file-btn.is-icon {
    gap: 0;
    padding: .2rem;
    justify-content: center;
    width: 34px;
    height: 34px;
}

.koomi-file-btn.is-icon .koomi-file-thumb {
    height: 100%;
    width: 100%;
    border: 0;
    border-radius: 6px;
}

.koomi-file-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 78px;
}

.koomi-file-thumb {
    height: 28px;
    width: 28px;
    border-radius: 5px;
    object-fit: cover;
    border: 1px solid var(--k-border);
}

.koomi-chip-wrap {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    align-items: center;
    min-height: 40px;
    padding: .35rem .5rem;
    border: 1px solid var(--k-border-strong);
    border-radius: 10px;
    background: var(--k-surface);
}

.koomi-chip-wrap .dim-options-empty {
    color: var(--k-text-soft);
}

.koomi-chip {
    display: inline-flex;
    align-items: center;
    margin: 0;
    border: 1px solid var(--k-border-strong);
    border-radius: 999px;
    background: var(--k-surface-soft);
    color: var(--k-text-body);
    font-size: .78rem;
    font-weight: 600;
    padding: .22rem .7rem;
    cursor: pointer;
    transition: all .12s ease;
}

.koomi-chip:hover {
    border-color: var(--k-text-soft);
}

.btn-check:checked+.koomi-chip {
    background: var(--k-primary);
    border-color: var(--k-primary);
    color: var(--k-surface);
}

.koomi-chip-locked {
    cursor: not-allowed;
}

.btn-check:disabled+.koomi-chip-locked {
    opacity: 1;
    background: var(--k-success);
    border-color: var(--k-success);
    color: var(--k-surface);
}

/* Only the genuinely read-only variant fields (value / SKU / average cost) are
   locked — retail and wholesale prices stay editable on an existing variation. */
.locked-variant-row input[readonly],
.locked-variant-row input[disabled] { cursor: not-allowed; }

/* ============================================================================
   19. COMPONENT STYLES CONSOLIDATED FROM INLINE <style> BLOCKS
   ============================================================================
   These lived as per-view/per-component <style> tags, each with its own
   hardcoded greys and blues. Class names are unchanged — the components' JS and
   markup still drive them — but the values are now the shared tokens, so they
   follow the palette like everything else.
   ============================================================================ */

/* ── x-issued-credentials: the one-time password handover panel ──────────── */
.koomi-credentials-backdrop {
    position: fixed;
    inset: 0;
    z-index: calc(var(--k-z-toast) + 10);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--k-space-4);
    background: rgba(15, 23, 42, .55);
}

.koomi-credentials-card {
    width: 100%;
    max-width: 460px;
    overflow: hidden;
    background: var(--k-surface);
    border-radius: var(--k-radius-lg);
    box-shadow: var(--k-shadow-lg);
}

.koomi-credentials-head { padding: var(--k-space-5); border-bottom: 1px solid var(--k-border); }
.koomi-credentials-head h5 { font-weight: var(--k-fw-bold); color: var(--k-text); }
.koomi-credentials-head p  { font-size: var(--k-fs-help); color: var(--k-text-muted); margin: 0; }

.koomi-credentials-body { padding: var(--k-space-5); }

.koomi-credentials-label {
    display: block;
    margin-bottom: 5px;
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
    color: var(--k-text-muted);
}

.koomi-credentials-value { display: flex; align-items: center; gap: var(--k-space-2); }

.koomi-credentials-value code {
    flex: 1 1 auto;
    padding: 9px var(--k-space-3);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
    color: var(--k-text);
    font-size: var(--k-fs-base);
    overflow-wrap: anywhere;
}

/* The password is meant to be read off the screen and typed elsewhere. */
.koomi-credentials-password {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 17px !important;
    font-weight: var(--k-fw-bold);
    letter-spacing: .06em;
}

.koomi-credentials-note { margin: var(--k-space-4) 0 0; font-size: var(--k-fs-help); color: var(--k-text-muted); }

.koomi-credentials-foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--k-space-2);
    padding: var(--k-space-3) var(--k-space-5);
    background: var(--k-surface-soft);
    border-top: 1px solid var(--k-border);
}

/* ── x-product-search-picker: the type-ahead product combobox ────────────── */

/* Toolbar: filter | search | action on one baseline. The button is sized by its
   own label rather than by a grid column, which is what made the spacing on the
   purchase screen look uneven against the fields beside it. */
.product-picker-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--k-space-3);
}
.product-picker-field { min-width: 0; }
.product-picker-field-filter { flex: 0 1 16rem; }
.product-picker-field-search { flex: 1 1 22rem; }
.product-picker-toolbar .k-label { white-space: nowrap; }
.product-picker-action {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-end;
}
/* The label above the fields is what sets their height; the button matches the
   control, not the label + control, so it lines up with the inputs. */
.product-picker-action .btn { white-space: nowrap; }

@media (max-width: 767.98px) {
    .product-picker-toolbar { flex-direction: column; align-items: stretch; }
    .product-picker-field-filter,
    .product-picker-field-search { flex: 1 1 auto; }
    .product-picker-action .btn { width: 100%; }
}

.product-picker-combobox { position: relative; }

.product-picker-results {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    z-index: var(--k-z-dropdown);
    max-height: 320px;
    overflow-y: auto;
    padding: 6px;
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius);
    box-shadow: var(--k-shadow-lg);
}

.product-picker-option {
    width: 100%;
    padding: 10px var(--k-space-3);
    border: 0;
    border-radius: var(--k-radius-sm);
    background: transparent;
    text-align: left;
    cursor: pointer;
}
.product-picker-option:hover,
.product-picker-option.is-active { background: var(--k-primary-soft); }

.product-picker-option-title { display: block; font-weight: var(--k-fw-medium); color: var(--k-text); }
.product-picker-option-meta  { display: block; margin-top: 2px; font-size: var(--k-fs-help); color: var(--k-text-muted); }
.product-picker-no-results   { padding: var(--k-space-3); font-size: 13px; color: var(--k-text-muted); }

/* Variation table: never scroll sideways — the item name wraps instead. */
.product-search-picker .modal .table-responsive { overflow-x: visible; }
.product-search-picker .modal .table { table-layout: fixed; width: 100%; font-size: 13px; }
.product-search-picker .modal .table td,
.product-search-picker .modal .table th { vertical-align: middle; }
.product-search-picker .modal .picker-item-name {
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
}
.product-search-picker .modal .table input.form-control-sm {
    min-width: 0;
    width: 100%;
    padding-inline: .4rem;
}

/* ── x-koomi.module-data-card: the read-only sync panel on show pages ────── */
.koomi-show-sync-card {
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius-lg);
    box-shadow: var(--k-shadow-sm);
}
.koomi-show-sync-card .card-header {
    background: var(--k-surface);
    border-bottom: 1px solid var(--k-border);
    border-radius: var(--k-radius-lg) var(--k-radius-lg) 0 0;
}
.koomi-show-sync-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--k-space-3) var(--k-space-5);
}
.koomi-show-sync-field {
    min-height: 64px;
    padding: 10px var(--k-space-3);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
}
.koomi-show-sync-label {
    display: block;
    margin-bottom: 4px;
    font-size: 11px;
    font-weight: var(--k-fw-medium);
    color: var(--k-text-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.koomi-show-sync-value {
    color: var(--k-text);
    font-weight: var(--k-fw-medium);
    word-break: break-word;
    white-space: pre-wrap;
}
@media (max-width: 767.98px) { .koomi-show-sync-grid { grid-template-columns: 1fr; } }
@media print { .koomi-show-sync-card { box-shadow: none; } }

/* ── Subscription: the seat-pricing quote box ───────────────────────────── */
.koomi-seat-quote {
    padding: 10px var(--k-space-4);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
}

/* ── Product details: IMEI search hit + variation disclosure ─────────────── */
.pos-var-toggle { cursor: pointer; }
.pos-var-chevron { transition: transform .2s ease; }
.pos-var-toggle[aria-expanded="true"] .pos-var-chevron { transform: rotate(180deg); }
.js-imei-row.imei-hit { background: var(--k-warning-soft) !important; }
.js-imei-row.imei-hit td { border-color: var(--k-warning-border) !important; }

/* Summary pill built in JS by x-product-search-picker (was an inline
   border/background string in that component's script). */
.k-stat-pill {
    padding: var(--k-space-2) var(--k-space-3);
    background: var(--k-surface-soft);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
}
.k-stat-pill-label { font-size: var(--k-fs-help); color: var(--k-text-muted); margin-bottom: 2px; }
.k-stat-pill-value { font-size: 15px; font-weight: var(--k-fw-bold); color: var(--k-text); }

/* ============================================================================
   20. POS TILL SCREEN
   ============================================================================
   Moved from a 540-line inline <style> in resources/views/pos.blade.php.

   The POS keeps a bespoke LAYOUT on purpose — a product grid beside a live
   cart is not a CRUD page, and it opts out of the shared table/card rules via
   `.page-wrapper.koomi-bespoke`. What it should not keep is a bespoke PALETTE:
   its greys, and three uses of the retired #3498db sky-blue, are now the same
   tokens as the rest of the app. Every selector is .pos-* namespaced, so
   nothing here leaks onto another screen.
   ============================================================================ */

.pos-panel-card {
        border-radius: .75rem;
    }

    .pos-section-title {
        font-weight: 700;
        margin-bottom: 1rem;
    }

    .pos-search-group .input-group-text {
        background: var(--k-surface);
        border-right: 0;
        color: var(--k-text-muted);
    }

    /* The field is a flex child of the input-group so it fills the space between the
       barcode icon and the Search button, with the clear (×) layered inside it. */
    .pos-search-group .pos-search-field {
        position: relative;
        flex: 1 1 auto;
        min-width: 0;
        display: flex;
    }

    .pos-search-group .pos-search-field .form-control {
        border-left: 0;
        border-right: 0;
        border-radius: 0;
        padding-left: 0;
        padding-right: 2.25rem;   /* room for the × */
        width: 100%;
    }

    /* Typing filters the grid on its own, so the Search button that used to close this
       group is gone. It carried the right-hand border and rounding, which left the field
       open-ended once it was removed; whichever element ends up last has to finish the
       control. Written against :last-child so putting the button back needs no CSS change. */
    .pos-search-group .pos-search-field:last-child .form-control {
        border-right: 1px solid var(--k-border-strong);
        border-top-right-radius: var(--k-radius);
        border-bottom-right-radius: var(--k-radius);
    }

    /* Marks the card a scan just acted on — a unit handed back lands in the grid
       among hundreds of others, and the eye needs telling which one it was. */
    .pos-product-card.pos-card-flash {
        outline: 2px solid var(--k-primary);
        outline-offset: 2px;
        transition: outline-color .4s ease-in-out;
    }

    .pos-search-clear {
        position: absolute;
        top: 50%;
        right: .6rem;
        transform: translateY(-50%);
        border: 0;
        background: transparent;
        color: var(--k-text-soft);
        line-height: 1;
        padding: .25rem;
        border-radius: 50%;
        cursor: pointer;
    }

    .pos-search-clear:hover {
        color: var(--k-text-body);
        background: var(--k-surface-hover);
    }

    /* The Search button is the last child, so it carries the right-hand rounding. */
    .pos-search-group .btn {
        border-top-left-radius: 0;
        border-bottom-left-radius: 0;
    }

    /* Rail on the left, product grid on the right. */
    .pos-browse {
        display: grid;
        grid-template-columns: minmax(150px, 200px) 1fr;
        gap: 1.25rem;
        align-items: start;
    }

    .pos-rail {
        border-right: 1px solid var(--k-border);
        padding-right: 1rem;
        /* A grid item defaults to min-width:auto, which lets wide content push out of
           its track instead of being constrained by it. */
        min-width: 0;
    }

    .pos-rail-title,
    .pos-scope-title {
        font-weight: 700;
        font-size: .95rem;
        margin-bottom: .75rem;
    }

    .pos-rail-list {
        display: flex;
        flex-direction: column;
        gap: .125rem;
    }

    .pos-rail-item {
        border: 0;
        background: transparent;
        color: var(--k-text-body);
        text-align: left;
        border-radius: .5rem;
        padding: .5rem .75rem;
        font-size: .875rem;
        transition: background-color .15s ease, color .15s ease;
    }

    .pos-rail-item:hover {
        background: var(--k-surface-hover);
    }

    .pos-rail-item[aria-pressed="true"] {
        background: var(--k-primary-soft);
        color: var(--k-primary);
        font-weight: 600;
    }

    /* A fixed 5 × 3 grid (15 per page) so every page looks the same and the cards
       never resize themselves depending on how many landed on the page. */
    /* The card decides how many fit, not a fixed count.
       The grid shares the screen with the cart now, so a hard "five across" left the
       cards too narrow to hold a name, an SKU and a price without every line wrapping.
       auto-fill against a minimum card width gives three on a half-width panel, more on
       a wide screen, and fewer on a small one — without a breakpoint for each case. */
    .pos-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
        gap: .75rem;
        align-content: start;
    }

    .pos-grid .pos-product-card {
        display: flex;
        flex-direction: column;
        height: 100%;
        min-height: 210px;
    }

    .pos-grid .pos-product-card img {
        width: 100%;
        height: 96px;
        object-fit: contain;
        flex: 0 0 auto;
    }

    .pos-grid .pos-product-card-body {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
    }

    /* The name gets a fixed two-line box, so the price/stock row always sits at the
       same height on every card regardless of how long the name is. */
    .pos-grid .pos-product-name {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        min-height: 2.4em;
        line-height: 1.2;
        font-size: .82rem;
    }

    .pos-grid .pos-product-meta {
        margin-top: auto;
    }

    /* On a phone the cards would otherwise drop to one across; two is still readable
       and halves the scrolling. */
    @media (max-width: 575.98px) {
        .pos-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }

    /* "Sales Closed" — a header chip that opens a small panel.
       position:fixed takes the panel out of every ancestor's stacking context, so the cards
       below (Bootstrap's .card is position:relative) can never paint over it. */
    #pos-summary-toggle {
        white-space: nowrap;
    }

    .pos-summary-panel {
        position: fixed;
        z-index: 2000;
        width: 21rem;
        max-width: calc(100vw - 2rem);
        padding: .85rem;
        background: var(--k-surface);
        border: 1px solid var(--k-border);
        border-radius: .625rem;
        box-shadow: 0 12px 32px rgba(15, 23, 42, .22);
    }

    .pos-summary-panel .form-control {
        min-width: 0;
    }

    .pos-summary-stats {
        display: grid;
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: .5rem;
        padding: .5rem .65rem;
        background: var(--k-surface-soft);
        border: 1px solid var(--k-border);
        border-radius: .5rem;
        font-size: .78rem;
        text-align: center;
    }

    .pos-summary-stats strong {
        font-size: .9rem;
    }

    /* Selected-customer details strip */
    .pos-customer-info-grid {
        display: grid;
        grid-template-columns: repeat(6, minmax(0, 1fr));
        gap: .75rem;
        margin-top: .5rem;
        padding: .6rem .75rem;
        background: var(--k-surface-soft);
        border: 1px solid var(--k-border);
        border-radius: .5rem;
        font-size: .82rem;
    }

    @media (max-width: 767.98px) {
        .pos-customer-info-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }

    .pos-pager {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 1rem;
        flex-wrap: wrap;
        border-top: 1px solid var(--k-border);
        margin-top: 1.25rem;
        padding-top: 1rem;
    }

    .pos-pages {
        display: flex;
        gap: .25rem;
    }

    .pos-page-btn {
        min-width: 2rem;
        height: 2rem;
        border: 1px solid var(--k-border);
        background: var(--k-surface);
        color: var(--k-text-body);
        border-radius: .375rem;
        font-size: .8125rem;
        line-height: 1;
    }

    .pos-page-btn[aria-current="page"] {
        background: var(--k-primary-soft);
        border-color: var(--k-primary-border);
        color: var(--k-primary);
        font-weight: 600;
    }

    .pos-page-btn:disabled {
        opacity: .45;
    }

    @media (max-width: 767.98px) {
        .pos-browse {
            grid-template-columns: 1fr;
        }

        .pos-rail {
            border-right: 0;
            border-bottom: 1px solid var(--k-border);
            padding-right: 0;
            padding-bottom: 1rem;
        }

        .pos-rail-list {
            flex-direction: row;
            flex-wrap: wrap;
        }
    }

    .pos-product-card {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        text-align: left;
        border: 1px solid var(--k-border);
        border-radius: .5rem;
        overflow: hidden;
        background: var(--k-surface);
        padding: 0;
        box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075);
        transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
    }

    .pos-product-card:hover {
        transform: translateY(-2px);
        box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .1);
        border-color: var(--k-border-strong);
    }

    .pos-product-card-disabled,
    .pos-product-card:disabled {
        opacity: .55;
        cursor: not-allowed;
        filter: grayscale(.2);
    }

    .pos-product-card-disabled:hover,
    .pos-product-card:disabled:hover {
        transform: none;
        box-shadow: 0 10px 26px rgba(15, 23, 42, 0.06);
        border-color: var(--k-border);
    }

    .pos-product-card img {
        width: 100%;
        height: 150px;
        object-fit: cover;
        background: var(--k-surface-soft);
    }

    .pos-product-card-body {
        padding: .9rem;
    }

    .pos-product-name {
        display: block;
        font-size: .875rem;
        line-height: 1.3;
        color: var(--k-text);
    }

    /* One line, cut short. An SKU is long and unbreakable, so left to wrap it took
       five lines of a card and pushed the price out of sight; the name is what the
       cashier reads, and the full code is on the item's own page. */
    .pos-product-sku {
        font-size: .75rem;
        color: var(--k-text-soft);
        margin-top: .15rem;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Price and stock sit on one line and stay there: wrapping "Out of stock" down
       the side of a narrow card was what made the grid look broken. */
    .pos-product-meta {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: .5rem;
        margin-top: .6rem;
        font-size: .78rem;
        color: var(--k-text-muted);
        white-space: nowrap;
    }

    .pos-product-meta > span {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .pos-product-meta span:first-child {
        font-weight: 700;
        font-size: .875rem;
        color: var(--k-text);
    }

    .pos-summary-card {
        position: sticky;
        top: 1rem;
    }

    .pos-cart-table thead th {
        text-transform: uppercase;
        font-size: .7rem;
        letter-spacing: .04em;
        color: var(--k-text-muted);
        background: var(--k-surface-soft);
    }

    /* Cart never scrolls sideways: the item name wraps, the inputs shrink.

       This has to out-rank `.page-wrapper .content .table-responsive`, which sets
       overflow-x:auto — a plain `.pos-cart-table` loses to it on specificity, so the
       cart had a horizontal scrollbar and the remove button was clipped off the end
       of the row. Both class names are on the same element. */
    .page-wrapper .content .table-responsive.pos-cart-table,
    .pos-cart-table {
        /* hidden, not visible: pairing `visible` with a scrolling y-axis makes the
           browser compute it back to `auto`, which is the sideways scrollbar this
           rule exists to defeat. Nothing overflows sideways anyway — the table is
           table-layout:fixed — so clipping costs nothing. */
        overflow-x: hidden;
        /* A long sale used to push the totals and the Pay button off the bottom of the
           screen, so finishing one meant scrolling the whole page past the cart. The
           cap itself is set by sizeCartViewport() in pos.blade.php, measured off four
           real rows. */
        overflow-y: auto;
    }

    /* The column headings stay put while the lines move under them. */
    .pos-cart-table thead th {
        position: sticky;
        top: 0;
        z-index: 2;
    }

    /* The tally between the last line and the money. */
    .pos-cart-count {
        font-size: .8rem;
        padding-bottom: .5rem;
        border-bottom: 1px dashed var(--k-border);
    }

    .pos-cart-table table {
        table-layout: fixed;
        width: 100%;
        font-size: .8rem;
    }

    .pos-cart-table td,
    .pos-cart-table th {
        padding-left: .35rem;
        padding-right: .35rem;
    }

    .pos-cart-table td:first-child {
        white-space: normal;
        overflow-wrap: anywhere;
        word-break: break-word;
    }

    .pos-cart-table input.form-control-sm {
        min-width: 0;
        width: 100%;
        padding-left: .35rem;
        padding-right: .35rem;
        font-size: .78rem;
    }

    .pos-cart-table .pos-stock-small,
    .pos-cart-table .text-muted.small {
        font-size: .7rem;
    }

    /* Spinners cost ~16px of a 92px cell and are useless next to a keyboard, so a
       price like 115.0000 gets the whole cell to be read in. */
    .pos-cart-table input[type="number"] {
        -moz-appearance: textfield;
    }
    .pos-cart-table input[type="number"]::-webkit-outer-spin-button,
    .pos-cart-table input[type="number"]::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }

    /* The remove button is sized to its column instead of inheriting the standard
       small-button padding, which was wider than the cell it sits in. */
    .pos-cart-table .pos-remove {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 26px;
        height: 26px;
        min-height: 26px;
        padding: 0 !important;
        font-size: .9rem;
        line-height: 1;
    }

    /* A repair sits in the grid beside stock, so it needs a face of its own where a
       product would carry its photo — there is nothing to photograph. */
    .pos-repair-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 96px;
        flex: 0 0 auto;
        border-radius: .5rem;
        background: var(--k-warning-soft, var(--k-surface-soft));
        color: var(--k-warning-strong, var(--k-text-muted));
        font-size: 1.6rem;
    }

    .pos-repair-card {
        border-color: var(--k-warning, var(--k-border-strong));
    }

    /* The count beside the Repairs facet — how many are waiting to be paid for. */
    .pos-facet-count {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 18px;
        height: 18px;
        padding: 0 5px;
        border-radius: 999px;
        background: var(--k-danger);
        color: var(--k-text-invert);
        font-size: .68rem;
        font-weight: 700;
        line-height: 1;
    }

    /* Category / Brand / Repairs segmented toggle */
    /* The rail is at most 200px, and three labelled facets need about 310px, so the
       group wraps instead of running out over the product grid. A pill radius on a
       two-row box reads as broken, hence the rounded rectangle. */
    .pos-facet-toggle {
        display: flex;
        flex-wrap: wrap;
        gap: .25rem;
        padding: .25rem;
        border-radius: .85rem;
        background: var(--k-surface-hover);
        margin-bottom: .75rem;
    }

    .pos-facet-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: .35rem;
        /* Grow to share whatever row they land on, so a wrapped row is not ragged. */
        flex: 1 1 auto;
        min-width: 0;
        border: 0;
        background: transparent;
        color: var(--k-text-muted);
        font-size: .78rem;
        font-weight: 600;
        padding: .35rem .6rem;
        border-radius: 999px;
        cursor: pointer;
        transition: background .12s ease, color .12s ease;
    }

    .pos-facet-btn > span:not(.pos-facet-count) {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .pos-facet-btn:hover {
        color: var(--k-text);
    }

    .pos-facet-btn.active {
        background: var(--k-primary);
        color: var(--k-surface);
        box-shadow: 0 1px 2px rgba(15, 23, 42, .12);
    }

    /* Pickup / Delivery segmented toggle */
    .pos-ordertype-toggle {
        display: flex;
        gap: .25rem;
        padding: .25rem;
        border-radius: 999px;
        background: var(--k-surface-hover);
    }

    .pos-ordertype-btn {
        flex: 1 1 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: .4rem;
        border: 0;
        background: transparent;
        color: var(--k-text-muted);
        font-size: .8rem;
        font-weight: 600;
        padding: .4rem .75rem;
        border-radius: 999px;
        cursor: pointer;
        transition: background .12s ease, color .12s ease;
    }

    .pos-ordertype-btn:hover {
        color: var(--k-text);
    }

    .pos-ordertype-btn.active {
        background: var(--k-primary);
        color: var(--k-surface);
        box-shadow: 0 1px 2px rgba(15, 23, 42, .12);
    }

    /* Collapsible customer card */
    .pos-customer-header {
        cursor: pointer;
    }

    .pos-customer-chevron {
        color: var(--k-text-soft);
        transition: transform .18s ease;
    }

    .pos-customer-header.collapsed .pos-customer-chevron {
        transform: rotate(180deg);
    }

    /* Variation modal table: no horizontal scroll, name wraps */
    .pos-variation-table {
        max-height: 360px;
        overflow-y: auto;
        overflow-x: visible;
    }

    .pos-variation-table table {
        table-layout: fixed;
        width: 100%;
        font-size: .82rem;
    }

    .pos-variation-table .pos-var-name {
        white-space: normal;
        overflow-wrap: anywhere;
        word-break: break-word;
    }

    .pos-variation-table input.form-control-sm {
        min-width: 0;
        width: 100%;
        padding-left: .35rem;
        padding-right: .35rem;
    }

    .pos-imei-card {
        border: 1.5px solid var(--k-border);
        border-radius: 10px;
        background: var(--k-surface);
        padding: .6rem .75rem;
        cursor: pointer;
        font-family: monospace;
        font-size: .85rem;
        transition: border-color .12s ease, background .12s ease;
    }

    .pos-imei-card:hover {
        border-color: var(--k-primary);
    }

    .pos-imei-card.selected {
        border-color: var(--k-success);
        background: var(--k-success-soft);
        box-shadow: 0 0 0 3px rgba(34, 197, 94, .18);
    }

    /* A unit the shop has already sold, shown so a cashier holding one can see it is
       ours. Green when they may take it back — the border is the invitation — and red
       when they may not, in which case the card is disabled and does nothing at all. */
    .pos-imei-card-return {
        border-color: var(--k-success);
        border-style: dashed;
    }

    .pos-imei-card-return:hover {
        border-style: solid;
        border-color: var(--k-success);
        background: var(--k-success-soft);
    }

    .pos-imei-card-sold {
        border-color: var(--k-danger);
        background: var(--k-danger-soft, rgba(220, 38, 38, .06));
        cursor: not-allowed;
        opacity: .75;
    }

    /* Disabled kills :hover in most browsers, but not all — say it outright so a red
       card never looks like it is about to do something. */
    .pos-imei-card-sold:hover {
        border-color: var(--k-danger);
    }

    .pos-imei-note {
        font-family: var(--k-font, inherit);
        font-size: .72rem;
        font-weight: var(--k-fw-medium);
        margin-top: .2rem;
    }

    .pos-cart-table thead th {
        font-size: .78rem;
        text-transform: uppercase;
        color: var(--k-text-muted);
        border-bottom: 1px solid var(--k-border);
    }

    .pos-stock-small {
        font-size: .75rem;
        color: var(--k-text-muted);
    }

/* ── IMEI list: inline status chip (was an inline <style> in imeilist) ───── */
.imei-page .imei-status-preview {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
}
.imei-page .imei-status-dot {
    width: 8px;
    height: 8px;
    border-radius: var(--k-radius-pill);
    background: currentColor;
}

/* Every row carries three editable controls, a reference and a price. Below this the
   columns are too narrow to read, so the wrapper scrolls instead — which is what
   .table-responsive is there for.

   `fixed` is the part that matters. A <select> is as wide as its longest option, and
   these options are whole product names with SKUs ("Samsung S21 Ultra 12GB 256GB Silver
   Open Box — …"). Under the default `auto` layout the browser sizes each cell to that
   content and the selects spill straight across the neighbouring columns, so the
   variation picker landed on top of PO / Sale Ref and Save was pushed off the card.
   Fixed layout makes the declared widths binding. */
.imei-page .imei-table { min-width: 1140px; table-layout: fixed; }

/* …and with the columns now binding, every control has to live inside its own cell
   rather than overflow it. `min-width: 0` is what lets a select shrink below the width
   of its own options. */
.imei-page .imei-table td .form-control,
.imei-page .imei-table td .form-select {
    width: 100%;
    max-width: 100%;
    min-width: 0;
}

/* A product name is far longer than its column. The cell is the boundary; the full name
   is in the link's title. */
.imei-page .imei-table td > a.text-truncate { max-width: 100%; }

/* Three stacked controls make a tall cell — line them up at the top rather than floating
   each one in the middle of its own row. */
.imei-page .imei-table > tbody > tr > td { vertical-align: top; }
.imei-page .imei-table td .btn { white-space: nowrap; }

/* Every <select> on the page is upgraded to select2 (assets/js/script.js), which hides
   the real control and renders a `.select2-container` span in its place — and that span
   is inline-block where a <select> was block. That is what actually broke this table:
   the product and variation pickers stopped stacking and lined up side by side, running
   out of their cell and across PO / Sale Ref, while in the status cell the container sat
   beside the status chip and covered the Save button. Blocks again, one per line. */
.imei-page .imei-table td .select2-container {
    display: block;
    width: 100% !important;
    max-width: 100%;
}

.imei-page .imei-table td .select2-container + .select2-container,
.imei-page .imei-table td .select2-container + .form-select,
.imei-page .imei-table td .form-select + .select2-container { margin-top: 4px; }

/* The chip above the status picker is inline-flex, so the picker used to come up beside
   it rather than under it. */
.imei-page .imei-table td .imei-status-preview { display: flex; }

/* ── Sign-up: keep the number spinners visible and inside the field ─────── */
/* (was an inline <style> in signup.blade.php) */
.account-page input[type="number"] { position: relative; padding-right: 25px; }
.account-page input[type="number"]::-webkit-inner-spin-button,
.account-page input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: inner-spin-button !important;
    opacity: 1;
    width: 30px;
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Sortable multi-select  (x-ui.sortable-select)

   A picker on top chooses which values; the list under it shows them in order
   and is dragged to change it. The list is styled as a set of rows rather than
   chips because the order is the point, and a numbered row reads as a sequence
   where a wrapping row of chips does not.
   ═══════════════════════════════════════════════════════════════════════════ */

.k-sortable-select {
    display: block;
}

.k-sortable-list {
    list-style: none;
    margin: var(--k-space-3) 0 0;
    padding: var(--k-space-2);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
    background: var(--k-surface-soft);
    display: flex;
    flex-direction: column;
    gap: var(--k-space-2);
}

.k-sortable-list:empty {
    display: none;
}

.k-sortable-item {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
    padding: var(--k-space-2) var(--k-space-3);
    background: var(--k-surface);
    border: 1px solid var(--k-border-strong);
    border-radius: var(--k-radius-sm);
    box-shadow: var(--k-shadow-xs);
    font-size: var(--k-fs-base);
    color: var(--k-text-body);
    cursor: grab;
    user-select: none;
}

.k-sortable-item:active {
    cursor: grabbing;
}

/* The row being carried: faded, so the gap it leaves reads as the drop target. */
.k-sortable-item.k-sortable-dragging {
    opacity: .45;
    border-style: dashed;
}

/* The row the pointer is currently over. */
.k-sortable-item.k-sortable-over {
    border-color: var(--k-primary);
    box-shadow: var(--k-shadow-focus);
}

.k-sortable-grip {
    color: var(--k-text-soft);
    font-size: 13px;
    line-height: 1;
    flex: 0 0 auto;
}

/* The position number is what makes the order explicit rather than implied. */
.k-sortable-pos {
    flex: 0 0 auto;
    min-width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--k-radius-pill);
    background: var(--k-primary-soft);
    color: var(--k-primary-strong);
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-bold);
}

.k-sortable-label {
    flex: 1 1 auto;
    font-weight: var(--k-fw-normal);
    color: var(--k-text);
}

.k-sortable-actions {
    flex: 0 0 auto;
    display: inline-flex;
    gap: var(--k-space-1);
}

.k-sortable-btn {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius-sm);
    background: var(--k-surface);
    color: var(--k-text-muted);
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}

.k-sortable-btn:hover:not(:disabled) {
    background: var(--k-primary-soft);
    border-color: var(--k-primary-border);
    color: var(--k-primary-strong);
}

.k-sortable-btn:focus-visible {
    outline: none;
    box-shadow: var(--k-shadow-focus);
    border-color: var(--k-border-focus);
}

.k-sortable-btn:disabled {
    opacity: .35;
    cursor: default;
}

.k-sortable-remove:hover:not(:disabled) {
    background: var(--k-danger-soft);
    border-color: var(--k-danger-border);
    color: var(--k-danger-strong);
}

.k-sortable-empty {
    margin: var(--k-space-2) 0 0;
    font-size: var(--k-fs-help);
    color: var(--k-text-muted);
}

/* Touch: drag events do not fire, so the move buttons are the whole mechanism
   and need to be comfortably tappable. */
@media (hover: none) {
    .k-sortable-item { cursor: default; }
    .k-sortable-btn { width: 32px; height: 32px; font-size: 13px; }
}

/* ── Purchase items: line-level landed cost (shipping share + extras) ─────── */
.k-line-ship { width: 100%; max-width: 92px; }
.k-line-cost-note {
    display: block;
    margin-top: 2px;
    font-size: var(--k-fs-help);
    color: var(--k-text-muted);
    white-space: nowrap;
}
.k-line-expense-btn { white-space: nowrap; }
.k-line-expense-count {
    display: inline-block;
    min-width: 1.25rem;
    /* The gap is owned by the button's flex layout now, so the count sits right
       beside the plus instead of being pushed off it. */
    margin-left: 0;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--k-primary-soft);
    color: var(--k-primary);
    font-size: var(--k-fs-help);
    font-weight: var(--k-fw-medium);
    text-align: center;
}
/* The remove control is an icon in a cell of its own - centre it so the last
   column does not read as a ragged edge next to the totals. */
#items-table td.k-line-actions { white-space: nowrap; text-align: center; }
#items-table td.k-line-actions .k-btn-row { justify-content: center; flex-wrap: nowrap; }

.k-ship-alloc-note.is-off { color: var(--k-danger); font-weight: var(--k-fw-medium); }

/* Extra-expense rows inside the modal. */
.k-expense-row { display: flex; gap: var(--k-space-2); align-items: flex-start; }
.k-expense-row .k-expense-kind { flex: 0 0 9.5rem; }
.k-expense-row .k-expense-label { flex: 1 1 auto; min-width: 0; }
.k-expense-row .k-expense-amount { flex: 0 0 8rem; }
.k-expense-row .k-expense-remove { flex: 0 0 auto; }
@media (max-width: 575.98px) {
    .k-expense-row { flex-wrap: wrap; }
    .k-expense-row > * { flex: 1 1 100%; }
}

/* ── DataTables chrome: one background per control, one baseline per row ─────
   Three things were wrong here at once:

   1. With dataTables.bootstrap4 the pager is <li class="paginate_button page-item">
      wrapping <a class="page-link">. Both matched the pill rules above, so every
      page number painted a box inside a box.
   2. The "Columns" toggle is built by hand into .koomi-dt-top-tools rather than
      into .dt-buttons, so the pill styling — scoped to .dt-buttons — never reached
      it and it did not match Excel / PDF beside it.
   3. The pager carried a 14px top padding, which dropped it below the
      "Showing 1 to 3 of 3" text sitting next to it.
   ------------------------------------------------------------------------- */

/* ── Export / Columns toolbar ─────────────────────────────────────────────── */
.koomi-dt .koomi-dt-top-tools {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--k-space-2);
}
.koomi-dt .koomi-dt-top-tools .dt-buttons {
    display: inline-flex;
    align-items: center;
    gap: var(--k-space-2);
    margin: 0;
    padding: 0;
}

/* One pill definition for every button in the toolbar, wherever it was built. */
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn,
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn:visited {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 34px;
    margin: 0;
    padding: 0 var(--k-space-3);
    background: var(--k-surface);
    background-image: none;
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius-sm);
    box-shadow: none;
    color: var(--k-text-body);
    font-size: 13px;
    font-weight: var(--k-fw-medium);
    line-height: 1;
    text-shadow: none;
    white-space: nowrap;
}
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn:hover,
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn:focus {
    background: var(--k-surface-soft);
    border-color: var(--k-border-strong);
    color: var(--k-text);
    outline: none;
}
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn:focus-visible {
    border-color: var(--k-primary);
    box-shadow: 0 0 0 3px var(--k-primary-soft);
}
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn-hidden { display: none !important; }

/* Whatever DataTables nests inside a button stays transparent, so a second
   background can never appear behind the label. */
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn > span,
.koomi-dt .koomi-dt-top-tools .koomi-dt-btn > span > span {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    margin: 0 !important;
    line-height: 1;
}

/* ── Pager ────────────────────────────────────────────────────────────────── */
.dataTables_wrapper .dataTables_paginate ul.pagination {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    margin: 0;
    padding: 0;
}
/* The <li> is a wrapper; the <a class="page-link"> inside it is the control. */
.dataTables_wrapper .dataTables_paginate ul.pagination > li.paginate_button,
.koomi-dt .dataTables_wrapper .dataTables_paginate ul.pagination > li.paginate_button {
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    margin: 0 !important;
    padding: 0 !important;
    min-width: 0 !important;
    height: auto !important;
}
/* The pills already sit in a gapped flex row — the old spacing margin doubled it. */
.dataTables_wrapper .dataTables_paginate ul.pagination .page-link { margin-left: 0 !important; }

/* ── Bottom bar: length | info + pager, all on one baseline ───────────────── */
.koomi-dt .dataTables_wrapper .koomi-dt-bottom { align-items: center; }
.koomi-dt .dataTables_wrapper .koomi-dt-bottom-page { align-items: center; }
.koomi-dt .dataTables_wrapper .koomi-dt-bottom-length,
.koomi-dt .dataTables_wrapper .dataTables_length,
.koomi-dt .dataTables_wrapper .dataTables_info,
.koomi-dt .dataTables_wrapper .dataTables_paginate {
    display: flex;
    align-items: center;
    min-height: 34px;
    margin: 0 !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}

/* Below ~576px the labels would wrap the toolbar onto a second line — with the
   Buttons liner gone, "> span" is the label itself, so the icons survive. */
@media (max-width: 575.98px) {
    .koomi-dt .koomi-dt-top-tools .koomi-dt-btn > span:not(.koomi-dt-caret) { display: none; }
    .koomi-dt .koomi-dt-top-tools .koomi-dt-btn { padding: 0 11px; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Import Center
   One card per importable dataset, grouped by area. The cards are links, so
   they carry the same hover/focus affordance as the rest of the shell.
   ────────────────────────────────────────────────────────────────────────── */
.koomi-import-group {
    margin-bottom: 1.5rem;
}

.koomi-import-group-title {
    margin-bottom: .65rem;
    font-size: .74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--k-text-muted);
}

.koomi-import-card {
    display: flex;
    align-items: center;
    gap: .75rem;
    height: 100%;
    padding: .85rem .9rem;
    border: 1px solid var(--k-border);
    border-radius: 12px;
    background: var(--k-surface);
    color: inherit;
    text-decoration: none;
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.koomi-import-card:hover,
.koomi-import-card:focus-visible {
    border-color: var(--k-primary);
    box-shadow: 0 6px 18px rgba(15, 23, 42, .07);
    color: inherit;
    transform: translateY(-1px);
}

.koomi-import-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 38px;
    width: 38px;
    height: 38px;
    border-radius: 10px;
    background: var(--k-primary-soft);
    color: var(--k-primary);
}

.koomi-import-icon svg {
    width: 18px;
    height: 18px;
}

.koomi-import-body {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
}

.koomi-import-name {
    font-size: .88rem;
    font-weight: 600;
    color: var(--k-text-body);
}

.koomi-import-desc {
    font-size: .74rem;
    line-height: 1.35;
    color: var(--k-text-muted);
}

/* Marks a dataset that opens its own purpose-built importer. */
.koomi-import-tag {
    margin-left: .35rem;
    padding: .05rem .35rem;
    border-radius: 999px;
    background: var(--k-surface-hover);
    border: 1px solid var(--k-border);
    font-size: .62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--k-text-soft);
    vertical-align: middle;
}

.koomi-import-chevron {
    margin-left: auto;
    font-size: .7rem;
    color: var(--k-text-soft);
}

.koomi-import-section {
    margin-bottom: .5rem;
    font-size: .8rem;
    font-weight: 700;
    color: var(--k-text-body);
}

.koomi-import-table code {
    font-size: .76rem;
    color: var(--k-primary);
    background: var(--k-primary-soft);
    padding: .1rem .35rem;
    border-radius: 5px;
}

.koomi-import-req {
    display: inline-block;
    padding: .05rem .4rem;
    border-radius: 999px;
    background: var(--k-warning-soft);
    border: 1px solid var(--k-warning-border);
    color: var(--k-warning-strong);
    font-size: .66rem;
    font-weight: 700;
}

/* Import result: the counts, then the rows that could not be taken in. */
.koomi-import-stats {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

.koomi-import-stat {
    padding: .25rem .6rem;
    border: 1px solid var(--k-border);
    border-radius: 999px;
    background: var(--k-surface-soft);
    font-size: .76rem;
    color: var(--k-text-muted);
}

.koomi-import-stat strong {
    color: var(--k-text-body);
}

.koomi-import-stat.is-created {
    border-color: var(--k-success-border);
    background: var(--k-success-soft);
    color: var(--k-success-strong);
}

.koomi-import-stat.is-updated {
    border-color: var(--k-primary);
    background: var(--k-primary-soft);
    color: var(--k-primary);
}

.koomi-import-stat.is-failed {
    border-color: var(--k-danger-border);
    background: var(--k-danger-soft);
    color: var(--k-danger-strong);
}

.koomi-import-errors {
    padding-left: 1.1rem;
    font-size: .78rem;
    color: var(--k-danger-strong);
}

.koomi-import-errors li {
    margin-bottom: .15rem;
}

/* ── Repeatable barcode rows on the item form ────────────────────────────────
   An item answers to more than one code, so the field is a list. Each row is the
   input plus its remove control, sized so the boxes line up with every other
   control in the form grid. */
.k-barcode-row {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
}

.k-barcode-row + .k-barcode-row {
    margin-top: var(--k-space-2);
}

.k-barcode-row .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

.k-barcode-row .js-remove-barcode {
    flex: 0 0 auto;
    width: var(--k-control-h);
    height: var(--k-control-h);
    min-height: var(--k-control-h);
    padding: 0 !important;
    font-size: 1.1rem;
    line-height: 1;
}

.k-barcode-row .js-remove-barcode:disabled {
    opacity: .4;
}

/* ── Attribute options: value wide, Display narrow ───────────────────────────
   One row per predefined option: the value people type, a small Yes/No deciding
   whether it shows in the variation's name, and a remove control. The value is
   the field that matters, so it takes whatever is left. */
.option-row .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

.option-row .k-option-display-label {
    flex: 0 0 auto;
}

.option-row .k-option-display {
    flex: 0 0 5.5rem;
    width: 5.5rem;
}

.option-row .remove-option {
    flex: 0 0 auto;
}

/* select2 replaced a control inside an input-group, so it has to size itself the
   way that control did. The app-wide `width: 100% !important` makes the replaced
   dropdown claim the entire row and squeeze every sibling down to nothing — which
   is what flattened the option rows and the purchase expense rows. */
.input-group > .select2-container {
    flex: 1 1 auto;
    width: auto !important;
}

.k-expense-row > .select2-container {
    flex: 0 0 9.5rem;
    width: 9.5rem !important;
}

/* ── Status colour: a swatch beside its hex ──────────────────────────────────
   Two views of one value, so a colour can be picked or typed. The swatch is
   sized to the control height so the pair reads as a single field. */
.k-status-color {
    display: flex;
    align-items: center;
    gap: var(--k-space-2);
}

.k-status-color .form-control-color {
    flex: 0 0 auto;
    width: 46px;
    min-height: var(--k-control-h);
    height: var(--k-control-h);
    padding: 4px;
    cursor: pointer;
}

.k-status-color .js-status-color-hex {
    flex: 1 1 auto;
    min-width: 0;
    text-transform: uppercase;
}

/* ── "Working in" strip ──────────────────────────────────────────────────────
   A quiet one-line banner naming the branch and warehouse the session is on.
   Deliberately not an .alert: it is standing context, not something that
   happened, so it never gets a dismiss button and never moves the page. */
.koomi-working-in {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--k-space-2);
    padding: var(--k-space-2) var(--k-space-3);
    margin-bottom: var(--k-space-3);
    background: var(--k-info-soft, var(--k-primary-soft));
    border: 1px solid var(--k-info-border, var(--k-primary));
    border-radius: var(--k-radius);
    font-size: var(--k-fs-help);
    line-height: 1.3;
}

.koomi-working-in-icon { color: var(--k-primary); }

.koomi-working-in-label {
    color: var(--k-text-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .68rem;
    font-weight: var(--k-fw-medium);
}

.koomi-working-in-place {
    font-weight: var(--k-fw-semibold);
    color: var(--k-text);
}

.koomi-working-in-sep {
    font-size: .6rem;
    color: var(--k-text-muted);
}

/* Pushed to its own end of the line, and dropped entirely when there is no room
   for it — the place name is the part that must always be readable. */
.koomi-working-in-note {
    margin-left: auto;
    color: var(--k-text-muted);
}

@media (max-width: 575.98px) {
    .koomi-working-in-note { display: none; }
}

/* ── Header avatar fallback ────────────────────────────────────────────────
   The photo column can name a file that is no longer on disk, which rendered
   as a broken-image icon in the top bar. The header now falls back to the
   user's initials; .user-letter already sizes and centres the box, so this
   only has to give it a ground to sit on. */
.user-info .user-letter .koomi-header-initials {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    background: var(--k-primary, #2563eb);
    color: var(--k-text-invert, #fff);
    font-weight: var(--k-fw-semibold, 600);
    font-size: .875rem;
    letter-spacing: .02em;
    user-select: none;
}

/* ── Filter toggle / apply buttons ─────────────────────────────────────────
   The theme's filter.svg, closes.svg and search-whites.svg are all fill="white".
   That worked while .btn-filter / .btn-filters were the theme's solid blue, but
   the secondary-button rule above repaints them white — leaving a white icon on
   a white button, i.e. an empty square. The markup now uses Font Awesome, which
   inherits currentColor and therefore follows the button.

   The theme's open/close swap keys off `.btn-filter.setclose > img`, which no
   longer matches an <i>, so it is restated here. */
.search-set .btn-filter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.search-set .btn-filter > i { display: inline-block; }
.search-set .btn-filter span { display: none; }
.search-set .btn-filter.setclose > i { display: none; }
.search-set .btn-filter.setclose span { display: inline-flex; }

/* Open reads as "click to close" — the theme said so with a solid red button,
   which is too loud next to a light toolbar. A soft danger tint says the same. */
.search-set .btn-filter.setclose {
    background: var(--k-danger-soft) !important;
    border-color: var(--k-danger-border) !important;
    color: var(--k-danger) !important;
}

/* Narrow icon-only "apply" buttons in the filter panels. */
.btn-filters {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    line-height: 1;
}

/* The toolbar's search affordance is a solid primary square; the theme forced its
   <img> white with a brightness/invert filter, which does nothing to an <i>. */
.search-input .search-icon > i {
    color: var(--k-text-invert);
    font-size: .8125rem;
}

/* ── Person links on document lists ────────────────────────────────────────
   The customer / vendor name on an invoice or purchase row is a way through to
   that person's screen. The arrow marks it as one without turning the column
   into a wall of blue: the name stays the reading colour until hovered. */
.koomi-person-link {
    color: var(--k-text-body);
    text-decoration: none;
}

.koomi-person-link i {
    color: var(--k-text-soft);
    font-size: .7em;
    vertical-align: baseline;
}

.koomi-person-link:hover,
.koomi-person-link:hover i {
    color: var(--k-primary);
    text-decoration: underline;
}

/* ── POS line discounts ────────────────────────────────────────────────────
   What a line was, and what the discount made it. The old price is struck
   through and muted so the eye lands on the price actually being charged. */
.pos-price-was {
    text-decoration: line-through;
    color: var(--k-text-soft);
    margin-right: .35rem;
}

.pos-price-now {
    color: var(--k-success, #16a34a);
    font-weight: var(--k-fw-semibold, 600);
}

.pos-line-net { margin-top: .2rem; line-height: 1.2; }

/* The $ / % switch, sized to sit in a narrow cart column. */
.pos-line-discount .pos-disc-mode {
    cursor: pointer;
    font-weight: var(--k-fw-semibold, 600);
    min-width: 26px;
    padding-left: .4rem;
    padding-right: .4rem;
    background: var(--k-surface-soft);
}

.pos-line-discount .pos-disc-mode:hover {
    background: var(--k-primary-soft);
    color: var(--k-primary);
}

.pos-line-discount .pos-disc-entry { min-width: 46px; }

/* ── Repair form: the customer block ───────────────────────────────────────
   One of two panels sits here — the walk-in's details to type, or what we
   already hold on the saved customer that was picked. Inset so it reads as a
   block belonging to the Customer choice above it rather than more fields. */
.koomi-repair-party {
    padding: var(--k-space-3) var(--k-space-4);
    background: var(--k-surface);
    border: 1px solid var(--k-border);
    border-radius: var(--k-radius);
}

.koomi-repair-party-head {
    margin-bottom: var(--k-space-3);
    font-weight: var(--k-fw-semibold, 600);
    color: var(--k-text);
}

.koomi-repair-party-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--k-space-3);
}

@media (max-width: 767.98px) {
    .koomi-repair-party-grid { grid-template-columns: 1fr; }
}
