/* KAYROQ — shared styles.
   Colours taken from the brand's own packaging (Rosemary Shampoo bottle, 21 Oct 2026):
   white pack, near-black type, one lime-green accent #BBCB46.

   How the lime is used, and why:
   - #BBCB46 is a FILL colour. Dark text on it = 8.8:1 (easy to read).
     White text on it = 1.8:1 (unreadable), so the panel never puts white text on the lime.
   - As a text colour on white the lime is also 1.8:1, so labels, links and icons use
     --kq-lime-dark #657A15 instead = 4.8:1 on white. Same hue, same brand, readable.
   - Due / overdue warnings are amber and red on purpose. They must never be the brand
     green, or an overdue order would look like a good one. */

:root {
    --kq-lime:       #BBCB46;   /* the packaging green — fills only, dark text on top */
    --kq-lime-dark:  #657A15;   /* text, icons, links, active labels */
    --kq-lime-soft:  #F4F8E2;   /* active menu row, highlighted table row */
    --kq-lime-line:  #E2EAB8;   /* borders that should feel brand-ish */

    --kq-ink:        #1F2328;   /* the near-black of the pack lettering */
    --kq-muted:      #6B7280;
    --kq-line:       #E5E7EB;
    --kq-bg:         #F7F8F5;   /* clean off-white, like the bottle */

    --kq-due:        #B45309;   /* due tomorrow */
    --kq-overdue:    #B91C1C;   /* late */

    /* row tints for the Stock list — lighter than the chips that sit on them */
    --kq-row-low:        #FEF6EB;
    --kq-row-low-hover:  #FBEBD6;
    --kq-row-out:        #FDF0F0;
    --kq-row-out-hover:  #F9E0E0;

    --kq-sidebar-w:  232px;
}

body {
    background: var(--kq-bg);
    color: var(--kq-ink);
    font-size: 15px;
}

/* top bar */
.kq-topbar {
    background: #fff;
    border-bottom: 1px solid var(--kq-line);
    padding: .35rem .25rem;
    position: sticky;
    top: 0;
    z-index: 1030;
}

/* wordmark: black letters, a lime leaf over the O — as on the bottle */
.kq-brand {
    font-weight: 700;
    letter-spacing: .16em;
    color: var(--kq-ink);
    font-size: 1.05rem;
}
.kq-brand:hover { color: var(--kq-ink); }
.kq-brand .kq-o { position: relative; }
.kq-brand .kq-o::after {
    content: "";
    position: absolute;
    top: -.46em;
    left: 50%;
    transform: translateX(-50%) rotate(-32deg);
    width: .42em;
    height: .26em;
    background: var(--kq-lime);
    border-radius: 100% 0 100% 0;
}
.kq-menu-btn { font-size: 1.4rem; color: var(--kq-ink); text-decoration: none; }
.kq-user { color: var(--kq-muted); font-size: .9rem; }

/* frame */
.kq-shell { display: flex; align-items: flex-start; }
.kq-sidebar {
    width: var(--kq-sidebar-w);
    background: #fff;
    border-right: 1px solid var(--kq-line);
    min-height: calc(100vh - 54px);
}
.kq-main {
    flex: 1 1 auto;
    padding: 1.25rem;
    min-width: 0;
}
.kq-title { font-size: 1.35rem; font-weight: 600; margin-bottom: 1rem; }

/* menu */
.kq-nav { padding: .75rem 0; }
.kq-nav .nav-link {
    color: var(--kq-ink);
    padding: .55rem 1.1rem;
    display: flex;
    align-items: center;
    gap: .6rem;
    border-left: 3px solid transparent;
}
.kq-nav .nav-link:hover { background: var(--kq-bg); }
.kq-nav .nav-link.active {
    color: var(--kq-lime-dark);
    background: var(--kq-lime-soft);
    border-left-color: var(--kq-lime);
    font-weight: 600;
}
.kq-nav .nav-link.active .bi { color: var(--kq-lime-dark); }
.kq-nav .kq-soon { color: #A9AEB8; cursor: default; }
/* A module that lives on another server: the little arrow says the tab changes. */
.kq-nav .kq-away { font-size: .7rem; opacity: .65; margin-left: .25rem; vertical-align: text-top; }
.kq-nav .kq-soon small {
    margin-left: auto;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .06em;
}

/* A group heading (Masters). It is a button, not a link — it goes nowhere, it
   only folds. Reset the button so it sits in the list like every other row. */
.kq-nav .kq-group {
    width: 100%;
    background: none;
    border: 0;
    border-left: 3px solid transparent;
    text-align: left;
    font-weight: 600;
}
.kq-nav .kq-group .kq-caret {
    margin-left: auto;
    font-size: .75rem;
    transition: transform .15s ease;
}
/* Bootstrap puts .collapsed on the button while the panel is shut. */
.kq-nav .kq-group.collapsed .kq-caret { transform: rotate(-90deg); }
/* A group holding the page you are on keeps the brand colour, so the heading
   still tells you where you are when the list is folded away. */
.kq-nav .kq-group.open { color: var(--kq-lime-dark); }

/* The rows inside a group: indented, a touch smaller, same active mark. */
.kq-subnav .nav-link {
    padding-left: 2.1rem;
    font-size: .94rem;
}

/* cards */
.kq-card {
    background: #fff;
    border: 1px solid var(--kq-line);
    border-radius: 10px;
    padding: 1rem 1.15rem;
}
.kq-card h2 { font-size: 1rem; font-weight: 600; margin-bottom: .75rem; }
.kq-check { display: flex; gap: .55rem; padding: .3rem 0; }
.kq-check .bi-check-circle-fill { color: var(--kq-lime-dark); }
.kq-check .bi-x-circle-fill { color: var(--kq-overdue); }
.kq-note { color: var(--kq-muted); font-size: .88rem; }

/* buttons — the lime always carries dark text */
.btn-kq {
    background: var(--kq-lime);
    border: 1px solid var(--kq-lime);
    color: var(--kq-ink);
    font-weight: 600;
}
.btn-kq:hover { background: #AEBF36; border-color: #AEBF36; color: var(--kq-ink); }
.btn-kq-outline {
    background: #fff;
    border: 1px solid var(--kq-lime-line);
    color: var(--kq-lime-dark);
    font-weight: 600;
}
.btn-kq-outline:hover { background: var(--kq-lime-soft); color: var(--kq-lime-dark); }

/* status chips — green only for good news */
.kq-chip {
    display: inline-block;
    padding: .12rem .5rem;
    /* Square, not a pill — the owner's call, 26 Oct. Every status label in the
       panel is a .kq-chip, so this is the only place it is set. */
    border-radius: 0;
    font-size: .78rem;
    font-weight: 600;
}
.kq-chip-ok      { background: var(--kq-lime);    color: var(--kq-ink); }
.kq-chip-due     { background: #FDF0DC;           color: var(--kq-due); }
.kq-chip-overdue { background: #FBE4E4;           color: var(--kq-overdue); }
/* Work in hand. Panel.php has mapped five statuses to this for weeks and it was
   never written, so Pending and In my godown rendered as bare text beside the
   chips - which is why the history read as if only some rows counted. Neutral,
   not green: green is good news only (see the colour rules at the top). */
.kq-chip-work    { background: #EEF1F4; color: #46505C; box-shadow: inset 0 0 0 1px #DDE3E9; }

/* links */
a { color: var(--kq-lime-dark); }
a:hover { color: #51620F; }

@media (max-width: 991.98px) {
    .kq-sidebar { min-height: auto; }
    .kq-main { padding: 1rem .9rem; }
}

/* colour swatches on the setup page (section 0 only) */
.kq-swatch {
    border: 1px solid var(--kq-line);
    border-radius: 8px;
    padding: .5rem .6rem;
    min-width: 142px;
    background: #fff;
}
.kq-swatch span {
    display: block;
    height: 26px;
    border-radius: 5px;
    border: 1px solid rgba(0, 0, 0, .08);
    margin-bottom: .35rem;
}
.kq-swatch strong { display: block; font-size: .84rem; }
.kq-swatch code { font-size: .76rem; color: var(--kq-muted); }
.kq-swatch small { display: block; font-size: .72rem; color: var(--kq-muted); }

/* ---- section 1: sign in, users, tables ---------------------------------- */

.kq-login-page { background: var(--kq-bg); }
.kq-login {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}
.kq-login-card {
    background: #fff;
    border: 1px solid var(--kq-line);
    border-top: 4px solid var(--kq-lime);
    border-radius: 12px;
    padding: 1.75rem 1.5rem;
    width: 100%;
    max-width: 380px;
}
.kq-login-head { text-align: center; margin-bottom: 1.5rem; }
.kq-brand-lg { font-size: 1.6rem; display: inline-block; }

/* the person menu in the top bar */
.kq-userbtn {
    color: var(--kq-ink);
    background: transparent;
    border: 1px solid var(--kq-line);
    border-radius: 999px;
    padding: .2rem .7rem;
}
.kq-userbtn:hover { background: var(--kq-lime-soft); color: var(--kq-ink); }

/* tables */
.kq-table { font-size: .93rem; }
.kq-table thead th {
    background: var(--kq-bg);
    border-bottom: 1px solid var(--kq-line);
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--kq-muted);
    font-weight: 600;
    white-space: nowrap;
}
.kq-table td, .kq-table th { padding: .6rem .85rem; }
.kq-table tbody tr:hover > td { background: var(--kq-lime-soft); }

/* Stock list: the whole row carries the warning, not only the chip — the owner
   asked for it on 27 Oct, because a 0 in one column is easy to scroll past.
   Amber for low, red for out: the same family as the chips and the due/overdue
   dates, never the brand green, which would read as good news.
   These sit AFTER the hover rule so a tinted row keeps its tint, and each has
   its own stronger hover so the row never turns lime on a product that has run
   out. Both are lighter than the chip on top of them, so the chip still reads. */
.kq-table tbody tr.kq-row-low > td       { background: var(--kq-row-low); }
.kq-table tbody tr.kq-row-out > td       { background: var(--kq-row-out); }
.kq-table tbody tr.kq-row-low:hover > td { background: var(--kq-row-low-hover); }
.kq-table tbody tr.kq-row-out:hover > td { background: var(--kq-row-out-hover); }
.kq-table code { color: var(--kq-ink); background: var(--kq-bg); padding: .05rem .35rem; border-radius: 4px; }
.kq-card.p-0 .kq-table { border-radius: 10px; overflow: hidden; }

/* permission ticks */
.kq-perm-table .form-check-input { margin: 0; }
.kq-perm-table .form-check-input:checked {
    background-color: var(--kq-lime-dark);
    border-color: var(--kq-lime-dark);
}
.kq-row-off td { opacity: .45; }
.kq-row-off small { margin-left: .35rem; }

/* a third button, only for destructive things */
.btn-kq-danger {
    background: #fff;
    border: 1px solid #F0C5C5;
    color: var(--kq-overdue);
    font-weight: 600;
}
.btn-kq-danger:hover { background: #FBE4E4; color: var(--kq-overdue); }

/* chips */
.kq-chip-off { background: var(--kq-line); color: var(--kq-muted); }

/* Money still owed. Amber, like a due date — never the brand green, which
   would make a debt look like good news. Not used yet: it was the vendor
   opening balance, which was dropped on 22 Oct, and it is what the orders and
   the ledger will use. */
.kq-owed { color: var(--kq-due); font-weight: 600; }

/* WhatsApp's own green, and only here: it is a logo colour, not one of ours.
   Darkened from #25D366 to reach 4.6:1 on white. */
.kq-wa { color: #128C4A; font-size: .85rem; }
.kq-wa:hover { color: #0E6E3A; }

/* A vendor's papers — GST certificate, PAN card, a cheque. Square thumbnails
   that wrap, so ten of them do not make the card taller than the screen. */
.kq-files {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
}
.kq-file {
    width: 104px;
    margin: 0;
}
.kq-file img {
    width: 104px;
    height: 104px;
    object-fit: cover;
    border: 1px solid var(--kq-line);
    border-radius: 8px;
    background: #fff;
}
.kq-file figcaption {
    display: flex;
    align-items: center;
    gap: .25rem;
    margin-top: .2rem;
    font-size: .72rem;
    line-height: 1.2;
}
/* The file name is the long part; it gets the room and the ellipsis, while the
   remove button keeps its size. */
.kq-file figcaption > span {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.kq-file .kq-file-del {
    flex: 0 0 auto;
    padding: 0 .35rem;
    line-height: 1.2;
}

/* messages */
.kq-alert-ok {
    background: var(--kq-lime-soft);
    border: 1px solid var(--kq-lime-line);
    color: #3F4B0C;
}
.kq-alert-bad {
    background: #FBE4E4;
    border: 1px solid #F0C5C5;
    color: var(--kq-overdue);
}

/* focus ring in the brand colour */
.form-control:focus, .form-check-input:focus, .btn:focus-visible {
    border-color: var(--kq-lime);
    box-shadow: 0 0 0 .2rem rgba(187, 203, 70, .35);
}

/* ---- section 2: products ------------------------------------------------ */

/* SKUs are stored in capitals, so show them that way while typing too */
.kq-upper { text-transform: uppercase; }
.kq-upper::placeholder { text-transform: none; }

/* product photos */
.kq-th-photo { width: 56px; }
.kq-thumb {
    width: 40px;
    height: 40px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--kq-line);
    background: #fff;
    display: block;
}
.kq-thumb-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #C3C7D0;
}
.kq-photo-box {
    border: 1px dashed var(--kq-lime-line);
    border-radius: 10px;
    background: var(--kq-lime-soft);
    min-height: 190px;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.kq-photo-box img {
    max-width: 100%;
    max-height: 260px;
    object-fit: contain;
    display: block;
}
.kq-photo-empty {
    text-align: center;
    color: var(--kq-muted);
    font-size: .88rem;
}
.kq-photo-empty .bi {
    display: block;
    font-size: 1.8rem;
    margin-bottom: .25rem;
    color: #B9C08E;
}

/* raw material lines on the product page */
.kq-mat-table td, .kq-mat-table th { padding: .35rem .4rem; }
.kq-mat-table thead th { font-size: .72rem; }
.kq-mat-del { padding: .1rem .45rem; line-height: 1.2; }
.kq-matlink { white-space: nowrap; }

/* a product row opens its dialog */
.kq-row-open { cursor: pointer; }
.kq-row-open:focus-visible {
    outline: 2px solid var(--kq-lime-dark);
    outline-offset: -2px;
}
.kq-photo-box-sm { min-height: 150px; }
.kq-photo-box-sm img { max-height: 220px; }
.kq-card-sub {
    font-size: .95rem;
    font-weight: 600;
    margin-bottom: .6rem;
}
.kq-dl { margin: 0; }
.kq-dl dt {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--kq-muted);
    font-weight: 600;
    margin-top: .6rem;
}
.kq-dl dt:first-child { margin-top: 0; }
.kq-dl dd { margin: .1rem 0 0; }

/* PDF tool */
.kq-counts { margin-top: .25rem; }
.kq-count { font-size: 1.6rem; font-weight: 600; line-height: 1.1; }
.kq-count-warn { color: var(--kq-due); }
.kq-plain { list-style: none; padding-left: 0; }
.kq-plain li { padding: .2rem 0 .2rem 1.1rem; position: relative; }
.kq-plain li::before {
    content: "";
    position: absolute;
    left: 0; top: .72em;
    width: 6px; height: 6px;
    border-radius: 2px;
    background: var(--kq-lime);
}

/* mapping an unknown marketplace code to a product, on the job screen */
.kq-map { min-width: 230px; }
.kq-map .form-select { max-width: 170px; }

/* the label tool's own product list */
.kq-codechip {
    display: inline-block;
    border: 1px solid var(--kq-line);
    border-radius: 6px;
    padding: .08rem .4rem;
    margin: .1rem .2rem .1rem 0;
    font-size: .8rem;
    color: var(--kq-muted);
}
.kq-codechip code { color: var(--kq-ink); }
.kq-move { padding: .05rem .4rem; line-height: 1.3; }
.kq-plainnum { padding-left: 1.1rem; margin-bottom: 0; }

/* back arrow beside a page title */
.kq-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--kq-line);
    border-radius: 8px;
    color: var(--kq-ink);
    background: #fff;
    margin-right: .5rem;
    vertical-align: .05em;
    font-size: .95rem;
    text-decoration: none;
}
.kq-back:hover { background: var(--kq-lime-soft); border-color: var(--kq-lime-line); color: var(--kq-ink); }

/* ===================================================================
   Form fields — the label lives INSIDE the box (22 Oct)

   The label starts where the text will go, in the muted grey, and lifts to a
   small caption the moment the box has anything in it or the cursor is in it.
   Every field also carries a leading icon, so a long form can be read down the
   left edge without reading a word.

   Why by hand and not Bootstrap's .form-floating: that one owns the whole box
   and leaves no room for the icon. The trick is the same — `placeholder=" "`
   on the input so `:placeholder-shown` tells us whether it is empty — but the
   padding is ours, so the icon fits.
   =================================================================== */
.kq-field { position: relative; margin-bottom: .85rem; }

.kq-field > .form-control,
.kq-field > .form-select {
    height: auto;
    padding: 1.35rem .75rem .4rem 2.5rem;
    border-color: var(--kq-line);
}
.kq-field > .form-control:focus,
.kq-field > .form-select:focus {
    border-color: var(--kq-lime-line);
    /* The brand lime at low opacity — never Bootstrap's blue. */
    box-shadow: 0 0 0 .2rem rgba(187, 203, 70, .25);
}
.kq-field > textarea.form-control { padding-top: 1.5rem; min-height: 5.5rem; }

/* The icon. Muted until the field is in use, then the brand green, so the eye
   is told where it is without a colour change loud enough to distract. */
.kq-field > .kq-field-icon {
    position: absolute;
    left: .85rem;
    top: 1.05rem;
    font-size: .95rem;
    color: #9AA1AC;
    pointer-events: none;
    transition: color .15s ease;
}
.kq-field:focus-within > .kq-field-icon { color: var(--kq-lime-dark); }

/* The label itself. Deliberately dull: it is a hint, not the content. */
.kq-field > label {
    position: absolute;
    left: 2.5rem;
    top: .72rem;
    margin: 0;
    color: #9AA1AC;
    font-size: .95rem;
    font-weight: 400;
    line-height: 1;
    pointer-events: none;
    transform-origin: left top;
    transition: transform .14s ease, color .14s ease;
}
.kq-field > .form-control:focus ~ label,
.kq-field > .form-control:not(:placeholder-shown) ~ label,
.kq-field > .form-select ~ label,
/* A date box always shows dd/mm/yyyy, so it is never "empty" to the eye —
   its label has to stay up or the two sit on top of each other. */
.kq-field > input[type="date"] ~ label,
.kq-field.filled > label {
    transform: translateY(-.52rem) scale(.78);
    color: #8A919C;
}
.kq-field:focus-within > label { color: var(--kq-lime-dark); }

/* A required field is marked on the label, not with a separate line of text. */
.kq-field > label .kq-req { color: var(--kq-overdue); }

/* The help line under a field. */
.kq-field-help {
    display: block;
    margin: -.55rem 0 .85rem 2.5rem;
    color: var(--kq-muted);
    font-size: .78rem;
}

/* A field the panel refused, and why. */
.kq-field.is-bad > .form-control,
.kq-field.is-bad > .form-select { border-color: #E9A8A8; }
.kq-field.is-bad > .kq-field-icon,
.kq-field.is-bad > label { color: var(--kq-overdue); }

/* Two fields that belong together sit on one row without doubling the gap. */
.kq-row-tight > [class^="col"] > .kq-field:last-child { margin-bottom: .85rem; }

/* ===================================================================
   The search bar above a list
   =================================================================== */
.kq-search { position: relative; flex: 1 1 auto; min-width: 0; }
.kq-search > .form-control {
    padding-left: 2.3rem;
    padding-right: 2.1rem;
    border-color: var(--kq-line);
}
.kq-search > .form-control:focus {
    border-color: var(--kq-lime-line);
    box-shadow: 0 0 0 .2rem rgba(187, 203, 70, .25);
}
.kq-search > .bi-search {
    position: absolute;
    left: .75rem;
    top: 50%;
    transform: translateY(-50%);
    color: #9AA1AC;
    font-size: .9rem;
    pointer-events: none;
}
.kq-search:focus-within > .bi-search { color: var(--kq-lime-dark); }
/* Chrome draws its own × inside a search input; ours is the only one. */
.kq-search > .form-control::-webkit-search-cancel-button { display: none; }
.kq-search > .kq-search-clear {
    position: absolute;
    right: .45rem;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: none;
    color: var(--kq-muted);
    line-height: 1;
    padding: .15rem .3rem;
    border-radius: 50%;
}
.kq-search > .kq-search-clear:hover { background: var(--kq-bg); color: var(--kq-ink); }

/* The bar as a whole: a white strip above the table, so the page reads as
   two blocks (what you are looking for / what was found) and not five
   floating controls. */
.kq-toolbar {
    background: #fff;
    border: 1px solid var(--kq-line);
    border-radius: 10px;
    padding: .65rem .7rem;
    margin-bottom: .85rem;
}
.kq-toolbar .btn { white-space: nowrap; }

/* How many rows the search found. */
.kq-found { color: var(--kq-muted); font-size: .82rem; }

/* ===================================================================
   Lists
   =================================================================== */
.kq-table thead th {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--kq-muted);
    font-weight: 600;
}
.kq-row-open { cursor: pointer; }
.kq-row-open:focus-visible {
    outline: 2px solid var(--kq-lime-dark);
    outline-offset: -2px;
}
/* The first cell carries the name; give it the weight so the eye lands there. */
.kq-table td.kq-cell-name { font-weight: 600; }
.kq-table td.kq-cell-name .kq-note { font-weight: 400; }

/* Nothing found / nothing yet. */
.kq-empty { padding: 2.2rem 1rem; text-align: center; color: var(--kq-muted); }
.kq-empty .bi {
    display: block;
    font-size: 1.9rem;
    margin-bottom: .5rem;
    color: #C8CDD4;
}
.kq-empty strong { display: block; color: var(--kq-ink); margin-bottom: .2rem; }

/* The card heading, with its own small icon. */
.kq-card h2 .bi {
    color: var(--kq-lime-dark);
    margin-right: .35rem;
    font-size: .95rem;
}
.kq-card h2 .kq-note { font-weight: 400; margin-left: .3rem; }

/* The row of buttons at the foot of a form. */
.kq-formbar {
    display: flex;
    gap: .5rem;
    align-items: center;
    margin-top: 1rem;
}
.kq-formbar .kq-note { margin-left: auto; }

/* The file picker, as a panel you click rather than a bare browse button —
   the native control gives no room to say what is allowed. */
.kq-droplabel {
    display: block;
    text-align: center;
    padding: 1.1rem .9rem;
    border: 1px dashed var(--kq-lime-line);
    border-radius: 10px;
    background: var(--kq-lime-soft);
    cursor: pointer;
}
.kq-droplabel:hover { background: #EDF4D6; }
.kq-droplabel .bi {
    display: block;
    font-size: 1.5rem;
    color: var(--kq-lime-dark);
    margin-bottom: .25rem;
}
.kq-droplabel strong { display: block; color: var(--kq-ink); font-size: .95rem; }
.kq-droplabel .kq-note { display: block; margin-top: .15rem; font-size: .8rem; }

/* The count inside the In use / All buttons. */
.kq-count {
    display: inline-block;
    min-width: 1.3rem;
    padding: 0 .3rem;
    margin-left: .25rem;
    border-radius: 999px;
    background: rgba(31, 35, 40, .12);
    font-size: .74rem;
    font-weight: 600;
}
.btn-kq-outline .kq-count { background: var(--kq-lime-soft); }

/* A tick under a field, lined up with the text above it rather than the icon. */
.form-check.kq-field-help { margin-left: 2.5rem; padding-left: 1.3rem; }
.form-check.kq-field-help .form-check-input { margin-left: -1.3rem; }
.form-check-input:checked { background-color: var(--kq-lime-dark); border-color: var(--kq-lime-dark); }
.form-check-input:focus {
    border-color: var(--kq-lime-line);
    box-shadow: 0 0 0 .2rem rgba(187, 203, 70, .25);
}

/* A second strip under the main one — the vendor filter on the raw material
   list. Lighter than the toolbar above it so the page still reads top-down. */
.kq-subbar {
    padding: .45rem .7rem;
    background: var(--kq-bg);
}

/* "+2" on a thumbnail when a material has more pictures than the one shown.
   A class rather than :has(), so it does not depend on how new the browser is. */
.kq-thumb-wrap { position: relative; display: inline-block; }
.kq-thumb-more {
    position: absolute;
    right: -4px;
    bottom: -4px;
    background: var(--kq-ink);
    color: #fff;
    font-size: .62rem;
    font-weight: 600;
    line-height: 1;
    padding: .12rem .25rem;
    border-radius: 999px;
}

/* A due date, coloured by how close it is. Amber a day out, red once gone —
   the same amber and red as everywhere else, and never the brand green, which
   would make a late order look fine. */
.kq-due-overdue { color: var(--kq-overdue); font-weight: 600; }
.kq-due-due     { color: var(--kq-due);     font-weight: 600; }
.kq-due-words   { font-size: .74rem; font-weight: 600; }
.kq-due-overdue .kq-due-words { color: var(--kq-overdue); }
.kq-due-due .kq-due-words     { color: var(--kq-due); }
/* The whole row, when the order is late, so it is seen before it is read. */
.kq-table tbody tr:has(.kq-due-overdue) > td { background: #FDF6F6; }
.kq-table tbody tr:has(.kq-due-overdue):hover > td { background: #FBE9E9; }

/* The history down one order's page. */
.kq-steps { list-style: none; margin: 0; padding: 0 0 0 1.35rem; position: relative; }
.kq-steps::before {
    content: "";
    position: absolute;
    left: .32rem;
    top: .45rem;
    bottom: .45rem;
    width: 2px;
    background: var(--kq-line);
}
.kq-step { position: relative; padding: 0 0 1rem 0; }
.kq-step::before {
    content: "";
    position: absolute;
    left: -1.2rem;
    top: .35rem;
    width: .7rem;
    height: .7rem;
    border-radius: 50%;
    background: #fff;
    border: 2px solid var(--kq-line);
}
.kq-step.is-now::before { border-color: var(--kq-lime-dark); background: var(--kq-lime); }
.kq-step:last-child { padding-bottom: 0; }
.kq-step-when { font-size: .78rem; color: var(--kq-muted); }

/* One heading per day, so a busy day does not repeat its date down every row. */
.kq-step-day {
    position: relative;
    margin: 1.1rem 0 .5rem;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--kq-muted);
}
.kq-step-day:first-child { margin-top: 0; }
/* Hides the rail behind the heading, so the day reads as a break in the thread */
.kq-step-day::before {
    content: "";
    position: absolute;
    left: -1.35rem;
    top: -.35rem;
    bottom: -.2rem;
    width: 6px;
    background: #fff;   /* the card behind the timeline */
}

/* The chip and what it happened to, on one line; everything else beneath it,
   so the eye lands on the material and not on a string of dotted fragments. */
.kq-step-line { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.kq-step-what { font-weight: 600; }
.kq-step-meta { font-size: .8rem; color: var(--kq-muted); margin-top: .15rem; }
.kq-step-note {
    font-size: .88rem;
    margin-top: .3rem;
    padding-left: .6rem;
    border-left: 2px solid var(--kq-line);
    color: var(--kq-muted);
}

/* A step on the whole order, not on one material: it is the lot moving, so it
   is set apart from the material lines above it. */
.kq-step.is-order .kq-step-what { font-style: italic; }
.kq-step.is-order::before { background: var(--kq-ink); border-color: var(--kq-ink); }

/* The printable order sheet. */
.kq-sheet { max-width: 760px; margin: 0 auto; background: #fff; padding: 2rem; }
.kq-sheet h1 { font-size: 1.4rem; margin: 0; }
.kq-sheet table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
.kq-sheet th, .kq-sheet td { border: 1px solid var(--kq-line); padding: .5rem .6rem; text-align: left; }
.kq-sheet th { background: var(--kq-lime-soft); font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }
@media print {
    .kq-noprint { display: none !important; }
    body { background: #fff; }
    .kq-sheet { padding: 0; max-width: none; }
}

/* The little label in front of a filter row, so the two rows line up. */
.kq-filter-label { min-width: 6.5rem; }

/* A quiet divider inside a card, where one form splits into two ideas. */
.kq-rule { border: 0; border-top: 1px solid var(--kq-line); margin: 1.1rem 0 .9rem; }

/* Who to call about an order. The number is what the person wants, so it is
   a big tap target, not a line of small print. */
.kq-who-name { font-weight: 600; }
.kq-calls { display: flex; flex-direction: column; gap: .4rem; margin-top: .7rem; }
.kq-call {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .5rem .7rem;
    border: 1px solid var(--kq-lime-line);
    border-radius: 8px;
    background: var(--kq-lime-soft);
    color: var(--kq-ink);
    text-decoration: none;
    font-weight: 600;
}
.kq-call:hover { background: #EDF4D6; color: var(--kq-ink); }
.kq-call .bi { color: var(--kq-lime-dark); font-size: 1rem; }
.kq-call span { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.kq-call em {
    font-style: normal;
    font-weight: 400;
    font-size: .72rem;
    color: var(--kq-muted);
}
/* WhatsApp keeps its own green here, as it does in the lists. */
.kq-call-wa { background: #EAF7EF; border-color: #BFE3CD; }
.kq-call-wa:hover { background: #DCF1E4; }
.kq-call-wa .bi { color: #128C4A; }

/* The product's picture beside an order. */
.kq-order-photo {
    width: 76px;
    height: 76px;
    object-fit: cover;
    border: 1px solid var(--kq-line);
    border-radius: 8px;
    background: #fff;
}
.kq-order-photo-empty {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #C8CDD4;
    font-size: 1.4rem;
}

/* One vendor's line inside an order. A late one is edged in red, so a page
   with four lines on it says which one to deal with first. */
.kq-stage h2 { font-size: .98rem; }
.kq-stage.is-late { border-color: #E9A8A8; box-shadow: inset 3px 0 0 var(--kq-overdue); }

/* One vendor's line inside an order row on the list. */
.kq-line { display: flex; align-items: baseline; gap: .5rem; padding: .12rem 0; }
.kq-line + .kq-line { border-top: 1px dashed var(--kq-line); }
.kq-line-who { flex: 1 1 auto; min-width: 0; font-size: .88rem; }
.kq-line-due { font-size: .82rem; white-space: nowrap; }
.kq-table tbody tr.kq-row-late > td { background: #FDF6F6; }
.kq-table tbody tr.kq-row-late:hover > td { background: #FBE9E9; }

/* "1 Getting the materials" / "2 From here it is one way" — the two halves of
   an order, so the page reads as a sequence rather than a pile of cards. */
.kq-step-head {
    display: flex;
    align-items: baseline;
    gap: .55rem;
    font-size: 1rem;
    font-weight: 600;
    margin: 1.4rem 0 .7rem;
}
.kq-step-head:first-of-type { margin-top: .4rem; }
.kq-step-head > span {
    flex: 0 0 auto;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background: var(--kq-lime);
    color: var(--kq-ink);
    font-size: .8rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.kq-step-head small { font-weight: 400; color: var(--kq-muted); font-size: .82rem; }

/* ===================================================================
   An order's lines, as rows rather than cards (22 Oct)

   The first version put a full contact card, a full history and a
   six-field form under every line, so a two-vendor order was a wall of
   forms. The usual job is "who is late, ring them, tick it off" — so the
   row says that in one line and everything else folds away.
   =================================================================== */
.kq-row2 + .kq-row2 { border-top: 1px solid var(--kq-line); }
.kq-row2.is-late { background: #FDF6F6; box-shadow: inset 3px 0 0 var(--kq-overdue); }
.kq-row2.is-done .kq-row2-what strong { color: var(--kq-muted); font-weight: 600; }

.kq-row2-main {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .7rem .9rem;
    flex-wrap: wrap;
}
.kq-row2-what { flex: 1 1 14rem; min-width: 0; }
.kq-row2-what strong { display: block; font-size: .95rem; }
.kq-row2-what .kq-note { font-size: .82rem; }
.kq-row2-due { flex: 0 0 auto; text-align: right; font-size: .88rem; min-width: 6.5rem; }
.kq-row2-do { flex: 0 0 auto; display: flex; gap: .3rem; align-items: center; }
.kq-row2-do form { margin: 0; }

/* What folds out of a row. */
.kq-row2-more {
    padding: .2rem .9rem 1rem;
    border-top: 1px dashed var(--kq-line);
}

/* The contact details without their own frame, inside a row. */
.kq-bare { padding: 0; }

/* WhatsApp keeps its own green on an icon button. */
.kq-wa-btn { color: #128C4A; border-color: #BFE3CD; }
.kq-wa-btn:hover { background: #EAF7EF; color: #0E6E3A; }

/* "It changed hands" — the rare thing, folded away so the common form is
   four boxes and not six. */
.kq-rare { margin-bottom: .9rem; }
.kq-rare > summary { cursor: pointer; }
.kq-rare > summary::marker { color: var(--kq-muted); }

.kq-wait-icon { font-size: 1.6rem; color: #C8CDD4; }

/* Who supplies a material: a plain list, name on the left, how long they take
   on the right. */
.kq-makers { list-style: none; margin: 0; padding: 0; }
.kq-makers li {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .6rem;
    padding: .3rem 0;
}
.kq-makers li + li { border-top: 1px solid var(--kq-line); }

/* A short list of tick boxes, two or three across rather than one long column. */
.kq-ticks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    gap: .2rem .8rem;
}

/* "Filled in from this product's recipe" — says the panel did the work, so
   the table below is read as a starting point rather than a form to complete. */
.kq-filled {
    display: flex;
    gap: .7rem;
    align-items: flex-start;
    padding: .6rem .8rem;
    margin-bottom: .9rem;
    border: 1px solid var(--kq-lime-line);
    border-radius: 8px;
    background: var(--kq-lime-soft);
}
.kq-filled .bi { color: var(--kq-lime-dark); font-size: 1.1rem; }

/* One card for a whole order (22 Oct): a head, then bands for each part,
   instead of a card per line and a history under every one of them. */
.kq-order-head {
    display: flex;
    gap: 1rem;
    align-items: center;
    flex-wrap: wrap;
    padding: 1rem 1.15rem;
}
.kq-sub-head {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .5rem 1.15rem;
    background: var(--kq-bg);
    border-top: 1px solid var(--kq-line);
    border-bottom: 1px solid var(--kq-line);
    font-weight: 600;
    font-size: .92rem;
}
.kq-sub-head .bi { color: var(--kq-lime-dark); }
.kq-step-no {
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 50%;
    background: var(--kq-lime);
    color: var(--kq-ink);
    font-size: .76rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* The "all products" line of the picking totals on the Shipping labels result. */
.kq-table tr.kq-sum td { background: var(--kq-lime-soft); font-weight: 600; border-top: 1px solid var(--kq-lime-line); }

/* "Where those units come from": one block per product, the figure always on the
   right so a column of numbers can be read down. Sub-lines are the mixed parcels. */
.kq-where-row { border-top: 1px solid var(--kq-line, #e3e0d8); padding: .55rem 0; }
.kq-where-row:first-child { border-top: 0; }
.kq-where-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .25rem; }
.kq-where-head .text-end { margin-left: auto; }
.kq-where-line { display: flex; gap: .5rem; font-size: .9rem; color: var(--kq-muted, #6b6a66); }
.kq-where-line .text-end { margin-left: auto; font-variant-numeric: tabular-nums; }
.kq-where-sub { padding-left: 1.1rem; }

/* Said on the form, not an error: what you typed is safe but wants a look.
   Amber because it is a warning, never the brand lime (see the colour rules). */
.kq-warn {
    background: #FDF0DC;
    border-left: 3px solid var(--kq-due);
    color: var(--kq-due);
    font-size: .9rem;
    padding: .5rem .75rem;
    border-radius: 4px;
}

/* The vendor details dialog: label on the left, the value on the right, nothing
   to press. Numbers are there to be read or copied, not dialled by accident. */
.kq-vcard-row {
    display: flex;
    gap: 1rem;
    padding: .45rem 0;
    border-top: 1px solid var(--kq-line);
}
.kq-vcard-row:first-child { border-top: 0; padding-top: 0; }
.kq-vcard-label { flex: 0 0 7.5rem; color: var(--kq-muted); font-size: .85rem; }
.kq-vcard-value { flex: 1 1 auto; word-break: break-word; }

/* Which kind of order. Two cards rather than a dropdown: the choice changes the
   whole rest of the page, so it should look like a decision, not a setting. */
.kq-kind { display: grid; gap: .6rem; grid-template-columns: 1fr 1fr; margin-bottom: 1rem; }
.kq-kind--three { grid-template-columns: repeat(3, 1fr); }
.kq-kind-pick {
    display: block;
    padding: .7rem .85rem;
    border: 1px solid var(--kq-line);
    border-radius: 8px;
    cursor: pointer;
    background: #fff;
}
.kq-kind-pick:hover { border-color: var(--kq-lime-line); }
.kq-kind-pick.is-on { border-color: var(--kq-lime-dark); background: var(--kq-lime-soft); }
.kq-kind-pick.is-off { opacity: .5; cursor: default; }
.kq-kind-pick input { margin-right: .4rem; }
.kq-kind-label { font-weight: 600; }
.kq-kind-help { display: block; font-size: .8rem; color: var(--kq-muted); margin-top: .2rem; }
@media (max-width: 575px) { .kq-kind { grid-template-columns: 1fr; } }

/* The line that just moved, so the eye finds it after the page comes back.
   Fades out on its own; it is a pointer, not a state. */
.is-just-saved { background: var(--kq-lime-soft); transition: background 1.2s ease-out; }

/* Stock: two shelves, four states. */
.kq-stock-tabs { display: flex; gap: .5rem; border-bottom: 1px solid var(--kq-line); margin-bottom: .9rem; }
.kq-stock-tab {
    padding: .5rem .9rem;
    border-bottom: 2px solid transparent;
    color: var(--kq-muted);
    font-weight: 600;
    text-decoration: none;
}
.kq-stock-tab:hover { color: var(--kq-ink); }
.kq-stock-tab.is-on { color: var(--kq-lime-dark); border-bottom-color: var(--kq-lime-dark); }

.kq-stock-pills { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .9rem; }
.kq-pill {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .35rem .7rem;
    border: 1px solid var(--kq-line);
    border-radius: 0;
    font-size: .85rem;
    font-weight: 600;
    color: var(--kq-muted);
    text-decoration: none;
    background: #fff;
}
.kq-pill:hover { border-color: var(--kq-lime-line); }
/* The state colours, so a pressed filter says which state it is showing.
   Amber for low and red for out — warnings are never green. */
.kq-pill.is-on { background: var(--kq-lime-soft); border-color: var(--kq-lime-dark); color: var(--kq-lime-dark); }
.kq-pill-in.is-on  { background: var(--kq-lime-soft); border-color: var(--kq-lime-dark); color: var(--kq-lime-dark); }
.kq-pill-low.is-on { background: #FDF0DC; border-color: var(--kq-due); color: var(--kq-due); }
.kq-pill-out.is-on { background: #FBE4E4; border-color: var(--kq-overdue); color: var(--kq-overdue); }

.kq-stock-search { display: flex; gap: .5rem; align-items: center; max-width: 460px; }
/* The Add button sits beside the search, and drops above it on a phone. */
/* Dashboard tiles. One figure each, and each one is the way into its section. */
.kq-tiles { display: grid; gap: .75rem; grid-template-columns: repeat(3, 1fr); }
.kq-tile {
    display: block;
    padding: 1.1rem 1.2rem;
    background: #fff;
    border: 1px solid var(--kq-line);
    border-radius: 10px;
    text-decoration: none;
    color: var(--kq-ink);
}
.kq-tile:hover { border-color: var(--kq-lime-dark); color: var(--kq-ink); }
.kq-tile-value { display: block; font-size: 2rem; font-weight: 700; line-height: 1.1; }
.kq-tile-label { display: block; font-size: .85rem; color: var(--kq-muted); margin-top: .15rem; }
.kq-tile.is-low .kq-tile-value { color: var(--kq-due); }
.kq-tile.is-out .kq-tile-value { color: var(--kq-overdue); }
@media (max-width: 767px) { .kq-tiles { grid-template-columns: 1fr; } }

/* What is already on its way. Blue-grey on purpose: it is neither a warning
   nor good news on its own — it is the other half of the decision. */
.kq-coming { font-size: .8rem; font-weight: 600; color: #46607C; white-space: nowrap; }

.kq-table tr.kq-click { cursor: pointer; }
.kq-history-btn { padding: .15rem .45rem; line-height: 1.2; }
/* Sell entry: the dates, the word between them, and who bought it. */
.kq-sales-filter { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.kq-sales-filter input[type="date"] { width: auto; }
.kq-sales-filter select { width: auto; max-width: 13rem; }
@media (max-width: 575px) { .kq-sales-filter select { max-width: 100%; flex: 1 1 100%; } }
.kq-sales-filter [hidden] { display: none !important; }

/* The strip under every list. The numbers go on a phone — too small to hit —
   and Back/Next stay, with the line of words saying where you are. */
.kq-pager {
    display: flex; align-items: center; justify-content: space-between;
    gap: .75rem; flex-wrap: wrap; padding: .75rem .85rem;
    border-top: 1px solid var(--kq-line);
}
.kq-pager-links { display: flex; align-items: center; gap: .35rem; }
.kq-pager-numbers { display: flex; gap: .35rem; }
.kq-pager .btn.disabled { opacity: .4; pointer-events: none; }
@media (max-width: 575px) {
    .kq-pager { justify-content: center; }
    .kq-pager-numbers { display: none; }
    .kq-pager-links { width: 100%; justify-content: space-between; }
}

/* Sell entry, gathered under the product: a heading row per product with the
   day's figure on it, and the entries that make it up underneath. Each product
   is its own <tbody>, so the rule between them is the rule between products. */
.kq-sold tbody + tbody { border-top: 2px solid var(--kq-line); }
.kq-sold tbody tr.kq-sold-head > *       { background: var(--kq-lime-soft); }
.kq-sold tbody tr.kq-sold-head:hover > * { background: var(--kq-lime-soft); }
.kq-sold tr.kq-sold-head th { font-weight: 600; }
.kq-sold tr.kq-sold-head .kq-note { margin-left: .5rem; font-weight: 400; }
.kq-sold tbody tr + tr > td:first-child { padding-left: 1.6rem; }

/* One day at a time, with an arrow either side. */
.kq-daybar { display: flex; align-items: center; gap: .6rem; margin: .25rem 0 1rem; }
.kq-daybar-date { font-weight: 600; font-size: 1rem; color: var(--kq-ink); }
.kq-daybar-date .kq-note { font-weight: 400; margin-left: .35rem; }

.kq-stock-bar { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; margin-bottom: 1rem; }
.kq-sub-head--split { display: flex; justify-content: space-between; align-items: center; gap: .75rem; flex-wrap: wrap; }
@media (max-width: 575px) {
    .kq-stock-bar { flex-direction: column-reverse; align-items: stretch; }
    .kq-stock-bar .btn { width: 100%; }
}

/* The same total, split by shelf. */
.kq-places { display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; margin-top: 1rem;
             padding-top: .9rem; border-top: 1px solid var(--kq-line); }
.kq-place-value { display: block; font-size: 1.4rem; font-weight: 700; line-height: 1.1; }
.kq-place-label { display: block; font-size: .78rem; color: var(--kq-muted); margin-top: .1rem; }
@media (max-width: 575px) { .kq-places { grid-template-columns: 1fr; gap: .35rem; }
    .kq-place { display: flex; justify-content: space-between; align-items: baseline; }
    .kq-place-value { font-size: 1.1rem; } }

.kq-stock-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.kq-stock-figure { font-size: 2.2rem; font-weight: 700; line-height: 1; }
.kq-in { color: var(--kq-lime-dark); }
.kq-out { color: var(--kq-overdue); }
