/*
   KeyCode Retail Jewellery — themes
   ---------------------------------
   Every colour in this application is a custom property declared here. No
   component below, and no component in any other stylesheet, may name a colour
   directly. A theme is therefore nothing but a block that redefines these
   properties, and adding a fifth is one block here plus one row in the
   database's allowed list.

   If a theme change ever requires touching a component, that component has a
   hard-coded colour and that is the bug.

   The server writes the chosen key onto <html data-theme="…"> so the first
   paint is already right — there is no flash of the wrong palette.

   MEENAKARI is the default and the one the owner chose to start with: enamel
   work, deep jade with gold and coral. The other three are here because the
   owner kept all four; each was drawn against the same dense weights-and-rates
   grid, which is the only honest test for a counter palette.
*/

/* ══════════════════════════════════════════════ meenakari — the default ══ */
:root,
:root[data-theme="meenakari"] {
    --ground:       #0F3833;   /* deep jade, the enamel itself            */
    --raised:       #133F39;   /* a card lifted off it                    */
    --sunken:       #0B2E2A;   /* a well: grids, inputs                   */
    --ink:          #EDF3F0;
    --ink-soft:     #A9C4BC;
    /*  RAISED 23 Sep 2026 from #6F918A, which read at 3.7:1 on this ground -
        under the 4.5:1 floor for small text, and the owner's word was that the
        labels "are not visible properly at all ages". Every theme's faint ink
        now clears 5:1, because this token colours nearly every label, hint and
        unit on the product. See the note over .field > span.  */
    --ink-faint:    #97B8B1;

    --line:         #1B4A44;
    --line-strong:  #2A6259;

    --accent:       #E8A33D;   /* gold — the metal, and the one bold thing */
    --accent-soft:  #2A2416;
    --accent-ink:   #0F3833;   /* text ON the accent                      */

    --second:       #E2725B;   /* coral, for a second emphasis only       */

    --ok:           #7FC6A8;   --ok-soft:   #12332C;
    --warn:         #E8C15A;   --warn-soft: #2B2717;
    --bad:          #E97A6B;   --bad-soft:  #33201C;

    /*  THE METALS AND THE MONEY, on a table. Added 4 Sep 2026 on the owner's
        ruling: gold column gold, silver column silver, amount on green with
        white on it - and applied everywhere, not just the purchase register.

        A COLUMN OF FIGURES IS FOUND BY ITS COLOUR BEFORE IT IS READ. On a
        register eighteen columns wide, "which of these is the gold" costs a
        second every time; the colour answers it before the eye arrives.

        PER PALETTE, because a gold that reads on Meenakari's deep jade is
        invisible on Sindoor's ivory. The MONEY green is the one fixed colour
        of the four - the owner asked for green with white on it, and a green
        that changed per palette would be four different greens to keep legible
        against one white.  */
    --metal-gold:   #E8B54D;
    --metal-silver: #B9C2CC;
    --money-bg:     #1C7A50;   --money-ink: #FFFFFF;

    --shadow:    0 1px 2px rgba(0,0,0,.30), 0 10px 30px rgba(0,0,0,.26);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.34);
}

/* ══════════════════════════════════════════════════════════════ assay ══ */
/*  Platinum and one sapphire. The most legible of the four across many
    numeric columns, and the only light-ground theme with a cool cast.      */
:root[data-theme="assay"] {
    --ground:       #F4F5F6;
    --raised:       #FFFFFF;
    --sunken:       #ECEFF1;
    --ink:          #191C1F;
    --ink-soft:     #545E66;
    --ink-faint:    #5F6971;   /* 5.6:1 on white - see the meenakari note */

    --line:         #E1E5E8;
    --line-strong:  #C6CDD3;

    --accent:       #1F4E79;
    --accent-soft:  #E4EDF5;
    --accent-ink:   #FFFFFF;

    --second:       #7A5230;

    --ok:           #1C7A50;   --ok-soft:   #E4F2EB;
    --warn:         #8A6410;   --warn-soft: #FAF0D9;
    --bad:          #A42B22;   --bad-soft:  #FBE9E7;

    /*  Assay is a light palette, so both metals darken to hold their own
        against near-white.  */
    --metal-gold:   #8A6100;
    --metal-silver: #566270;
    --money-bg:     #1C7A50;   --money-ink: #FFFFFF;

    --shadow:    0 1px 2px rgba(25,28,31,.06), 0 10px 30px rgba(25,28,31,.08);
    --shadow-sm: 0 1px 2px rgba(25,28,31,.10);
}

/* ════════════════════════════════════════════════════════════ sindoor ══ */
/*  Oxblood and antique brass on ivory. Warm, prints well, and looks like the
    shop rather than like software.                                        */
:root[data-theme="sindoor"] {
    --ground:       #FBF7F0;
    --raised:       #FFFFFF;
    --sunken:       #F5EEE3;
    --ink:          #2A1A1C;
    --ink-soft:     #6E5457;
    --ink-faint:    #745B5F;   /* 6.2:1 on white - see the meenakari note */

    --line:         #EADFD2;
    --line-strong:  #D8C6B4;

    --accent:       #5C1A24;
    --accent-soft:  #F6E7E5;
    --accent-ink:   #FBF7F0;

    --second:       #B08D57;

    --ok:           #4F7A4A;   --ok-soft:   #EAF1E7;
    --warn:         #8A6410;   --warn-soft: #F8EFDA;
    --bad:          #96242B;   --bad-soft:  #F8E6E6;

    /*  Sindoor is ivory with antique brass, so the gold leans brass rather
        than yellow or it fights the accent beside it.  */
    --metal-gold:   #8A6320;
    --metal-silver: #5E6670;
    --money-bg:     #1C7A50;   --money-ink: #FFFFFF;

    --shadow:    0 1px 2px rgba(42,26,28,.06), 0 10px 30px rgba(42,26,28,.08);
    --shadow-sm: 0 1px 2px rgba(42,26,28,.10);
}

/* ═══════════════════════════════════════════════════════════ showroom ══ */
/*  Champagne gold on a warm near-black. The lit case after dark.          */
:root[data-theme="showroom"] {
    --ground:       #14110E;
    --raised:       #1A1613;
    --sunken:       #100D0B;
    --ink:          #F2EBDF;
    --ink-soft:     #B0A594;
    --ink-faint:    #A19887;   /* 6.6:1 on the ground - see the meenakari note */

    --line:         #2A241D;
    --line-strong:  #3E352A;

    --accent:       #E0B872;
    --accent-soft:  #2A2318;
    --accent-ink:   #14110E;

    --second:       #C08457;

    --ok:           #8FBF8F;   --ok-soft:   #1B2419;
    --warn:         #DFBE6A;   --warn-soft: #2A2417;
    --bad:          #D98A7C;   --bad-soft:  #2E1C19;

    /*  Showroom is champagne on near-black - the lightest gold of the four,
        because the ground it sits on is the darkest.  */
    --metal-gold:   #E7C77E;
    --metal-silver: #C3CAD3;
    --money-bg:     #1C7A50;   --money-ink: #FFFFFF;

    --shadow:    0 1px 2px rgba(0,0,0,.40), 0 10px 30px rgba(0,0,0,.34);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.44);
}

/* ═════════════════════════════════════════════════════ shape and type ══ */
/*  Not themed: a theme changes colour, never the geometry or the type. Two
    themes that also disagreed about spacing would be two designs.          */
:root {
    --radius:     4px;
    --radius-sm:  3px;

    --font:  "Karla", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
    --serif: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
    --mono:  "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
}

/* ══════════════════════════════════════════════════════════════ base ══ */
*, *::before, *::after { box-sizing: border-box; }

/*  THE ROOT IS STATED, NOT ASSUMED (23 Sep 2026). Every size in this file is
    in rem, so every size in the product is a multiple of this one number -
    and until now it was the browser's default, which meant the product's type
    was set by something nobody here had written down.  */
html { -webkit-text-size-adjust: 100%; font-size: 16px; }

body {
    margin: 0;
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font);
    /*  Raised from 15px with the legibility pass: this is the size of every
        piece of text that does not ask for one - a paragraph, a table cell, a
        line of a list - on every page in the product.  */
    font-size: 16px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

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

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.spacer { flex: 1; }
.r { text-align: right; }
.c { text-align: center; }
.muted { color: var(--ink-faint); }

/* ═════════════════════════════════════════════════════════════ chrome ══ */
.topbar {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 22px;
    height: 56px;
    background: var(--raised);
    border-bottom: 1px solid var(--line);
}

.brand {
    font-family: var(--serif);
    font-size: 1.35rem;
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    letter-spacing: .01em;
}

.brand b { color: var(--accent); font-weight: 600; }

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 22px; }

/*  THE TOP BAR SPANS THE WINDOW - the owner's ruling of 4 Sep 2026, "here logo
    should be in left exactly".

    IT WAS A .wrap LIKE THE PAGE BELOW IT, so on any screen wider than 1240px
    `margin: 0 auto` centred the whole bar and left the corner empty. Measured
    at 706px the mark still started 148px in, which is the wrap's own margin
    doing exactly what it was written to do - in the one place it should not.

    A PAGE IS READ IN A COLUMN AND A BAR IS NOT. The reading column keeps its
    1240px so a paragraph never runs the width of a monitor; the bar is chrome,
    and chrome belongs at the edges of the thing it frames - the mark hard left,
    the shop and the sign-out hard right.  */
/*  THREE THINGS HELD IT IN, and taking away only the first two made it worse.

    max-width  the 1240px reading column, which is the obvious one.

    margin     `margin: 0 auto`, and this is the one that actually centred it.
               On a FLEX ITEM auto margins centre regardless of width, so with
               the max-width gone the bar simply centred at its content width -
               measured at 1366px the mark had moved from 148px in to 478px in.
               It looked like the fix had made it worse because it had.

    padding    the wrap's own 22px on top of the bar's 22px, which is what put
               the mark 44px in when it finally did reach the left.

    AND THEN IT MUST FILL THE BAR. A flex item is content-width by default, so
    without `flex: 1` the spacer inside it has nothing to push against and the
    shop name and sign-out never reach the right-hand edge.  */
.topbar > .topbar-in {
    max-width: none;
    margin: 0;
    padding: 0;
    flex: 1 1 auto;

    /*  The inner block lays its own children out in a row, so the spacer can
        do its work; it was relying on inline flow before.  */
    display: flex;
    align-items: center;
    gap: 16px;
}

main { min-height: 60vh; padding: 26px 0 60px; }

.footer {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 22px;
    border-top: 1px solid var(--line);
    color: var(--ink-faint);
    font-size: .84rem;
}

/*  THE APP FOOTER (23 Sep 2026) - logo, the two sites, the support numbers
    (Views/Shared/_AppFooter.cshtml). One row on a desk, wrapping to stacked
    lines on a phone; the links take the theme's ink so they read on every
    palette, and the accent only on hover.  */
.app-footer .footer-in { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; width: 100%; }
.app-footer .footer-brand img { height: 48px; width: auto; display: block; border-radius: 8px; box-shadow: var(--shadow-sm); }
.app-footer .footer-links,
.app-footer .footer-call { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; }
.app-footer a { color: var(--ink-soft); text-decoration: none; font-weight: 600; }
.app-footer a:hover { color: var(--accent); text-decoration: underline; }
.app-footer .footer-call a { font-family: var(--mono, monospace); letter-spacing: .02em; white-space: nowrap; }
.app-footer .footer-nums { color: var(--ink-faint); }
.app-footer .footer-k { color: var(--ink-faint); font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; }
@media (max-width: 640px) {
    .app-footer .footer-in { flex-direction: column; align-items: flex-start; }
    .app-footer .spacer { display: none; }
}

/* ══════════════════════════════════════════════════════════════ card ══ */
.card {
    background: var(--raised);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 18px 20px;
}

.card-head {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 14px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--line);
}

.card-head h1, .card-head h2, .card-head h3 {
    font-family: var(--serif);
    font-weight: 600;
    margin: 0;
    line-height: 1.1;
}

.card-head h1 { font-size: 1.85rem; }
.card-head h2 { font-size: 1.45rem; }
.card-head h3 { font-size: 1.2rem; }

/* ═════════════════════════════════════════════════════════════ button ══ */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--font);
    font-size: .84rem;
    font-weight: 700;
    letter-spacing: .02em;
    padding: 8px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line-strong);
    background: transparent;
    color: var(--ink);
    text-decoration: none;
    cursor: pointer;
    transition: border-color .12s ease, color .12s ease;
}

.btn:hover:not([disabled]) { border-color: var(--accent); color: var(--accent); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

.btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}

.btn-primary:hover:not([disabled]) { color: var(--accent-ink); filter: brightness(1.08); }

/*  A QUIET BUTTON IS STILL A BUTTON - the owner, 23 Sep 2026: "Set it as look
    Like Button Not flat Label text", for all the project. It used to have a
    transparent border and read as a line of text until the pointer found it
    ("Print", "Show", "Parties" beside a heading). It keeps .btn's border, and
    .btn's hover, and differs from a plain .btn in nothing but being the
    secondary choice beside a primary one. The ✕ in a grid row is styled on
    its own (.tbl.grid .c-del) and is unaffected.  */
.btn-quiet { color: var(--ink); }

/*  GOING SOMEWHERE LOOKS DIFFERENT FROM DOING SOMETHING - the owner, the same
    day, once every quiet button had its border: "Differentiate ... all button
    for navigation" (Sale register, Purchase register beside a card).

    THE MARKUP ALREADY SAYS WHICH IS WHICH: a link (<a class="btn">) opens
    another screen, a <button> acts on this one. So a non-primary LINK is a
    rounded pill on a soft tint, and a button keeps the square bordered shape -
    no view had to change, and a screen added next year gets it right by using
    the right element. The orange primary keeps its own look whichever it is.  */
a.btn:not(.btn-primary):not(.c-del) {
    border-radius: 999px;
    background: var(--accent-soft);
    border-color: color-mix(in srgb, var(--accent) 35%, var(--line));
    color: var(--ink);
    padding-left: 18px;
    padding-right: 18px;
}
a.btn:not(.btn-primary):not(.c-del):hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

.btn.is-bad { color: var(--bad); }
.btn.is-bad:hover:not([disabled]) { border-color: var(--bad); color: var(--bad); }

/* ══════════════════════════════════════════════════════════════ forms ══ */
.field { display: flex; flex-direction: column; gap: 4px; }

/*  A PASSWORD BOX WITH AN EYE IN IT (22 Sep 2026). site.js wraps every
    password input and puts the eye in the right edge; the box keeps its
    own width and only gives up room for the eye on the right.  */
.pwd-wrap { position: relative; display: flex; min-width: 0; }
.pwd-wrap > input { flex: 1 1 auto; width: 100%; min-width: 0; padding-right: 2.2rem; }
.pwd-eye {
    position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; padding: 0; border: 0; border-radius: var(--radius-sm);
    background: none; color: var(--ink-faint); cursor: pointer;
}
.pwd-eye:hover { color: var(--ink); background: var(--sunken); }
.pwd-eye .ico { width: 18px; height: 18px; }

/*  THE LABEL OVER A BOX, READ AT ANY AGE (23 Sep 2026).
    The owner's word, with the sale bill on screen: *"there is visibility issue
    in layout, labels are not visible properly at all ages"*. Four things were
    working against the reader at once, and all four were the style's doing:

    IT WAS TINY - .68rem is under 11px at this base, and the shell shrank it
    again to .64rem. It is now .8rem, which is the smallest size on the screen
    that still has to be READ rather than glanced at.

    IT WAS THE FAINTEST INK ON THE PALETTE, at 3.6:1 on white. The token is
    darker now, and the label takes the SOFT ink rather than the faint one -
    the label names the box a hand is about to key, so it is not the quietest
    thing on the screen.

    IT WAS UPPERCASE, which throws away the shape of the word: CUSTOMER — NAME
    OR MOBILE is read letter by letter, "Customer — name or mobile" is read at
    a glance. Every label in the product is already written in sentence case in
    its view, so taking the transform off simply shows what was typed.

    IT WAS LETTER-SPACED at .08em, which is a display trick for capitals and
    pulls mixed-case words apart. A trace is left, no more.  */
.field > span, label > span.lbl {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--ink-soft);
}

/*  A FIELD'S LABEL MAY CARRY AN EXAMPLE, the same way a column heading does -
    "10000+25000" over a cash box that takes a sum. It goes on the LABEL and
    not in the box: a placeholder is text sitting in an empty field, and a
    screen with ten of them looks full before anything has been keyed.

    It is not upper-cased or letter-spaced with the label above it: this is an
    example to be read literally, and "10000+25000" spaced out is harder to
    read than the thing it is showing.  */
.field > span > .chint {
    display: block;
    margin-top: 1px;
    font-size: .72rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    opacity: .9;
}

input, select, textarea {
    font-family: var(--font);
    font-size: .92rem;
    color: var(--ink);
    background: var(--sunken);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    padding: 8px 10px;
    width: 100%;
}

/*  ═══ NO SPINNERS ON A NUMBER BOX ═══
    The owner.s ruling of 4 Sep 2026, *"throughout project numeric input disable
    up down arrow"*.

    THEY ARE NOT USABLE ON THIS DATA AND THEY COST A COLUMN. Nobody reaches a
    weight of 12.321 by clicking a stepper, and on a fourteen-column grid the
    two arrows eat the right-hand end of every numeric cell - which is exactly
    where the digits are, because every figure on this system is right-aligned.
    The keyboard.s own up and down keys still step the value for anyone who
    wants them; only the drawn control goes.

    BOTH VENDOR PREFIXES ARE NEEDED. WebKit and Blink draw the buttons as
    pseudo-elements and only listen to `-webkit-appearance`; Firefox draws them
    itself and only listens to `appearance: textfield`. Setting one and not the
    other fixes it in the browser you happened to test in.  */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

input[readonly] { color: var(--ink-soft); }

.grid-form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px 14px;
}

/* ═════════════════════════════════════════════════════════════ tables ══ */
.tblwrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }

table.tbl { width: 100%; border-collapse: collapse; font-size: .92rem; }

.tbl thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--sunken);
    text-align: left;
    /*  A COLUMN HEADING KEEPS ITS CAPITALS - it is one or two words naming a
        column, read once per table and then skipped, and capitals tell it
        apart from the figures under it at a glance. But it was .70rem in the
        faintest ink, which is a heading nobody over forty can read at all: it
        takes the soft ink and a size it deserves (23 Sep 2026).  */
    font-size: .75rem;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    /*  FULL INK, EXTRA BOLD - the owner, 23 Sep 2026, on every list: "make table
        Header label bold, all list throughout the project". 700 in the soft ink
        still read as light grey capitals; the heading now leads its column.  */
    color: var(--ink);
    padding: 9px 12px;
    border-bottom: 1px solid var(--line-strong);
    white-space: nowrap;
}

/*  WHERE ONE GROUP OF COLUMNS ENDS AND THE NEXT BEGINS.

    The vendor list shows six figures across - an opening and a closing for each
    of gold, silver and money - and six numbers in a row read as one run unless
    something says where the halves divide. A rule down the left of each group
    does it without a second colour or a heavier border.

    NOT .grp, which this stylesheet already gave to the collapsible menu group;
    a table cell borrowing that name would inherit its radius.  */
.tbl th.colgrp, .tbl td.colgrp { border-left: 1px solid var(--line-strong); }

/* ─────────────────────────────────── find a saved document, from the head ── */
/*
    The voucher search sits in the page head beside the step arrows, so its list
    has to hang OVER the screen rather than push the grids down - a picker that
    moved the bill every time somebody typed would be unusable on a screen where
    the bill is the point.

    THE WRAPPER IS THE POSITIONING CONTEXT. Without `position: relative` here the
    absolute list would hang off the page itself and land wherever the last
    positioned ancestor happens to be.
*/
.findvoucher { position: relative; flex: 0 0 auto; }

.findvoucher > input {
    width: 12rem;
    padding: 5px 9px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--raised);
    color: var(--ink);
    font-size: .86rem;
}

.findvoucher .hits {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 40;
    min-width: 26rem;
    box-shadow: var(--shadow);
}

/*  Three columns: the number, who it was with, and when. The number is the one
    being searched for, so it leads and keeps the monospace.  */
.findvoucher .hit { grid-template-columns: auto 1fr auto; }

/*  A SEARCH THAT FOUND NOTHING SAYS SO. An empty box that simply does not
    appear reads as a search that did not run.  */
.hits .hit.is-none {
    display: block;
    padding: 8px 10px;
    color: var(--ink-faint);
    cursor: default;
}

/* ────────────────────────────── the metals and the money, on every table ── */
/*
    The owner's ruling of 4 Sep 2026, given against the purchase register and
    explicitly for everywhere: gold column in gold, silver column in silver,
    the amount on green with white on it.

    ONE PLACE, SO IT IS THE SAME EVERYWHERE. Three classes here rather than a
    colour written into each of the nine tables that show these figures - the
    register, the ledger, the vendor lists, stock, the dashboard. A colour
    copied nine times is a colour that is eight different colours by Christmas.

    THE MONEY IS A CHIP, NOT A PAINTED CELL. A solid green filling the whole
    cell edge to edge turns a table into a block of colour and hides the row
    striping under it; the figure itself carries the green, so the column reads
    as money at a glance and the table still reads as a table. It keeps the
    monospace, so the figures still line up inside their chips.

    NOT ON A BLANK. A nought is not shown on these screens - the owner's rule -
    and painting an empty cell green would put a green box where there is no
    money at all. `:not(:empty)` is what keeps the blanks blank.
*/
.tbl td.c-gold,   .tbl th.c-gold   { color: var(--metal-gold); }
.tbl td.c-silver, .tbl th.c-silver { color: var(--metal-silver); }

.tbl tfoot th.c-gold, .tbl tfoot th.c-silver { font-weight: 700; }

.tbl td.c-money:not(:empty), .tbl tfoot th.c-money:not(:empty) {
    background: var(--money-bg);
    color: var(--money-ink);
    border-radius: var(--radius-sm);
    padding-inline: 8px;
}

/*  A LINK INSIDE A GREEN CELL MUST STOP BEING THE LINK COLOUR, or the accent
    on green is the one pair on this screen nobody can read.  */
.tbl td.c-money a, .tbl td.c-money .muted { color: var(--money-ink); }

/* ───────────────────────────────────────── a register reads down the middle ── */
/*
    The owner's ruling of 4 Sep 2026: "Purchase register table content centre
    alignment", and for all of them.

    AND THE FIGURES CENTRE WITH THEM SINCE 5 Sep 2026 - the owner asked again,
    looking at the monthly report: *"align numeric cell in center"*, *"same for
    yearly report"*. The `.mono` guard that used to sit in this selector is off.

    THE NOTE THAT USED TO BE HERE SAID WHY IT WAS ON, and it is worth keeping
    because it is still true of one kind of column: a column of weights that do
    not line up on the point is a column nobody can add up by eye. Centring
    10.000 / 517.877 / 89.972 staggers the decimal points.

    SO `.r` IS STILL OBEYED, and that is now what the exception rests on rather
    than on a guess about what `.mono` means. A cell marked `.r` is one somebody
    decided ADDS UP DOWN THE PAGE - and 438 of them do, nearly all in the books:
    the day book, the ledger, the trial balance, the balance sheet, the profit
    and loss. Centring a trial balance is not a style choice; it is a report an
    accountant hands back.

    THE LINE IS THEREFORE: a register reads down the middle, and a book reads
    down its decimal point. Both are the owner's rules; this is where they meet.
*/
.tbl tbody td:not(.r):not(.l),
.tbl thead th:not(.r):not(.l) { text-align: center; }

/*  A NAME STAYS LEFT - the owner's correction of 4 Sep 2026, "here Party name
    Will Be Left Aligned".

    AND IT IS THE RIGHT EXCEPTION, not a special case. A name is the longest and
    most variable thing in any of these tables, so centring it puts every row's
    first letter in a different place and the eye has nothing to run down. The
    figures line up on their right edge for the same reason, and everything in
    between - a code, a date, a count - is short enough that centring it costs
    nothing.

    `:not(.l)` IS IN THE CENTRING RULE ITSELF because the centring selector
    carries three classes and would otherwise outrank a plain `td.l`. An
    override that loses to the thing it overrides is worse than none: it looks
    applied in the markup and does nothing on the screen.  */
.tbl td.l, .tbl th.l { text-align: left; }

/*  ── AND A TABLE THAT READS DOWN THE MIDDLE ALL THE WAY ACROSS ──
    The owner's ruling of 5 Sep 2026, sent with the sale bill's Recent bills
    list: *"align numeric in table centre"*.

    THE RULE ABOVE STOPS AT `.r`, ON PURPOSE. A cell marked `.r` is one somebody
    decided ADDS UP DOWN THE PAGE, and 438 of them do - the day book, the
    ledger, the trial balance, the profit and loss. Centring a column of money
    staggers its decimal points, and a trial balance whose figures do not line
    up is a report an accountant hands back.

    A RECENT-BILLS LIST IS NOT ONE OF THOSE. Nobody adds up the last four bills;
    it is a list you scan to find the one you want to reopen, with a column of
    icons on the end. So the money in it centres with everything else, and the
    table says so itself rather than every cell in it being re-marked.

    ═══ WHY A CLASS ON THE TABLE AND NOT `.r` STRIPPED OUT OF THE MARKUP ═══

    Because `.r` IS THE RECORD OF A DECISION. Stripping it from these cells
    would throw away what it says - that this is a figure - and leave nothing
    behind to put it back from. A table opting out is one line, it is visible
    where somebody is reading the markup, and it reverses by deleting a word.

    IT WINS ON SPECIFICITY, and that is not luck: `.tbl.mid tbody td.r` carries
    three classes to `.tbl thead th.r`'s two and `.r`'s one. An override that
    loses to the thing it overrides is worse than none - it looks applied in the
    markup and does nothing on the screen, which is exactly how the totals row
    stayed left-aligned for an afternoon.  */
.tbl.mid tbody td.r,
.tbl.mid thead th.r { text-align: center; }

/*  A HEADING SITS OVER ITS OWN COLUMN, and every cell sits on one line ── */
/*
    The owner, 4 Sep 2026: "if header is centered then data should be in center
    and vertically, except vendor name".

    THE MISMATCH WAS REAL. A figure column's cells are `.r` and its heading was
    not always, so PURCHASES sat centred over a column of right-aligned counts
    and the two never lined up. Wherever the two disagreed, the eye had to find
    the join itself.

    THEY ARE MADE TO AGREE BY MOVING THE HEADING, NOT THE FIGURES, and that is
    the one place this does not follow the ruling literally. Centring a column
    of 41.000 / 13.408 / 21.339 staggers the decimal points, and the owner's own
    earlier rule is that "a column of weights that do not line up on the point
    is a column nobody can add up by eye". So the heading comes to the figures.
    Every other column - a count, a word, a date - centres, heading and cell
    together.

    VERTICALLY CENTRED EVERYWHERE. A row whose name wraps to two lines had its
    figures sitting at the top of the cell, level with the first line of the
    name rather than with the name itself.
*/
.tbl th, .tbl td { vertical-align: middle; }

/*  The heading of a figure column takes the column's own alignment.  */
.tbl thead th.r { text-align: right; }

/*  A SECOND LINE UNDER A FIGURE, not a second figure beside it.

    Two monospace numbers a space apart in one right-aligned cell read as one
    long number - "21.339 -16.161" was taken for a single value - and the pair
    widens the column until it runs under its neighbour's heading. The working
    goes underneath, smaller and quieter, where it reads as belonging to the
    figure above rather than competing with it.  */
.tbl .sub {
    display: block;
    font-size: .82em;
    line-height: 1.3;
    color: var(--ink-faint);
}

/*  A PARTY'S NAME READS AS A NAME, not as a link - the owner's ruling of
    4 Sep 2026: "make vendor name data bold black".

    IT IS STILL A LINK and still goes somewhere; what changes is that it stops
    ANNOUNCING itself as one. On a register the name is the thing being read -
    it is how a row is identified before any figure on it means anything - and a
    column of accent-coloured underlined text competes with the money for the
    eye while telling it nothing it needs.

    THE UNDERLINE COMES BACK ON HOVER, so the fact that it can be clicked is
    still discoverable at the moment somebody reaches for it. A name that gave
    no sign at all would be a link nobody found.
*/
.tbl a.nm {
    color: var(--ink);
    font-weight: 700;
    text-decoration: none;
}

.tbl a.nm:hover, .tbl a.nm:focus-visible { text-decoration: underline; }

/*  AND THE FIGURES CARRY WEIGHT - the same ruling, "large and bold".

    ON THE BODY CELLS, NOT ON THE WHOLE TABLE: the heading row is already 700
    and small-capped, and the entry GRIDS are excluded outright - those cells
    hold input boxes, and a bold shell around a normal-weight box reads as two
    different fields.

    THE QUIET TEXT STAYS QUIET. "1 item" beside a vendor, a working under a
    figure, a greyed note - these are there to be read second. Bolding
    everything in the row would flatten that back out and leave nothing for the
    eye to land on first.  */
.tbl:not(.grid) tbody td { font-weight: 600; }

.tbl:not(.grid) tbody td .muted,
.tbl:not(.grid) tbody td .sub,
.tbl:not(.grid) tbody td .soon,
.tbl:not(.grid) tbody td small { font-weight: 400; }

.tbl td { padding: 9px 12px; border-bottom: 1px solid var(--line); }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:nth-child(even) td { background: var(--sunken); }

.empty-cell { color: var(--ink-faint); text-align: center; padding: 26px 12px; }

/* ══════════════════════════════════════════════════════════════ pills ══ */
.pill {
    display: inline-block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    padding: 2px 9px;
    border-radius: 999px;
    border: 1px solid currentColor;
    white-space: nowrap;
}

.pill.ok   { color: var(--ok);   background: var(--ok-soft); }
.pill.warn { color: var(--warn); background: var(--warn-soft); }
.pill.bad  { color: var(--bad);  background: var(--bad-soft); }
.pill.gold { color: var(--accent); background: var(--accent-soft); }

/* ══════════════════════════════════════════════════════ theme picker ══ */
/*  The swatches show the real palette of each theme, so the choice is made by
    looking rather than by reading a name. Each button paints itself from
    literal values because it must show a palette that is NOT the one
    currently applied — the only place in this stylesheet where that is
    correct, and the reason is here so nobody 'fixes' it later.            */
.theme-picker { display: flex; gap: 8px; align-items: center; }

.theme-dot {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 2px solid var(--line-strong);
    cursor: pointer;
    padding: 0;
    position: relative;
    overflow: hidden;
}

.theme-dot[aria-pressed="true"] { border-color: var(--accent); }

.theme-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, var(--dot-ground) 0 55%, var(--dot-accent) 55% 100%);
}

.theme-dot[data-theme-key="meenakari"] { --dot-ground: #0F3833; --dot-accent: #E8A33D; }
.theme-dot[data-theme-key="assay"]     { --dot-ground: #F4F5F6; --dot-accent: #1F4E79; }
.theme-dot[data-theme-key="sindoor"]   { --dot-ground: #FBF7F0; --dot-accent: #5C1A24; }
.theme-dot[data-theme-key="showroom"]  { --dot-ground: #14110E; --dot-accent: #E0B872; }

/* ═══════════════════════════════════════════════════════════ toasts ══ */
.toast-rail {
    position: fixed;
    right: 18px;
    bottom: 18px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    z-index: 60;
}

.toast {
    background: var(--raised);
    border: 1px solid var(--line-strong);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    padding: 11px 15px;
    max-width: 380px;
    font-size: .88rem;
}

.toast.ok  { border-left-color: var(--ok); }
.toast.bad { border-left-color: var(--bad); }

/*  A tickbox with its wording beside it.

    This lives here rather than in the panel's own stylesheet because the
    Person screens use it too - and when it lived there, the box inherited the
    220px width every other input gets and the label wrapped underneath it. A
    component used by two shells belongs in the one both of them load.  */
.check { display: flex; align-items: center; gap: 7px; font-size: .88rem; }
.check input { width: auto; flex: none; margin: 0; }

/*  Picking a theme, with a swatch of the palette itself.

    Here rather than in the panel's stylesheet because THREE shells use it now
    - SuperAdmin choosing the landing palette, the owner choosing a shop's
      starting one, and a user choosing their own at the counter. The counter
    loaded it once without these rules and the radios floated away from their
    labels, which is the same bug `.check` had and for the same reason.  */
.theme-picks {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px;
}

.theme-pick {
    display: flex;
    gap: 11px;
    align-items: flex-start;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 13px 14px;
    background: var(--ground);
    cursor: pointer;
}

.theme-pick:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.theme-pick input { width: auto; flex: none; margin-top: 3px; }
.theme-pick b { display: block; font-size: .95rem; }
.theme-pick span { font-size: .8rem; color: var(--ink-faint); }

/*  Naming the colours is what a stylesheet is for; showing them is what a
    picker is for. Two stops rather than a gradient - a theme is a ground and
    an accent, and a blend implies neither.  */
.swatch {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    flex: none;
    border: 1px solid var(--line-strong);
    background: linear-gradient(135deg, var(--sw-accent) 0 50%, var(--sw-ground) 50% 100%);
}

.swatch[data-theme-key="meenakari"] { --sw-ground: #0F3833; --sw-accent: #E8A33D; }
.swatch[data-theme-key="assay"]     { --sw-ground: #F4F5F6; --sw-accent: #1F4E79; }
.swatch[data-theme-key="sindoor"]   { --sw-ground: #FBF7F0; --sw-accent: #5C1A24; }
.swatch[data-theme-key="showroom"]  { --sw-ground: #14110E; --sw-accent: #E0B872; }

/*  Dashboard tiles.

    A dashboard is scanned, not read: the figure comes first and large, the
    label second and small. The reverse - a label with a number after it - is a
    table pretending to be a dashboard.  */
.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
}

.tile {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--raised);
    padding: 15px 17px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.tile b {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.55rem;
    font-weight: 500;
    line-height: 1.15;
    overflow-wrap: anywhere;
}

.tile span {
    font-size: .8rem;
    color: var(--ink-soft);
    letter-spacing: .05em;
    text-transform: uppercase;
}

.tile small { font-size: .78rem; color: var(--ink-soft); }

/*  The one figure the counter is judged on. Accent, and only ever one tile -
    a dashboard where everything is emphasised emphasises nothing.

    It spans two columns because at 1.9rem a lakh figure does not fit a
    160px tile, and it wrapped mid-number: "1,32,00" over "0". A headline
    figure that breaks across lines is worse than a smaller one.  */
.tile.lead { border-color: var(--accent); grid-column: span 2; }
.tile.lead b { color: var(--accent); font-size: 1.9rem; overflow-wrap: normal; }

@media (max-width: 520px) {
    .tile.lead { grid-column: span 1; }
    .tile.lead b { font-size: 1.55rem; }
}

/*  Money owed cuts both ways and the two must not be read as one another.  */
.tile.owed b  { color: var(--warn); }
.tile.owing b { color: var(--bad); }

/* ------------------------------------------------------------ the week --- */

/*  Seven bars, drawn with grid rather than a charting library. A week of
    takings is a shape, and the shape is the whole point - the numbers are
    already in the tiles above.  */
.week {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 8px;
    align-items: end;
    height: 130px;
    margin-top: 6px;
}

.week-bar {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    gap: 6px;
    height: 100%;
}

.week-fill {
    width: 100%;
    background: var(--accent-soft);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    min-height: 3px;
}

/*  Today reads differently from the six days behind it, or the operator has
    to count along the axis to find where they are.  */
.week-bar.today .week-fill { background: var(--accent); }

.week-day { font-size: .72rem; color: var(--ink-faint); }
.week-val { font-size: .72rem; font-family: var(--mono); color: var(--ink-soft); }

/* ---------------------------------------------------------- shop cards --- */

.shops { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }

.shop {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--raised);
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.shop h3 { margin: 0; font-family: var(--serif); font-size: 1.2rem; }
.shop-figs { display: flex; gap: 18px; flex-wrap: wrap; }
.shop-figs div { display: flex; flex-direction: column; }
.shop-figs b { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 1.05rem; }
.shop-figs span { font-size: .72rem; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .05em; }
.shop .btn { align-self: flex-start; margin-top: auto; }

/*  The working shell: a menu down the side, the screen beside it.

    Shared by the counter and the owner's pages, and near enough to the
    SuperAdmin panel's that admin.css now only holds what is genuinely the
    panel's own. A component used by three shells lives here - the lesson
    `.check` and `.theme-pick` both taught.  */

.shell {
    display: grid;
    grid-template-columns: 208px minmax(0, 1fr);
    gap: 28px;
    align-items: start;
    padding-top: 22px;
}

@media (max-width: 900px) {
    .shell { grid-template-columns: minmax(0, 1fr); gap: 16px; }
}

.menu {
    display: flex;
    flex-direction: column;
    gap: 1px;
    position: sticky;
    top: 16px;
}

@media (max-width: 900px) {
    .menu { position: static; flex-direction: row; flex-wrap: wrap; gap: 6px; }
    .menu-h { display: none; }
}

.menu a {
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    color: var(--ink-soft);
    text-decoration: none;
    /*  LARGER AND BOLDER - the owner.s ruling of 4 Sep 2026. This is the
        list a counter hand reads forty times a day, at arm.s length, on a
        screen that is rarely the one it was designed on. .9rem in the soft
        ink was the quietest text on the page and it is the most used.  */
    font-size: .96rem;
    font-weight: 600;
    border-left: 2px solid transparent;
}

.menu a:hover { background: var(--sunken); color: var(--ink); }

/*  A real edge, not only a tint: a tint alone fails for anybody who cannot
    see the hue, and the weight change carries it on its own.  */
.menu a.on {
    background: var(--accent-soft);
    border-left-color: var(--accent);
    color: var(--accent);
    font-weight: 700;
}

/*  A screen that is not built yet is IN THE MENU but not a link. Hiding it
    means the shop cannot see what is coming; making it a link means a dead
    click and a support call.  */
.menu span.soon {
    padding: 8px 12px;
    font-size: .9rem;
    color: var(--ink-faint);
    border-left: 2px solid transparent;
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: default;
}

.menu span.soon::after {
    content: "soon";
    font-size: .68rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--sunken);
    border: 1px solid var(--line);
}

.menu-h {
    margin: 15px 0 4px 12px;
    font-size: .78rem;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.shell-main { display: flex; flex-direction: column; gap: 18px; min-width: 0; }

/*  Editing a row, and filtering a list.

    THESE LIVE HERE, NOT IN admin.css. They were written for the SuperAdmin
    panel and then used by the counter, and the counter does not load that
    stylesheet - so the item editor collapsed into one long column of boxes.
    That is the third component to make this mistake, after `.check` and
    `.theme-pick`.

    THE RULE, now stated once: admin.css holds only what is the PANEL's own -
    its shell, its side nav, its count tiles, its error-log trace. Anything a
    working screen might reuse belongs here.  */

/*  The editor sits beside what it edits rather than on another screen: a row
    is a handful of fields, and a round trip to see the list again after every
    save is a round trip nobody needs.  */
.editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--raised);
    padding: 18px 20px;
}

.editor h3 { margin: 0; font-size: 1.05rem; }
.editor .row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.editor .row > .field { flex: 1 1 180px; min-width: 0; }

/*  A ROW THAT STAYS A ROW. The tag form is two rows by the owner's word
    (20 Sep 2026); its seven boxes share the width rather than wrapping into
    a third. The wide one - the item name - takes a double share.  */
.editor .row.tight { flex-wrap: nowrap; }
.editor .row.tight > .field { flex: 1 1 0; }
.editor .row.tight > .field.wide { flex: 2 1 0; }
.editor .row.tight > .field.narrow { flex: 0.6 1 0; }
.editor .row.tight > .field > input,
.editor .row.tight > .field > select { min-width: 0; width: 100%; padding-left: 6px; padding-right: 6px; }
.editor .actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/*  ── THE HEAD OF AN EDITOR POPUP, THE SAME ON BOTH PARTY SCREENS ──
    The owner's rulings of 5 Sep 2026: "customer and vendor close button
    topmost right", and "vendor customer layout should look like uniform".

    THE TITLE ON THE LEFT AND THE CROSS ON THE RIGHT, on one line, with a rule
    under it so the form below reads as the form and not as more heading.

    IT IS `align-items: center` AND NOT THE ROW'S OWN flex-end. A row of FIELDS
    lines its boxes up along their bottoms, which is right for boxes and wrong
    for a heading beside a button: the cross would sit on the baseline of the
    h3 and hang below it.  */
.editor .editor-top {
    align-items: center;
    gap: 8px;
    padding-bottom: 8px;
    margin-bottom: 2px;
    border-bottom: 1px solid var(--line);
}

/*  A LITTLE BIGGER THAN AN ICON IN A TOOLBAR. This one is a modal's only
    visible way out, and a x that is hard to hit is a modal people escape by
    clicking the backdrop and then wondering why nothing happened.  */
.editor .editor-top .iconbtn {
    font-size: 1.1rem;
    line-height: 1;
    padding: 3px 9px;
}

/*  A row being edited has to be obvious, or somebody types into the form while
    looking at a different row and cannot work out what happened.  */
.tbl tr.is-editing td { background: var(--accent-soft); }

.rowform { display: flex; gap: 6px; align-items: flex-end; flex-wrap: wrap; }
.rowform input { min-width: 0; }

.filters { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }
.filters .field { min-width: 12rem; }

/* ══════════════════════════════════════════════ working-screen density ══ */
/*
    THE LANDING PAGE AND THE TILL ARE NOT THE SAME KIND OF PAGE.

    Everything above was written for the public page, where air is the point:
    generous type, serif headings, wide gaps, a 1240px column so a paragraph is
    readable. Applied to a data-entry screen that is exactly wrong - the
    operator wants to see forty items without scrolling, not eight, and a serif
    heading the size of a poster is not information.

    So the working shell tightens everything. Scoped under .shell, which every
    working screen already sits in, so nothing here can leak onto the landing
    page or the sign-in.
*/

.shell {
    font-size: 13.5px;
    line-height: 1.45;

    /*  A till screen uses the width of the till. The 1240px column is for
        reading prose, and a stock list is not prose.  */
    max-width: 1680px;
    gap: 20px;

    /*  186px HELD THE LABELS AT .81rem AND CLIPPED THEM AT .92 - "Customers &
        ve...", "Shop de...", "Financi...", which the owner sent screenshots of
        on 4 Sep 2026 after asking for the larger menu font.

        THIS IS THE RULE THAT DECIDES IT, and the 208px one further up is not:
        every counter screen carries `.shell` twice over and this later block
        wins. Widening the other one changed nothing, which is exactly the trap
        the menu font itself fell into.

        210px IS MEASURED AND NOT GUESSED - it is what the longest label on the
        menu needs at .92rem once its icon, its padding and a sub-menu.s indent
        are counted.  */
    grid-template-columns: 210px minmax(0, 1fr);
    padding-top: 16px;
}

.shell-main { gap: 12px; }

/* ------------------------------------------------------------- cards --- */

.shell .card { padding: 12px 14px; border-radius: var(--radius-sm); }

.shell .card-head {
    gap: 10px;
    margin-bottom: 10px;
    padding-bottom: 8px;
}

/*  Sans, not serif, and near the size of the text beneath it. A heading on a
    working screen labels a panel; it is not a title page.  */
.shell .card-head h1,
.shell .card-head h2,
.shell .card-head h3 {
    font-family: var(--font);
    font-weight: 700;
    letter-spacing: -.01em;
}

.shell .card-head h1 { font-size: 1.15rem; }
.shell .card-head h2 { font-size: 1rem; }
.shell .card-head h3 { font-size: .92rem; }

/* ------------------------------------------------------------ tables --- */

/*  The density that decides how much of the shop's stock fits on one screen.
    Nine pixels of padding and a 0.88rem face put about eighteen rows in a
    laptop; six and 0.82 put twenty-eight.  */
/*  LARGER AND BOLDER - the owner.s ruling of 4 Sep 2026, given on the purchase
    register: "make table font large and bold".

    THE DENSITY NOTE ABOVE STILL HOLDS and this costs rows: .82 to .90 is about
    two fewer lines on a laptop. It is worth it. These tables are read across -
    a weight against a fine against an amount - and a figure that has to be
    leaned in for is a figure that gets read off the wrong row.  */
.shell table.tbl { font-size: .90rem; }
/*  THE HEADING ROW WITH IT - the owner.s ruling of 4 Sep 2026, "make header
    slightly large and bold", sent after the body cells had already grown.

    THE WEIGHT WAS ALREADY 700; what was missing was CONTRAST. A heading set in
    the faintest ink on the page reads as light however heavy it is set, and
    beside a body row that is now 600 in full ink it had stopped leading the
    column at all. So it takes a size, and it takes the softer ink instead of
    the faint one.  */
.shell .tbl thead th {
    padding: 6px 9px;
    font-size: .78rem;
    letter-spacing: .05em;
    font-weight: 800;
    color: var(--ink);
}
.shell .tbl td { padding: 5px 9px; }

/*  A name and its code belong on one line. "Gold GOLD" wrapping into two rows
    is what made the first version of this screen unreadable.  */
.shell .tbl td > b + span.muted { margin-left: 5px; }

/* ------------------------------------------------------------- forms --- */

.shell .editor { padding: 12px 14px; gap: 9px; border-radius: var(--radius-sm); }
.shell .editor .row { gap: 8px; }
/*  THE SHELL TIGHTENS THE PRODUCT, IT DOES NOT SHRINK THE WRITING (23 Sep
    2026). It used to take another tenth of a rem off the label and the box -
    .64rem and .84rem - and since every keying window in the product runs
    inside the shell, THAT was the size the owner was actually reading. The
    padding still comes in; the type stays legible.  */
.shell .field > span, .shell label > span.lbl { font-size: .78rem; }

.shell input, .shell select, .shell textarea {
    padding: 6px 9px;
    font-size: .9rem;
    border-radius: var(--radius-sm);
}

.shell .btn { padding: 5px 11px; font-size: .86rem; }
.shell .grid-form { gap: 9px; }
.shell .pill { font-size: .70rem; padding: 1px 6px; }

/* -------------------------------------------------------------- menu --- */

.shell .menu a, .shell .menu span.soon { padding: 6px 10px; font-size: .90rem; }
.shell .menu-h { margin: 12px 0 3px 10px; font-size: .70rem; }

/* -------------------------------------------------------- dashboards --- */

.shell .tile { padding: 11px 13px; }
.shell .tile b { font-size: 1.3rem; }
.shell .tile.lead b { font-size: 1.55rem; }
.shell .tile span { font-size: .72rem; }
.shell .tiles { gap: 9px; }

/* --------------------------------------------------- two unequal panes --- */
/*
    A pane pair that is NOT half and half. Metals is four narrow columns and
    purities is five wider ones; splitting them evenly cramped the left one
    until every cell wrapped. The names say which is which rather than the
    caller remembering an order.
*/
.panes {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
    gap: 14px;
    align-items: start;
}

.panes > * { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

@media (max-width: 1100px) {
    .panes { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------- page header and hint --- */
/*
    The name of a screen is not content, so it does not sit in a card. A card
    is a panel OF something; wrapping a heading in one puts a box round a
    label and pushes the first real row further down every screen.
*/
.pagehead {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    padding: 2px 2px 0;
}

.pagehead h1 {
    font-family: var(--font);
    font-weight: 700;
    font-size: 1.2rem;
    letter-spacing: -.01em;
    margin: 0;
}

/*  One line of guidance, where the operator will read it - above the thing it
    is about, not inside a panel of its own.  */
.hint {
    margin: 0;
    font-size: .84rem;
    color: var(--ink-soft);
    border-left: 2px solid var(--line-strong);
    padding-left: 10px;
}

.hint b { color: var(--ink-soft); font-weight: 700; }

/*  A name and its code, a rate and its unit: two words that mean one thing
    must not be broken across two lines.  */
.nowrap { white-space: nowrap; }

/* ═══════════════════════════════════════════════════ the drawer, and icons ══ */
/*
    A menu that can be put away.

    A till is often a narrow screen, and the operator who knows where things
    are does not need the words. Collapsed, the drawer keeps the icons and the
    highlight - so it is still a map, not a mystery strip of symbols.

    The choice is remembered per browser, because it is a property of THAT
    till, not of the person: the same salesman wants the wide menu on the
    office machine and the narrow one on the counter.
*/

.ico {
    width: 17px;
    height: 17px;
    flex: none;
    /*  Optically centred against the cap height of the label beside it.  */
    margin-top: -1px;
}

.menu a, .menu span.soon {
    display: flex;
    align-items: center;
    gap: 10px;
}

/*  The label is what disappears; the icon is what stays.  */
/*  THE LABEL IS CLIPPED RATHER THAN WRAPPED, and that was right when the menu
    was set at .81rem. At .92 it started cutting real names - "Customers & ve…",
    "Shop de…", "Financi…" - which the owner sent screenshots of on 4 Sep 2026.

    THE ELLIPSIS STAYS, because a menu whose rows are two lines tall loses the
    scannable left column that makes it a menu at all. What changes is that
    there is more room for it to not be needed: the rail is wider, the flyout is
    wider, and the two longest labels were split into the two things they were
    actually doing ("Customers & vendors" is now Customers and Vendors).

    A TITLE ON EVERY ROW is what makes the clip survivable - _Menu.cshtml has
    always written one, so a clipped label still says what it is on hover.  */
.menu .lbl-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --------------------------------------------------------- the handle --- */

.drawer-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--raised);
    color: var(--ink-soft);
    cursor: pointer;
}

.drawer-toggle:hover { border-color: var(--accent); color: var(--accent); }

/*  THE WAY BACK INTO FULL SCREEN - the owner.s report of 4 Sep 2026, "when
    exit from full screen, no option to go in full screen there".

    SHAPED LIKE THE MENU BUTTON BESIDE IT, because it is the same kind of thing:
    a control over how much of the screen the work gets, not a control over the
    document. Two neighbours doing one job should not be two different objects.

    IT NEEDS NO STATE. The top bar is what full screen hides, so a button that
    lives in the top bar is already absent in the mode and present out of it -
    which is exactly when it is wanted.  */
.fullenter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--raised);
    color: var(--ink-soft);
    cursor: pointer;
}

.fullenter:hover { border-color: var(--accent); color: var(--accent); }

/*  A phone has no chrome to put away and no room to hide the menu into. Both
    controls go, the same as the exit button already does.  */
@media (max-width: 600px) {
    .fullenter { display: none; }
}

/* ------------------------------------------------------ put away, then --- */

.shell.is-collapsed { grid-template-columns: 46px minmax(0, 1fr); }

.shell.is-collapsed .menu a,
.shell.is-collapsed .menu span.soon {
    justify-content: center;
    padding: 8px 0;
    gap: 0;
}

.shell.is-collapsed .menu .lbl-text { display: none; }

/*  The "soon" badge is a word, and words are what collapsing removes. The
    item stays greyed, which is what it was actually saying.  */
.shell.is-collapsed .menu span.soon::after { display: none; }

/*  A section heading with no words left is a gap. A rule in its place keeps
    the grouping, which is the part that was doing the work.  */
.shell.is-collapsed .menu-h {
    margin: 8px 8px 6px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    background: var(--line);
    color: transparent;
}

@media (max-width: 900px) {
    /*  Narrow screens already stack the menu into a row; collapsing it there
        would leave a row of unlabelled symbols with nowhere to go.  */
    .shell.is-collapsed { grid-template-columns: minmax(0, 1fr); }
    .shell.is-collapsed .menu .lbl-text { display: inline; }
    .shell.is-collapsed .menu a { justify-content: flex-start; padding: 6px 10px; gap: 8px; }
}

/* ═══════════════════════════════════════════════════════════ form fields ══ */
/*
    FIELDS ARE WHITE ON EVERY THEME. The owner asked for it, and it is right:
    a data-entry box is paper. On the dark themes a field the colour of the
    page reads as decoration rather than as somewhere to type, and an operator
    keying two hundred lines a day needs the boxes to be the loudest thing on
    the screen.

    Tokens rather than literals so a theme could still differ - but nothing
    ships differing, because the point is that they do not.
*/
:root {
    --field-bg:     #FFFFFF;
    --field-ink:    #14110E;
    --field-line:   #B9C0C4;
    --field-faint:  #7A8388;
    --field-off:    #EDEFF0;   /* readonly and disabled */
}

input, select, textarea {
    background: var(--field-bg);
    color: var(--field-ink);
    border: 1px solid var(--field-line);
}

input::placeholder, textarea::placeholder { color: var(--field-faint); }

/*  The browser paints its own dropdown and date picker from this.  */
select, input[type="date"], input[type="number"] { color-scheme: light; }

input:focus, select:focus, textarea:focus {
    border-color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: -1px;
}

input[readonly], input[disabled], select[disabled], textarea[readonly] {
    background: var(--field-off);
    color: var(--field-faint);
}

/*  A tickbox is not a field of paper - it is a control, and painting it white
    on white loses it entirely.  */
input[type="checkbox"], input[type="radio"] {
    background: none;
    border: 0;
    accent-color: var(--accent);

    /*  AND AN OUTLINE WHEN IT IS EMPTY - the owner's ruling of 4 Sep 2026.

        accent-color paints a tickbox only once it is TICKED; an unticked one is
        drawn by the browser in its own grey, which on these grounds all but
        disappears. "Show cancelled" looked like a stray square with a label
        beside it, and a control nobody can see is a control nobody uses.

        THE MARK IS RED because that is what he asked for, and it happens to be
        the right colour for this particular tick: what it reveals is cancelled
        documents. --bad is the palette's own red, so it stays legible on ivory
        and on near-black alike rather than being one fixed #f00.  */
    outline: 1px solid var(--bad);
    outline-offset: 1px;
    border-radius: 2px;
}

/*  TICKED, IT GOES RED TOO, so the box says the same thing in both states -
    the browser would otherwise fill it with the gold accent and outline it in
    red, which is two colours making one statement.  */
input[type="checkbox"]:checked, input[type="radio"]:checked { accent-color: var(--bad); }

/* ══════════════════════════════════════════════════ menu groups and drawer ══ */
/*
    THE MODULES ARE THE MENU: Master, Retail, Wholesale, Mortgage,
    Manufacturing, Setting. A group the shop has not bought is shown locked
    rather than hidden - a customer who cannot see what else exists never asks
    for it.

    Built on <details>, so opening and closing needs no script, survives the
    script failing, and answers to the keyboard on its own.
*/

.grp { border-radius: var(--radius-sm); }

.grp > summary {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    list-style: none;
    /*  AND THE GROUP HEADING WITH IT, or the heading ends up smaller than the
        items under it.  */
    font-size: .92rem;
    font-weight: 700;
    letter-spacing: .01em;
    color: var(--ink);
    user-select: none;
}

.grp > summary::-webkit-details-marker { display: none; }
.grp > summary:hover { background: var(--sunken); }

/*  The chevron is the only moving part, and it turns rather than swapping -
    a glyph that changes shape reads as a different control.  */
.chev {
    margin-left: auto;
    width: 7px;
    height: 7px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    opacity: .5;
    transition: transform .15s ease;
}

.grp[open] > summary .chev { transform: rotate(45deg); }

/*  An open group is marked at its head, so a collapsed menu still says which
    section you are in.  */
.grp[open] > summary { color: var(--accent); }

.grp-items {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 2px 0 6px;
}

/*  A rail down the left of the children: it says "these belong to that" more
    quietly than an indent alone.  */
.grp-items > a, .grp-items > span.soon {
    margin-left: 16px;
    border-left: 1px solid var(--line);
    padding-left: 12px;
}

.grp-items > a.on {
    border-left-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 700;
}

.grp.locked > summary { color: var(--ink-faint); }
.grp.locked .lock { font-size: .7rem; opacity: .8; }

/* ------------------------------------------------- a sub-menu --- */
/*
    A GROUP THAT OUTGREW ONE LIST. Wholesale reached ten lines under one
    heading and became a thing to scan rather than a thing to know your way
    around, so it splits into Purchase, Sale and Reports.

    THE SAME DISCLOSURE AS A GROUP, one level in - not a different control that
    happens to look similar. It keeps the keyboard support, it works before the
    script has loaded, and the sub-menu holding the current screen is the one
    that opens.

    QUIETER THAN THE GROUP ABOVE IT: lighter weight and a smaller type size, so
    the eye still reads the group first and the sub-menu second. Two headings
    shouting equally would leave the reader deciding which is which.
*/
.subgrp > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: 16px;
    padding: 5px 8px 5px 10px;
    border-left: 1px solid var(--line);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    cursor: pointer;
    list-style: none;
    font-size: .87rem;
    font-weight: 600;
    color: var(--ink-soft);
    user-select: none;
}

.subgrp > summary::-webkit-details-marker { display: none; }
.subgrp > summary:hover { background: var(--sunken); }
.subgrp[open] > summary { color: var(--accent); }
.subgrp[open] > summary .chev { transform: rotate(45deg); }

/*  The children of a sub-menu take their own rail, further in - so a line
    says which sub-menu it is under without being read.  */
.subgrp > .grp-items { padding: 1px 0 4px; }
.subgrp > .grp-items > a,
.subgrp > .grp-items > span.soon { margin-left: 26px; }

/*  Put away, a sub-menu is its icon and nothing else - the same rule the
    groups follow, for the same reason: at 56px there is no room for a rail,
    an indent or a word.  */
.shell.is-collapsed .subgrp > summary {
    justify-content: center;
    margin-left: 0;
    padding: 6px 0;
    gap: 0;
    border-left: 0;
}

.shell.is-collapsed .subgrp .chev { display: none; }

/* ───────────────────────── the collapsed rail's menus fly out on hover ── */
/*
    The owner's ruling of 4 Sep 2026: "in menu sub menu should show on hover,
    when click that sub menu".

    A COLLAPSED RAIL IS A ROW OF SYMBOLS AND A TOOLTIP. Hovering a group said
    only its NAME - "Retail" - which tells somebody what they are pointing at
    and not what is inside it, so reaching anything meant opening the whole menu
    back up first. The group's own items come out beside it now, and are
    clickable.

    CSS AND NOT SCRIPT, for the reason the groups are <details> in the first
    place: it works before the JavaScript has loaded and if it never does, which
    on a till on a bad connection is a real state.

    :focus-within CARRIES THE KEYBOARD. Tabbing into a group opens the same
    panel a mouse does, so the rail is not a mouse-only control.
*/
.shell.is-collapsed .menu .grp { position: relative; }

/*  NEVER INLINE IN THE RAIL. A 46px column cannot hold a menu item, so an open
    group used to stack unlabelled icons under its own icon - which read as more
    groups rather than as that group's contents.  */
.shell.is-collapsed .menu .grp > .grp-items { display: none; }

.shell.is-collapsed .menu .grp:hover > .grp-items,
.shell.is-collapsed .menu .grp:focus-within > .grp-items {
    display: block;

    /*  AND content-visibility, WHICH IS THE ONE THAT ACTUALLY HIDES IT.

        A shut <details> does not hide its contents with display:none any more -
        the browser uses `content-visibility: hidden`, which display cannot
        override. The panel was being given `display: block` and staying
        invisible, and the probe caught it as "focusing a group opens nothing".  */
    content-visibility: visible;

    position: absolute;
    left: 100%;
    top: 0;
    z-index: 60;

    /*  AND THE FLYOUT WITH IT. It is the same labels in a narrower box, so a
        rail panel left at 210 would clip what the open menu no longer does.  */
    min-width: 232px;
    padding: 6px;
    background: var(--raised);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

/*  INSIDE THE PANEL THE WORDS COME BACK. The collapsed rules hide every label
    and centre every row, which is right in a 46px rail and wrong in a 210px
    panel - without this the flyout would be a second column of symbols.  */
.shell.is-collapsed .menu .grp > .grp-items .lbl-text { display: inline; }

.shell.is-collapsed .menu .grp > .grp-items a,
.shell.is-collapsed .menu .grp > .grp-items span.soon {
    justify-content: flex-start;
    padding: 7px 10px;
    gap: 9px;
}

.shell.is-collapsed .menu .grp > .grp-items span.soon::after { display: inline; }

/*  A SUB-MENU INSIDE THE PANEL STANDS OPEN. It is already a flyout; making
    somebody open a second disclosure inside it would be two clicks to reach
    what the hover was for.  */
.shell.is-collapsed .menu .grp > .grp-items .subgrp > .grp-items {
    display: block;

    /*  AND content-visibility AGAIN - the same trap the panel itself fell into.
        A shut <details> hides its contents with `content-visibility: hidden`,
        which `display: block` cannot override, and a sub-menu is only OPEN when
        the screen you are on is inside it. On every other screen the three
        items rendered but took part in no layout: the panel sized itself as if
        they were not there, and they hung out of the bottom of it over the
        page, on no background at all.  */
    content-visibility: visible;
}

.shell.is-collapsed .menu .grp > .grp-items .subgrp > summary {
    justify-content: flex-start;
    margin-left: 0;
    padding: 6px 10px;
    gap: 9px;
}

.shell.is-collapsed .menu .grp > .grp-items .subgrp .chev { display: none; }

/*  AND THE PANEL HAS TO WIN THE PAGE - the owner.s report of 4 Sep 2026,
    "see the menu on hover layout issue", sent with the register.s heading row
    printed straight through the middle of the flyout.

    THE PANEL.S OWN z-index WAS NEVER IN THE COMPARISON. It says 60, and 60 was
    true - inside .menu. A `position: sticky` element makes its OWN STACKING
    CONTEXT whatever its z-index, and .menu is sticky, so everything in the rail
    is sealed into a context sitting at auto. The register.s heading row is
    sticky too, at z-index 1, in the ROOT context - and 1 beats auto. Sixty
    against one, and one won, because they were never being compared.

    SO THE NUMBER GOES ON THE SEALED BOX, not on what is inside it. 50 and not
    60: it must clear a sticky table heading and the voucher-search list at 40,
    and it must stay UNDER the dialogs and drawers that sit at 60 - a menu that
    paints over a modal is the next bug.  */
.shell.is-collapsed .menu { z-index: 50; }

/*  AND THE PANEL HAS TO BE CLICKABLE, which is a SECOND thing and was still
    wrong after the stacking was fixed.

    A shut <details> puts its contents behind `::details-content`, and THAT is
    the box carrying `content-visibility: hidden` - not the div inside it. The
    override further up sets it on `.grp-items`, which is enough to lay the
    panel out and paint it, and not enough to make it exist to the pointer:
    elementsFromPoint over the open flyout returned the TABLE UNDERNEATH and
    never the panel at all. A menu that can be seen and not clicked.

    So it goes on the pseudo-element, where the browser actually put it. The
    rules that hide a group at rest are `display: none` on .grp-items and are
    untouched by this - a shut group in the rail still shows nothing.  */
.shell.is-collapsed .menu .grp::details-content,
.shell.is-collapsed .menu .grp > .grp-items .subgrp::details-content {
    content-visibility: visible;
}

/*  A SUB-MENU IN THE PANEL READS AS A HEADING, NOT AS A CHOICE.

    "Purchase" and "Purchase entry" arrived at the same pixel, in the same
    weight, in the same colour, each with an icon - so the flyout read as seven
    equal things to click, two of which cannot be clicked to anywhere. Worse,
    the heading was set 0.8px SMALLER than the items under it.

    The indent below was zeroed for the RAIL, where 46px has no room for one.
    Inside a 210px panel it is the whole of what says these three belong to
    that.  */
.shell.is-collapsed .menu .grp > .grp-items .subgrp > summary {
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--ink-faint);
    cursor: default;
    padding: 9px 10px 3px;
}

.shell.is-collapsed .menu .grp > .grp-items .subgrp > summary:hover { background: none; }

/*  The icon and the chevron both go: a heading that carries a symbol is being
    offered as a destination.  */
.shell.is-collapsed .menu .grp > .grp-items .subgrp > summary svg { display: none; }

.shell.is-collapsed .menu .grp > .grp-items .subgrp > .grp-items {
    margin-left: 9px;
    border-left: 1px solid var(--line);
    padding-left: 3px;
}

@media (max-width: 900px) {
    /*  The rail is a row of full-width items on a narrow screen, not a column
        of symbols, so there is nothing to fly out of.  */
    .shell.is-collapsed .menu .grp > .grp-items,
    .shell.is-collapsed .menu .grp:hover > .grp-items,
    .shell.is-collapsed .menu .grp:focus-within > .grp-items {
        display: revert;
        position: static;
        min-width: 0;
        padding: 0;
        background: none;
        border: 0;
        box-shadow: none;
    }
}

.shell.is-collapsed .subgrp > .grp-items > a,
.shell.is-collapsed .subgrp > .grp-items > span.soon { margin-left: 0; }

@media (max-width: 900px) {
    .shell.is-collapsed .subgrp > summary {
        justify-content: flex-start;
        margin-left: 16px;
        padding: 5px 8px 5px 10px;
        gap: 8px;
        border-left: 1px solid var(--line);
    }

    .shell.is-collapsed .subgrp .chev { display: block; }
    .shell.is-collapsed .subgrp > .grp-items > a,
    .shell.is-collapsed .subgrp > .grp-items > span.soon { margin-left: 26px; }
}

/* ------------------------------------------- the drawer, put away --- */

.shell.is-collapsed .grp > summary { justify-content: center; padding: 8px 0; gap: 0; }
.shell.is-collapsed .grp .chev,
.shell.is-collapsed .grp .lock { display: none; }

/*  Collapsed, a group's children indent from nothing and the rail has no room.
    Icons only, centred, still marked when current.  */
.shell.is-collapsed .grp-items > a,
.shell.is-collapsed .grp-items > span.soon {
    margin-left: 0;
    border-left: 0;
    padding-left: 0;
    justify-content: center;
}

@media (max-width: 900px) {
    .shell.is-collapsed .grp > summary { justify-content: flex-start; padding: 7px 10px; gap: 10px; }
    .shell.is-collapsed .grp .chev { display: block; }
}

/* ═════════════════════════════════════════════════════ tighter chrome ══ */
/*
    THE SPACE ABOVE THE WORK. A landing page opens with air; a working screen
    opens with the work. Every pixel between the top bar and the first row is a
    pixel of the stock list that is not on screen.

    So the shell starts almost immediately under the bar, and the menu is
    tightened to match - a menu with more air than the table beside it reads as
    the more important of the two, which it is not.
*/

.shell { padding-top: 8px; }
main:has(.shell) { padding: 0 0 24px; }

.topbar:has(+ main .shell) { padding: 6px 0; }

.shell .card { padding: 10px 12px; }
.shell .card-head { margin-bottom: 8px; padding-bottom: 6px; }
.shell-main { gap: 10px; }

.shell .pagehead { padding-top: 0; }

/*  The menu, tightened. Grouped items were already indented; the rows
    themselves did not need to be tall as well.  */
/*  LARGER AND BOLDER IN THE SHELL TOO - and this is the pair that actually
    decides it. The base .menu rules are overridden here for every counter
    screen, so raising those alone changed nothing the shop can see: a size set
    in one place and overridden in another is a size that was never set.  */
.shell .grp > summary { padding: 5px 9px; font-size: .95rem; }
.shell .grp-items { padding: 1px 0 4px; }
.shell .menu a, .shell .menu span.soon { padding: 4px 9px; font-size: .92rem; font-weight: 600; }
.shell .menu-h { margin: 9px 0 2px 9px; }
.shell .menu { gap: 0; }

/*  A shop switcher in the top bar, for an owner with more than one.  */
.shopswitch { display: inline-flex; }
.shopswitch select {
    width: auto;
    min-width: 9rem;
    padding: 3px 8px;
    font-size: .8rem;
}

/*  The two ways into a shop, side by side on its card.  */
.shop-go { display: flex; gap: 8px; align-items: center; margin-top: auto; }
.shop-go form { display: inline; }

/* ══════════════════════════════════════════════════ the counter's screens ══ */
/*
    The party picker, the bill grid and the totals panel. These live HERE and
    not in admin.css because admin.css holds only what is the SuperAdmin
    panel's own - and three components have already learned that the hard way
    by inheriting a 220px input width they had no use for.
*/

/*  THE PARTY PICKER sits under the box it belongs to rather than in a dialog.
    Choosing a customer is the first thing that happens on every bill, and a
    modal for it would be a click before every sale.  */
.hits {
    display: flex;
    flex-direction: column;
    margin-top: 4px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--raised);
    max-height: 15rem;
    overflow-y: auto;
}

/*  AND `hidden` HAS TO BEAT THE `display` ABOVE.

    `[hidden] { display: none }` lives in the BROWSER's own stylesheet, and any
    author rule that sets `display` outbids it. So `.hits { display: flex }`
    quietly broke `box.hidden = true` everywhere it is used - the list stayed on
    screen after a party was picked, after the box was cleared, after Escape and
    after a blur, because the attribute was being set on an element the
    stylesheet had already told to be a flex column.

    IT LOOKED LIKE A SCRIPT BUG AND WAS NOT. The counter that discards a stale
    search was added for this and could not have fixed it: nothing was
    re-rendering the list, it had simply never gone away.

    Every list that hides itself needs this line. `display` in an author rule
    and `hidden` in the script are two people deciding the same thing.  */
.hits[hidden] { display: none; }

/*  THE AREA PICKER (22 Sep 2026) drops its list OVER the row below rather
    than pushing it down - the bill head is one line of boxes, and a list
    that grew the row would move every box the hand was about to reach.  */
.area-field { position: relative; }
.area-hits { position: absolute; left: 0; right: 0; top: 100%; z-index: 30; min-width: 14rem; box-shadow: 0 10px 24px rgba(0, 0, 0, .18); }
.area-hits .hit { grid-template-columns: 1fr auto; }

.hits .hit {
    display: grid;
    grid-template-columns: 1fr auto auto;
    gap: 10px;
    align-items: baseline;
    padding: 6px 10px;
    border: 0;
    border-bottom: 1px solid var(--line);
    background: none;
    color: var(--ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.hits .hit:last-child { border-bottom: 0; }
.hits .hit:hover, .hits .hit:focus { background: var(--sunken); }

/*  The one the arrow keys are on. Marked with the accent rather than the hover
    colour, because the two can be on different rows at once - a mouse resting
    somewhere while the hand walks the list with the keys.  */
.hits .hit.is-on {
    background: var(--accent-soft);
    box-shadow: inset 3px 0 0 var(--accent);
}

/* ─────────────────────────────────────────────────────────── the bill grid ── */
/*
    Nineteen columns, and a jeweller reads DOWN them. So the cells are tight,
    the boxes fill their cell, and nothing moves between rows: a box that
    cannot apply to a line is disabled where it stands rather than hidden,
    because a grid whose columns shift between rows cannot be read down at all.
*/
/*  THE HEADING OF A COLUMN SOMEBODY KEYS INTO IS BOLD AND IN FULL INK
    (23 Sep 2026) - the owner's word, "do such header label in bold".

    A REGISTER'S HEADING IS READ ONCE and then the eye lives in the figures,
    so it stays quiet. A KEYING GRID'S heading is read on every line: it is
    the only thing telling the hand whether this box wants a weight, a rate or
    a percentage, and it was set in the same soft grey as a report's. Bold, in
    the ink the rest of the screen is written in.

    THE EXAMPLE UNDER IT DOES NOT FOLLOW - "weight or pcs" stays light and
    quiet, or the heading and its footnote become one grey block again.  */
.tbl.grid th { padding: 5px 6px; font-size: .8rem; letter-spacing: .04em; white-space: nowrap; }

/*  THE SHELL'S OWN HEADING RULE IS TWO CLASSES AND TWO ELEMENTS DEEP, and it
    paints every heading in the soft ink. Matching it and adding a class is
    what makes this one win - written plainly rather than left to depend on
    which rule happens to sit further down the file.  */
.tbl.grid thead th,
.shell .tbl.grid thead th { font-weight: 700; color: var(--ink); }

.tbl.grid thead th .chint,
.shell .tbl.grid thead th .chint { font-weight: 400; color: var(--ink-soft); }
/*  THE ENTRY GRID KEEPS ITS OWN SIZE. Raising the register tables raised this
    one too by inheritance, and this is the fourteen-column grid - it is sized
    to its input boxes, and a derived cell a size larger than the box beside it
    reads as a different kind of field.  */
.tbl.grid td { padding: 3px 4px; font-size: .86rem; }

/*  THE BOX AND THE CELL BESIDE IT MOVE TOGETHER - that is what the note above
    is guarding. Raised together on 23 Sep 2026, from .82/.8, for the same
    reason the labels were: a figure keyed at eleven pixels is a figure keyed
    on trust.  */
.tbl.grid input,
.tbl.grid select {
    width: 100%;
    min-width: 0;
    padding: 4px 5px;
    font-size: .86rem;
    border-radius: 3px;
}

.tbl.grid input.r { text-align: right; font-variant-numeric: tabular-nums; }

/*  A box that does not apply to this kind of line. Still in its column, still
    the same width, plainly not for typing in.  */
.tbl.grid .off {
    background: var(--sunken);
    border-color: var(--line);
    opacity: .45;
}

/*  Old metal and cash come OFF the bill, and the row says so before anybody
    reads the sign in the amount column.  */
.tbl.grid tr.is-old  td { background: var(--warn-soft); }
.tbl.grid tr.is-cash td { background: var(--accent-soft); }

/*  THE ROW'S REMOVE IS RED (22 Sep 2026) - the owner's word, "remove X use
    red colour". It takes a line off the bill; it should not look like the
    quiet buttons beside it. Same on every grid that has it: the sale bill,
    the purchase, the wholesale panels.  */
.tbl.grid .c-del {
    padding: 1px 7px;
    line-height: 1.2;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--bad);
    border-color: var(--bad);
}
.tbl.grid .c-del:hover:not([disabled]) { background: var(--bad); color: #fff; border-color: var(--bad); }

/* ────────────────────────────────────────────────────────── the totals panel ─ */
/*
    Top to bottom in the owner's own order: OLD, Total New, Total Old, TOTAL,
    discount, GST, GRAND, then the money taken and what is left.
*/
/*  A NOTCH LARGER THAN A TABLE (23 Sep 2026) - the owner's word, "slightly
    large each label in sale panels".

    THIS PANEL IS NOT A TABLE OF ROWS, it is the twenty names a bill is agreed
    by: TOTAL, DIS, GST, GRAND, CASH, DUE. They are read one at a time, across
    a counter, while somebody is waiting - and they were sized as ordinary
    table cells, which is the size for a register nobody reads aloud.

    THE NAME TAKES THE WEIGHT, not the figure's own column: the figures are
    already mono and bold where they matter, and making both heavy would leave
    the eye nothing to land on.

    THE WHOLESALE PANEL IS NOT TOUCHED - it sets its own .72rem, four classes
    deep, because it carries three money columns where this one carries one.  */
.tbl.totals td { padding: 4px 8px; border-bottom: 0; font-size: .96rem; }
.tbl.totals tbody td:first-child { font-weight: 600; }
.tbl.totals tbody tr:nth-child(even) td { background: none; }
.tbl.totals tbody tr:hover td { background: var(--sunken); }

/*  THE LABELS READ DOWN THE LEFT - the owner.s ruling of 4 Sep 2026, "align
    labels to left".

    THEY WERE CENTRED, and not by anyone.s choice: the centring rule written for
    the registers matches any body cell carrying no alignment class, and every
    label in this panel is exactly that. Centred in a two-column strip they
    drifted towards the figures and the eye had no left edge to run down - on
    the one panel that is read as a LIST of names rather than as a table.

    IT IS SET HERE AND NOT BY ADDING `.l` TO TWENTY CELLS, because the next row
    somebody adds would be centred again and nobody would know why.  */
/*  THE `:not()` IS NOT DECORATION - it is what makes this rule win.

    The centring rule for the registers is written `.tbl tbody
    td:not(.mono):not(.r):not(.l)`, and a `:not()` carries the specificity of what
    is inside it - so that selector counts FOUR classes and a plain
    `.tbl.totals tbody td:first-child` counts three. It lost, silently, and the
    labels stayed centred while the stylesheet said they were left. Matching the
    count is what makes the later rule the winning one.  */
.tbl.totals tbody td:first-child:not(.r) { text-align: left; }

/*  AND A PERCENTAGE BOX IS THE SIZE OF A PERCENTAGE. 7.5rem was one width for
    every box in the panel - right for CASH, which takes six figures and a
    decimal, and absurd for GST %, which takes "3". A box far wider than
    anything that can go in it reads as a box somebody has not finished
    filling in.  */
.tbl.totals .tiny {
    width: 7.5rem;
    padding: 2px 6px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.tbl.totals .pct { width: 4rem; }

#totals .actions { margin-top: 10px; }
#totals .ok  { color: var(--ok); }
#totals .bad { color: var(--bad); }

/* ──────────────────────────────────────────────────────────────── a dialog ── */
/*
    A customer who is not on file is created WITHOUT LEAVING THE BILL - a
    modal, never a browser prompt and never a separate screen.
*/
dialog {
    max-width: 40rem;
    width: calc(100vw - 3rem);
    padding: 18px 20px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--raised);
    color: var(--ink);
}

dialog::backdrop { background: rgb(0 0 0 / .62); }

/*  THE CORNER CLOSE, on every dialog (site.js puts it there). The heading
    keeps out of its way; the footer button that only closed is gone.  */
dialog { padding-top: 22px; }
dialog h3 { padding-right: 2.4rem; }
dialog .dlg-x {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 30px;
    height: 30px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--sunken);
    color: var(--ink-soft);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
}
dialog .dlg-x:hover { color: var(--ink); border-color: var(--line-strong); }
dialog .dlg-closer { display: none; }
dialog h3 { margin: 0 0 12px; font-size: 1.15rem; }
dialog .row { margin-bottom: 8px; }

/* ═══════════════════════════════════════════ a row of fields, ANYWHERE ══ */
/*
    `.row` and `.actions` were written as `.editor .row` and `.editor .actions`,
    which is right until a screen puts a row of fields somewhere that is not an
    editor - and then every field claims a full line, because a `.field` is a
    flex COLUMN and nothing was making them sit side by side.

    That is exactly what happened to the sale bill's header: eleven boxes, one
    per line, and a till that needed scrolling before a single line was keyed.
    Same lesson as `.check` and `.theme-pick` before it - if two shells render
    it, it is not the panel's.

    The `.editor` rules above still exist and still win where they apply; these
    are the same shape for everywhere else.
*/
.row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.row > .field { flex: 1 1 180px; min-width: 0; }
.actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

.shell .row { gap: 8px; }

/* ═════════════════════════════════════════════════ the bill, made tight ══ */
/*
    A TILL USES THE WIDTH OF THE TILL. The operator wants the lines on screen,
    not a form: the header is reference material they read once and the grid is
    where the work happens, so the header gives up its air first.
*/
.billhead .field { flex: 0 1 9.5rem; }
.billhead .field.wide { flex: 1 1 14rem; }
/*  THE HEAD OF A BILL WAS THE SMALLEST TYPE ON THE SCREEN (23 Sep 2026).

    It tightened itself twice over: the shell takes a size off everything, and
    then this took another off the head - so the customer's name, the mobile
    and the day's rate, which are the first six things keyed on every bill,
    ended up smaller than the register tables nobody types into.

    The padding stays tight, because the head must not push the grid down the
    page. Only the writing grew.  */
.billhead input, .billhead select { padding: 4px 7px; font-size: .88rem; }
.billhead .field > span, .billhead label > span.lbl { font-size: .84rem; }
.billhead .row { gap: 6px 8px; margin-bottom: 6px; }
.billhead .row:last-child { margin-bottom: 0; }
.shell .billhead.card { padding: 8px 10px; }

/*  Prev, Next and New belong on one line at the end of the header, not stacked
    down the side of it.  */
.billhead .actions { gap: 6px; }
.billhead .actions .btn { padding: 4px 10px; }

/* ────────────────────────────────────────── the grid's columns, sized ── */
/*
    BY THE COLUMN'S KEY, NEVER BY ITS POSITION.

    These were written as nth-child, which is fine for exactly one grid and
    wrong the moment there are two: the purchase grid has ten columns where the
    sale bill has twenty, so every width landed on its neighbour - Unit came out
    as wide as an item name, and Item came out a stub.

    Every cell already carries data-col for the hide-a-column setting, so that
    is what sizes them too. A grid with a different set of columns gets the
    right widths for the ones it has, and one that gains a column next year does
    not shift the twelve after it.
*/
.tbl.grid { table-layout: fixed; width: 100%; }

.tbl.grid [data-col="group"]      { width: 7rem; }    /* a metal name can be DIAMOND */
.tbl.grid [data-col="kind"]       { width: 4rem; }
.tbl.grid [data-col="unit"]       { width: 4rem; }    /* gm or Pc, and the arrow beside it */
.tbl.grid [data-col="weight"]     { width: 5.2rem; }
.tbl.grid [data-col="less"]       { width: 4.4rem; }
.tbl.grid [data-col="lesspct"]    { width: 3.6rem; }
.tbl.grid [data-col="net"]        { width: 4.8rem; }
.tbl.grid [data-col="rate"]       { width: 6.8rem; }
.tbl.grid [data-col="labunit"]    { width: 4.2rem; }
.tbl.grid [data-col="labpcs"]     { width: 4.2rem; }
.tbl.grid [data-col="labrate"]    { width: 4.8rem; }
.tbl.grid [data-col="labour"]     { width: 5.4rem; }
.tbl.grid [data-col="wastagepct"] { width: 4rem; }
.tbl.grid [data-col="wastage"]    { width: 5.2rem; }
.tbl.grid [data-col="other"]      { width: 4.6rem; }
.tbl.grid [data-col="stamp"]      { width: 4.6rem; }
.tbl.grid [data-col="purity"]     { width: 5.4rem; }
.tbl.grid [data-col="amount"]     { width: 6.6rem; }

/*  ── THE ITEM CELL TAKES THE SLACK; THE ITEM BOX DOES NOT ──
    The owner's ruling of 5 Sep 2026, looking at a sale bill whose item box ran
    half the width of the screen: *"reduce item input text"*.

    ITEM IS THE ONLY COLUMN WITH NO WIDTH, on purpose - `table-layout: fixed`
    hands whatever is left over to the cells that did not ask for a size, and
    something has to absorb it or the table stops short of the window. That part
    is right and stays.

    WHAT WAS WRONG IS THAT THE INPUT GREW WITH IT. A shop with half its columns
    switched off left ten spare rem in the row, all of it inside one text box,
    and a box that wide reads as the most important thing on the line when it is
    a name. So the CELL still stretches and the BOX stops at a sensible width.

    IT IS max-width AND NOT width, so the box still shrinks below it when every
    column is on and the row is tight - which is the case this grid is really
    built for.  */
.tbl.grid [data-col="item"] input { max-width: 15rem; }

/*  ══════════════════════════ suggesting an item name as it is typed ══ */
/*
    The owner's ruling of 5 Sep 2026: *"also do item name suggestion here"*.

    ═══ WHY NOT THE <datalist> THAT WAS ALREADY THERE ═══

    There has been one on that box since the bill was built, and it is why the
    request reads as a bug rather than a feature: a datalist matches from the
    START of the option. Typing "ring" offers nothing at all when the master
    holds "Gents ring" and "Ladies ring 22K" - which is most of what a jeweller
    would type, because the useful word is almost never the first one.

    It also cannot be driven from the keyboard consistently, cannot be styled,
    and on a till the operator cannot see whether it is open. A picker on a
    keying grid has to answer "is there a list up, and what is highlighted"
    without anybody moving their eyes off the row.

    ═══ IT IS POSITIONED FIXED, AND THAT IS DELIBERATE ═══

    The grid sits inside a scrolling wrapper. A list absolutely positioned
    inside that wrapper is CLIPPED by it on the last row of a full bill - the
    suggestions would open below the visible area and be cut off exactly when
    the list is longest. Fixed takes it out of the wrapper's box entirely, and
    the script puts it under the input from a rect read at the moment it opens.

    THE PANEL IS A SIBLING OF THE PAGE, not of the row, for the same reason.
*/
.acbox {
    position: fixed;
    z-index: 90;
    min-width: 14rem;
    max-height: 15rem;
    overflow-y: auto;
    background: var(--field-bg);
    color: var(--field-ink);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
    padding: 3px;
}

.acbox[hidden] { display: none; }

.acbox .ac {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 4px 8px;
    border-radius: 5px;
    cursor: pointer;
    font-size: .84rem;
    line-height: 1.35;
    white-space: nowrap;
}

/*  THE HIGHLIGHT IS A BACKGROUND, NOT A BORDER. A border changes the row's
    height by two pixels, so the whole list shuffles as the arrow keys walk it
    and the eye loses its place.  */
.acbox .ac.on { background: var(--accent-soft); }

/*  WHAT THE ITEM WILL BRING WITH IT, beside its name - the metal and the
    making. Picking an item fills six boxes on the line, and an operator who
    cannot see which item carries what has to pick one to find out.  */
.acbox .ac .acsub {
    margin-left: auto;
    padding-left: 10px;
    font-size: .76rem;
    color: var(--ink-soft);
}

/*  A LIST WITH NOTHING IN IT STILL SAYS SO. Closing silently on a word the
    master has never seen reads as a picker that has stopped working - and the
    answer, on this bill, is that typing a new name is allowed and creates the
    item. So it says that.  */
.acbox .acnone {
    padding: 5px 8px;
    font-size: .8rem;
    color: var(--ink-soft);
}

/*  ══════════════════════════════════════════════ the wholesale grid ══ */
/*
    SIXTEEN COLUMNS THAT MUST FIT, because a bill that scrolls sideways is a
    bill whose Amount column cannot be seen while the Weight is being keyed -
    and those are the two figures an operator checks against each other.

    So every column is cut to the figure it actually holds and the widths are
    scoped to THIS grid: `data-col` names are shared with the retail sale bill,
    which has its own seventeen and its own reasons for their widths.

    THE ITEM TAKES WHAT IS LEFT. It is the only column whose content has no
    natural width, so it is the one that flexes - and it is deliberately not
    given a large minimum, because a long item name is served by the box
    GROWING AS IT IS TYPED rather than by a wide column sitting empty on every
    other row.
*/
/*  THE TABLE IS AS WIDE AS ITS COLUMNS, not as wide as the pane.

    Stretching it to 100% would spread the leftover space across every column
    and leave none to grow into. Sized to its columns, the space to the right
    of the grid IS the room a growing column takes - it can be seen before it
    is used, and while any of it is left the bill does not scroll sideways.  */
.tbl.grid.ws-grid { width: auto; }

/*  ═══════════════════════════════════ eighteen columns on any screen ═══ */
/*
    EVERY COLUMN IS A MULTIPLE OF ONE UNIT, so the whole grid can be scaled by
    changing that single figure. On a narrower screen the columns and the type
    come down together and the bill still shows Weight and Amount at once,
    which is the thing worth protecting - an operator checking a figure against
    the scales cannot do it through a scrollbar.

    THE STEPS, and what the grid comes to at each. The third column is what is
    left for it after the 13.5rem summary, the gap and the shell's padding -
    roughly the viewport less 258px while the panel is beside the grid, and
    less 28px once it has dropped underneath at 1100.

        screen    unit      grid     room      fits
        1920    1.00rem    1427px   1662px     yes, 235px spare to grow into
        1750    0.92rem    1313px   1492px     yes
        1600    0.86rem    1227px   1342px     yes
        1500    0.80rem    1142px   1242px     yes
        1440    0.80rem    1142px   1182px     yes
        1366    0.74rem    1056px   1108px     yes - the common laptop
        1300    0.70rem     999px   1042px     yes
        1150    0.63rem     899px    892px     within a few pixels
        1099    0.63rem     899px   1071px     yes - the panel is underneath

    THE BREAKPOINTS ARE SET WHERE THE GRID WOULD OTHERWISE OVERFLOW, not at
    round numbers. A step at 1300 would have left a 1366 laptop 91px short,
    which is a scrollbar on the most ordinary screen there is.

    IT STOPS SHRINKING BEFORE IT STOPS BEING READABLE. Under about 1100px the
    honest answer is that eighteen columns do not belong on the screen, and
    `.tblwrap` scrolls the grid inside its own box - the page itself never
    scrolls sideways, and the summary beside it never moves.
*/
.tbl.grid.ws-grid { --wsu: 1rem; --wsf: .8rem; }

@media (max-width: 1750px) { .tbl.grid.ws-grid { --wsu: .92rem; --wsf: .77rem; } }
@media (max-width: 1600px) { .tbl.grid.ws-grid { --wsu: .86rem; --wsf: .74rem; } }
@media (max-width: 1500px) { .tbl.grid.ws-grid { --wsu: .80rem; --wsf: .71rem; } }
@media (max-width: 1400px) { .tbl.grid.ws-grid { --wsu: .74rem; --wsf: .68rem; } }
@media (max-width: 1300px) { .tbl.grid.ws-grid { --wsu: .70rem; --wsf: .66rem; } }
@media (max-width: 1150px) { .tbl.grid.ws-grid { --wsu: .63rem; --wsf: .63rem; } }

.tbl.grid.ws-grid input,
.tbl.grid.ws-grid select { font-size: var(--wsf); }

/*  THE HEADING IS READ FIRST AND READ OFTEN, so it is set ABOVE the figures
    rather than under them - the owner's word, 2 Sep 2026: *"make Grid Header
    Slightly Large and Bold for betetr visbility."*

    It was 94 per cent of the box's own type, which on a 0.7rem unit put the
    label below the size it was labelling. A heading smaller than its column is
    a heading the eye skips on the way to the figure, and this grid has
    eighteen of them to tell apart.

    THE EXAMPLE UNDER IT DOES NOT GROW WITH IT - `.chint` keeps its own size and
    its normal weight, so the label gets the emphasis and the example stays the
    quiet second line it was meant to be.  */
.tbl.grid.ws-grid th { font-size: calc(var(--wsf) * 1.08); font-weight: 700; }

/*  A HEADING MAY TAKE TWO LINES rather than push its column wider. "Tunch+Wst"
    over a box that holds 99+99 is a heading longer than the figure under it,
    and the figure is what the column is for.  */
.tbl.grid.ws-grid th { white-space: normal; line-height: 1.2; }

.tbl.grid.ws-grid [data-col="no"]      { width: calc(var(--wsu) * 2.2); }
/*  WIDE ENOUGH FOR "Silver" AND ITS ARROW. A select that clips its own longest
    option - "Sil" - is a box the operator has to open in order to read, on the
    one column that must be read first.

    THE MINIMUM IS STATED AS WELL AS THE WIDTH, because a fixed-layout table
    will still shrink a column that another one is holding open by its
    min-width. That is exactly what was happening here: the item column carries
    `min-width: 11rem` from the sale bill's rules, and this grid's narrower
    `width` alone did not undo it.  */
.tbl.grid.ws-grid [data-col="group"]   { width: calc(var(--wsu) * 7); min-width: calc(var(--wsu) * 7); }

/*  The select fills its cell and must not be squeezed under the word it has to
    show.  */
.tbl.grid.ws-grid select { min-width: calc(var(--wsu) * 5.4); }

/*  THE ITEM IS THE COLUMN WITH SLACK IN IT, so it is the one that gives when
    the eighteen have to fit. Long enough for PAYAL, NATHIYA, KACHHI and the
    rest of the shop's own words; a longer name still types and the box
    scrolls, which costs nothing, where a column pushed off the screen costs
    the operator the figure it held.  */
/*  WIDER, INTO THE SPARE ROOM (29 Oct 2026, the owner: "item name is not
    visible completely" - "pendent D-0", "breslet D-(" on a mixed gold/silver
    bill). 8.5 units held about ten letters; a name and its design number is
    thirteen or more. The extra comes out of the room to the right of the grid
    that the table above keeps spare, so each step takes only what its
    narrowest screen has:

        step     unit    item   grid + extra    room at the step's narrowest
        1920     1.00    13     1427 +  72      1662 (1920)
        1750     0.92    13     1313 +  66      1492 (1750)
        1600     0.86    13     1227 +  62      1342 (1600)
        1500     0.80    11.5   1142 +  38      1182 (1440)
        1400     0.74    12     1056 +  41      1108 (1366)
        1300     0.70    11.5    999 +  34      1042 (1300)
        1150     0.63     8.5   as before - already within a few pixels

    A name longer still types, and the full name shows on hover.  */
.tbl.grid.ws-grid { --wsi: 13; }
@media (max-width: 1500px) { .tbl.grid.ws-grid { --wsi: 11.5; } }
@media (max-width: 1400px) { .tbl.grid.ws-grid { --wsi: 12; } }
@media (max-width: 1300px) { .tbl.grid.ws-grid { --wsi: 11.5; } }
@media (max-width: 1150px) { .tbl.grid.ws-grid { --wsi: 8.5; } }
.tbl.grid.ws-grid [data-col="item"]    { width: calc(var(--wsu) * var(--wsi)); min-width: 0; }
.tbl.grid.ws-grid [data-col="cash"]    { width: calc(var(--wsu) * 4.4); }
.tbl.grid.ws-grid [data-col="weight"]  { width: calc(var(--wsu) * 5.4); }   /* 1350.000 fits */
.tbl.grid.ws-grid [data-col="paper"]   { width: calc(var(--wsu) * 4.8); }
.tbl.grid.ws-grid [data-col="boxout"]  { width: calc(var(--wsu) * 4.8); }
.tbl.grid.ws-grid [data-col="less"]    { width: calc(var(--wsu) * 4.6); }

/*  NO SPINNERS IN A GRID - AND NOW NOWHERE AT ALL.

    A number box keeps two little arrows on the right, and they take about a
    sixth of a narrow column - which is why 12.321 was showing as "12.32" with
    the last digit under the arrows. Nobody has ever nudged a gold weight up by
    ones, and the keyboard is faster than the mouse for the ones who might.

    THIS RULE USED TO LIVE HERE, scoped to this one grid. On 4 Sep 2026 the
    owner asked for it everywhere - *"throughout project numeric input disable
    up down arrow"* - so it moved to the form-field section at the top of this
    file and the copy that was here is gone. Two rules doing one job is one that
    gets fixed and one that does not.  */
.tbl.grid.ws-grid [data-col="net"]     { width: calc(var(--wsu) * 5); }
/*  JUST 99+99, which is the widest tunch and wastage the trade quotes. Five
    characters, and the box carries its own floor because the six-character one
    every other box has would hold this column open a character too wide.  */
.tbl.grid.ws-grid [data-col="tunch"]   { width: calc(var(--wsu) * 3.7); }
.tbl.grid.ws-grid .w-tw { min-width: 5ch; }
.tbl.grid.ws-grid [data-col="pclab"]   { width: calc(var(--wsu) * 5.4); }
.tbl.grid.ws-grid [data-col="labrate"] { width: calc(var(--wsu) * 4.6); }
.tbl.grid.ws-grid [data-col="labour"]  { width: calc(var(--wsu) * 5); }
.tbl.grid.ws-grid [data-col="gold"]    { width: calc(var(--wsu) * 5.4); }
.tbl.grid.ws-grid [data-col="silver"]  { width: calc(var(--wsu) * 5.4); }
.tbl.grid.ws-grid [data-col="del"]     { width: calc(var(--wsu) * 2); }

/*  GOLD AND SILVER ARE THE ANSWER THE BILL EXISTS FOR.

    Every other column is something keyed or something on the way; these two
    are what the party owes in metal, and they are what the operator reads back
    down the screen. So the pair is set apart - ruled off from the working,
    heavier, and each metal in its own colour: GOLD ON ORANGE, SILVER ON WHITE.

    THE COLOUR IS THE METAL, which is why the two differ here and nowhere else
    on the screen. The eye finds the gold column without reading the heading,
    and on a bill that carries both metals at once that is most of the work.

    LIGHT ON EVERY THEME, and the ink is set with them. These two cells are
    read the way a field is read, and the shop's dark themes must not turn the
    figures they exist for into dark grey on orange.  */
.tbl.grid.ws-grid [data-col="gold"],
.tbl.grid.ws-grid [data-col="silver"] {
    font-weight: 600;
    color: #1A1408;
}

.tbl.grid.ws-grid [data-col="gold"] {
    background: #F7C978;
    border-left: 2px solid var(--line);
}

.tbl.grid.ws-grid [data-col="silver"] {
    background: #FFFFFF;
    border-right: 2px solid var(--line);
}

/*  The headings keep the colours, so the band reads top to bottom as one
    column rather than as a stripe that starts under the label.  */
.tbl.grid.ws-grid thead th[data-col="gold"],
.tbl.grid.ws-grid thead th[data-col="silver"] { color: #1A1408; }

.tbl.grid.ws-grid thead th[data-col="gold"] .chint,
.tbl.grid.ws-grid thead th[data-col="silver"] .chint { opacity: .75; }

.tbl.grid.ws-grid tbody td[data-col="gold"],
.tbl.grid.ws-grid tbody td[data-col="silver"] { font-size: .84rem; }

/*  A CASH ROW TINTS ITSELF, and it must not repaint the two metal cells - they
    are empty on a cash line and an orange cell that says nothing is a cell
    somebody looks at twice.  */
.tbl.grid.ws-grid tbody tr.is-cash td[data-col="gold"],
.tbl.grid.ws-grid tbody tr.is-cash td[data-col="silver"] { background: var(--accent-soft); }
/*  A BHAV IS SIX DIGITS - 125000 - and never more, so the column is cut to
    six and no wider. The space it gives up goes to the item name.  */
.tbl.grid.ws-grid [data-col="rate"]    { width: calc(var(--wsu) * 4.6); }
.tbl.grid.ws-grid [data-col="amount"]  { width: calc(var(--wsu) * 6.4); }

/*  EVERY BOX HOLDS ITS ORDINARY FIGURE WITHOUT GROWING: six characters, which
    is 12.123 in a weight and 70+5 in a tunch. Stated in `ch` - the width of a
    digit in the box's own font - so it holds whatever the shop's theme does to
    the type. The columns above are all wider than this; it is the floor that
    proves it, not the thing that sets it.  */
.tbl.grid.ws-grid input { min-width: 6ch; }

/*  THE WHOLESALE PANEL IS NARROWER THAN THE SALE COUNTER'S.

    Every rupee it shows is a rupee not shown to the grid, and this grid has
    eighteen columns to fit. Three and a half rem come off the pane and go to
    the bill, which is where the keying happens; the panel is read once a line
    and the grid is read on every box.

    The figures are set a shade smaller with it, so a lakh still fits on one
    line rather than wrapping - a summary that wraps is taller than the grid it
    sits beside and looks like the more important half.  */
/*  FIFTEEN REM, NOT THIRTEEN AND A HALF. It was cut to 13.5 to give the grid
    room, and that was too far: a metal column has to hold -548.000 and the
    money column 291,644.38 on the same line, and at 13.5 they ran into each
    other. A panel whose figures collide is worth less than the rem and a half
    it saves.  */
.panes.bill.ws-panes { grid-template-columns: minmax(0, 1fr) 15rem; }

/*  ══════════════════════════════════ the screen is the bill ══ */
/*
    TWO PANES THAT FILL WHAT IS LEFT OF THE WINDOW, top to bottom. The height
    is set in the script, measured from where the panes actually begin, because
    the strip above them changes height with the party's address and a figure
    guessed here would be wrong on half the bills.

    THE SUMMARY IS WHOLE, ALWAYS. It is the three balances the bill exists to
    move, and a panel that had to be scrolled to would be read once at the
    start and never again. It gets the full height of the right-hand side; if
    it ever outgrows that, it scrolls inside itself and the grid never moves.

    THE GRIDS SHARE THE LEFT, sale over jama and in that proportion - three
    parts to two. Each scrolls INSIDE ITS OWN BOX, so the headings stay put and
    the total row at the foot of each stays where it was: the two things an
    operator looks up at and down to while keying.

    Below 1100 the panel drops underneath and the lock is taken off in the
    script - a stacked layout with a fixed height is a layout with a hole
    in it.
*/
.panes.bill.ws-panes { align-items: stretch; }
.panes.bill.ws-panes > * { min-height: 0; }

/*  A GRID IS AS TALL AS ITS LINES, AND IT NEVER SCROLLS INSIDE ITSELF.

    `flex: 0 0 auto` - take exactly the height the rows need and give none of
    it back. A line added to the sale grid pushes the jama grid, the bhav strip
    and the buttons down the page, and the page grows with them.

    IT WAS BUILT TO SHRINK AND SCROLL FIRST, each grid boxed to a share of the
    window with its own scrollbar. That is wrong for a bill: a wholesale bill
    is READ DOWN, from the first sale line to what is left on the account, and
    three little scrolling windows make an operator hunt for a line they can
    see the edge of. One page that gets longer is what a bill does on paper.

    THE HORIZONTAL SCROLL STAYS. `.tblwrap` keeps its own sideways scroll for a
    narrow screen; with the box now as tall as its contents, the vertical one
    can never appear.  */
.ws-panes .ws-sale,
.ws-panes .ws-jama,
.ws-panes .ws-bhav { flex: 0 0 auto; }

/*  THE SUMMARY STAYS WITH THE OPERATOR AS THE BILL GETS LONGER.

    The left side now grows down the page, so the panel is stuck to the top of
    the window rather than to the top of the bill: key the twentieth sale line
    and the three balances are still beside it. It scrolls inside itself only
    if it is ever taller than the window.  */
.ws-panes .ws-right {
    min-height: 0;
    position: sticky;
    top: .5rem;
    max-height: calc(100vh - 1rem);
    overflow-y: auto;
}

/*  NO STICKY HEADINGS HERE ANY MORE. They were for grids that scrolled inside
    themselves; the grids now grow with their lines and the page scrolls
    instead, so a heading pinned to the top of a box that never scrolls only
    risks lifting itself over the row above it.

    ═══ EACH GRID'S HEADING CARRIES ITS OWN COLOUR ═══

    Green for the sale, pink for the jama, blue for the bhav - the owner's
    rule of 1 Sep 2026. The three grids are the same eighteen columns three
    times over, and on a long bill the heading is the only thing that says
    which one the eye has landed in. A colour does that in the moment it takes
    to look up; a word has to be read.

    THE TINT IS ON THE HEADING ONLY, not the rows. Three washed tables would
    fight each other and the metal pair, which is the colour that means
    something on every row.

    LIGHT ON EVERY THEME, with the ink pinned to match - the shop's dark themes
    would otherwise put faint grey lettering on a pale green band.  */
.ws-panes .ws-sale thead th { background: #E3F2E4; color: #2F4034; }
.ws-panes .ws-jama thead th { background: #FBE3EC; color: #46303B; }
.ws-panes .ws-bhav thead th { background: #E1ECFA; color: #2C3A4A; }

/*  The metal pair keeps its own colours through all three - a heavier selector
    than the bands above, on purpose.  */
.ws-panes .ws-bhav thead th[data-col="gold"] { background: #F7C978; color: #1A1408; }
.ws-panes .ws-bhav thead th[data-col="silver"] { background: #FFFFFF; color: #1A1408; }

/*  The metal pair keeps its colours through the sticky heading - the rule
    above is one selector heavier than the one that painted them, and a gold
    column that lost its orange at the top would stop being a band.  */
.ws-panes .ws-sale thead th[data-col="gold"],
.ws-panes .ws-jama thead th[data-col="gold"] { background: #F7C978; color: #1A1408; }

.ws-panes .ws-sale thead th[data-col="silver"],
.ws-panes .ws-jama thead th[data-col="silver"] { background: #FFFFFF; color: #1A1408; }

/*  THE PANEL IS TOLD ITS WIDTH; ITS TABLES HAVE TO BE TOLD TOO.

    A table sizes itself to its contents unless it is stopped, so four columns
    of figures inside a 13.5rem pane simply grew past it - and what stuck out
    was the AMOUNT column, which is the one the pane exists to show. Worse, it
    pushed the PAGE wide enough to scroll, which is the one thing this screen
    must never do.

    `table-layout: fixed` with `width: 100%` makes the columns share what there
    is instead of demanding what they want. The label column takes a third and
    wraps - "Brought forward" over two lines is ordinary - and the three figures
    divide the rest.  */
.panes.bill.ws-panes .tbl.sum,
.panes.bill.ws-panes .tbl.totals {
    table-layout: fixed;
    width: 100%;
}

.panes.bill.ws-panes .tbl.sum td,
.panes.bill.ws-panes .tbl.sum th,
.panes.bill.ws-panes .tbl.totals td,
.panes.bill.ws-panes .tbl.totals th {
    padding: 4px 3px;
    font-size: .72rem;
}

/*  ONLY THE LABEL MAY BREAK MID-WORD. "Brought forward" over two lines is
    ordinary; WEIGHT broken into WEIGH / T is a heading nobody can read, and
    that is what `anywhere` did when it was set on every cell.  */
.panes.bill.ws-panes .tbl.sum td:first-child,
.panes.bill.ws-panes .tbl.totals td:first-child { overflow-wrap: anywhere; }

/*  THE MONEY COLUMN IS THE WIDE ONE. A metal reads -548.000 at its worst and
    the money 2,91,644.38 at its ordinary - so the four columns are not equal,
    and the label gives up what the amount needs. Stated column by column
    because `table-layout: fixed` shares evenly otherwise, and evenly is what
    made the figures overlap.  */
.panes.bill.ws-panes .tbl.sum tr > :nth-child(1),
.panes.bill.ws-panes .tbl.totals tr > :nth-child(1) { width: 20%; }

.panes.bill.ws-panes .tbl.sum tr > :nth-child(2),
.panes.bill.ws-panes .tbl.sum tr > :nth-child(3),
.panes.bill.ws-panes .tbl.totals tr > :nth-child(2),
.panes.bill.ws-panes .tbl.totals tr > :nth-child(3) { width: 24%; }

.panes.bill.ws-panes .tbl.sum tr > :nth-child(4),
.panes.bill.ws-panes .tbl.totals tr > :nth-child(4) { width: 32%; }

/*  Figures never wrap and never overlap: they are one line each, and the
    column is sized for the longest one that belongs in it.  */
.panes.bill.ws-panes .tbl.sum .mono,
.panes.bill.ws-panes .tbl.totals .mono {
    white-space: nowrap;
    font-size: .76rem;
}

/*  THE PANEL'S HEADINGS GIVE UP THEIR LETTER-SPACING. Nine hundredths of an em
    on every character is what turned WEIGHT into WEIGH and NET WT. into a
    clipped stub - the spacing is set for headings that have a column to
    themselves, and these have a third of thirteen rem between three of them.
    They wrap instead.  */
.panes.bill.ws-panes .tbl thead th {
    letter-spacing: 0;
    white-space: normal;
    font-size: .6rem;
}

/*  CASH RECEIVED AND CASH PAID STACK rather than sit side by side. Two money
    boxes across 13.5rem gives each about five characters, and a box that
    cannot show what was keyed into it is worse than one below the other.

    SCOPED TO THE RIGHT-HAND PANE AND NOTHING ELSE. Written against the whole
    of `.ws-panes` it also caught the party strip - which is now inside these
    panes - and stood Party, Mobile, Address, Bill no., Date and Settle in a
    column six boxes tall, pushing the grids off the screen.  */
.panes.bill.ws-panes .ws-right .row { flex-wrap: wrap; }
.panes.bill.ws-panes .ws-right .field { flex: 1 1 100%; min-width: 0; }
.panes.bill.ws-panes .ws-right input { max-width: 100%; }

/*  THE PARTY LIST HANGS OVER THE BILL, it does not push it down.

    In the flow it was a block between the strip and the grids, so every
    keystroke that changed the number of matches moved the sale grid, the jama
    grid and the bhav strip down the screen - and choosing a name moved them
    all back up again. On a screen locked to the window that also re-measured
    the panes on every letter typed.

    Lifted out and hung under the party box: four or five names over the top of
    the grid for as long as it takes to pick one, and nothing else moves.  */
.panes.bill.ws-panes .editor { position: relative; }

.panes.bill.ws-panes .hits {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 60;
    width: min(32rem, 100%);
    margin-top: 2px;
    box-shadow: 0 8px 22px rgb(0 0 0 / .22);
}

/*  THE PARTY STRIP IS ONE ROW. It is the head of the bill and it is read
    across - party, mobile, address, number, date, how it settles - and it must
    not take height from the grids under it.

    THE ROOM GOES WHERE THE WORDS ARE. A mobile is ten digits, a bill number is
    a short code and a date is a date: each of those is a box of known size and
    a wide one is just empty space. A party's name and an address have no
    length at all - they are as long as the party is - so they take what the
    fixed three do not, and the address takes the most because it is the
    longest thing on the strip and the one a bill is carried by.  */
.panes.bill.ws-panes .editor .row { flex-wrap: nowrap; gap: 8px; }

.panes.bill.ws-panes .editor .f-party   { flex: 2 1 10rem; }
.panes.bill.ws-panes .editor .f-address { flex: 3 1 14rem; }

.panes.bill.ws-panes .editor .f-mobile  { flex: 0 0 7.5rem; }   /* ten digits */
.panes.bill.ws-panes .editor .f-billno  { flex: 0 0 7.5rem; }
.panes.bill.ws-panes .editor .f-date    { flex: 0 0 9.5rem; }   /* and its picker */
.panes.bill.ws-panes .editor .f-settle  { flex: 0 0 7.5rem; }

/*  THE OPENING BOXES IN THE NEW-PARTY POPUP. Three of them across one row, and
    each holds a weight in 00.000 or an amount - so they are sized for the
    figure rather than for the label above them, and they are equal because a
    reader compares them down the row.  */
#party-add .f-open { flex: 1 1 8rem; }
#party-add .f-open input { text-align: right; }

/*  TIGHTER ROWS IN THE PANEL. These tables are read, not keyed, and there are
    five rows of three figures in each; the sale bill's roomier spacing put
    more air between the balances than there is figure, and pushed the Save
    button under them off the foot of the window.  */
.panes.bill.ws-panes .tbl.sum td,
.panes.bill.ws-panes .tbl.sum th,
.panes.bill.ws-panes .tbl.totals td,
.panes.bill.ws-panes .tbl.totals th { padding: 2px 3px; line-height: 1.25; }

.panes.bill.ws-panes .card-head { margin-bottom: 2px; }
.panes.bill.ws-panes .note { margin: 4px 0 0; }
.panes.bill.ws-panes .field { margin-top: 4px; }
.panes.bill.ws-panes > .ws-right { gap: 8px; }

/*  SAVE TAKES THE WHOLE WIDTH OF THE PANEL. It is the one thing on this side
    that is pressed rather than read, and a button that fills its column cannot
    be missed or half-hit.  */
.btn.btn-wide { display: block; width: 100%; text-align: center; }

/*  A last line of defence: whatever else is put in this pane later, it is
    clipped to the pane rather than allowed to widen the page.  */
.panes.bill.ws-panes .card { padding: 10px; overflow: hidden; min-width: 0; }

@media (max-width: 1100px) {
    .panes.bill.ws-panes { grid-template-columns: minmax(0, 1fr); }
}

/*  THE TOTAL ROW IS READ, NOT KEYED, and it should look it: a tint behind it
    and the figures in bold. It is the line the operator checks against the
    scales and against the party's own reckoning, so it must be findable
    without counting rows up from the bottom.  */
.tbl.grid.ws-grid tfoot tr.is-sum td {
    background: var(--sunken);
    font-weight: 700;
    border-top: 2px solid var(--line);
}

/*  THE HEADING CARRIES AN EXAMPLE. Several columns take something other than a
    plain number - a rate in a unit that is not obvious, a percentage of
    something, a sum - and one line of grey under the label is the shortest way
    to say which: on every row, rather than in a tooltip nobody hovers over or
    a manual nobody opens.

    EVERY GRID, not just the wholesale one. This was scoped to `.ws-grid`, so
    when the retail sale and purchase headings gained their own examples on
    2 Sep 2026 the spans rendered as ordinary text beside the label instead of
    as a quiet second line - which is worse than no hint, because it makes the
    heading itself hard to read.  */
.tbl.grid th .chint {
    display: block;
    font-weight: 400;
    font-size: .71rem;
    line-height: 1.25;
    /*  .62 was a whisper on top of an already faint ink - the example under
        "Unit" or "Less" could not be read at all across a counter (23 Sep
        2026). It is still the quieter line; it is now a readable one.  */
    opacity: .85;
    letter-spacing: 0;
    text-transform: none;
}

/*  A heading may take two lines rather than push its column wider - true of
    every grid that carries an example under the label.  */
.tbl.grid th:has(.chint) { white-space: normal; line-height: 1.2; }

/*  THE COLUMN GROWS WITH WHAT IS TYPED IN IT, AND THE ROW SHIFTS.

    PAPER holds "1*1.123+2*0.210" and PC x LAB holds "10*50+20*30", and neither
    column can be that wide on every row - the grid would scroll and the
    figures that are read against each other would come apart.

    IT WAS TRIED AS AN OVERLAY FIRST, the box lifting out over its neighbours,
    AND THAT WAS WRONG: what it lifted over were the boxes still to be keyed,
    so the operator lost sight of the very controls being worked towards. A
    grid is keyed left to right and nothing may cover what is to the right.

    So the COLUMN widens and everything after it moves along, and the room
    comes out of the ITEM column, which is the one with slack in it. The table
    keeps its width, so the bill still does not scroll sideways - and when the
    box is cleared the column goes back to what it was.

    The widening is done in the script, which is where the measuring is; this
    is only the transition that keeps the shift from being a jump.  */
.tbl.grid.ws-grid th,
.tbl.grid.ws-grid td { transition: width .12s ease-out; }

/*  Measures a box's contents without being seen. One of it, off the page.  */
.ws-ruler {
    position: absolute;
    top: -9999px;
    left: -9999px;
    white-space: pre;
    visibility: hidden;
}

/*  THE KEYS, said once at the top of the screen rather than on a help
    screen nobody opens - one line, read twice in the first week.  */
.kbd-hint { font-size: .74rem; margin-left: .6rem; }

/*  ITEM TAKES WHAT IS LEFT. It is the only column whose content has no natural
    width - a name is as long as the piece is - so it is the one that flexes.  */
.tbl.grid [data-col="item"] { width: auto; min-width: 11rem; }

/*  The delete button's column, which has no key because it is not a column of
    the document - it is a control.  */
.tbl.grid th:last-child, .tbl.grid td:last-child { width: 2.2rem; }

/*  The derived cells are read, never keyed, so they are the loud ones: a
    jeweller checks Net wt and Amount down the column and nothing else.  */
.tbl.grid .c-net, .tbl.grid .c-amount { font-weight: 600; }
.tbl.grid .c-amount { font-size: .84rem; }

/*  The summary is a NARROW COLUMN ON THE RIGHT, not half the screen. It is a
    short list of figures - fifteen labels and fifteen numbers - and giving it
    an equal half only stretched the gap between the two until the eye had to
    travel to pair them up. A fixed width also means it does not move when the
    bill list beside it grows.  */
.panes.bill { grid-template-columns: minmax(0, 1fr) 17rem; align-items: start; }

.panes.bill .tbl.totals .tiny { width: 6.5rem; }

@media (max-width: 1100px) {
    .panes.bill { grid-template-columns: minmax(0, 1fr); }
}

/*  MAXIMISED. The 1680px column is a reading measure and the sale bill is not
    read, it is keyed: nineteen columns, and every one of them a jeweller wants
    on screen at once. A screen sets ViewData["Wide"] and gets the window.  */
.wrap.shell.wide { max-width: none; padding: 0 12px; }

/* ═══════════════════════════════════════════════════════════ full screen ══ */
/*
    A SCREEN THAT IS KEYED, NOT READ. The sale bill has nineteen columns and an
    operator who wants the lines in front of them - not a menu they know by
    heart and a bar telling them which shop they are standing in.

    The chrome is RENDERED AND HIDDEN rather than left out, and that is the
    whole design: Escape brings it back at once, with no reload and without
    losing a bill that is half keyed. A mode that had to reload to leave would
    be one nobody dared press.
*/
body.fullscreen .topbar { display: none; }
body.fullscreen main,
body.fullscreen main:has(.shell) { padding: 0; min-height: 100vh; }

body.fullscreen .shell {
    grid-template-columns: minmax(0, 1fr);
    max-width: none;
    gap: 0;
    padding: 8px 12px;
}

body.fullscreen .shell > nav.menu { display: none; }

/*  The way out. Fixed, because in full screen there is no bar for it to sit
    in and it must never be the thing somebody has to scroll to find.  */
.fullbar {
    /*  It exists only while there is something to exit FROM. Rendered always so
        the class change alone switches the mode, hidden until it means
        something - a way out of a place you are not in is a puzzle.  */
    display: none;
    position: fixed;
    top: 6px;
    right: 8px;
    z-index: 60;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    background: var(--raised);
    color: var(--ink-soft);
    font: inherit;
    font-size: .74rem;
    cursor: pointer;
    opacity: .55;
}

body.fullscreen .fullbar { display: inline-flex; }

/*  AND THE PAGE HEAD MAKES ROOM FOR IT.

    The pill is FIXED at the top right. On the bill there is a `.docbar` above
    the heading which already reserves 190px for it, so nothing collided and
    nobody noticed. The PURCHASE has no step bar, so no docbar is rendered, the
    heading is the first thing on the page - and Preview and Reset sat directly
    under the pill, all three unreadable and two of them unclickable.

    THE COLLISION MUST NOT DEPEND ON WHETHER SOME OTHER ELEMENT HAPPENS TO BE
    THERE. So the room is reserved on the head itself, and given back only when
    a docbar above it has already reserved it.

    THE ORDER OF THESE TWO IS THE FALLBACK. A browser without :has() keeps the
    first rule, and the bill's buttons simply sit 190px further left - which is
    tidy rather than broken. The other way round would leave the collision.  */
body.fullscreen .pagehead { padding-right: 190px; }
body.fullscreen:has(.docbar) .pagehead { padding-right: 2px; }

.fullbar:hover { opacity: 1; color: var(--ink); border-color: var(--accent); }

.fullbar kbd {
    padding: 0 4px;
    border: 1px solid var(--line-strong);
    border-radius: 3px;
    font-family: var(--mono);
    font-size: .74rem;
}

/*  A button that reads as part of a sentence, for a hint line.  */
.linkish {
    border: 0;
    padding: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

/* ────────────────────────────────────────────── the bill's two modes ── */
/*
    AUTO MAKING. The line is priced and the making charge is worked back from
    it, so the Amount cell is the one that is TYPED and the making rate is the
    one that is read. Ordinary mode is the other way round, and the grid says
    which is which by what it lets you into.
*/
.tbl.grid .c-target { display: none; }

.tbl.grid.is-auto .c-target { display: block; width: 100%; }

/*  Under the priced figure: what the line is actually worth once the GST
    inside it is taken out. The customer pays the figure above; the books carry
    the one below, and a jeweller asked to explain the bill needs both.  */
.tbl.grid.is-auto .c-amount-shown {
    display: block;
    margin-top: 1px;
    font-size: .76rem;
    color: var(--ink-faint);
}

/*  DERIVED, so it is read and not keyed. The box the operator owns is put
    away while auto mode is on rather than written into - a mode that edits the
    other mode's boxes leaves its figures behind when it is switched off, and a
    making rate of minus a hundred brought a line to nought that way.  */
.tbl.grid .c-labshown { display: none; }

.tbl.grid.is-auto .c-labrate { display: none; }

.tbl.grid.is-auto .c-labshown {
    display: block;
    text-align: right;
    font-family: var(--mono);
    font-size: .8rem;
    color: var(--ink-soft);
    padding: 3px 2px;
}

.tbl.grid.is-auto .c-labunit {
    pointer-events: none;
    opacity: .55;
    background: var(--sunken);
}

/*  Priced below the metal on it. Said on the row, where the mistake is, before
    the save refuses the whole bill.  */
.tbl.grid tr.is-short .c-target,
.tbl.grid tr.is-short .c-amount-shown { color: var(--bad); }

/*  THE MELT-LOSS COLUMN BELONGS TO OLD METAL ALONE. It appears when a line is
    Old and goes again when the last one leaves, so a shop that takes no old
    metal never sees a column it has no use for.  */
.tbl.grid.no-old [data-col="lesspct"] { display: none; }

/*  The unit the rate box wants, per row - gold is quoted per 10 gm and silver
    per kg, they share a column, and the two figures look identical.  */
.tbl.grid .c-rateunit {
    display: block;
    font-size: .70rem;
    color: var(--ink-faint);
    text-align: right;
    line-height: 1;
}

/*  ── HOW THIS ROW'S MAKING WAS WORKED OUT ──
    The owner's ruling of 5 Sep 2026: "pcs x rate change based on unit gm / pc /
    % selection".

    IT SITS UNDER THE FIGURE, in the same shape as the rate box's unit note
    above and for the same reason: the heading stands over twenty rows that may
    each be charged a different way, so only the row can say which. "pcs x rate"
    used to be printed in the heading over gram lines and percentage lines
    alike.

    FAINT AND SMALL, because it is a note about the figure and not the figure.
    A working the same weight as the number it explains competes with it in a
    column somebody is scanning for money.  */
.tbl.grid .c-labhow {
    display: block;
    font-size: .70rem;
    color: var(--ink-faint);
    text-align: right;
    line-height: 1;
    white-space: nowrap;
}

/*  Two buttons in one cell must not wrap onto two lines.  */
.tbl .nowrap { white-space: nowrap; }
.tbl .nowrap .btn { padding: 2px 8px; font-size: .76rem; }

/*  The three things a shop sets up, side by side. A picker hidden in a
    dropdown is one nobody finds, and somebody who does not know there are three
    formats will set up one and wonder why the other did not change.  */
.tabs { display: flex; flex-wrap: wrap; gap: 8px; }

.tabs .tab {
    display: block;
    flex: 1 1 12rem;
    padding: 8px 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--sunken);
    color: var(--ink-soft);
    text-decoration: none;
}

.tabs .tab b { display: block; color: var(--ink); }
.tabs .tab .muted { font-size: .76rem; }
.tabs .tab:hover { border-color: var(--line-strong); }

.tabs .tab.on {
    border-color: var(--accent);
    background: var(--accent-soft);
    box-shadow: inset 3px 0 0 var(--accent);
}

/*  AN ICON THAT IS A BUTTON. Three words in every row of a list is more reading
    than the figures beside them, so the row's actions are icons - each with a
    title on hover and a label for a screen reader, because an icon on its own
    is a rebus somebody has to guess.  */
.iconbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 24px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--ink-soft);
    cursor: pointer;
}

.iconbtn:hover {
    border-color: var(--line-strong);
    background: var(--sunken);
    color: var(--ink);
}

.iconbtn .ico { width: 15px; height: 15px; }

/*  Cancelling is the one that cannot be undone by clicking again, so it says so
    on the way to being pressed rather than only afterwards.  */
.iconbtn.is-bad:hover { color: var(--bad); border-color: var(--bad); }

/*  READ ALOUD, NEVER SEEN. The label inside an icon button, and the one beside
    a bare tickbox in a settings table.

    It was being used in three places before it was defined anywhere, which
    means those labels were printing as loose words next to the icons rather
    than being hidden. Clipped rather than `display: none`, because a screen
    reader skips what is not displayed - and the whole point is that it is read.
*/
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/*  THE AMOUNT BOX IS KEYABLE ON MORE THAN AUTO MODE.

    New, auto  the line is priced and the making charge is worked back from it
    Old        the metal is AGREED - a shop weighs the chain, looks at it and
               says a number, and the weight is recorded beside it
    Cash       the figure is the whole line

    In every one of those the figure is a judgement somebody made, which is why
    it is typed rather than derived - and why it sits in the Amount column,
    where a reader looks for it.  */
.tbl.grid tr.is-old .c-target,
.tbl.grid tr.is-cash .c-target { display: block; width: 100%; }

/*  What the line actually comes to, under what was keyed - they differ on an
    auto line carrying GST, and a jeweller asked to explain the bill needs both. */
.tbl.grid tr.is-old .c-amount-shown,
.tbl.grid tr.is-cash .c-amount-shown {
    display: block;
    margin-top: 1px;
    font-size: .76rem;
    color: var(--ink-faint);
}

/*  A LINE THAT CAME OFF A TAG. Marked, because the difference matters: a
    tagged line is a particular ring with a cost and a history, and an untagged
    one is a description somebody typed.  */
.tbl.grid tr.is-tagged [data-col="item"] { box-shadow: inset 3px 0 0 var(--ok); }

/*  The scan box sits with the line buttons, and is the width of a tag.  */
#scan-wrap input {
    width: 9rem;
    font-family: var(--mono);
    font-size: .82rem;
}

/* ──────────────────────────────────── a grid with room to spare ── */
/*
    A TEN-COLUMN GRID IS A DIFFERENT LAYOUT PROBLEM FROM A NINETEEN-COLUMN ONE.

    In a fixed-layout table the one column left on `auto` absorbs every pixel
    the others do not use. On the sale bill that is right - nineteen columns
    leave little over, and the item name should have it. On the purchase entry
    it is wrong: nine narrow columns left the Item box EIGHT HUNDRED PIXELS
    wide, a single input stretched across half the screen with the rest of the
    row huddled at the far end.

    So a grid that knows it has room says so. The item name gets a generous but
    BOUNDED width, and the slack goes to the column at the end that holds
    nothing but the delete button - where empty space is simply empty space.
*/
.tbl.grid.grid-roomy [data-col="item"] { width: 24rem; }

.tbl.grid.grid-roomy th:last-child,
.tbl.grid.grid-roomy td:last-child { width: auto; }

/* ══════════════════════════════════════════════ the palette swatches ══ */
/*
    THE ONE PLACE IN THIS APPLICATION ALLOWED TO NAME A COLOUR TWICE.

    Everywhere else a component reads --accent and gets whatever the current
    theme says. A swatch cannot: it has to show MEENAKARI'S gold while the page
    is wearing ASSAY, and a custom property only ever holds one answer at a
    time - the current theme's.

    So each swatch carries its own two colours, copied from the theme block
    above. They are a PICTURE OF a palette rather than a use of one, which is
    why this does not break the rule the top of this file sets out.

    If a theme's ground or accent changes up there, change it here too. Nothing
    will break if you forget - the swatch will simply be a small lie.
*/
.sw-meenakari { --sw-ground: #0F3833; --sw-accent: #E8A33D; }
.sw-assay     { --sw-ground: #F4F5F6; --sw-accent: #1F4E79; }
.sw-sindoor   { --sw-ground: #FBF7F0; --sw-accent: #5C1A24; }
.sw-showroom  { --sw-ground: #14110E; --sw-accent: #E0B872; }

/* ═══════════════════════════════════════════ receipt: which way the money ══ */
/*
    TWO CARDS, NOT A DROPDOWN. Which way the money went is the one thing on that
    screen that must be read without thinking, and a select showing "Receipt"
    looks identical to a select showing "Payment" at arm's length across a
    counter. Getting it wrong moves a customer's due by twice the amount.
*/
.sides { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }

/*  A HEADLINE FIGURE WITH ITS TWO HALVES UNDER IT. Used where a total is
    worth reading before the table - the fine outstanding sheet, where the
    number somebody wants is "how much of my gold is out".  */
.sum-card {
    flex: 1 1 220px;
    display: grid;
    gap: 2px;
    align-content: start;
    padding: 12px 14px;
}

.sum-card .k { color: var(--muted); font-size: .82rem; }
.sum-card .big { font-size: 1.35rem; line-height: 1.2; }
.sum-card .muted { font-size: .8rem; }

.side {
    flex: 1 1 220px;
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    gap: 2px 12px;
    align-items: center;
    padding: 14px 16px;
    background: var(--raised);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    cursor: pointer;
}

.side-ico { grid-row: 1 / span 2; color: var(--ink-faint); }
.side-ico .ico { width: 26px; height: 26px; }

.side b { font-size: 1.05rem; }
.side span:last-child { font-size: .82rem; color: var(--ink-soft); }

.side.is-on {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent);
    background: var(--accent-soft);
}

.side.is-on .side-ico { color: var(--accent); }

/*  Keyboard focus has to be visible on the CARD, not on the hidden radio.  */
.side:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/*  The amount is the figure the whole screen is about.  */
input.big { font-size: 1.25rem; font-weight: 500; }

/*  WHAT WILL BE LEFT, worked out as the amount is keyed - the question a
    customer asks while the receipt is being written.  */
.willbe {
    margin: 4px 0 0;
    padding: 10px 14px;
    background: var(--sunken);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    font-size: .95rem;
}

.willbe b { color: var(--accent); }

/*  A cancelled row is evidence, not a mistake to hide - so it stays legible
    and simply reads as struck.  */
tr.is-dead td { opacity: .55; text-decoration: line-through; }
tr.is-dead .pill { text-decoration: none; }

/* ═══════════════════════════════════════════════════ a register ══ */
/*
    A BOOK, NOT A LIST. The purchase register runs forwards in days, each day a
    block with its own foot - which is what a jeweller means by a register, and
    what makes it checkable against a vendor's statement a day at a time.

    THE DAY BAR IS A HEADING INSIDE THE TABLE, so the columns stay in step down
    the whole page. Separate tables per day would let each one size its columns
    to its own figures, and a register whose columns move between days cannot
    be read down.
*/
tr.daybar > th {
    padding: 10px 8px 4px;
    background: var(--sunken);
    border-top: 1px solid var(--line-strong);
    font-size: .82rem;
    font-weight: 700;
    text-align: left;
    letter-spacing: .01em;
}

tr.daybar > th .muted { font-weight: 400; }

/*  The day's own figures: marked, but quieter than the page's foot - one is a
    subtotal and the other is the answer.  */
tr.daysum > th {
    padding: 5px 8px 9px;
    border-bottom: 1px solid var(--line-strong);
    font-size: .82rem;
    font-weight: 600;
    color: var(--ink-soft);
    white-space: nowrap;
}

/*  A REGISTER IS READ ACROSS, so the figures are held together: monospace
    columns of one width, and nothing wraps mid-row.  */
.tbl.reg td, .tbl.reg th { white-space: nowrap; }
.tbl.reg td .muted { font-size: .78rem; }

@media print {
    /*  A day must not be split across a page break where it can be helped -
        a block whose foot is on the next sheet is a subtotal nobody can see
        what belongs to.  */
    .tbl.reg tbody { break-inside: avoid; }
    tr.daybar > th { background: none; }
}

/*  A RULE BETWEEN THE PRIMARY HEADS on a trial balance. Read as one long list
    it is a list nobody finds anything in.  */
tr.grp-row td {
    padding-top: 14px;
    border-bottom: 1px solid var(--line-strong);
    color: var(--accent);
    font-size: .82rem;
    letter-spacing: .06em;
    text-transform: uppercase;
}

/* ══════════════════════════════════════════════ ON PAPER: content only ══ */
/*
    WHAT PRINTS IS THE DOCUMENT, NOT THE SCREEN IT WAS READ ON.

    A day book printed with the menu down its left, the sign-out button at the
    top and a Print button in the middle of it is a screenshot, not a report.
    Nobody files a screenshot, and the columns that matter end up squeezed into
    two thirds of the page to make room for navigation that means nothing on
    paper.

    So printing takes away everything that is a CONTROL and keeps everything
    that is CONTENT. The rule for deciding which is which: if it does something
    when you click it, it does nothing on paper.

    THE FIGURES GO BLACK ON WHITE whatever palette the shop works in. Meenakari
    is gold on jade and reads beautifully on a screen; on a laser printer it is
    a grey rectangle, and on an inkjet it is an afternoon's worth of ink.
*/
.printhead { display: none; }

@media print {
    /* ------------------------------------------------- the chrome goes --- */
    .topbar,
    .footer,
    .menu,
    .drawer-toggle,
    .fullbar,
    .filters,
    .actions,
    .hits,
    .shopswitch,
    .signout,
    dialog,
    .btn,
    .iconbtn,
    .pagehead .hint,
    .card-head .spacer {
        display: none !important;
    }

    /*  Anything the screen needs and the paper does not.  */
    .no-print { display: none !important; }

    /*  A dialog left open would print over the report.  */
    dialog[open] { display: none !important; }

    /* ------------------------------------------ the page is the paper --- */
    html, body {
        background: #FFFFFF !important;
        color: #000000 !important;
    }

    /*  The shell is a two-column layout with a menu in the first column. With
        the menu gone the column would still be there, holding the report to
        two thirds of the sheet.  */
    .shell,
    .shell.wide,
    .wrap,
    .panes,
    .panes.bill {
        display: block !important;
        max-width: none !important;
        width: auto !important;
        margin: 0 !important;
        padding: 0 !important;
        grid-template-columns: none !important;
    }

    .shell-main { min-width: 0 !important; }

    /*  THE BALANCE SHEET KEEPS ITS TWO COLUMNS ON PAPER. Everything else is
        unstacked for print because a screen layout wastes a sheet; this one IS
        the layout - liabilities left, assets right, the two totals on one
        line.  */
    .bsheet {
        display: grid !important;
        grid-template-columns: 1fr 1fr !important;
        gap: 8mm !important;
    }

    /*  A card is a thing lifted off a background. On paper there is no
        background to lift it off, so it is a heading and a table.  */
    .card {
        background: none !important;
        border: 0 !important;
        box-shadow: none !important;
        padding: 0 !important;
        margin: 0 0 10mm !important;
        break-inside: auto;
    }

    .card-head {
        border: 0 !important;
        padding: 0 0 2mm !important;
    }

    .card-head h2 { font-size: 1.05rem; }

    /* ---------------------------------------------- what the paper says --- */
    /*  Shown only here: the shop, the report and when it was run. On screen
        the bar says the first and the heading says the second; on paper
        neither is printed, and a sheet of figures with no name and no date on
        it is a sheet somebody has to ask about.  */
    .printhead {
        display: flex !important;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 4mm;
        margin-bottom: 4mm;
        padding-bottom: 2mm;
        border-bottom: 1px solid #000;
    }

    .printhead b { font-size: 1.1rem; }
    .printhead span { font-size: .8rem; }
    .printhead .mono { margin-left: auto; }

    .pagehead h1 { font-size: 1.25rem; margin: 0 0 3mm; }

    /* ------------------------------------------------------ the tables --- */
    .tblwrap {
        overflow: visible !important;
        border: 0 !important;
    }

    /*  THE TABLE MUST FIT THE SHEET.

        On screen a wide table scrolls inside its own box. On paper there is
        nowhere to scroll to: the table simply makes the PAGE wider than the
        paper, and the browser answers by cropping the left-hand columns - which
        is how a ledger prints with its dates and voucher numbers missing.

        So in print nothing is nowrap and everything may break. A wrapped
        narration over two lines is readable; a date column that is not on the
        sheet is not.  */
    .tbl {
        width: 100% !important;
        max-width: 100% !important;
        border-collapse: collapse !important;
        font-size: 9pt;
        table-layout: auto !important;
    }

    .tbl th,
    .tbl td,
    .nowrap,
    .tbl .nowrap {
        white-space: normal !important;
        overflow-wrap: anywhere;
    }

    /*  And nothing anywhere may push the page wider than the paper.  */
    html, body, main, .shell-main, .tblwrap, .card {
        overflow: visible !important;
        max-width: 100% !important;
    }

    .tbl th,
    .tbl td {
        border-bottom: 1px solid #999 !important;
        padding: 1.6mm 2mm !important;
        background: none !important;
        color: #000 !important;
    }

    .tbl thead th {
        border-bottom: 1px solid #000 !important;
        background: none !important;
    }

    /*  A HEADER ROW ON EVERY SHEET. A trial balance runs to three pages and
        the second one is unreadable without its column names.  */
    .tbl thead { display: table-header-group; }
    .tbl tfoot { display: table-footer-group; }

    /*  A row must not be split across two sheets.  */
    .tbl tr { break-inside: avoid; }

    /*  Struck through on screen by opacity, which prints as grey mush.  */
    tr.is-dead td {
        opacity: 1 !important;
        text-decoration: line-through !important;
    }

    /*  The pills and the coloured words: the ink is not worth it, but the
        WORD is - "Cancelled", "Sale", "Receipt" all carry meaning.  */
    /*  EVERYTHING BLACK, said once on the container rather than class by class.

        The first attempt named .muted, .mono, .ok and .bad - and missed
        whichever class the next screen introduces. On paper there is no such
        thing as a figure that should be gold: the whole point of a printed
        report is that it survives a laser printer and a photocopier.  */
    .shell-main,
    .shell-main * {
        color: #000 !important;
        background: none !important;
        box-shadow: none !important;
    }

    /*  Said again after the sweep above, because the sweep would otherwise
        take the outline off the one thing that needs one.  */
    .pill { border: 1px solid #666 !important; }

    /*  A notice is content when it is the answer - "the books agree" is the
        whole point of a trial balance - so it prints, in outline.  */
    .notice {
        border: 1px solid #000 !important;
        background: none !important;
        color: #000 !important;
        padding: 2mm 3mm !important;
    }

    @page { margin: 12mm; }
}

/* ══════════════════════════════════════════════════════ the balance sheet ══ */
/*
    TWO COLUMNS OF EQUAL WIDTH, liabilities left and assets right. It is the
    shape every balance sheet in the trade is read in, and the two totals must
    end up on the same line - a reader checks that they agree by looking across,
    not by scrolling.

    The first attempt borrowed the bill screen's layout, which is a wide grid
    beside a narrow summary panel, and put the whole of the assets side into a
    column meant for totals.
*/
.bsheet {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: stretch;
}

@media (max-width: 900px) {
    .bsheet { grid-template-columns: 1fr; }
}

/*  BOTH SIDES THE SAME HEIGHT, so the two totals sit on one line however many
    ledgers each side happens to have. The table stretches, the empty space
    falls in the middle, and the feet line up.  */
.bsheet .card { display: flex; flex-direction: column; }
.bsheet .tblwrap { flex: 1; display: flex; }
.bsheet .tbl { width: 100%; height: 100%; }

/*  A group heading, and its ledgers under it. The heading carries the figure a
    reader adds up; the ledgers under it are the detail, quieter.  */
.bsheet .tbl tbody tr td:first-child b { font-size: .98rem; }

/*  THE RULE ABOVE THE TOTAL, which is what makes it a total rather than
    another row.  */
.bsheet .tbl tfoot th {
    border-top: 2px solid var(--line-strong);
    font-size: 1.02rem;
    padding-top: 12px;
}

.bsheet-profit {
    margin: 14px 0 0;
    padding: 12px 16px;
    background: var(--sunken);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
}

.bsheet-profit b { color: var(--accent); }

/* ═══════════════════════════════════════════════════ the wholesale bill ══ */
/*
    TWO GRIDS: metal out and metal back. They are the same arithmetic with the
    sign turned round, and they are shown apart because a jeweller reads them
    apart - the owner's own screen colours them differently for the same
    reason.
*/
.jama-h { color: var(--second); }

.tbl.is-jama thead th { border-bottom-color: var(--second); }

/*  A BOX THAT WILL NOT PARSE. The Less and Labour boxes take arithmetic, and a
    sum that is not one has to say so where it was typed - not on save, after a
    screenful of keying.  */
input.is-wrong {
    border-color: var(--bad) !important;
    outline: 1px solid var(--bad);
}

/*  THE SUMMARY: gold, silver and money side by side, in every block. A
    wholesale party has three balances and a panel showing one figure would be
    answering a question nobody asked.  */
.tbl.sum { width: 100%; }
.tbl.sum td, .tbl.sum th { padding: 6px 8px; }

.tbl.sum tr.is-sum td {
    border-top: 1px solid var(--line-strong);
    font-weight: 500;
}

.tbl.sum tr.is-final td {
    border-top: 2px solid var(--accent);
    font-size: 1.02rem;
}

.tbl.sum tr.is-final .mono { color: var(--accent); }

/*  The bhav row is the one line on the screen that prices everything below
    it.  */
.bhav-row {
    padding: 10px 12px;
    background: var(--sunken);
    border-radius: var(--radius-sm);
}

/* ═════════════════════════════════ prev and next, on every transaction ══ */
/*
    NOT NAMED `.steps`. It was, and `landing.css` - which loads AFTER this
    sheet - owns `.steps` for the landing page's numbered list. The bar
    inherited a grid meant for cards and stacked itself down the screen on
    every transaction page. A class name is shared across every stylesheet the
    page loads, so a name this generic was always going to be claimed twice.
*/

/*  PREV LEFT, THE NUMBER BETWEEN THEM, NEXT RIGHT - the owner's rule of
    1 Sep 2026. The number is a BOX rather than loose text: it is the thing
    being read, and the arrows are the things being clicked.  */
.docnav {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    gap: 6px;
}

.docnav-no {
    /*  Wide enough for SL/26-27/0004 and no wider, so the arrows either side
        of it never move as the number changes.  */
    min-width: 9rem;
    padding: 1px 8px;
    text-align: center;
    font-size: .8rem;
    line-height: 1.5;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--sunken);
}

.docnav-last { padding: 1px 9px; font-size: .74rem; }

/*  AT THE END OF THE BOOK THE ARROW STAYS PUT, greyed rather than hidden: a
    control that vanishes makes the two either side of it move, and somebody who
    has learned where to click has to look again.  */
.iconbtn.is-off { opacity: .35; pointer-events: none; }

/*  The heading and anything sitting beside it on one line.  */
.head-line { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.head-line h1 { margin: 0; }

/*  IN FULL SCREEN THERE IS NO HEADER, so the bar gets one - AS SHORT AS IT CAN
    BE. Every pixel here is a pixel off the grid, which is the thing the screen
    is actually for. It takes up flow space rather than floating: a bar that
    covers the first line of a grid is a bar somebody has to scroll past.  */
.docbar { display: none; }

body.fullscreen .docbar {
    display: flex;
    align-items: center;
    position: sticky;
    top: 0;
    z-index: 60;
    min-height: 0;
    padding: 3px 10px;
    /*  Room for the exit pill, which is fixed and would otherwise sit on top
        of the Latest button.  */
    padding-right: 190px;
    background: var(--raised);
    border-bottom: 1px solid var(--line);
}

/*  Small enough to belong to a bar rather than to the page.  */
.docbar .iconbtn { padding: 2px 5px; }
.docbar .iconbtn svg { width: 15px; height: 15px; }

/*  In the ordinary header the bar is a passenger beside the shop name, so it
    gives up a little more height again.  */
.topbar .docnav-no { min-width: 8.5rem; font-size: .78rem; }
.topbar .docnav-last { font-size: .72rem; }

/*  THE LINE UNDER A CASH BOX that says which way the money moved. Small, quiet
    and directly under the box it belongs to - the label says whose hand, this
    says what it does to the account.  */
.panes.bill.ws-panes .tiny-note {
    margin: 2px 0 6px;
    font-size: .72rem;
    line-height: 1.3;
}

/*  ═════════════════════════════════════════════════ the bhav strip ═══ */
/*
    A THIRD GRID, and deliberately not a fourth colour. Sale is plain, jama is
    red because metal is coming back, and the bhav strip is the account rather
    than the goods - so it is set off with a rule and a heading rather than a
    wash, which would make three loud tables where two already compete.
*/
.tbl.grid.ws-grid.is-bhav thead th { border-bottom-color: var(--accent); }

.bhav-h { color: var(--accent); }

.tbl.grid.ws-grid [data-col="brate"]   { width: calc(var(--wsu) * 5.4); }
.tbl.grid.ws-grid [data-col="bpure"]   { width: calc(var(--wsu) * 5.8); }
.tbl.grid.ws-grid [data-col="bamount"] { width: calc(var(--wsu) * 6.4); }
.tbl.grid.ws-grid [data-col="beffect"] { width: auto; min-width: calc(var(--wsu) * 9); }

/*  THE BOX THAT WAS WORKED OUT rather than keyed, and it should not look like
    somewhere to type. It stays a box because the moment it IS typed into, the
    row turns round and it becomes the keyed one.  */
.tbl.grid.ws-grid.is-bhav tr:not(.is-buy) .b-amt,
.tbl.grid.ws-grid.is-bhav tr.is-buy .b-gold,
.tbl.grid.ws-grid.is-bhav tr.is-buy .b-silver { background: var(--sunken); }

/*  WHICH WAY THE ROW GOES, said in words at the end of it - a sign in a column
    is read as a keying mistake far more often than as a direction.  */
.tbl.grid.ws-grid.is-bhav .b-says { font-size: calc(var(--wsf) * .92); white-space: nowrap; }
.tbl.grid.ws-grid.is-bhav tr.is-buy .b-says { color: var(--ok); }

/*  The 99.50 tick sits in the heading beside the button, not in a row of its
    own - it is one word about the whole strip.  */
.card-head .tick {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: .8rem;
    font-size: .74rem;
    color: var(--ink-faint);
}

.card-head .tick input { width: auto; margin: 0; }

/*  Gold and silver on their own lines in the bhav total - never added.  */
.tbl.grid.ws-grid.is-bhav .b-g,
.tbl.grid.ws-grid.is-bhav .b-s { display: block; line-height: 1.2; }

/*  ═══════════════════════════════════════════ the keys, at the top ═══ */
/*
    ONE LINE, SMALL AND GREY. Every shortcut the wholesale bill has, where it
    can be read BEFORE it is needed - which is the whole difference between a
    hint and a label. F3 opens the bhav strip, so its hint could never live on
    the bhav strip.

    It must not compete with the bill: after the first week it is furniture.
*/
.keys {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 14px;
    margin: -6px 0 8px;
    font-size: .78rem;
    color: var(--ink-faint);
}

.keys span { white-space: nowrap; }

.keys kbd {
    display: inline-block;
    min-width: 1.1rem;
    padding: 1px 4px;
    border: 1px solid var(--line-strong);
    border-bottom-width: 2px;
    border-radius: 3px;
    background: var(--raised);
    color: var(--ink);
    font: inherit;
    font-size: .74rem;
    text-align: center;
}

/*  THE GRID HEADINGS ARE COMPACT ON THIS SCREEN.

    A 1.45rem serif heading with 26px of padding and a rule under it is right
    for a card that holds one thing. Here there are three of them down one
    column, and between them they were taking the height of four keyed lines -
    on the screen where lines are the whole point.

    The heading still names the grid and the button still sits beside it; what
    goes is the air around them.  */
.ws-panes .card-head {
    align-items: center;
    gap: 8px;
    margin: 6px 0 2px;
    padding-bottom: 0;

    /*  NO RULE UNDER IT. The grid's own coloured heading band starts a pixel
        below and separates the two far better than a grey line - which was
        drawing a second boundary a few pixels above the real one.  */
    border-bottom: 0;
}

.ws-panes .card-head:first-child { margin-top: 0; }

.ws-panes .card-head h2 { font-size: .92rem; line-height: 1.2; }

/*  ADD A LINE IS THE MOST-PRESSED THING ON THE SCREEN, so it does not shrink
    with the heading beside it: bold and a shade larger than the label it sits
    against. It was cut to .72rem when the strip was compacted, which made the
    one control an operator reaches for the quietest thing in the row.

    The padding stays tight - the WEIGHT carries it, not the box.  */
.ws-panes .card-head .btn {
    padding: 2px 10px;
    font-size: .84rem;
    font-weight: 700;
}

.ws-panes .card-head .tick { margin-left: .4rem; font-size: .7rem; }

/*  EACH GRID HIDES THE COLUMN THAT IS NOT ITS BUSINESS.

    One row builder serves all three grids - the arithmetic is one set of rules
    and must stay one piece of code - so the cells that do not apply are hidden
    per grid rather than built differently. `table-layout: fixed` drops a
    hidden column's width entirely, and every total cell names its column, so
    the foot stays under the heading.

    THE SALE GRID HAS NO PURITY: metal going out is priced at its tunch and
    nothing further. THE JAMA GRID HAS NO RATE: metal coming back is taken to
    fine, and pricing it is what the bhav strip is for.  */
/*  ═══ THE THREE WINDOWS ═══

    Gold, silver, and both - the owner's ruling of 2 Sep 2026. It is a VIEW
    over one set of tables, so the whole of it is here: one class at the top of
    the screen turns off the other metal's column in both grids, in the bhav
    strip, in the summary and in the weight panel at once.

    HIDDEN, NOT REMOVED. Every cell keeps its id, so the script that fills them
    goes on finding what it looks for. A screen that removed them would need
    the script to know which window it was in, and the day somebody added a
    figure without checking is the day it threw on a null.  */
.ws-only-gold   [data-col="silver"],
.ws-only-gold   .m-silver { display: none; }

.ws-only-silver [data-col="gold"],
.ws-only-silver .m-gold   { display: none; }

/*  THE GROUP BOX HAS ONE METAL AND CASH IN A SCOPED WINDOW, so it needs far
    less room than the seven rem a DIAMOND once asked for.  */
.ws-only-gold   .tbl.grid.ws-grid [data-col="group"],
.ws-only-silver .tbl.grid.ws-grid [data-col="group"]
    { width: calc(var(--wsu) * 5); min-width: calc(var(--wsu) * 5); }

/*  ═══ WHAT EACH SCOPED WINDOW DOES NOT ASK FOR ═══
    The owner's ruling of 2 Sep 2026.

    GOLD HAS NO BOX OUT. Boxes are silver's - payal and anklets arrive in them
    and go back in them - and a gold bill has never had a figure to put there.
    The column comes off BOTH grids, and Less falls back to being the paper.

    AND NOTHING IS PRICED ON A GOLD LINE. The Rate column goes from the sale
    side as well as the jama side, so a gold bill carries its metal to fine and
    what gets priced is priced on the BHAV STRIP - which is where a tranche
    belongs anyway: at a rate agreed for a quantity, not line by line.  */
.ws-only-gold [data-col="boxout"],
.ws-only-gold [data-col="rate"] { display: none; }

/*  AND THE CAPTION STOPS SAYING "box" - the owner.s ruling of 4 Sep 2026,
    "remove label box from gold billing only, that will be Less only".

    The column above already says Less falls back to being the paper here. What
    it did not do was tell the HEADING: it went on reading "Less / paper + box"
    over a window with no box column in it, which is a caption naming a figure
    the operator cannot key and will never see. The word goes; the column and
    the arithmetic behind it are untouched, and on silver - which does have
    boxes - the working still reads in full.

    THE SELECTOR CARRIES THE GRID.S OWN CLASSES because the rule it has to beat
    is `.tbl.grid th .chint`, and a plainer `.ws-only-gold [data-col] .chint`
    loses to it on specificity by a single element name - which shows as the
    caption simply not going away.  */
.ws-only-gold .tbl.grid th[data-col="less"] .chint { display: none; }

/*  SILVER KEEPS ITS BOXES and loses the sale side's rate for the same reason
    gold does. The jama grid has never shown a rate on either window.

    BY THE WRAPPER'S CLASS, not by the grid's id. `.ws-sale` says which of the
    three grids this is without depending on a name that is unique to one page
    - which is what let the layout probe check this rule at all.  */
.ws-only-silver .ws-sale [data-col="rate"] { display: none; }

/*  ═══ A SCOPED GRID FILLS THE PANE ═══

    The mixed grid is `width: auto` on purpose: eighteen columns sized to their
    figures, with the gap to the right of Amount being the room a growing
    column takes. That is right when eighteen columns nearly fill the screen.

    TAKE FOUR COLUMNS OFF AND THE GAP STOPS BEING ROOM AND STARTS BEING A HOLE.
    The owner's words, 2 Sep 2026: *"input Box Can fit According to Screen Size
    After Amount Blank spaces are present."*

    So a scoped grid is stretched to its pane, and the room goes to the two
    columns that have a use for it.

    NOT TO THE ITEM. It took the lot at first and that was wrong - the owner's
    correction, 2 Sep 2026: *"Reduce Item Input Box And Manage Width to Paper
    and Labour."* An item description is a short phrase and four hundred pixels
    of box for it is four hundred pixels not given to the two columns that
    genuinely run out: PAPER holds "1*1.123+2*0.210" and PC x LAB holds
    "10*50+20*30", and those are the boxes the growing mechanism was built for.

    SO PAPER AND PC x LAB ARE THE FLEXIBLE ONES HERE, and the item is given a
    fixed width - roomier than the mixed grid's, because there is room, but a
    box and not a field.

    THE HAPPY CONSEQUENCE: with those two already wide enough for an ordinary
    working, they rarely need to grow at all, so the row stops shifting while
    it is keyed. The growing still works when a sum runs long.  */
.ws-only-gold   .tbl.grid.ws-grid,
.ws-only-silver .tbl.grid.ws-grid { width: 100%; }

    SHARED, NOT HANDED TO ONE. Given the slack outright, Paper and Pc x Lab
    came out at nearly two hundred pixels each for a box holding "1*2+2*3",
    which is the same mistake as the item's four hundred wearing a different
    hat. The three columns that are TYPED INTO rather than read take a
    proportion each, so none of them is a field with a figure lost in it.  */
.ws-only-gold   .tbl.grid.ws-grid,
.ws-only-silver .tbl.grid.ws-grid { table-layout: fixed; }

.ws-only-gold   .tbl.grid.ws-grid [data-col="item"],
.ws-only-silver .tbl.grid.ws-grid [data-col="item"]  { width: 13%; }

.ws-only-gold   .tbl.grid.ws-grid [data-col="paper"],
.ws-only-silver .tbl.grid.ws-grid [data-col="paper"] { width: 10%; }

.ws-only-gold   .tbl.grid.ws-grid [data-col="pclab"],
.ws-only-silver .tbl.grid.ws-grid [data-col="pclab"] { width: 11%; }

#sale-grid [data-col="pct99"] { display: none; }
#jama-grid [data-col="rate"]  { display: none; }

.tbl.grid.ws-grid [data-col="pct99"] { width: calc(var(--wsu) * 4.4); }

/*  ═══════════════════════════════════════════ the stock check ═══ */
/*
    THE TWO FIGURES A PERSON CAN ACTUALLY CHECK - what the scale should read,
    and how many boxes are on the shelf - set larger than everything around
    them. A stock screen is used standing at a shelf with a scale, and the
    figure being checked should be readable without leaning in.
*/
.checkpair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin: 6px 0 12px;
}

.checkpair > div {
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--sunken);
}

.checkpair .lbl {
    display: block;
    font-size: .74rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.checkpair .big {
    display: block;
    font-size: 1.6rem;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
}

.checkpair .muted { font-size: .72rem; }

@media (max-width: 700px) {
    .checkpair { grid-template-columns: 1fr; }
}

/*  A shortfall is red where it stands, not hidden - it is the figure that
    sends somebody to look for the missing purchase.  */
.tbl td.is-bad { color: var(--bad); font-weight: 600; }

@media print {
    /*  THE TWO CHECKABLE FIGURES SURVIVE THE PRINTER, and in ink rather than
        in a tint - a goods-received note is carried to the parcel on paper,
        and a background colour is the first thing a printer throws away.  */
    .checkpair > div {
        background: none;
        border: 1px solid #000;
        padding: 3mm 4mm;
    }

    .checkpair .big { font-size: 14pt; }
    .checkpair .lbl { color: #000; }
}

/* ═════════════════════════════════════════ the user menu, top right ══ */
/*
    THE OWNER'S RULING OF 5 Sep 2026: *"add top most right user icon where in
    show name, password change option, signout, financial year change"*.

    THE BAR HAD GROWN INTO A ROW OF LOOSE CONTROLS - a name, a shop picker, a
    year picker and a Sign out button, four things competing for the corner of
    every screen, and the two that mattered least were the widest. They are one
    thing: who am I, and where am I working.

    A <details> AND NOT A SCRIPT, the same as the menu groups and for the same
    reason: it works before the JavaScript has loaded and if it never does.
*/

.usermenu { position: relative; margin-left: auto; }

.usermenu > summary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--raised);
    color: var(--ink);
    cursor: pointer;
    list-style: none;
    font-size: .88rem;
    font-weight: 600;
    user-select: none;
}

.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu > summary:hover { border-color: var(--accent); color: var(--accent); }
.usermenu[open] > summary { border-color: var(--accent); }

.usermenu > summary svg { width: 18px; height: 18px; }

/*  THE NAME GOES ON A NARROW SCREEN AND THE ICON STAYS. A till is 1366 wide and
    a phone is not; the icon is what the owner asked for and the name is the
    part that can be given up.  */
@media (max-width: 700px) {
    .usermenu .who { display: none; }
}

/* ------------------------------------------------------- the panel --- */

.usermenu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);

    /*  ABOVE EVERYTHING THE PAGE HAS. The registers' sticky heading row sits at
        z-1 in the root context and painted straight through the menu rail's
        flyout on 4 Sep 2026 - the same trap, and this panel hangs over the same
        tables. 60 clears the sticky heading and the voucher list at 40.  */
    z-index: 60;

    min-width: 230px;
    padding: 6px;
    background: var(--raised);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow);

    /*  SHUT EXPLICITLY, and not left to the disclosure.

        A <details> hides its own contents, and this panel is `position:
        absolute` - out of flow, and the browser's hiding did not reach it: with
        the details CLOSED the panel measured 230 x 231 and was fully painted
        over the page. A menu that never closes.

        SO IT IS SAID HERE. `display: none` at rest and flex when open is the
        same shape the collapsed rail's flyout uses, and it does not depend on
        how any browser chooses to implement a shut disclosure.  */
    display: none;
    flex-direction: column;
    gap: 2px;
}

/*  AND ONLY WHEN IT IS OPEN.

    THE RAIL FLYOUT NEEDED `content-visibility: visible` because it is forced
    open by :hover on a <details> that is SHUT - a shut one hides its contents
    that way and nothing else overrides it. Copying that onto this panel's base
    rule defeated the disclosure outright: the menu was 230 x 231 and fully
    visible with the details closed, which is a menu that never closes.

    THE SAME PROPERTY, THE OPPOSITE MISTAKE. There it had to be overridden; here
    it is what does the hiding. It is scoped to [open] so the browser's own
    behaviour is left alone when shut - and the panel is positioned absolutely,
    so on the open state this only has to undo the skipping, not lay anything
    out.  */
.usermenu[open] .usermenu-panel { display: flex; content-visibility: visible; }

/*  WHO, AND WHERE. The name is repeated inside the panel rather than only on
    the button, because on a narrow screen the button shows an icon alone and
    the panel is then the only place it says whose account this is.  */
.usermenu-who {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 6px 10px 8px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 4px;
}

.usermenu-who .muted { font-size: .78rem; }

.usermenu-item {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--ink-soft);
    font: inherit;
    font-size: .88rem;
    font-weight: 600;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.usermenu-item:hover { background: var(--sunken); color: var(--ink); }

/*  SIGNING OUT IS THE ONE THAT ENDS THE SESSION, so it reads as the one that
    does something different. Not red - it is not a mistake to sign out - just
    set apart by a rule above it.  */
.usermenu-item.is-out {
    margin-top: 4px;
    border-top: 1px solid var(--line);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}

/*  THE TWO PICKERS SIT INSIDE THE PANEL and fill it, rather than keeping the
    narrow width they had in the bar. A select that is 9rem in a 230px panel is
    a control with a gap beside it for no reason.  */
.usermenu-panel .shopswitch { display: block; padding: 4px 6px; }
.usermenu-panel .shopswitch select { width: 100%; min-width: 0; }
.usermenu-panel .signout { display: block; }

/* ══════════════════════════ purchase against sale: three views ══ */
/*
    The owner's ruling of 5 Sep 2026 - a comparison report with a table, a bar
    chart and a pie.

    THE TABS ARE RADIOS AND `:checked ~`, not script. The same reason the menu
    groups are <details>: it works before the JavaScript has loaded and if it
    never does. Three labels and four rules is the whole mechanism.

    THE CHARTS ARE DIVS AND ONE INLINE SVG. No chart library - this product
    ships no third-party JavaScript, a till is often on a bad line, and a
    library that failed to load would take the report down with it. Bars are
    rectangles; a pie is three arcs.
*/

.cmp-tabs {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--line);
}

/*  THE RADIO ITSELF IS NOT DRAWN - the label is the tab. It stays in the DOM
    and focusable rather than `display: none`, so the three are still one group
    a keyboard can walk with the arrow keys.

    THEY SIT BESIDE THE PANES, not inside the tab bar: `:checked ~` is a GENERAL
    SIBLING selector and only reaches elements that share a parent with the
    input. Nested in the bar it matched nothing and every pane stayed hidden - a
    set of tabs with no content under them. So the selectors below are written
    against `.cmp > input`.  */
.cmp > input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    margin: 0;
}

.cmp-tabs label {
    padding: 5px 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    font-size: .88rem;
    font-weight: 600;
    color: var(--ink-soft);
    cursor: pointer;
    user-select: none;
}

.cmp-tabs label:hover { border-color: var(--accent); color: var(--accent); }

/*  AND THE ACTIVE TAB IS FOUND BY ITS `for`, because the label is no longer
    adjacent to its input. One rule per tab, which is three - the price of the
    markup that makes the panes work.  */
#v-table:checked ~ .cmp-tabs label[for="v-table"],
#v-bar:checked   ~ .cmp-tabs label[for="v-bar"],
#v-pie:checked   ~ .cmp-tabs label[for="v-pie"] {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent);
}

/*  A KEYBOARD MUST SEE WHERE IT IS. With the radio drawn at nothing, the label
    has to carry the focus ring or tabbing into this control is invisible.  */
#v-table:focus-visible ~ .cmp-tabs label[for="v-table"],
#v-bar:focus-visible   ~ .cmp-tabs label[for="v-bar"],
#v-pie:focus-visible   ~ .cmp-tabs label[for="v-pie"] {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ----------------------------------------------------- the panes --- */

/*  ALL THREE ARE IN THE PAGE and two are hidden - so switching costs no round
    trip and the printed copy can carry whichever was on screen.  */
.cmp-pane { display: none; }

#v-table:checked ~ #pane-table,
#v-bar:checked   ~ #pane-bar,
#v-pie:checked   ~ #pane-pie { display: block; }

/* ------------------------------------------------- the bar chart --- */

.cmp-legend {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 10px;
    font-size: .84rem;
}

.cmp-legend .muted { margin-left: auto; }

/*  A SWATCH, used by the legend, the bars and the pie key - one class so the
    three cannot drift into different colours for one series.  */
.sw {
    display: inline-block;
    width: 11px;
    height: 11px;
    border-radius: 2px;
    vertical-align: -1px;
    margin-right: 5px;
}

/*  OUT IS THE MONEY GREEN THIS PRODUCT ALREADY USES for an amount, IN is the
    metal red. A third series takes the accent. None of them is chosen for
    prettiness: they are the two colours every other screen here uses for the
    two directions.  */
.sw-out, .cmp-bar.sw-out, .cmp-pie .sw-out { background: var(--money-bg); fill: var(--money-bg); }
.sw-mid, .cmp-bar.sw-mid, .cmp-pie .sw-mid { background: var(--accent);   fill: var(--accent); }
.sw-in,  .cmp-bar.sw-in,  .cmp-pie .sw-in  { background: var(--bad);      fill: var(--bad); }

.cmp-plot {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 250px;
    padding: 0 4px 0;
    border-bottom: 1px solid var(--line-strong);
    overflow-x: auto;
}

.cmp-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    height: 100%;
    min-width: 44px;
}

.cmp-bars {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 210px;
}

/*  A BAR OF NOTHING IS STILL A BAR. `min-height` keeps a hairline where a
    period sold nothing, so the column reads as empty rather than as missing -
    which on a comparison is a real difference.  */
.cmp-bar {
    display: block;
    width: 14px;
    min-height: 2px;
    border-radius: 2px 2px 0 0;
}

.cmp-tick {
    margin-top: 6px;
    font-size: .74rem;
    color: var(--ink-faint);
    white-space: nowrap;
}

/* ------------------------------------------------- the pie chart --- */

.cmp-pie-wrap {
    display: flex;
    align-items: center;
    gap: 28px;
    flex-wrap: wrap;
    padding: 8px 0;
}

.cmp-pie { width: 240px; height: 240px; flex: 0 0 auto; }

/*  A HAIRLINE BETWEEN SLICES, in the page's own ground - two slices of similar
    colour meeting with no edge read as one.  */
.cmp-pie path, .cmp-pie circle { stroke: var(--raised); stroke-width: 1.5; }

.cmp-key { flex: 1 1 16rem; min-width: 0; }

.cmp-key-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 5px 0;
    border-bottom: 1px solid var(--line);
}

.cmp-key-name { flex: 1 1 auto; font-weight: 600; }

.cmp-key p { margin-top: 10px; font-size: .8rem; }

/*  PRINTED, THE TABS GO and whichever pane is showing prints on its own.  */
@media print {
    .cmp-tabs { display: none; }
}

/* ═══════════════════════════════════ the day's rate, in the top bar ══ */
/*
    The owner's ruling of 5 Sep 2026: *"show today rate on top bar button and
    rate value also"*.

    THE FIGURE AND THE WAY TO CHANGE IT ARE ONE CONTROL, so it is a link that
    looks like a button and reads like a strip of figures. A button that only
    opened the rate screen would make somebody click to find out what the rate
    is; a figure with no way in would make them hunt the menu to change it.
*/

.ratebar {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 4px 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--raised);
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}

.ratebar:hover { border-color: var(--accent); }
.ratebar > svg { width: 16px; height: 16px; color: var(--ink-faint); }

.ratebar .rate {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    font-size: .84rem;
}

/*  THE METAL'S SHORT NAME, quiet - it is the label and the figure is the
    point. "Gold 1,25,000" reads as one thing; two equal weights read as two.  */
.ratebar .rate-m {
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.ratebar .rate b { font-size: .92rem; font-weight: 700; }

/*  THE UNIT IS PART OF THE FIGURE. 92,000 means nothing without knowing
    whether it is a kilo or ten grams, and a jeweller reading the wrong one is
    off by a hundred.  */
.ratebar .rate-u { font-size: .7rem; color: var(--ink-faint); }

/*  ═══ A STALE RATE SAYS SO ═══

    A shop that has not keyed this morning still has a rate in force and the
    till still bills at something, so it is SHOWN rather than hidden - greyed,
    with its age beside it.

    A THREE-DAY-OLD FIGURE PRINTED PLAINLY under the word "today" is one the
    counter bills against without looking, and nothing else on the screen would
    ever say otherwise. The grey is the warning and the "3 d" is the evidence.  */
.ratebar .rate.is-old,
.ratebar .rate.is-old b { color: var(--ink-faint); font-weight: 500; }

.ratebar .rate-old {
    padding: 0 4px;
    border-radius: 3px;
    background: var(--warn-soft);
    color: var(--warn);
    font-size: .72rem;
    font-weight: 700;
}

/*  A TILL IS WIDE AND A PHONE IS NOT. Below the width where the bar starts to
    crowd, the rate goes - it is a convenience, and the menu still holds the
    screen that keys it.  */
@media (max-width: 1100px) {
    .ratebar .rate-u { display: none; }
}

@media (max-width: 860px) {
    .ratebar { display: none; }
}

/*  THE PUT-INTO-STOCK LINES (21 Sep 2026): the cross that takes a line off
    sits at the row's end, level with the boxes.  */
.editor .row.tight > .l-del { flex: 0 0 auto; align-self: flex-end; margin-bottom: 4px; }

/* ─────────────────────────────────────────────── a link to the copy ── */
/*  THE SHARE BOX (23 Sep 2026) - opened from the Share link button on a
    preview, over the preview, so nobody leaves the page. The link sits in a
    box of its own the full width, because it is the thing being handed on.  */
.sharebox { max-width: 34rem; }
.sharebox-url { display: flex; gap: 8px; margin: 10px 0 12px; }
.sharebox-url input {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    font-family: var(--mono);
    font-size: .85rem;
}
.sharebox .field input { width: 100%; }

/*  THE PAGE A CUSTOMER OPENS. The document and one line saying whose it is -
    and on a phone the sheet fits the width rather than asking to be scrolled
    sideways, which is how a bill is read on WhatsApp.  */
.shared-doc .sheet { max-width: 100%; overflow-x: auto; }
.shared-foot {
    display: flex;
    gap: 8px;
    max-width: 1240px;
    margin: 0 auto;
    padding: 10px 16px 24px;
    border-top: 1px solid var(--line);
    color: var(--ink-soft);
    font-size: .85rem;
}
.shared-foot .spacer { flex: 1 1 auto; }
.shared-gone { max-width: 34rem; margin: 12vh auto 0; padding: 24px; text-align: center; }
.shared-gone h1 { font-size: 1.3rem; margin: 0 0 10px; }

/* ═════════════════════════════════════════ the attractive dashboard ══ */
/*  The owner, 23 Sep 2026: "Make dashboard Attractive and easy to
    understand" (Wholesale/Dashboard.cshtml). Every colour is a theme token -
    metal gold, metal silver, money, ok, bad - so all four palettes carry it.

    QUICK LINKS ride under the heading; the two new-bill links are primary
    because they are what the screen is opened for.  */
.dash-quick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/*  HEADLINE CARDS - a coloured band down the left says what the figure is
    counted in before the label is read; the big number, then one plain line
    saying what it means, then the split underneath.  */
.dash-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; margin: 14px 0 18px; }
.dash-kpi {
    position: relative; display: grid; gap: 3px; align-content: start;
    padding: 16px 18px 14px 22px; overflow: hidden; text-decoration: none; color: var(--ink);
}
.dash-kpi::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 6px; background: var(--line-strong); }
.dash-kpi.is-gold::before   { background: var(--metal-gold); }
.dash-kpi.is-silver::before { background: var(--metal-silver); }
.dash-kpi.is-money::before  { background: var(--ok); }
.dash-kpi.is-plain::before  { background: var(--accent); }
.dash-kpi.is-gold   .dash-v { color: var(--metal-gold); }
.dash-kpi.is-silver .dash-v { color: var(--metal-silver); }
.dash-kpi.is-money  .dash-v { color: var(--ok); }
a.dash-kpi:hover { border-color: var(--accent); }
.dash-k { font-size: .76rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); }
.dash-v { font-size: 1.9rem; line-height: 1.15; font-weight: 700; }
.dash-v small { font-size: .55em; font-weight: 600; color: var(--ink-soft); }
.dash-s { font-size: .82rem; color: var(--ink-soft); }
.dash-foot { font-size: .8rem; color: var(--ink-faint); border-top: 1px dashed var(--line); padding-top: 6px; margin-top: 4px; }

/*  THE DAY AND THE MONTH AS TILES - an arrow for the way the metal moved
    (up and out on a sale, down and in on a purchase), rupees for the drawer.  */
.dash-flow { display: grid; grid-template-columns: repeat(auto-fit, minmax(175px, 1fr)); gap: 10px; }
.dash-tile {
    position: relative; display: grid; gap: 2px; align-content: start;
    padding: 12px 10px 12px 50px; border-radius: var(--radius-sm);
    background: var(--sunken); border: 1px solid var(--line); min-height: 74px;
}
.dash-tile b { font-size: .92rem; line-height: 1.3; white-space: pre-line; }   /* gold and silver on their own lines */
.dash-arrow {
    position: absolute; left: 12px; top: 12px; width: 32px; height: 32px; border-radius: 50%;
    display: grid; place-items: center; font-weight: 800; font-size: 1.05rem;
    background: var(--raised); border: 1px solid var(--line-strong); color: var(--ink-soft);
}
.dash-tile.is-out     .dash-arrow { color: var(--metal-gold); border-color: var(--metal-gold); }
.dash-tile.is-in      .dash-arrow { color: var(--ok); border-color: var(--ok); }
.dash-tile.is-cashin  .dash-arrow { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.dash-tile.is-cashout .dash-arrow { color: var(--bad); border-color: var(--bad); background: var(--bad-soft); }
.dash-tile.is-net     { background: var(--accent-soft); }
.dash-tile.is-net .dash-arrow { color: var(--accent); border-color: var(--accent); }

@media print { .dash-quick { display: none; } .dash-kpi::before { print-color-adjust: exact; -webkit-print-color-adjust: exact; } }

/*  The retail dashboard's two groups (Counter/Index.cshtml) and a red card
    for money going out.  */
.dash-group { font-size: 1.05rem; margin: 18px 0 -4px; color: var(--ink-soft); letter-spacing: .02em; }
.dash-kpi.is-bad::before { background: var(--bad); }
.dash-kpi.is-bad .dash-v { color: var(--bad); }
a.dash-kpi .dash-foot { color: var(--accent); }

/*  A TABLE NEVER WIDENS THE PAGE ON A PHONE (23 Sep 2026, the owner: "check
    once web application is fully mobile responsive"). Most tables sit in a
    .tblwrap that scrolls sideways; eleven views had one that did not (the
    policy pages, the preview sheets, the bill screens' side tables), and on a
    375px phone such a table made the WHOLE page scroll sideways - Data safety
    came out 559px wide. Under 700px a table outside a .tblwrap becomes its own
    sideways-scrolling block instead. Desk layouts are untouched.  */
@media (max-width: 700px) {
    :not(.tblwrap) > table.tbl,
    :not(.tblwrap) > table.stmt,
    .policy table { display: block; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/*  THE GOOGLE PLAY BADGE (Views/Shared/_PlayBadge.cshtml) - top and bottom of
    every screen, never in the menu. Black with white words on every theme,
    as a Play badge is everywhere; the icon alone in a phone's header bar.  */
.play-badge {
    display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto;
    padding: 5px 12px 5px 9px; border-radius: 8px; border: 1px solid #A6A6A6;
    background: #000; color: #fff; text-decoration: none; line-height: 1;
}
.play-badge:hover { border-color: #fff; color: #fff; }
.play-badge .play-mark { width: 20px; height: 22px; display: block; }
.play-badge .play-words { display: grid; gap: 1px; }
.play-badge .play-words small { font-size: .56rem; letter-spacing: .08em; }
.play-badge .play-words b { font-size: .95rem; font-weight: 700; letter-spacing: .01em; }
@media (max-width: 700px) {
    .play-badge.in-top { padding: 6px 8px; }
    .play-badge.in-top .play-words { display: none; }
}
@media print { .play-badge { display: none; } }

/*  THE MAIN DASHBOARD LINE at the top of the menu - drawn like a group
    heading (same size, weight and ink), a link rather than a list, and filled
    with the accent while it is the screen open, as in the owner's mock-up.  */
.menu .grp-direct > a {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px; font-size: .95rem; font-weight: 800; color: var(--ink);
    border-left: 0; margin-bottom: 4px;
}
.menu .grp-direct.on > a,
.menu .grp-direct > a.on { background: var(--accent); color: var(--accent-ink); }
.menu .grp-direct.on > a svg, .menu .grp-direct > a.on svg { color: var(--accent-ink); }

/* ══════════════════════════════════════════════ the main dashboard ══ */
/*  The owner's mock-up, 23 Sep 2026 (Dashboard/Index.cshtml) - and the
    pieces the module dashboards share with it: the round-icon KPI card and
    the coloured quick-action tile.  */

/*  THE WELCOME BAND - warm gold behind the name, the date card on the right.  */
.md-hero {
    display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 18px 28px;
    margin: 18px 0 16px; padding: 22px 26px; border-radius: var(--radius);
    background: linear-gradient(110deg, #FFF6E3 0%, #F6E3BE 55%, #E9C98A 100%);
    border: 1px solid #E8D3A6; color: #3B2A10;
}
.md-hero-brand { display: grid; line-height: 1; }
.md-welcome { font-family: "Cormorant Garamond", Georgia, serif; font-style: italic; font-size: 1.6rem; color: #7A5418; }
.md-name { font-family: "Cormorant Garamond", Georgia, serif; font-weight: 600; font-size: 3rem; color: #8A5A14; letter-spacing: .01em; }
.md-tag { font-size: .85rem; margin-top: 6px; color: #5A4420; }
.md-hero-shop { display: grid; gap: 4px; border-left: 2px solid #C9A15A; padding-left: 22px; }
.md-hero-shop b { font-size: 1.25rem; }
.md-lines { font-size: .9rem; color: #5A4420; }
.md-date { display: grid; gap: 2px; padding: 12px 18px; min-width: 190px; position: relative; padding-left: 58px; }
.md-date-ico { position: absolute; left: 16px; top: 16px; width: 30px; height: 30px; color: var(--accent); }
.md-date-ico svg { width: 30px; height: 30px; }
.md-date b { font-size: 1.15rem; }

/*  KPI CARD - a round coloured icon, the label, the figure, one plain line.  */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; margin-bottom: 16px; }
.kpi {
    position: relative; display: grid; gap: 3px; align-content: start;
    padding: 18px 18px 16px 84px; border-left: 4px solid var(--line-strong); min-height: 108px;
}
.kpi .kpi-ico, .mod .kpi-ico {
    display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%;
    color: #fff; background: var(--ink-soft);
}
.kpi .kpi-ico { position: absolute; left: 18px; top: 20px; }
.kpi .kpi-ico svg, .mod .kpi-ico svg { width: 26px; height: 26px; }
.kpi-k { font-size: .76rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-soft); }
.kpi-v { font-size: 1.75rem; font-weight: 700; line-height: 1.15; color: var(--ink); }
.kpi-s { font-size: .82rem; color: var(--ink-soft); }
.is-gold   { --tone: #C8901F; }
.is-green  { --tone: #1E8E5A; }
.is-blue   { --tone: #1F5FAF; }
.is-red    { --tone: #C62846; }
.is-amber  { --tone: #E08A12; }
.is-purple { --tone: #7B3FB8; }
.is-pink   { --tone: #D13C78; }
.is-teal   { --tone: #0F8C8C; }
.is-navy   { --tone: #1E3A5F; }
.kpi[class*="is-"] { border-left-color: var(--tone); }
.kpi[class*="is-"] .kpi-ico, .mod[class*="is-"] .kpi-ico { background: var(--tone); }

/*  THE WEEK BESIDE THE KEY FIGURES, and the quick actions beside that.  */
.md-row { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 14px; }
@media (max-width: 1100px) { .md-row { grid-template-columns: minmax(0, 1fr); } .md-hero { grid-template-columns: 1fr; } .md-hero-shop { border-left: 0; padding-left: 0; } }
.md-overview-in { display: grid; grid-template-columns: minmax(0, 1fr) 190px; grid-template-rows: auto auto; gap: 4px 18px; }
.md-chart { width: 100%; height: 190px; grid-column: 1; }
.md-axis { stroke: var(--line-strong); stroke-width: 1; }
.md-area { fill: color-mix(in srgb, #C8901F 22%, transparent); }
.md-line { fill: none; stroke: #C8901F; stroke-width: 3; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.md-dot { fill: var(--raised); stroke: #C8901F; stroke-width: 2; vector-effect: non-scaling-stroke; }
.md-days { grid-column: 1; display: flex; justify-content: space-between; font-size: .78rem; color: var(--ink-soft); padding: 0 2px; }
.md-days .on { color: var(--ink); font-weight: 800; }
.md-figs { grid-column: 2; grid-row: 1 / span 2; display: grid; gap: 12px; align-content: center; border-left: 1px solid var(--line); padding-left: 16px; }
.md-figs > div { display: grid; grid-template-columns: 40px 1fr; grid-template-rows: auto auto; column-gap: 10px; align-items: center; }
.md-fig-ico { grid-row: span 2; width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); }
.md-fig-ico svg { width: 22px; height: 22px; }
.md-figs b { font-size: 1.2rem; }
@media (max-width: 640px) { .md-overview-in { grid-template-columns: 1fr; } .md-figs { grid-column: 1; grid-row: auto; border-left: 0; padding-left: 0; } }

/*  QUICK ACTIONS - big coloured squares, the icon over the word.  */
.qa-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 520px) { .qa-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.qa {
    display: grid; place-items: center; gap: 8px; min-height: 92px; padding: 12px 6px;
    border-radius: 12px; text-decoration: none; text-align: center;
    color: #fff; font-weight: 800; font-size: .9rem;
    background: linear-gradient(160deg, color-mix(in srgb, var(--tone) 82%, #fff) 0%, var(--tone) 100%);
    box-shadow: var(--shadow-sm); transition: transform .12s ease, filter .12s ease;
}
.qa svg { width: 30px; height: 30px; color: #fff; }
a.qa:hover { transform: translateY(-2px); filter: brightness(1.06); color: #fff; }
.qa.is-locked { opacity: .45; cursor: not-allowed; }

/*  ONE CARD PER MODULE - its icon, three figures, the way into its dashboard.  */
.mod-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; margin-top: 12px; }
.mod { display: grid; gap: 8px; align-content: start; border-top: 4px solid var(--tone, var(--line-strong)); }
.mod-head { display: flex; align-items: center; gap: 12px; font-size: 1.05rem; margin-bottom: 4px; }
.mod-head .kpi-ico { width: 40px; height: 40px; }
.mod-head .kpi-ico svg { width: 22px; height: 22px; }
.mod-fig { display: flex; justify-content: space-between; gap: 10px; font-size: .9rem; border-bottom: 1px dashed var(--line); padding-bottom: 5px; }
.mod-fig span { color: var(--ink-soft); }
.mod-go { margin-top: 4px; font-weight: 800; color: var(--tone, var(--accent)); text-decoration: none; }
.mod-go:hover { text-decoration: underline; }
.mod.is-locked { opacity: .6; }
.mod .lock { margin-left: auto; }
.is-silver { --tone: #6E7681; }
/*  Quick-action tiles under a page heading: a touch of room, and eight across
    on a desk so they sit in one row; four, then two, as the screen narrows.  */
.qa-grid.qa-top { margin-top: 12px; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
.qa-grid.qa-top .qa { min-height: 78px; }
.kpi .dash-foot { display: block; }

/*  THE SHELL'S CARD PADDING WON (23 Sep 2026, the owner's screenshots).
    `.shell .card { padding: 10px 12px }` is two classes to `.kpi`'s one, so
    inside the working shell the room kept for the round icon vanished and the
    icon sat over the figure - and the date card's calendar over the weekday.
    And `.pagehead` is a flex row, so a tile grid inside it shrank to one
    column on the right. Both are restated here at the shell's weight.  */
.shell .kpi, .kpi.card { padding: 18px 18px 16px 84px; }
.shell .md-date, .md-date.card { padding: 12px 18px 12px 58px; }
.pagehead > .qa-grid, .pagehead > .hint { flex: 1 0 100%; }
.shell .md-hero, .md-row, .kpi-row, .mod-row { min-width: 0; }
@media (max-width: 520px) {
    .shell .kpi, .kpi.card { padding: 14px 12px 12px 70px; }
    .kpi .kpi-ico { width: 42px; height: 42px; left: 14px; top: 16px; }
    .kpi-v { font-size: 1.45rem; }
}

/* ═══════════════════════════════════════ the owner's mock-up, round two ══ */
/*  "do like this" (23 Sep 2026) - the navy menu, the chart with its grid and
    figures, a spark line on the sales card and the three-card row under it.
    Only figures the books actually hold are drawn: no invented trend chips.  */

/*  THE NAVY MENU. The menu's own colours are redefined inside it, so every
    part of it - groups, sub-menus and the collapsed rail's fly-out panels -
    turns navy together without a rule per piece.  */
.shell > nav.menu {
    --raised: #132A52; --sunken: rgba(255,255,255,.08);
    --ink: #FFFFFF; --ink-soft: #D2DBEA; --ink-faint: #93A1BA;
    --line: rgba(255,255,255,.12); --line-strong: rgba(255,255,255,.22);
    --accent: #E6B85C; --accent-soft: rgba(230,184,92,.16); --accent-ink: #1B1F2A;
    background: linear-gradient(180deg, #0E1D3A 0%, #142C57 100%);
    color: var(--ink); padding: 10px 8px; border-radius: 14px;
    align-self: start; box-shadow: var(--shadow);
}
.shell > nav.menu .grp-direct > a,
.shell > nav.menu .grp-direct.on > a { border-radius: 10px; }
.shell > nav.menu .grp-direct.on > a {
    background: linear-gradient(100deg, #E9C27A 0%, #C8901F 100%); color: #1B1F2A;
}
.shell > nav.menu .grp-direct.on > a svg { color: #1B1F2A; }
.shell > nav.menu .grp[open] > summary { color: var(--accent); }
.shell > nav.menu a.on { color: #FFE3A8; }

/*  THE SALES CARD'S SPARK LINE - the same seven days, bottom right.  */
.kpi-spark { position: absolute; right: 14px; bottom: 12px; width: 92px; height: 30px; }
.kpi-spark path { fill: none; stroke: var(--tone); stroke-width: 2; vector-effect: non-scaling-stroke; }
.kpi-chip {
    justify-self: start; margin-top: 6px; padding: 2px 8px; border-radius: 6px;
    font-size: .76rem; font-weight: 800; background: var(--ok-soft); color: var(--ok);
}
.kpi-chip.down { background: var(--bad-soft); color: var(--bad); }
.kpi .kpi-ico { box-shadow: 0 0 0 5px color-mix(in srgb, var(--tone) 16%, transparent); }

/*  THE CHART'S GRID AND FIGURES.  */
.md-grid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 4; vector-effect: non-scaling-stroke; }
.md-ylab { font-size: 11px; fill: var(--ink-soft); }
.md-tip rect { fill: #1E3A5F; }
.md-tip text { fill: #fff; font-size: 12px; font-weight: 700; }
.md-chart { overflow: visible; }

/*  THE ROW UNDER THE MODULES - recent documents, balances, today by kind.  */
.md-lower { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr); gap: 14px; margin-top: 16px; }
@media (max-width: 1100px) { .md-lower { grid-template-columns: minmax(0, 1fr); } }
.md-list { display: grid; gap: 2px; }
.md-list > div { display: grid; grid-template-columns: 34px 1fr auto; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.md-list > div:last-child { border-bottom: 0; }
.md-li-ico { width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; background: color-mix(in srgb, var(--tone) 14%, transparent); color: var(--tone); }
.md-li-ico svg { width: 18px; height: 18px; }
.md-list b.pos { color: var(--ok); } .md-list b.neg { color: var(--bad); }
.md-donut-wrap { display: grid; grid-template-columns: 140px 1fr; align-items: center; gap: 14px; }
@media (max-width: 420px) { .md-donut-wrap { grid-template-columns: 1fr; justify-items: center; } }
.md-donut { width: 140px; height: 140px; transform: rotate(-90deg); }
.md-donut circle { fill: none; stroke-width: 16; }
.md-donut-mid { position: relative; }
.md-donut-mid > span { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; line-height: 1.1; }
.md-donut-mid b { font-size: 1.5rem; }
.md-legend { display: grid; gap: 6px; font-size: .86rem; }
.md-legend > div { display: grid; grid-template-columns: 10px 1fr auto; gap: 8px; align-items: center; }
.md-legend i { width: 10px; height: 10px; border-radius: 50%; }
.pill.paid { background: var(--ok-soft); color: var(--ok); }
.md-chart { height: auto; aspect-ratio: 640 / 200; }
.md-days { display: none; }
.md-donut circle { stroke-width: 6; }
.md-chart { aspect-ratio: 420 / 202; }
.md-ylab { font-size: 12px; }
.md-tip text { font-size: 12px; }

/*  THE NAVY RUNS THE FULL HEIGHT (24 Sep 2026, the owner: "it should be
    complete background"). The panel stopped where its last group did and the
    page's grey showed under it. It is now at least one screen tall and stays
    in view as the page scrolls (it was already sticky at 16px, hence the 32).
    An open group that makes the menu longer still grows it, as before - no
    inner scroll bar, which would also clip the collapsed rail's fly-outs.  */
.shell > nav.menu { min-height: calc(100vh - 32px); }
@media (max-width: 900px) { .shell > nav.menu { min-height: 0; } }

/*  COMPACT TILES UNDER A PAGE HEADING (24 Sep 2026, the owner: "height is
    more compact"). On the module dashboards the tiles are a way in, not the
    content, so the icon sits BESIDE the word and the tile is one line high -
    about half what it was. Long words wrap inside the tile rather than
    making it taller. The Main Dashboard's square tiles are unchanged.  */
.qa-grid.qa-top { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.qa-grid.qa-top .qa {
    display: flex; align-items: center; justify-content: flex-start; gap: 9px;
    min-height: 0; padding: 9px 12px; border-radius: 10px;
    text-align: left; font-size: .86rem; line-height: 1.15;
}
.qa-grid.qa-top .qa svg { width: 20px; height: 20px; flex: 0 0 20px; }

/*  AND THE MAIN DASHBOARD'S QUICK ACTIONS (24 Sep 2026, the owner: "make
    Main Dashboard quick action tiles compact too") - the same one-line tile,
    icon beside the word, as many across as the card holds.  */
.md-quick .qa-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.md-quick .qa {
    display: flex; align-items: center; justify-content: flex-start; gap: 9px;
    min-height: 0; padding: 9px 12px; border-radius: 10px;
    text-align: left; font-size: .86rem; line-height: 1.15;
}
.md-quick .qa svg { width: 20px; height: 20px; flex: 0 0 20px; }
.md-quick .qa-grid, .qa-grid.qa-top { grid-auto-rows: 1fr; }

/*  THE SCAN BUTTON AND BOX on the Main Dashboard (24 Sep 2026) - under the
    date card, teal as on the phone; the box shows the piece a tag reads.  */
.md-side { display: grid; gap: 10px; justify-items: stretch; }
.md-scan {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 10px 16px; border: 0; border-radius: 10px; cursor: pointer;
    background: #0F8C8C; color: #fff; font-weight: 800; font-size: .95rem;
    box-shadow: var(--shadow-sm);
}
.md-scan:hover { filter: brightness(1.08); }
.md-scan svg { width: 20px; height: 20px; color: #fff; }
.scan-video { width: 100%; max-height: 260px; border-radius: 8px; background: #000; margin-top: 8px; }
.scan-out { margin-top: 10px; }
.scan-ok, .scan-bad { font-weight: 800; margin: 0 0 8px; }
.scan-ok { color: var(--ok); }
.scan-bad { color: var(--bad); }
.scan-piece { display: grid; gap: 4px; }
.scan-piece > div { display: flex; justify-content: space-between; gap: 12px; border-bottom: 1px dashed var(--line); padding: 3px 0; }
.scan-piece span { color: var(--ink-soft); }

/*  THE SIGN-IN PAGES READ IN BLACK (24 Sep 2026, the owner: "correct login
    page view, font visibility"). The soft and faint inks - the panel's
    paragraphs and ticks, the field labels, "Are you the owner?" - are
    near-black inside the sign-in box; nothing outside it changes.  */
.auth { --ink: #111111; --ink-soft: #1F232B; --ink-faint: #2E333D; }
.auth .muted, .auth .field > span, .auth-say p, .auth-say li, .auth-say .fine { color: var(--ink-soft); }

/*  A PRODUCT BY KEYCODE TECHNOLOGY (Views/Shared/_MadeBy.cshtml) - under the
    sign-in form: the line, the logo, the company name and both sites.  */
.made-by {
    display: grid; justify-items: center; gap: 6px; text-align: center;
    margin-top: 18px; padding: 16px 14px; border: 1px solid var(--line);
    border-radius: var(--radius); background: #fff;
}
.made-by-k { font-size: .72rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
.made-by-logo img { display: block; width: 190px; max-width: 100%; height: auto; }
.made-by-name { font-size: .95rem; color: #111111; }
.made-by-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; font-size: .9rem; }
.made-by-links a { color: #1F5FAF; font-weight: 700; text-decoration: none; }
.made-by-links a:hover { text-decoration: underline; }

/*  AND IN THE FOOTER OF EVERY PAGE - the line and a small logo.  */
.footer-by { display: inline-flex; align-items: center; gap: 8px; text-decoration: none; color: var(--ink-soft); font-size: .8rem; }
.footer-by img { height: 34px; width: auto; border-radius: 4px; background: #fff; }
.footer-by:hover { color: var(--ink); }
.secret-btn { padding: 1px 8px; font-size: .75rem; margin-left: 6px; }

/* ═══════════════════════════════════════════ the Item Catalog (24 Sep 2026) ══ */
/*  Staff screens (Areas/Company/Views/Catalog) and the shared page a retailer
    opens (Views/Shared/Catalog.cshtml). Cards grouped by category and
    sub-category; each leads with its cover photo.  */

/*  ── staff: the list ── */
.cat-scan { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.cat-scan-ico { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 10px; background: #0F8C8C; color: #fff; }
.cat-scan-ico svg { width: 22px; height: 22px; }
.cat-scan p { flex-basis: 100%; margin: 0; }
.cat-share-box { display: grid; gap: 8px; border-left: 4px solid #1E8E5A; }
.cat-share-row { display: flex; gap: 8px; flex-wrap: wrap; }
.cat-share-row input { flex: 1; min-width: 16rem; }
.cat-group { margin-top: 18px; }
.cat-h { font-size: 1.25rem; margin: 0 0 8px; padding-bottom: 6px; border-bottom: 2px solid var(--accent); }
.cat-sub { font-size: 1rem; margin: 14px 0 8px; color: var(--ink-soft); }
.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.cat-card { display: flex; flex-direction: column; background: var(--raised); border: 1px solid var(--line); border-radius: 12px; overflow: hidden; text-decoration: none; color: var(--ink); box-shadow: var(--shadow-sm); transition: transform .12s ease, box-shadow .12s ease; }
.cat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.cat-card.is-hidden { opacity: .6; }
.cat-pic { position: relative; aspect-ratio: 1 / 1; background: var(--sunken); }
.cat-pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cat-nopic { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 6px; color: var(--ink-faint); }
.cat-nopic svg { width: 40px; height: 40px; }
.cat-badge { position: absolute; top: 8px; right: 8px; padding: 2px 8px; border-radius: 999px; background: rgba(0,0,0,.65); color: #fff; font-size: .72rem; font-weight: 800; }
.cat-badge.off { left: 8px; right: auto; background: #C62846; }
.cat-body { display: grid; gap: 3px; padding: 10px 12px 12px; }
.cat-no { font-size: .95rem; }
.cat-name { font-weight: 700; }
.cat-meta { font-size: .82rem; color: var(--ink-soft); }
.cat-stock { margin-top: 4px; font-size: .8rem; font-weight: 800; }
.cat-stock.yes { color: var(--ok); }
.cat-stock.no { color: var(--ink-faint); }

/*  ── staff: one design ── */
.cat-edit { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 1000px) { .cat-edit { grid-template-columns: minmax(0, 1fr); } }
.cat-inline { display: flex; gap: 6px; }
.cat-inline input { flex: 1; min-width: 0; }
.cat-drop { display: grid; justify-items: center; gap: 4px; padding: 20px; border: 2px dashed var(--line-strong); border-radius: 12px; cursor: pointer; text-align: center; background: var(--sunken); }
.cat-drop:hover { border-color: var(--accent); }
.cat-drop svg { width: 30px; height: 30px; color: var(--accent); }
.cat-thumbs { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-top: 12px; }
.cat-thumb { margin: 0; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: #fff; }
.cat-thumb img, .cat-thumb video { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; background: #000; }
.cat-thumb figcaption { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; padding: 6px; }
.cat-thumb form { margin: 0; }
.cat-mini { padding: 2px 8px; font-size: .74rem; }

/*  ── staff: orders ── */
.cat-dl { display: grid; gap: 6px; margin: 0 0 14px; }
.cat-dl div { display: grid; grid-template-columns: 6rem minmax(0, 1fr); gap: 10px; }
.cat-dl dt { color: var(--ink-soft); font-size: .85rem; }
.cat-dl dd { margin: 0; overflow-wrap: anywhere; }
.cat-lines { display: grid; gap: 8px; }
.cat-line { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 8px; border: 1px solid var(--line); border-radius: 10px; }
.cat-line-pic { width: 56px; height: 56px; border-radius: 8px; overflow: hidden; background: var(--sunken); display: grid; place-items: center; }
.cat-line-pic img { width: 100%; height: 100%; object-fit: cover; }
.cat-line-pic svg { width: 26px; height: 26px; color: var(--ink-faint); }
.cat-line-say { display: grid; gap: 2px; }
.cat-line-qty { display: grid; justify-items: end; gap: 2px; }
.cat-line-qty .ok { color: var(--ok); } .cat-line-qty .bad { color: var(--bad); }

/*  ── the shared catalog a retailer opens ── */
.pc { max-width: 72rem; margin: 0 auto; padding: 0 0 90px; }
.pc-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; padding: 22px 20px; margin-bottom: 14px; border-radius: 14px; color: #fff;
    background: radial-gradient(90% 90% at 100% 0%, rgba(214,165,72,.35) 0%, transparent 60%), linear-gradient(150deg, #0E2240, #16345F); }
.pc-k { margin: 0 0 4px; font-size: .74rem; letter-spacing: .18em; text-transform: uppercase; color: #E9C27A; font-weight: 800; }
.pc-head h1 { margin: 0; font-family: var(--serif); font-size: 2rem; }
.pc-sub { margin: 4px 0 0; color: #D6DEEB; }
.pc-sub a { color: #fff; }
.pc-count { font-size: .85rem; color: #E9C27A; white-space: nowrap; }
.pc-chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 10px; position: sticky; top: 0; background: var(--ground); z-index: 5; }
.pc-chips a { flex: 0 0 auto; padding: 6px 14px; border-radius: 999px; border: 1px solid var(--line-strong); background: #fff; color: var(--ink); text-decoration: none; font-weight: 700; font-size: .9rem; }
.pc-chips a small { color: var(--ink-soft); margin-left: 4px; }
.pc-cat { scroll-margin-top: 60px; margin-top: 16px; }
.pc-cat h2 { font-family: var(--serif); font-size: 1.5rem; margin: 0 0 6px; padding-bottom: 6px; border-bottom: 2px solid #C8901F; }
.pc-cat h3 { font-size: 1.02rem; margin: 14px 0 8px; color: var(--ink-soft); }
.pc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 14px; }
.pc-card { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; box-shadow: 0 2px 10px rgba(14,34,64,.06); }
.pc-card.in { border-color: #1E8E5A; box-shadow: 0 0 0 2px rgba(30,142,90,.25); }
.pc-pics { position: relative; display: flex; overflow-x: auto; scroll-snap-type: x mandatory; aspect-ratio: 1 / 1; background: #F3F4F6; }
.pc-pics img, .pc-pics video { flex: 0 0 100%; width: 100%; height: 100%; object-fit: cover; scroll-snap-align: start; background: #000; }
.pc-pics img { background: #F3F4F6; }
.pc-nopic { margin: auto; color: var(--ink-faint); }
.pc-n { position: absolute; bottom: 8px; right: 8px; padding: 2px 8px; border-radius: 999px; background: rgba(0,0,0,.6); color: #fff; font-size: .75rem; font-weight: 800; pointer-events: none; }
.pc-body { display: grid; gap: 8px; padding: 12px 14px 14px; }
.pc-title { display: grid; gap: 1px; }
.pc-title b { font-size: .95rem; color: #7A5418; }
.pc-title span { font-weight: 800; font-size: 1.05rem; }
.pc-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 10px; margin: 0; }
.pc-facts div { display: grid; }
.pc-facts dt { font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft); }
.pc-facts dd { margin: 0; font-weight: 700; font-size: .9rem; }
.pc-desc { margin: 0; font-size: .85rem; color: var(--ink-soft); }
.pc-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.pc-stock { font-size: .78rem; font-weight: 800; margin-right: auto; }
.pc-stock.yes { color: #1E8E5A; } .pc-stock.no { color: #7A5418; }
.pc-add { border: 0; border-radius: 8px; padding: 8px 14px; font-weight: 800; cursor: pointer; background: linear-gradient(180deg, #D6A548, #B8862F); color: #fff; }
.pc-card.in .pc-add { background: #1E8E5A; }
.pc-qty { display: inline-flex; align-items: center; border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden; }
.pc-qty button { border: 0; background: #F3F4F6; width: 32px; height: 32px; font-size: 1.1rem; font-weight: 800; cursor: pointer; }
.pc-qty b { min-width: 30px; text-align: center; }
.pc-bar { position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%); width: min(100% - 28px, 36rem); display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 10px 12px 10px 18px; border-radius: 14px; background: #0E2240; color: #fff; box-shadow: 0 12px 30px rgba(0,0,0,.3); z-index: 20; }
.pc-bar button, .pc-go { border: 0; border-radius: 10px; padding: 10px 18px; font-weight: 800; cursor: pointer; background: linear-gradient(180deg, #E9C27A, #C8901F); color: #0E2240; }
.pc-dlg { max-width: 30rem; }
.pc-list { display: grid; gap: 4px; margin-bottom: 12px; max-height: 30vh; overflow: auto; }
.pc-list div { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; padding: 6px 8px; border-radius: 8px; background: #F7F4EE; }
.pc-dlg form { display: grid; gap: 10px; }
.pc-acts { display: flex; justify-content: flex-end; gap: 8px; }
.pc-ghost { border: 1px solid var(--line-strong); background: #fff; border-radius: 10px; padding: 10px 14px; cursor: pointer; }
.pc-say { margin: 0; font-weight: 700; }
.pc-say.ok { color: #1E8E5A; } .pc-say.bad { color: #C62846; }
.pc-empty { padding: 30px; text-align: center; color: var(--ink-soft); }
@media (max-width: 560px) { .pc-head h1 { font-size: 1.5rem; } .pc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } .pc-facts { grid-template-columns: 1fr; } .pc-body { padding: 10px; } .pc-add { width: 100%; } }
/*  Hidden means hidden - the display rules above must not bring back the
    quantity box before a design is added, or the basket bar when it is empty.  */
.pc-qty[hidden], .pc-bar[hidden] { display: none !important; }
.pc { padding-left: 14px; padding-right: 14px; }

/*  SMALL SUB-CATEGORIES SHARE A ROW (24 Sep 2026). Each sub-category keeps
    its own heading, but a group of one or two designs no longer takes a whole
    row: the groups wrap side by side, each as wide as its cards.  */
.pc-subs, .cat-subs { display: flex; flex-wrap: wrap; gap: 6px 22px; align-items: flex-start; }
.pc-sb, .cat-sb { flex: 0 1 auto; min-width: 0; max-width: 100%; }
.pc-subs .pc-grid, .cat-subs .cat-grid { display: flex; flex-wrap: wrap; gap: 14px; }
.pc-subs .pc-card { width: 250px; }
.cat-subs .cat-card { width: 220px; }
@media (max-width: 560px) {
    .pc-sb, .cat-sb { flex-basis: 100%; }
    .pc-subs .pc-grid { gap: 10px; }
    .pc-subs .pc-card { width: calc(50% - 5px); }
}
/*  The photo strip swipes; the "2 ›" badge says there is more, so no bar.  */
.pc-pics { scrollbar-width: none; }
.pc-pics::-webkit-scrollbar { display: none; }

/*  ONE GRID PER CATEGORY (24 Sep 2026, the owner: "catalog layout in web
    should be grid system"). Every card in a category sits in the same grid -
    equal widths, straight rows and columns - and each sub-category's heading
    runs across a full row of that grid, so the grouping stays and the cards
    line up. Replaces the side-by-side wrapping above.  */
.pc-subs, .cat-subs { display: grid; gap: 14px; align-items: stretch; }
.cat-subs { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.pc-subs  { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.pc-sb, .cat-sb, .pc-subs .pc-grid, .cat-subs .cat-grid { display: contents; }
.pc-subs h3, .cat-subs .cat-sub { grid-column: 1 / -1; margin: 10px 0 0; padding-bottom: 4px; border-bottom: 1px dashed var(--line-strong); }
.pc-subs .pc-card, .cat-subs .cat-card { width: auto; }
@media (max-width: 560px) {
    .pc-subs { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .pc-subs .pc-card { width: auto; }
}
.cat-del { color: var(--bad); border-color: var(--bad); margin-left: auto; }

/*  FOUR OR MORE TO A ROW (24 Sep 2026, the owner: "do it in grid system, one
    row holds at least 4 images"). Inside a category every design flows in ONE
    grid - no row break per sub-category, which left a row with one card. The
    cards keep their sub-category order and each carries its sub-category as a
    small label. 4 across from a laptop up (more on a wide screen), 3 on a
    tablet, 2 on a phone.  */
.cat-subs, .pc-subs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (min-width: 1500px) { .cat-subs, .pc-subs { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .cat-subs, .pc-subs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .cat-subs, .pc-subs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.cat-subs .cat-sub, .pc-subs h3 { display: none; }
.cat-subtag, .pc-subtag {
    justify-self: start; display: inline-block; padding: 1px 8px; border-radius: 999px;
    font-size: .7rem; font-weight: 800; letter-spacing: .04em;
    background: #FBEFD9; color: #7A5418; border: 1px solid #EFD9AE;
}
.pc-subtag { margin-bottom: -2px; }

/*  COMBOS (24 Sep 2026, Sql/98) - a set of designs sold together. On the
    staff grid: a "Set" badge, a tick in select mode. On the combo screen: the
    pieces table. On the shared page: a "Set of N" badge, the pieces under the
    card, and a one-item page for a link to a single design or combo.  */
.cat-badge.set { left: 8px; right: auto; top: auto; bottom: 8px; background: #7A5418; }
.cat-card.is-combo { border-color: #D6A548; }
.cat-tick { display: none; position: absolute; top: 8px; left: 8px; width: 28px; height: 28px; border-radius: 50%; place-items: center;
    background: #fff; border: 2px solid var(--line-strong); color: transparent; font-weight: 900; }
.cat-picking .cat-card:not(.is-combo) .cat-tick { display: grid; }
.cat-picking .cat-card.is-combo { opacity: .45; cursor: not-allowed; }
.cat-card.is-picked { outline: 3px solid #1E8E5A; outline-offset: -3px; }
.cat-card.is-picked .cat-tick { background: #1E8E5A; border-color: #1E8E5A; color: #fff; }
.cat-pickbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; position: sticky; top: 8px; z-index: 5; border-left: 4px solid #1E8E5A; }
.cat-pickbar[hidden] { display: none; }
.cat-parts { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; margin: 6px 0 12px; }
.cat-parts legend { font-weight: 800; padding: 0 6px; }
.cat-parts-t { width: 100%; }
.cat-parts-t td { vertical-align: middle; }
.cat-part-pic { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; display: block; }
.cat-part-q { width: 4.5rem; text-align: right; }
.cat-parts-add { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.cat-parts-add select { min-width: 18rem; max-width: 100%; }
.cat-setw { padding: 8px 0; }
.cat-line-part { padding-top: 2px; padding-bottom: 2px; opacity: .9; }
.cat-line-part .cat-line-pic { visibility: hidden; height: 1px; }

.pc-setbadge { position: absolute; top: 8px; left: 8px; padding: 3px 10px; border-radius: 999px; background: #7A5418; color: #fff; font-size: .75rem; font-weight: 800; pointer-events: none; }
.pc-collage { flex: 0 0 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 2px; background: #fff; }
.pc-collage img { width: 100%; height: 100%; object-fit: cover; }
.pc-inset { margin: 0; font-size: .8rem; color: var(--ink-soft); }
.pc-set summary { cursor: pointer; font-weight: 700; font-size: .85rem; color: #7A5418; }
.pc-parts { display: grid; gap: 6px; margin-top: 8px; }
.pc-parts .pc-part { display: flex; flex-direction: row; align-items: center; gap: 8px; padding: 6px; border: 1px solid var(--line); border-radius: 10px; background: #fff; box-shadow: none; overflow: visible; }
.pc-parts .pc-part.in { border-color: #1E8E5A; }
.pc-part-pic { flex: 0 0 48px; width: 48px; height: 48px; border-radius: 8px; overflow: hidden; background: #F3F4F6; }
.pc-part-pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pc-part-txt { flex: 1; min-width: 0; font-size: .85rem; line-height: 1.3; }
.pc-part-txt small { display: block; color: var(--ink-soft); }
.pc-add-sm { padding: 6px 10px; width: auto !important; }
.pc-part.in .pc-add-sm { background: #1E8E5A; }
.pc-one { max-width: 34rem; margin: 0 auto 18px; }
.pc-one .pc-big .pc-title span { font-size: 1.3rem; }
section.pc-cat > .pc-parts { max-width: 34rem; margin: 0 auto; }
.pc-collage { grid-template-rows: 1fr 1fr; height: 100%; }
.pc-collage img { min-height: 0; }
.pc-collage img:only-child { grid-column: 1 / -1; grid-row: 1 / -1; }
.pc-collage img:first-child:nth-last-child(2), .pc-collage img:first-child:nth-last-child(2) ~ img { grid-row: 1 / -1; }
.pc-collage img:first-child:nth-last-child(3) { grid-row: 1 / -1; }

/*  COMPACT DESIGN FORM (24 Sep 2026, the owner: "compact this layout", "do it
    one row") - one twelve-column grid; weight, tunch, wastage and making share
    a line. Six columns on a tablet, two on a phone.  */
.cat-form { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 8px 10px; align-items: start; }
.cat-form .field { min-width: 0; margin: 0; }
.cat-form .field input, .cat-form .field select, .cat-form .field textarea { width: 100%; min-width: 0; }
.cat-form .c2 { grid-column: span 2; } .cat-form .c3 { grid-column: span 3; } .cat-form .c4 { grid-column: span 4; }
.cat-form .c9 { grid-column: span 9; } .cat-form .c12 { grid-column: 1 / -1; }
.cat-lbl { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.cat-new-btn { border: 0; background: none; padding: 0; color: var(--accent, #1B4F8A); font-weight: 800; font-size: .78rem; cursor: pointer; }
.cat-new-btn:hover { text-decoration: underline; }
.cat-form .cat-inline { margin-top: 6px; }
.cat-form .cat-inline[hidden] { display: none; }
@media (max-width: 1100px) {
    .cat-form { grid-template-columns: repeat(6, minmax(0, 1fr)); }
    .cat-form .c3 { grid-column: span 3; } .cat-form .c9 { grid-column: span 3; } .cat-form .c4 { grid-column: span 2; }
}
@media (max-width: 560px) {
    .cat-form .c2, .cat-form .c3, .cat-form .c4 { grid-column: span 3; } .cat-form .c9 { grid-column: 1 / -1; }
}

/*  THE COMBO FILTER on the catalog's head line - All · Designs · Combos.  */
.cat-kind { display: inline-flex; border: 1px solid var(--line-strong); border-radius: 999px; overflow: hidden; }
.cat-kind a { padding: 5px 12px; text-decoration: none; color: var(--ink); font-weight: 700; font-size: .85rem; }
.cat-kind a + a { border-left: 1px solid var(--line); }
.cat-kind a small { color: var(--ink-soft); font-weight: 600; margin-left: 2px; }
.cat-kind a.on { background: #0E2240; color: #fff; }
.cat-kind a.on small { color: #C9D6EA; }

/*  CATALOG ORDERS' STATUS TABS IN ONE ROW (24 Sep 2026) - under the heading,
    each as wide as its word, not stacked in a column beside it.  */
.pagehead .cat-tabs { flex: 1 0 100%; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.pagehead .cat-tabs .tab { flex: 0 0 auto; width: auto; min-width: 0; padding: 6px 16px; }

/*  WHOLESALE BILL - READABLE LABELS, IN BLACK (25 Sep 2026, "use black color font";, the owner: "on this screen
    there is a visibility issue with labels and layout, correct it"). Every
    small grey line on the bill is raised to the soft ink the rest of the
    product reads at, the column headings get their full ink, the bill number
    has room for all of SL/26-27/0006, and the panel's labels line up.  */
.panes.bill.ws-panes .tbl.grid.ws-grid thead th {
    color: #000;
    font-size: .76rem;
    vertical-align: bottom;
}
.panes.bill.ws-panes .tbl.grid.ws-grid thead th .chint {
    opacity: 1;
    color: #000;
    font-size: .74rem;
    font-weight: 500;
}
/*  The fine column is filled amber; its "fine" line stays readable on it.  */
.panes.bill.ws-panes .tbl.grid.ws-grid thead th[data-col="gold"] .chint,
.panes.bill.ws-panes .tbl.grid.ws-grid thead th[data-col="silver"] .chint { opacity: 1; color: inherit; }
.panes.bill.ws-panes .field > span { color: #000; }
.panes.bill.ws-panes .field > span > .chint { color: #000; font-size: .76rem; }
.panes.bill.ws-panes .editor .f-billno { flex: 0 0 10rem; }
.panes.bill.ws-panes .editor .f-billno input { font-size: .95rem; }
.panes.bill.ws-panes .tick > span, .panes.bill.ws-panes .tick .muted,
.panes.bill.ws-panes .check > span,
.panes.bill.ws-panes .check .muted { color: #000; }
/*  The Weight / less and Summary panels: labels flush left at one indent,
    headings in full ink.  */
.panes.bill.ws-panes #wdetail .tbl td:first-child,
.panes.bill.ws-panes #wsum .tbl td:first-child { text-align: left; padding-left: 8px; font-weight: 600; color: #000; }
.panes.bill.ws-panes #wdetail .tbl th,
.panes.bill.ws-panes #wsum .tbl th { color: #000; }
.panes.bill.ws-panes #wdetail .jama-h { padding-left: 8px; }

/*  THE SHORTCUT STRIP ABOVE THE BILL - soft ink, not the faintest grey that
    could not be read across a counter.  */
.keys { color: #000; font-size: .8rem; gap: 4px 14px; }
/*  Black across the wholesale bill - the party and head boxes, the grid's
    typed figures and its totals, the panel figures and the hints under the
    cash boxes (the owner, 25 Sep 2026: "use black color font").  */
.panes.bill.ws-panes,
.panes.bill.ws-panes .field > span,
.panes.bill.ws-panes .card-head h2,
.panes.bill.ws-panes .tbl.grid td,
.panes.bill.ws-panes .tbl.grid input,
.panes.bill.ws-panes .tbl.grid select,
.panes.bill.ws-panes .tbl.sum td,
.panes.bill.ws-panes .tbl.totals td,
.panes.bill.ws-panes .muted,
.panes.bill.ws-panes .hint,
.panes.bill.ws-panes small { color: #000; }
.panes.bill.ws-panes .tbl.grid thead th { color: #000; }

/*  A LITTLE LARGER (25 Sep 2026, the owner: "increase font size slightly") -
    each size on the wholesale bill up about one step: headings, the examples
    under them, what is typed in the grid, the labels, the panels and the
    shortcut strip. The column widths are the grid's own and still fit.  */
.panes.bill.ws-panes .tbl.grid.ws-grid thead th { font-size: .84rem; }
.panes.bill.ws-panes .tbl.grid.ws-grid thead th .chint { font-size: .8rem; }
.panes.bill.ws-panes .tbl.grid.ws-grid td,
.panes.bill.ws-panes .tbl.grid.ws-grid input,
.panes.bill.ws-panes .tbl.grid.ws-grid select { font-size: 1.02rem; }
.panes.bill.ws-panes .field > span { font-size: .92rem; }
.panes.bill.ws-panes .field > span > .chint { font-size: .82rem; }
.panes.bill.ws-panes .field input,
.panes.bill.ws-panes .field select,
.panes.bill.ws-panes .field textarea { font-size: 1.02rem; }
.panes.bill.ws-panes .tbl.sum td,
.panes.bill.ws-panes .tbl.totals td { font-size: 1.02rem; }
.panes.bill.ws-panes .tbl.sum th,
.panes.bill.ws-panes .tbl.totals th { font-size: .84rem; }
.panes.bill.ws-panes .card-head h2 { font-size: 1.12rem; }
.panes.bill.ws-panes .tick > span { font-size: .92rem; }
.keys { font-size: .86rem; }
.keys kbd { font-size: .8rem; }

/*  THE SHORTCUTS POPUP on the wholesale bill (25 Sep 2026) - the list that was
    a strip above the bill, one shortcut to a line in two columns, black and
    readable.  */
.keys-dlg { width: min(46rem, 94vw); padding: 16px 18px; border: 1px solid var(--line); border-radius: 12px; }
.keys-dlg::backdrop { background: rgba(0, 0, 0, .35); }
.keys-dlg-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.keys-dlg-head h3 { margin: 0; font-size: 1.15rem; color: #000; }
.keys-dlg .keys-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 22px; margin: 0; color: #000; font-size: .95rem; }
.keys-dlg .keys-list span { white-space: normal; padding: 4px 0; border-bottom: 1px dashed var(--line); }
.keys-dlg .keys-list kbd { font-size: .86rem; margin-right: 2px; }
.keys-dlg-foot { margin: 12px 0 0; color: #000; font-size: .88rem; }
@media (max-width: 600px) { .keys-dlg .keys-list { grid-template-columns: 1fr; } }
/*  Larger in the popup (25 Sep 2026, the owner: "increase font size").  */
.keys-dlg { width: min(54rem, 94vw); padding: 20px 24px; }
.keys-dlg-head h3 { font-size: 1.4rem; }
.keys-dlg .keys-list { font-size: 1.12rem; gap: 10px 28px; }
.keys-dlg .keys-list span { padding: 7px 0; }
.keys-dlg .keys-list kbd { font-size: 1rem; padding: 2px 7px; min-width: 1.6rem; }
.keys-dlg-foot { font-size: 1rem; }

/*  A HIDDEN FORM BOX STAYS HIDDEN (25 Sep 2026). `.field` sets its own
    display, which beat the browser's [hidden] - so the wholesale Settle box
    ("To fine") showed on the sale AND the purchase though both said hidden.  */
.field[hidden], label.field[hidden] { display: none !important; }

/*  THE TWO ARROWS BEFORE FIND BILL on the wholesale bill (25 Sep 2026).  */
.ws-arrows { display: inline-flex; gap: 6px; }
.ws-arrows .btn { color: #000; font-weight: 700; }
.ws-arrows .btn.is-off { opacity: .4; pointer-events: none; }

/*  THE TWO RIGHT-HAND PANELS, A LITTLE SMALLER AND STILL BOLD (25 Sep 2026,
    the owner: "slightly reduce font, keep bold"). The labels no longer break
    inside a word ("Gol / d", "Toda / y") - the first column keeps each word
    whole and takes the width it needs - and the headings fit their columns.  */
.panes.bill.ws-panes #wdetail .tbl td,
.panes.bill.ws-panes #wsum .tbl td { font-size: .9rem; font-weight: 700; }
.panes.bill.ws-panes #wdetail .tbl th,
.panes.bill.ws-panes #wsum .tbl th { font-size: .72rem; font-weight: 800; white-space: nowrap; overflow: visible; }
.panes.bill.ws-panes #wdetail .tbl td:first-child,
.panes.bill.ws-panes #wsum .tbl td:first-child {
    font-size: .9rem; font-weight: 700;
    white-space: nowrap; overflow-wrap: normal; word-break: normal;
    width: auto;
}
.panes.bill.ws-panes #wdetail .tbl tr > :nth-child(1),
.panes.bill.ws-panes #wsum .tbl tr > :nth-child(1) { width: auto; }
.panes.bill.ws-panes #wdetail .card-head h2,
.panes.bill.ws-panes #wsum .card-head h2 { font-size: 1.02rem; font-weight: 800; }
.panes.bill.ws-panes #wsum .field > span { font-size: .86rem; font-weight: 700; }

/*  WHOLESALE TOP BAR IN GOLD (the owner, 25 Sep 2026: "change background
    colour as golden") - a fixed gold, not --accent, so it stays gold on every
    theme. Only the bill/purchase screen has #btn-keys in its head.  */
.pagehead:has(#btn-keys) {
    background: linear-gradient(90deg, #F6D77A 0%, #E8B84A 55%, #D9A23A 100%);
    border: 1px solid #C99A2E; border-radius: 10px;
    padding: 8px 14px; margin-bottom: 10px;
}
.pagehead:has(#btn-keys) h1 { color: #1B1305; }
.pagehead:has(#btn-keys) .btn { background: #FFF8E6; border-color: #B8891F; color: #1B1305; }
.pagehead:has(#btn-keys) .btn:hover { background: #fff; }
.pagehead:has(#btn-keys) #find-doc { background: #FFFDF6; border-color: #B8891F; }

/*  GRID HEADINGS CENTRED (the owner, 25 Sep 2026: "do these label as center
    aligned") - heading and its example line, on both grids.  */
.ws-grid thead th, .ws-grid thead th.r { text-align: center; }
.ws-grid thead th .chint { text-align: center; }

/*  ROOM FOR "EXIT FULL SCREEN" (25 Sep 2026: "refresh button overlap to Esc
    full screen") - that button is fixed at the top right, so the gold bar
    keeps its right end clear and Refresh stops under it.  */
body.fullscreen .pagehead:has(#btn-keys) { padding-right: 190px; }

/*  Previous / Next now sit either side of Find bill (25 Sep 2026).  */
.ws-arrow { color: #000; font-weight: 700; }
.ws-arrow.is-off { opacity: .4; pointer-events: none; }


/*  WHOLESALE PREVIEW POPUP (25 Sep 2026) - the printed copy in a frame.  */
.prev-dlg { width: min(1100px, 96vw); height: 92vh; max-height: 92vh; padding: 0; border: 1px solid var(--line-strong); border-radius: 12px; background: #fff; color: #000; overflow: hidden; }
.prev-dlg[open] { display: flex; flex-direction: column; }
.prev-dlg::backdrop { background: rgba(0,0,0,.45); }
.prev-dlg-head { display: flex; align-items: center; gap: 8px; padding: 8px 14px; background: linear-gradient(90deg, #F6D77A, #D9A23A); }
.prev-dlg-head h3 { margin: 0; font-size: 1.05rem; color: #1B1305; }
.prev-dlg-head .btn { background: #FFF8E6; border-color: #B8891F; color: #1B1305; }
.prev-dlg iframe { flex: 1; width: 100%; border: 0; background: #fff; }
.prev-dlg iframe[hidden], .prev-dlg-none[hidden] { display: none; }
.prev-dlg-none { padding: 40px 24px; text-align: center; font-size: 1.05rem; }

/*  SUMMARY: GOLD MOVED LEFT, ROOM BEFORE AMOUNT (25 Sep 2026: "shift gold to
    left", "space b/w gold and amount").  */
.panes.bill.ws-panes #wsum .tbl .m-gold,
.panes.bill.ws-panes #wsum .tbl .m-silver { padding-right: 26px; }
.panes.bill.ws-panes #wsum .tbl tr > :last-child { padding-left: 14px; }

/*  SUMMARY COLUMNS, SET OUTRIGHT (25 Sep 2026, "not adjusted, shift gold
    column to left"): the label a fixed quarter, Amount a fixed third, and
    the metal columns share the middle with a wide gap on their right - so
    Gold ends well short of Amount instead of running into it.  */
.panes.bill.ws-panes #wsum .tbl.sum tr > :nth-child(1) { width: 24%; }
.panes.bill.ws-panes #wsum .tbl.sum tr > :nth-child(2),
.panes.bill.ws-panes #wsum .tbl.sum tr > :nth-child(3) { width: auto; }
.panes.bill.ws-panes #wsum .tbl.sum tr > :nth-child(4) { width: 36%; }
.panes.bill.ws-panes #wsum .tbl.sum td.m-gold, .panes.bill.ws-panes #wsum .tbl.sum th.m-gold,
.panes.bill.ws-panes #wsum .tbl.sum td.m-silver, .panes.bill.ws-panes #wsum .tbl.sum th.m-silver { padding-right: 34px; }
.panes.bill.ws-panes #wsum .tbl.sum tr > :nth-child(4) { padding-left: 10px; padding-right: 6px; }

/*  TODAY ROW IN GREEN (25 Sep 2026: "background of today row should be
    greenish") - the Summary's own Today line.  */
.panes.bill.ws-panes #wsum .tbl.sum tr.is-sum td { background: #D6F2DC; color: #000; }

/*  OLD ROW IN RED (25 Sep 2026: "background reddish") - the balance brought
    forward, the row holding #o-g.  */
.panes.bill.ws-panes #wsum .tbl.sum tr:has(#o-g) td { background: #F8D7D7; color: #000; }

/*  GRID FIGURES CENTRED (25 Sep 2026: "should be centered align") - the
    boxes and the worked-out cells on both grids and their Total rows, under
    the centred headings. Group and item stay left.  */
.panes.bill.ws-panes .ws-grid tbody td.r,
.panes.bill.ws-panes .ws-grid tfoot td.r,
.panes.bill.ws-panes .ws-grid tbody td input.r,
.panes.bill.ws-panes .ws-grid tbody td input.mono { text-align: center; }

/*  "Cash received from party" in green bold (25 Sep 2026).  */
.panes.bill.ws-panes #wsum .field:has(#cash-in) > span { color: #1B7F3A; font-weight: 800; }
/*  "Cash paid to party" in red bold (25 Sep 2026).  */
.panes.bill.ws-panes #wsum .field:has(#cash-out) > span { color: #C0262D; font-weight: 800; }

/*  PREVIEW POPUP WIDTH (25 Sep 2026: "popup width issue") - every dialog is
    capped at 40rem, which squeezed the bill sheet; this one takes most of the
    window. The corner x that site.js adds to every dialog is its close, so
    the head keeps clear of it and the extra Close button goes.  */
dialog.prev-dlg { max-width: 1280px; width: 96vw; height: 94vh; max-height: 94vh; padding: 0; }
dialog.prev-dlg .prev-dlg-head { padding-right: 52px; }
dialog.prev-dlg .prev-dlg-head h3 { padding-right: 0; margin: 0; }
dialog.prev-dlg #ws-preview-close { display: none; }
dialog.prev-dlg .dlg-x { top: 7px; right: 10px; z-index: 2; }

/*  THE FOOTER ON ONE ROW, AND LOW (25 Sep 2026: "arrange footer in one row",
    "compact height") - smaller logos and badge, tighter padding, and the
    copyright sits in the row instead of dropping under it. A phone still
    stacks it (the 640px rule above).  */
@media (min-width: 641px) {
    .footer.app-footer { padding: 6px 16px; font-size: .78rem; }
    .app-footer .footer-in { flex-wrap: nowrap; gap: 6px 16px; white-space: nowrap; }
    .app-footer .footer-brand img { height: 30px; border-radius: 6px; }
    .app-footer .footer-links, .app-footer .footer-call { flex-wrap: nowrap; gap: 4px 10px; }
    .app-footer .footer-by img { height: 24px; }
    .app-footer .footer-copy { order: 99; color: var(--ink-faint); font-size: .74rem; }
    .app-footer .play-badge.in-foot { padding: 3px 10px; }
    .app-footer .play-badge.in-foot .play-words b { font-size: .8rem; }
    .app-footer .play-badge.in-foot .play-mark { width: 16px; height: 18px; }
}

/*  THE RETURN SCAN on the jama head, and a returned line marked red at the
    item (25 Sep 2026, sale return).  */
#scan-back-wrap input { width: 9rem; font-family: var(--mono); font-size: .82rem; border-color: #C0262D; }
.tbl.grid tr.is-return [data-col="item"] { box-shadow: inset 3px 0 0 #C0262D; }

/*  A BOX THE SHELF DOES NOT HAVE, in red (25 Sep 2026 - Box out 1*250 with
    no 250 g box in stock). The reason is on the box's own tooltip.  */
.ws-grid input.w-box.is-short { background: #FDE2E2 !important; border-color: #C0262D !important; color: #9B1C1C !important; font-weight: 700; }

/*  WEIGHT / LESS WITHOUT FIGURES RUNNING TOGETHER (25 Sep 2026, mixed
    window: "250.000250.000"). The panel is narrow there; the table sizes
    itself to its figures, a little smaller, with a gap between columns.  */
.panes.bill.ws-panes #wdetail .tbl.totals { table-layout: auto; }
.panes.bill.ws-panes #wdetail .tbl.totals tr > * { width: auto !important; }
.panes.bill.ws-panes #wdetail .tbl.totals td.mono,
.panes.bill.ws-panes #wdetail .tbl.totals td.r { font-size: .8rem; padding-left: 8px; white-space: nowrap; }
.panes.bill.ws-panes #wdetail .tbl.totals th { padding-left: 8px; }

/*  THE FULL-SCREEN BUTTON ON THE WHOLESALE BAR (25 Sep 2026) - the way in
    when the chrome is showing, the way out when it is not. The corner pill
    is not needed on this screen, so the bar no longer keeps room for it.  */
.pagehead .ws-full { padding: 6px 9px !important; line-height: 0; }
.pagehead .ws-full svg { width: 18px; height: 18px; }
.pagehead .ws-full-out { display: none; }
body.fullscreen .pagehead .ws-full-in { display: none; }
body.fullscreen .pagehead .ws-full-out { display: inline-flex; }
body.fullscreen:has(.pagehead .ws-full-out) .fullbar { display: none; }
body.fullscreen .pagehead:has(.ws-full-out) { padding-right: 14px; }

/*  THE BHAV PANEL ACROSS THE WHOLE WIDTH (25 Sep 2026: "increase width of
    panel") - the grid ended two-thirds of the way across while its Total
    row ran to the edge, and the rate and gold boxes cut their own figures
    off (150000 -> 15000(, 13.267 -> 13.26). The table now fills the panel,
    the boxes are wide enough for a full figure, and "What it does" takes
    what is left.  */
.ws-panes .ws-bhav #bhav-grid { width: 100% !important; min-width: 100%; table-layout: auto !important; }
.ws-panes .ws-bhav #bhav-grid [data-col="no"]      { width: 3rem; }
.ws-panes .ws-bhav #bhav-grid [data-col="del"]     { width: 2rem; }
.ws-panes .ws-bhav #bhav-grid [data-col="group"]   { width: 9rem; }
.ws-panes .ws-bhav #bhav-grid [data-col="brate"],
.ws-panes .ws-bhav #bhav-grid [data-col="bpure"]   { width: 10rem; }
.ws-panes .ws-bhav #bhav-grid [data-col="gold"],
.ws-panes .ws-bhav #bhav-grid [data-col="silver"]  { width: 10rem; }
.ws-panes .ws-bhav #bhav-grid [data-col="bamount"] { width: 11rem; }
.ws-panes .ws-bhav #bhav-grid [data-col="beffect"] { width: auto; }
.ws-panes .ws-bhav #bhav-grid td input,
.ws-panes .ws-bhav #bhav-grid td select { width: 100%; min-width: 0; box-sizing: border-box; }

/*  RETAIL SALE WITHOUT RECENT BILLS (26 Sep 2026) - the totals keep their
    place at the right, their own width.  */
.panes.bill.no-recent { display: flex; justify-content: flex-end; }
.panes.bill.no-recent > #totals { width: min(100%, 26rem); }

/*  RETAIL SALE: TOTALS AT THE TOP RIGHT (26 Sep 2026) - the head and the
    lines take the room on the left, the totals a column of their own from
    the top. A narrow window stacks them, totals under the lines.  */
.rs-layout { display: grid; grid-template-columns: minmax(0, 1fr) 22rem; gap: 14px; align-items: start; }
.rs-layout > .rs-main { min-width: 0; display: grid; gap: 14px; }
.rs-layout > .rs-main > .card { margin: 0; }
.rs-layout > .panes.bill.no-recent { display: block; margin: 0; }
.rs-layout > .panes.bill.no-recent > #totals { width: auto; margin: 0; position: sticky; top: 8px; }
@media (max-width: 1100px) {
    .rs-layout { grid-template-columns: minmax(0, 1fr); }
}

/*  The retail sale's arrows and number, in its own heading row (26 Sep 2026).  */
.pagehead .rs-steps { display: inline-flex; align-items: center; }
.rs-layout > .rs-main > .pagehead { margin: 0; }
.rs-layout > .rs-main > dialog, .rs-layout > .rs-main > script { display: none; }
.rs-layout > .rs-main > dialog[open] { display: block; }

/*  RETAIL SALE LIKE THE GOLD BILL (26 Sep 2026): the gold bar across the top,
    then two halves that fill the window - the customer and lines on the left,
    the summary on the right running the full height, its card stretched.  */
.rs-layout { align-items: stretch; margin-top: 10px; }
.rs-layout > .rs-main { align-content: start; }
.rs-layout > .panes.bill.no-recent { display: flex; flex-direction: column; min-height: 0; }
.rs-layout > .panes.bill.no-recent > #totals { flex: 1 1 auto; position: static; display: flex; flex-direction: column; }
@media (max-width: 1100px) {
    .rs-layout > .panes.bill.no-recent > #totals { flex: none; }
}

/*  Retail Sale's Find bill on the gold bar, between the arrows (26 Sep 2026).  */
.pagehead .rs-find input { width: 13rem; padding: 7px 10px; border-radius: 6px; }
.pagehead:has(#btn-keys) #bill-find { background: #FFFDF6; border: 1px solid #B8891F; }

/*  THE SUMMARY FLUSH RIGHT AND NARROWER (26 Sep 2026: "shift completely in
    right, no space in right, shrink this panel width") - the column is
    18rem, the card fills it edge to edge, and the halves span the full
    width of the bar above.  */
.rs-layout { width: 100%; grid-template-columns: minmax(0, 1fr) 18rem !important; }
.rs-layout > .panes.bill.no-recent { width: 100%; max-width: none; justify-self: stretch; padding: 0; }
.rs-layout > .panes.bill.no-recent > #totals { width: 100% !important; max-width: none !important; margin: 0 !important; box-sizing: border-box; }
/* (the 7.5rem box width of 26 Sep went - it caught the GST tick too) */

/*  RETAIL IN BLUE (26 Sep 2026: "change background colour for retail, use
    bluish") - the wholesale bill keeps its gold bar; the retail sale's bar
    (the one holding #bill-find) is blue, so a glance says which counter.  */
.pagehead:has(#bill-find) {
    background: linear-gradient(90deg, #D6E8FB 0%, #A9CBF2 55%, #7FAEE6 100%);
    border-color: #5B8DC9;
}
.pagehead:has(#bill-find) h1 { color: #0E2A4F; }
.pagehead:has(#bill-find) .btn { background: #F4F9FF; border-color: #5B8DC9; color: #0E2A4F; }
.pagehead:has(#bill-find) .btn:hover { background: #fff; }
.pagehead:has(#btn-keys) #bill-find { background: #FBFDFF; border-color: #5B8DC9; }

/*  THE TOTALS INSIDE THEIR CARD (26 Sep 2026, "check it"): figures ran past
    the card's right edge and the GST tick was stretched to a box's width.
    The table is the card's width, label and figure share it, the boxes
    fill their cell, and the tick is a tick.  */
.rs-layout #totals .tbl.totals { width: 100%; table-layout: fixed; }
.rs-layout #totals .tbl.totals td { padding: 4px 6px; }
.rs-layout #totals .tbl.totals td:first-child { width: 52%; }
.rs-layout #totals .tbl.totals td.r { text-align: right; white-space: nowrap; }
.rs-layout #totals .tbl.totals input.tiny { width: 100%; max-width: 100%; box-sizing: border-box; }
.rs-layout #totals .tbl.totals input[type="checkbox"] { width: auto; flex: none; }
.rs-layout #totals .tbl.totals label.check { display: inline-flex; align-items: center; gap: 6px; width: auto; white-space: nowrap; }

/*  RETAIL SALE ON ONE SCREEN, NO VERTICAL SCROLL (26 Sep 2026).
    In full screen the site footer is not drawn under the bill - the halves
    already run to the foot of the window, so a footer below them was the
    scroll. And everything is a notch tighter: the bar, the bill head, the
    lines' head, and the totals' rows and boxes.  */
body.fullscreen:has(.rs-layout) .app-footer { display: none; }
body.fullscreen:has(.rs-layout) .shell { padding-top: 6px; padding-bottom: 6px; }
.rs-layout { margin-top: 8px; gap: 10px; }
.rs-layout > .rs-main { gap: 10px; }
.pagehead:has(#bill-find) { padding-top: 5px; padding-bottom: 5px; margin-bottom: 0; }
.rs-layout .card { padding-top: 10px; padding-bottom: 10px; }
.rs-layout .card.billhead .field { margin-top: 2px; }
.rs-layout .card.billhead .field > span { margin-bottom: 2px; }
.rs-layout .card.billhead input,
.rs-layout .card.billhead select { padding-top: 5px; padding-bottom: 5px; }
.rs-layout #totals .card-head { margin-bottom: 4px; padding-bottom: 4px; }
.rs-layout #totals .tbl.totals td { padding: 2px 6px; line-height: 1.25; }
.rs-layout #totals .tbl.totals input.tiny { padding: 3px 6px; height: 28px; }
.rs-layout #totals .actions { margin-top: 6px; }

/*  NO GAP UNDER THE BLUE BAR (26 Sep 2026: "remove this gap or margin") -
    the page column's own 10px gap, the halves' top margin and the first
    card's margin added up under the bar. One small gap is left.  */
.shell-main:has(> .rs-layout) { gap: 0; }
.rs-layout { margin-top: 6px !important; }
.rs-layout > .rs-main > :first-child,
.rs-layout > .rs-main > .card.billhead { margin-top: 0 !important; }
.rs-layout > .panes.bill.no-recent { margin-top: 0 !important; }

/*  THE SUMMARY NARROWER STILL (26 Sep 2026: "now shrink this panel width") -
    15rem, the wholesale bill's own right-hand width; labels a little
    smaller, the boxes share the half they sit in.  */
.rs-layout { grid-template-columns: minmax(0, 1fr) 15rem !important; }
.rs-layout #totals { padding-left: 8px; padding-right: 8px; }
.rs-layout #totals .tbl.totals td { padding: 2px 4px; font-size: .88rem; }
.rs-layout #totals .tbl.totals td:first-child { width: 50%; }
.rs-layout #totals .card-head h2 { font-size: 1rem; }
.rs-layout #totals .card-head .muted { font-size: .72rem; }

/*  NARROWER BOXES in the summary (26 Sep 2026: "reduce textbox width") -
    wide enough for 1,00,000.00, right-aligned against the figures above.  */
.rs-layout #totals .tbl.totals td:first-child { width: 56%; }
.rs-layout #totals .tbl.totals input.tiny { width: 5.6rem; max-width: 100%; height: 26px; padding: 2px 5px; text-align: right; }

/*  SEVEN FIGURES AND NO MORE (26 Sep 2026: "reduce textbox width, maximum 7
    number can be there") - each summary box is exactly seven digits wide in
    the figure face, and the screen stops an eighth being typed.  */
.rs-layout #totals .tbl.totals input.tiny {
    font-family: var(--mono); font-size: .9rem;
    width: calc(7ch + 14px) !important; padding: 2px 6px; box-sizing: border-box;
    -moz-appearance: textfield;
}
.rs-layout #totals .tbl.totals input.tiny::-webkit-outer-spin-button,
.rs-layout #totals .tbl.totals input.tiny::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/*  LABEL AND FIGURE SIDE BY SIDE (26 Sep 2026: "reduce label and value
    column gap, white spaces") - the summary is as wide as its longest label
    plus a seven-digit figure and no wider: the column sizes to its content,
    the table to its rows, and a small fixed gap sits between the two.  */
.rs-layout { grid-template-columns: minmax(0, 1fr) max-content !important; }
.rs-layout > .panes.bill.no-recent { width: max-content; }
.rs-layout #totals .tbl.totals { width: auto; table-layout: auto; }
.rs-layout #totals .tbl.totals td:first-child { width: auto; white-space: nowrap; padding-right: 10px; }
.rs-layout #totals .tbl.totals td.r { width: auto; padding-left: 0; }

/*  RETAIL SALE GRID CENTRED (26 Sep 2026: "label center aligned, also
    numeric input center aligned") - every heading and its example line, and
    every figure box and worked-out figure on the lines. The item name stays
    left, where a description reads.  */
#grid thead th, #grid thead th.r, #grid thead th .chint { text-align: center; }
#grid tbody td.r, #grid tfoot td.r,
#grid tbody input[type="number"], #grid tbody input.r, #grid tbody input.mono { text-align: center; }

/*  THE DAY'S RATES ON THE BLUE BAR, after "Retail Sale" (26 Sep 2026) -
    label and box on one line, the box wide enough for 1,50,000.00.  */
.pagehead .rs-rates { display: inline-flex; align-items: center; gap: 12px; margin-left: 14px; }
.pagehead .rs-rate { display: inline-flex; align-items: center; gap: 6px; margin: 0; width: auto; }
.pagehead .rs-rate > span { font-size: .82rem; font-weight: 700; color: #0E2A4F; white-space: nowrap; margin: 0; }
.pagehead .rs-rate input { width: 8.5rem; padding: 6px 8px; text-align: center; background: #FBFDFF; border: 1px solid #5B8DC9; border-radius: 6px; font-family: var(--mono); }

/*  The retail bar's tools, one group on the right (26 Sep 2026).  */
.pagehead .rs-tools { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }

/*  THE BAR, CORRECTED (26 Sep 2026: "correct this layout, shift right icon
    to rightmost, spaces are there"). The empty strip at the right was the
    190px once kept for the corner "Exit full screen" pill, which a bar with
    its own full-screen button no longer shows; the rate labels stood over
    their boxes because the field layout outranked the bar's. Both settled
    here, and the bar's items centre on one line.  */
body.fullscreen .pagehead:has(.ws-full-out),
.pagehead:has(.ws-full-out) { padding-right: 12px !important; }
.pagehead:has(#bill-find) { align-items: center !important; }
.pagehead .rs-rate { display: inline-flex !important; flex-direction: row !important; align-items: center !important; gap: 6px !important; }
.pagehead .rs-rate > span { margin: 0 !important; }
.pagehead .rs-rate input { width: 8rem !important; margin: 0 !important; }
.pagehead .rs-tools { margin-right: 0; }

/*  DUE IN RED, ADVANCE IN BLUE (26 Sep 2026) - the Retail Sale summary's
    last two rows, label and figure alike.  */
#totals .tbl.totals tr:has(#t-due) td,
#totals .tbl.totals tr:has(#t-due) td * { color: #C0262D !important; }
#totals .tbl.totals tr:has(#t-advance) td,
#totals .tbl.totals tr:has(#t-advance) td * { color: #1F5FAF !important; font-weight: 700; }

/*  OLD ₹ IN RED (26 Sep 2026) - the balance brought forward, a light red
    band like the wholesale summary's Old row.  */
#totals .tbl.totals tr:has(#t-old-balance) td { background: #F8D7D7; color: #000; }

/*  GRAND IN GREEN BOLD (26 Sep 2026).  */
#totals .tbl.totals tr:has(#t-grand) td,
#totals .tbl.totals tr:has(#t-grand) td * { color: #1B7F3A !important; font-weight: 800; }

/*  COUNTER POS COLOURS, as the Retail Sale (26 Sep 2026): OLD ₹ in a red
    band, TOTAL green bold, DUE red.  */
.rs-layout.pos #totals .tbl.totals tr:has(#t-old) td { background: #F8D7D7; color: #000; }
.rs-layout.pos #totals .tbl.totals tr:has(#t-total) td,
.rs-layout.pos #totals .tbl.totals tr:has(#t-total) td * { color: #1B7F3A !important; font-weight: 800; }
.rs-layout.pos #grid thead th, .rs-layout.pos #old-grid thead th { text-align: center; }
.rs-layout.pos #grid tbody td.r, .rs-layout.pos #grid tbody input.r,
.rs-layout.pos #old-grid tbody td.r, .rs-layout.pos #old-grid tbody input.r { text-align: center; }

/*  RETAIL PURCHASE GRID CENTRED LIKE THE RETAIL SALE (26 Sep 2026) - the
    purchase's roomy grid, headings, examples, figure boxes and worked-out
    figures; the item name stays left.  */
.rs-layout #grid.grid-roomy thead th,
.rs-layout #grid.grid-roomy thead th .chint,
.rs-layout #grid.grid-roomy tbody td.r,
.rs-layout #grid.grid-roomy tbody input.r { text-align: center !important; }

/*  THE PURCHASE REGISTER'S ITEMS POPUP (26 Sep 2026) - the count is a link,
    the popup a table as wide as it needs.  */
.items-open { font-weight: 700; text-decoration: underline; cursor: pointer; }
.items-dlg { width: min(1000px, 96vw); max-width: 96vw; }
.items-dlg-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; padding-right: 36px; }
.items-dlg-head h3 { margin: 0; padding: 0; }
.items-dlg .tbl td, .items-dlg .tbl th { text-align: center; white-space: nowrap; }
.items-dlg .tbl td.l, .items-dlg .tbl th.l { text-align: left; }

/*  EVERY REPORT'S TOTAL ROW ON A BLUE BAND (26 Sep 2026: "keep bluish
    background for all reports total in footer") - the whole foot row,
    the highlighted money cell included, so the total reads as one line.
    Screens only; paper keeps plain white.  */
@media screen {
    .tbl tfoot th, .tbl tfoot td { background: #DCEBFB !important; color: #0E2A4F; font-weight: 700; border-top: 2px solid #7FAEE6; }
    .tbl tfoot th.c-money, .tbl tfoot td.c-money { color: #0E4D24 !important; }
    .tbl tfoot th.c-gold, .tbl tfoot td.c-gold { color: #7A5200 !important; }
}

/*  CASH BLUE, UPI GREEN - AT ALL PLACES (26 Sep 2026). Report columns and
    their totals (c-cash / c-upi), and the CASH and UPI rows of every bill's
    Totals panel, label and box alike.  */
.c-cash, .tbl td.c-cash, .tbl th.c-cash { color: #1F5FAF !important; }
.c-upi, .tbl td.c-upi, .tbl th.c-upi { color: #1B7F3A !important; }
#totals .tbl.totals tr:has(#f-cash) td { color: #1F5FAF; font-weight: 700; }
#totals .tbl.totals tr:has(#f-cash) input { color: #1F5FAF; border-color: #7FAEE6; font-weight: 700; }
#totals .tbl.totals tr:has(#f-upi) td { color: #1B7F3A; font-weight: 700; }
#totals .tbl.totals tr:has(#f-upi) input { color: #1B7F3A; border-color: #8FCFA3; font-weight: 700; }

/*  DUE IN LIGHT RED - AT ALL PLACES (26 Sep 2026). Every Due column, its
    heading and its total on a light red band with dark red figures; the
    bills' Totals panels already print DUE in red.  */
.tbl td.c-due, .tbl th.c-due { background: #FDE8E8 !important; color: #9B1C1C !important; }
.tbl thead th.c-due { background: #F8D2D2 !important; }
.tbl tfoot td.c-due, .tbl tfoot th.c-due { background: #F6C9C9 !important; color: #7F1414 !important; }
.tbl td.c-due.c-money:not(:empty) { background: #FDE8E8 !important; color: #9B1C1C !important; }

/*  ...AND THE LABELS OF CASH AND UPI BOXES ON EVERY FORM (26 Sep 2026: "at
    all places") - receipts, expenses, mortgage and the rest. The wholesale
    bill's own cash labels keep their green and red, which outrank this.  */
.field:has(> input[id*="cash" i]) > span, .field:has(> input[class*="cash" i]) > span { color: #1F5FAF; font-weight: 700; }
.field:has(> input[id*="upi" i]) > span, .field:has(> input[class*="upi" i]) > span { color: #1B7F3A; font-weight: 700; }

/*  REPORTS PRINT IN LANDSCAPE, FIGURES WHOLE (26 Sep 2026: "also check
    preview", "make it in landscape"). A twelve-column register on a portrait
    sheet broke every figure in half - "4,50,/122", "BIL/LS". Every page in
    the signed-in shell prints on A4 landscape through a NAMED page, so bill
    sheets (their own layout, their own paper) are untouched; figures and
    headings never break inside a word; a long name may still wrap.  */
@media print {
    .shell-main { page: report; }
    .tbl td.mono, .tbl th.mono, .tbl td.r, .tbl th.r, .tbl tfoot th, .tbl tfoot td {
        white-space: nowrap !important; overflow-wrap: normal !important; word-break: normal !important;
    }
    .tbl thead th { overflow-wrap: normal !important; word-break: keep-all !important; }
    .tbl { font-size: 8.5pt !important; }
    .tbl th, .tbl td { padding: 1.4mm 1.6mm !important; }
}
@page report { size: A4 landscape; margin: 10mm 8mm; }

/*  THE PARTY POPUP IN FIVE COLUMNS (26 Sep 2026: "make this compact, convert
    to five column popup"). The popup is wide; the form is one five-column
    grid and its rows dissolve into it, so every box takes one cell - Name and
    Address take two, the head, the opening note, Note and the buttons the
    whole width. The bank row still hides itself for customers (an inline
    display:none outranks this).  */
dialog#editor-box { width: min(1080px, 96vw); max-width: 96vw; padding: 14px 18px; }
#editor-box #editor { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px 12px; align-items: end; }
#editor-box #editor > .row { display: contents; }
#editor-box #editor > .row.editor-top { display: flex; grid-column: 1 / -1; margin-bottom: 2px; }
#editor-box #editor .field { flex: none !important; width: auto; min-width: 0; margin: 0; }
#editor-box #editor .field > input, #editor-box #editor .field > select { width: 100%; min-width: 0; box-sizing: border-box; padding-top: 6px; padding-bottom: 6px; }
#editor-box #editor .field:has(#f-name), #editor-box #editor .field:has(#f-addr1) { grid-column: span 2; }
#editor-box #editor > .row > .hint { grid-column: span 2; align-self: center; font-size: .78rem; margin: 0; padding: 4px 8px; }
#editor-box #editor > .field:has(#f-remarks) { grid-column: 1 / -1; }
#editor-box #editor > .actions { grid-column: 1 / -1; margin-top: 4px; }
#editor-box #kind-fixed { display: inline-block; white-space: nowrap; }
@media (max-width: 760px) {
    #editor-box #editor { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/*  The wholesale Vendors/Party popup shares the ids, so it takes the same
    five columns; its second address line takes two cells beside the first.  */
#editor-box #editor .field:has(#f-addr2) { grid-column: span 2; }

/*  THE DASHBOARD WELCOME, COMPACT (26 Sep 2026: "compact this height") -
    "Welcome to" beside the name on one line, the name smaller, the date and
    Scan side by side instead of stacked, and less padding all round.  */
.md-hero { margin: 8px 0 10px; padding: 10px 20px; gap: 10px 22px; }
.md-hero-brand { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; row-gap: 0; }
.md-welcome { font-size: 1.15rem; }
.md-name { font-size: 2rem; }
.md-tag { flex-basis: 100%; margin-top: 2px; font-size: .78rem; }
.md-hero-shop { gap: 2px; padding-left: 18px; }
.md-hero-shop b { font-size: 1.1rem; }
.md-side { display: flex !important; flex-direction: row !important; align-items: center; gap: 10px; }
.md-date { padding: 6px 14px 6px 50px; min-width: 170px; }
.md-date-ico { top: 50%; transform: translateY(-50%); left: 14px; width: 26px; height: 26px; }
.md-date-ico svg { width: 26px; height: 26px; }
.md-date b { font-size: 1rem; }
.md-scan { padding: 10px 22px; white-space: nowrap; }

/*  THE MORTGAGE "NEW REFERRER" POPUP IN FIVE COLUMNS (26 Sep 2026), like the
    party popups: wide, one grid, name and address two cells each.  */
dialog.five-col { width: min(1000px, 96vw); max-width: 96vw; }
dialog.five-col { display: none; }
dialog.five-col[open] { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px 12px; align-items: end; }
dialog.five-col > h3, dialog.five-col > p, dialog.five-col > .actions { grid-column: 1 / -1; margin: 0; }
dialog.five-col > .row { display: contents; }
dialog.five-col .field { flex: none !important; min-width: 0; margin: 0; }
dialog.five-col .field.wide { grid-column: span 2; }
dialog.five-col .field > input, dialog.five-col .field > select { width: 100%; box-sizing: border-box; }
@media (max-width: 760px) { dialog.five-col[open] { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/*  MORTGAGE PAYMENT RECEIVING AND RELEASE, TWO HALVES (26 Sep 2026). The
    right half holds a real form or a ten-column table, so it is wider than
    a bill's totals: the lists take a little more than half, the entry the
    rest. The payment form stacks its boxes two to a row.  */
.rs-layout.wide-side { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) !important; }
.rs-layout.wide-side > .panes.bill.no-recent { width: auto; }
.rs-layout.wide-side > .panes.bill.no-recent > .card { width: 100% !important; box-sizing: border-box; }
#pay-entry > .row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; }
#pay-entry > .row > .field { flex: none !important; min-width: 0; }
#pay-entry > .row > .field.wide { grid-column: 1 / -1; }
#pay-entry > .row > .field input, #pay-entry > .row > .field select { width: 100%; box-sizing: border-box; }
#pay-entry > .row > .actions { grid-column: 1 / -1; justify-content: flex-end; }
#pay-entry #p-save { min-width: 9rem; }

/*  ISSUE MORTGAGE: A NARROWER TOTALS PANEL (26 Sep 2026: "reduce panel width
    so that Area fits in one row") - the date box was setting the panel's
    width. It is a fixed small box now, like the seven-figure ones, and the
    left half gets the room back so the customer row stays on one line.  */
.rs-layout #totals .tbl.totals input[type="date"] { width: 9.2rem !important; padding: 2px 4px; font-size: .85rem; }
.rs-layout #totals .tbl.totals td:first-child { font-size: .85rem; }
.rs-layout #totals > .field { margin-top: 6px !important; }
.rs-layout #totals > .field > input { width: 100%; box-sizing: border-box; }
/*  THE BILL DATE WAS HIDDEN UNDER THE TOTALS (1 Oct 2026, the owner: "at retail bill, bill date is hiding"):
    a row that may not wrap ran past its column on a narrower screen. One row
    while it fits; the last box drops to a second line when it does not.  */
.rs-layout > .rs-main .card.billhead .row { flex-wrap: wrap; }
.rs-layout > .rs-main .card.billhead .row > .field { min-width: 0; }
.rs-layout > .rs-main .card.billhead .row > .field > input { min-width: 0; width: 100%; box-sizing: border-box; }

/*  EVERY TABLE IN BLACK (26 Sep 2026: "make all table black font"). The
    ordinary text of every table - headings, cells, totals - is black instead
    of the theme's grey ink; the small grey sub-lines (a mobile under a name,
    Baki under a balance) go near-black. The colours asked for on purpose
    stay: cash blue, UPI green, due red, gold amber, the green bill figure,
    links, and the wholesale grids' own colours.  */
.tbl th, .tbl td { color: #000; }
.tbl td .muted, .tbl td .sub, .tbl th .muted, .tbl .chint { color: #333; }
@media screen { .tbl tfoot th, .tbl tfoot td { color: #000; } }

/*  MULTI MORTGAGE ENTRY ON THE BLUE BAR (26 Sep 2026): the next number and
    the total as two small figures after the name; the grid centred under
    it, full width.  */
.pagehead .mm-fig { display: inline-flex; align-items: baseline; gap: 6px; margin-left: 16px; padding: 4px 10px; border-radius: 6px; background: #F4F9FF; border: 1px solid #5B8DC9; }
.pagehead .mm-fig > span { font-size: .78rem; font-weight: 700; color: #0E2A4F; text-transform: uppercase; letter-spacing: .04em; }
.pagehead .mm-fig > b { font-size: 1.05rem; color: #000; }
.pagehead .mm-total > b { color: #1B7F3A; }
.pagehead:has(#bill-find) .btn.btn-primary { background: #1F4E79; border-color: #1F4E79; color: #fff; }
.mm-card { margin-top: 8px; }
.mm-card #grid thead th, .mm-card #grid thead th .chint, .mm-card #grid tbody td, .mm-card #grid tbody input { text-align: center; }

/*  THE METAL BALANCES IN LIGHT RED (26 Sep 2026: "gold silver in reddish") -
    the wholesale registers' Balance gold and Balance silver, heading and
    figures, on the same light red band as Due.  */
.tbl td.c-bal, .tbl th.c-bal { background: #FDE8E8 !important; color: #9B1C1C !important; }
.tbl thead th.c-bal { background: #F8D2D2 !important; }

/*  THE DAY LINE IN THE REGISTERS, DEEP ORANGE BOLD (26 Sep 2026: "separate
    font colour, use orange deep bold") - "Tuesday, 22 September 2026 · 1
    bill" reads apart from the rows under it. Every register that groups by
    day uses .daybar.  */
.tbl tr.daybar th, .tbl tr.daybar td { color: #C2410C !important; font-weight: 800 !important; }
.tbl tr.daybar th .muted, .tbl tr.daybar td .muted { color: #C2410C !important; font-weight: 700; }

/*  NO SIDEWAYS SCROLL OF THE PAGE (26 Sep 2026: "there is horizontal scroll
    of page, correct it"). The footer was told never to wrap (one row, 26
    Sep) - on a window narrower than its contents that pushed the whole page
    wider than the screen. It keeps one row when there is room and wraps when
    there is not. And a wide table scrolls inside its own box, never the page.  */
@media (min-width: 641px) {
    .app-footer .footer-in { flex-wrap: wrap !important; white-space: normal !important; row-gap: 4px; }
    .app-footer .footer-links, .app-footer .footer-call, .app-footer .footer-by { white-space: nowrap; }
}
.footer.app-footer, .app-footer .footer-in { max-width: 100%; box-sizing: border-box; min-width: 0; }
.shell, .shell-main, main { max-width: 100%; min-width: 0; }
.tblwrap { max-width: 100%; overflow-x: auto; }
/*  CLIP, NOT HIDDEN (26 Sep 2026): overflow hidden on html and body turned the
    body into a scroll box, which broke the sticky navy menu - it scrolled away
    and left a white gap under it on long pages. Clip stops the sideways scroll
    without that.  */
html, body { overflow-x: clip; }

/*  ═══ THE REPORTS' TOP, AS A HERO (26 Sep 2026: "make attractive, put top
    hero") ═══
    Every register and report built the same way - a heading, the summary
    cards (.sides / .sum-card) and the filter strip - gets one look:
      - the heading on a blue bar, the Print button on it, the explaining
        line under the heading gone (the owner took them off page by page);
      - the summary cards as coloured tiles, each its own colour, a thick
        left edge, the figure large;
      - the filters on a card of their own, compact, under the tiles.
    Screen only; paper keeps its plain header.  */
@media screen {
    .pagehead:has(> .head-line) {
        background: linear-gradient(90deg, #D6E8FB 0%, #A9CBF2 55%, #7FAEE6 100%);
        border: 1px solid #5B8DC9; border-radius: 10px; padding: 8px 14px; margin-bottom: 10px;
    }
    .pagehead:has(> .head-line) h1 { color: #0E2A4F; margin: 0; }
    .pagehead:has(> .head-line) .btn { background: #F4F9FF; border-color: #5B8DC9; color: #0E2A4F; }
    .pagehead:has(> .head-line) > .hint { display: none; }
    .pagehead:has(> .head-line) + .sides, .pagehead + .sides { margin-top: 0; }

    .sides:has(> .sum-card) { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 12px; }
    .sides > .sum-card {
        position: relative; margin: 0; padding: 12px 16px 12px 18px; border-radius: 10px;
        border: 1px solid transparent; border-left-width: 6px; box-shadow: 0 2px 8px rgba(14, 42, 79, .08);
    }
    .sides > .sum-card .k { font-size: .76rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
    .sides > .sum-card .big { font-size: 1.6rem; font-weight: 800; }
    .sides > .sum-card .muted { font-size: .78rem; color: #333; }
    .sides > .sum-card:nth-child(4n+1) { background: linear-gradient(135deg, #FFF7E3, #FBE7B5); border-color: #E9C46A; border-left-color: #C8901F; }
    .sides > .sum-card:nth-child(4n+1) .k, .sides > .sum-card:nth-child(4n+1) .big { color: #7A5200; }
    .sides > .sum-card:nth-child(4n+2) { background: linear-gradient(135deg, #F3F4F6, #E2E5EA); border-color: #C5CAD3; border-left-color: #6B7280; }
    .sides > .sum-card:nth-child(4n+2) .k, .sides > .sum-card:nth-child(4n+2) .big { color: #374151; }
    .sides > .sum-card:nth-child(4n+3) { background: linear-gradient(135deg, #E9F7EE, #CDEFD9); border-color: #8FCFA3; border-left-color: #1B7F3A; }
    .sides > .sum-card:nth-child(4n+3) .k, .sides > .sum-card:nth-child(4n+3) .big { color: #14532D; }
    .sides > .sum-card:nth-child(4n+4) { background: linear-gradient(135deg, #EAF2FD, #CFE1F8); border-color: #7FAEE6; border-left-color: #1F5FAF; }
    .sides > .sum-card:nth-child(4n+4) .k, .sides > .sum-card:nth-child(4n+4) .big { color: #0E2A4F; }

    .sides:has(> .sum-card) + form.filters {
        display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px;
        background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 10px 14px; margin-bottom: 12px;
    }
    .sides:has(> .sum-card) + form.filters .field { margin: 0; }
    .sides:has(> .sum-card) + form.filters .field > span { font-size: .76rem; margin-bottom: 2px; }
    .sides:has(> .sum-card) + form.filters input, .sides:has(> .sum-card) + form.filters select { padding-top: 5px; padding-bottom: 5px; }
}

/*  A MARGIN ROUND EVERY PRINTED REPORT (26 Sep 2026: "need preview margin",
    "all reports preview"). The page rule asks the printer for 10mm, but a
    browser set to "Margins: none" ignores it and the figures ran to the
    paper's edge - so the report carries its own margin inside the sheet as
    well. Bills print from their own layout and are untouched.  */
@media print {
    .shell-main { padding: 6mm 7mm !important; box-sizing: border-box; }
    .printhead { margin: 0 0 4mm !important; }
    .tbl tr.daybar th, .tbl tr.daybar td { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

/*  ON PAPER, THE TABLE AND ITS OWN HEADING ONLY (26 Sep 2026: "remove this",
    the name and the summary figures above a printed ledger). The sheet
    already carries the shop and the report on its printed head line and the
    party and range over the table, so the screen's heading and its summary
    tiles printed the same facts twice. Every report prints this way.  */
@media print {
    .shell-main > .pagehead,
    .shell-main > .sides,
    .shell-main > .notice { display: none !important; }
}

/*  A BORDER ROUND EVERY PRINTED REPORT PAGE (26 Sep 2026: "put page border
    also"). A fixed box is drawn again on every printed page, so a report
    that runs to three sheets has a frame on all three; the report's own
    margin keeps the figures inside it.  */
@media print {
    body:has(.shell-main)::before {
        content: ""; position: fixed; inset: 2.5mm; border: 1px solid #000;
        pointer-events: none; z-index: 1000;
    }
    .shell-main { padding: 7mm 8mm !important; }
}

/*  CASH BOOK AND LEDGER (26 Sep 2026): money in green, money out red, the
    filter a compact card under the tiles, numbers and balances on one line.  */
.tbl td.c-in, .tbl th.c-in { color: #1B7F3A !important; }
.tbl td.c-out, .tbl th.c-out { color: #B42318 !important; }
.card.filter-card { padding: 10px 14px; margin-bottom: 12px; }
.card.filter-card .filters { margin: 0; gap: 8px 12px; align-items: flex-end; }
.card.filter-card .field > span { font-size: .76rem; }
.card.filter-card input, .card.filter-card select { padding-top: 5px; padding-bottom: 5px; }

/*  THE MODULE DASHBOARDS' TOP, COMPACT (26 Sep 2026: "compact it") - the
    Mortgage, Wholesale, Manufacturing and Retail dashboards. The name, the
    "As at" date and the quick buttons share ONE line when they fit: the date
    sits beside its label, the buttons are slimmer and only as wide as their
    words.  */
@media screen and (min-width: 900px) {
    .pagehead:has(> .qa-grid.qa-top) { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; padding: 6px 12px; }
    .pagehead:has(> .qa-grid.qa-top) > .head-line { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; margin: 0; }
    .pagehead:has(> .qa-grid.qa-top) > .head-line > .spacer { display: none; }
    .pagehead:has(> .qa-grid.qa-top) > .head-line .filters { margin: 0; }
    .pagehead:has(> .qa-grid.qa-top) > .head-line .field { display: inline-flex !important; flex-direction: row !important; align-items: center; gap: 6px; margin: 0; flex: none !important; }
    .pagehead:has(> .qa-grid.qa-top) > .head-line .field > span { margin: 0; font-size: .78rem; white-space: nowrap; }
    .pagehead:has(> .qa-grid.qa-top) > .head-line .field > input { width: 9.5rem; padding: 4px 6px; }
    .pagehead > .qa-grid.qa-top { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 0 auto; grid-template-columns: none; grid-auto-rows: auto; }
    .pagehead > .qa-grid.qa-top .qa { min-height: 0 !important; padding: 7px 12px !important; gap: 8px; width: auto; flex: 0 0 auto; border-radius: 8px; }
    .pagehead > .qa-grid.qa-top .qa span { white-space: nowrap; font-size: .86rem; }
    .pagehead > .qa-grid.qa-top .qa svg { width: 16px; height: 16px; flex-basis: 16px; }
}

/*  BALANCE SHEET (26 Sep 2026): liabilities edged red, assets edged green,
    each head row in its side's colour on a light band, ledgers indented in
    black under it.  */
.bsheet .card.bs-liab { border-top: 4px solid #B42318; }
.bsheet .card.bs-asset { border-top: 4px solid #1B7F3A; }
.bsheet .bs-liab .card-head h2 { color: #B42318; }
.bsheet .bs-asset .card-head h2 { color: #1B7F3A; }
.bsheet .bs-liab tr:has(> td.bs-head) td { background: #FDECEC; color: #7F1414 !important; }
.bsheet .bs-asset tr:has(> td.bs-head) td { background: #E9F7EE; color: #14532D !important; }
.bsheet td.bs-ledger { padding-left: 22px !important; }

/*  PROFIT & LOSS (26 Sep 2026): income and profit tiles green, expenses and
    loss red; the table's expense side red and income side green; the net
    profit / loss line on its own band.  */
@media screen {
    .sides > .sum-card.pl-in { background: linear-gradient(135deg, #E9F7EE, #CDEFD9) !important; border-color: #8FCFA3 !important; border-left-color: #1B7F3A !important; }
    .sides > .sum-card.pl-in .k, .sides > .sum-card.pl-in .big { color: #14532D !important; }
    .sides > .sum-card.pl-out { background: linear-gradient(135deg, #FDECEC, #F8D2D2) !important; border-color: #EBA3A3 !important; border-left-color: #B42318 !important; }
    .sides > .sum-card.pl-out .k, .sides > .sum-card.pl-out .big { color: #7F1414 !important; }
    .tbl tr.daysum th { background: #FFF4D6; font-weight: 800; }
}

/*  SUPERADMIN ERROR LOG (26 Sep 2026): the open count on the menu, and the
    shops with open errors as chips above the list.  */
.err-badge { display: inline-block; min-width: 20px; margin-left: 6px; padding: 1px 6px; border-radius: 999px; background: #C0262D; color: #fff; font-size: .72rem; font-weight: 800; text-align: center; line-height: 1.5; }
.err-shops { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.err-shop { display: inline-flex; gap: 8px; align-items: baseline; padding: 6px 12px; border-radius: 8px; border: 1px solid #EBA3A3; background: #FDECEC; color: #7F1414; text-decoration: none; }
.err-shop span { font-size: .8rem; font-weight: 700; }
.err-shop.on { background: #C0262D; color: #fff; border-color: #C0262D; }

/*  CATALOG LINK SETTINGS (26 Sep 2026): the settings popup, the out-of-stock
    badge on a card, and the hide button in red.  */
.cat-linkset-dlg { width: min(30rem, 94vw); }
.cat-linkset-dlg form { display: grid; gap: 8px; }
.cat-linkset-dlg h3 { margin: 0; }
.cat-linkset-dlg hr { border: 0; border-top: 1px solid var(--line); margin: 4px 0; }
.cat-badge.out { background: #FDE2E2; color: #9B1C1C; border-color: #EBA3A3; }
.cat-hide-btn { color: #B42318 !important; border-color: #EBA3A3 !important; }
.cat-stockmode { display: inline-flex !important; flex-direction: row !important; align-items: center; gap: 6px; margin: 0 8px; }
.cat-stockmode > span { margin: 0; }

/* A scan not added - the popup that says why (26 Sep 2026). */
.scan-refused { max-width: 440px; border: 0; border-top: 5px solid #C62828; border-radius: 10px; padding: 18px 22px; }
.scan-refused h3 { margin: 0 0 6px; color: #C62828; }
.scan-refused #scan-refused-tag { margin: 0 0 6px; font-weight: 700; }
.scan-refused #scan-refused-why { margin: 0 0 14px; font-size: 1.02rem; line-height: 1.4; }
.scan-refused::backdrop { background: rgba(0,0,0,.45); }

/*  ═══ HEADER AND MENU STAY, THE PAGE SCROLLS (26 Sep 2026, the owner: "top
    header fixed, menu fixed, only page scroll vertically") ═══
    The bar sticks to the top; the navy menu sticks under it at exactly the
    height left on the screen, and a long open group scrolls INSIDE the menu
    rather than dragging the page. --tb-h is the bar's real height, measured
    by _Counter's script (the bar is shorter on counter screens).  */
.topbar { position: sticky; top: 0; z-index: 50; }
body:not(.fullscreen) .shell > nav.menu {
    top: calc(var(--tb-h, 60px) + 10px);
    height: calc(100vh - var(--tb-h, 60px) - 20px);
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,.25) transparent;
}
/*  The collapsed rail's fly-out panels hang outside the rail - an inner
    scroll would clip them, so the rail keeps its old overflow.  */
body:not(.fullscreen) .shell.is-collapsed > nav.menu { overflow: visible; }
@media (max-width: 900px) {
    body:not(.fullscreen) .shell > nav.menu { position: static; height: auto; overflow: visible; }
}
/*  Everything else that sticks to the top of the window now sticks under the
    bar instead of behind it.  */
body:not(.fullscreen) .ws-panes .ws-right { top: calc(var(--tb-h, 60px) + 8px); max-height: calc(100vh - var(--tb-h, 60px) - 16px); }
body:not(.fullscreen) .rs-layout > .panes.bill.no-recent > #totals { top: calc(var(--tb-h, 60px) + 8px); }
body:not(.fullscreen) .pc-chips { top: var(--tb-h, 60px); }
body:not(.fullscreen) .cat-pickbar { top: calc(var(--tb-h, 60px) + 8px); }


/* ════════════════════════════════════════ the manufacturing hero ══ */
/*  28 Sep 2026, the owner: "make it attractive hero for manufacturing module
    only". Issue and Receive open on a banner in the theme's accent: what the
    screen is, the Issue / Receive switch, and the five stages as a line the
    batch travels - done, here, to come. Only tokens, so every palette carries
    it; the ink on the banner is --accent-ink, the one colour every theme
    already guarantees against its accent.  */
.mf-hero {
    position: relative;
    overflow: hidden;
    margin: 0 0 12px;
    padding: 12px 18px 10px;
    border-radius: 12px;
    color: var(--accent-ink);
    background:
        radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--metal-gold) 30%, transparent) 0%, transparent 55%),
        linear-gradient(135deg, var(--accent) 0%, color-mix(in srgb, var(--accent) 72%, #000) 100%);
    box-shadow: var(--shadow);
}
.mf-hero::after {                       /* a faint ring, like a bangle, top right */
    content: "";
    position: absolute;
    right: -50px; top: -70px;
    width: 190px; height: 190px;
    border-radius: 50%;
    border: 16px solid color-mix(in srgb, var(--accent-ink) 9%, transparent);
    pointer-events: none;
}
.mf-hero-top { position: relative; z-index: 1; display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.mf-hero-text { flex: 1 1 22rem; min-width: 0; }
.mf-kicker { font-size: .66rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; opacity: .78; }
.mf-hero h1 { margin: 2px 0 3px; font-size: 1.3rem; line-height: 1.15; color: var(--accent-ink); }
.mf-hero p { margin: 0; max-width: 62rem; font-size: .82rem; line-height: 1.35; opacity: .9; }
.mf-hero-side { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.mf-switch { display: inline-flex; padding: 3px; border-radius: 999px; background: color-mix(in srgb, #000 22%, transparent); }
.mf-switch a { padding: 4px 12px; border-radius: 999px; color: var(--accent-ink); text-decoration: none; font-weight: 700; font-size: .85rem; opacity: .8; }
.mf-switch a.on { background: var(--accent-ink); color: var(--accent); opacity: 1; }
.mf-switch a:not(.on):hover { opacity: 1; }
.mf-stat { font-size: .74rem; font-weight: 700; padding: 2px 9px; border-radius: 999px; background: color-mix(in srgb, var(--accent-ink) 16%, transparent); }

.mf-steps { position: relative; z-index: 1; display: flex; list-style: none; margin: 8px 0 0; padding: 0; }
.mf-step { flex: 1 1 0; position: relative; text-align: center; }
.mf-step + .mf-step::before {          /* the line between two stages */
    content: ""; position: absolute; top: 13px; right: 50%; width: 100%; height: 2px;
    background: color-mix(in srgb, var(--accent-ink) 25%, transparent);
}
.mf-step.done + .mf-step::before, .mf-step.done + .mf-step.here::before { background: var(--metal-gold); }
.mf-step a { position: relative; z-index: 1; display: inline-flex; flex-direction: column; align-items: center; gap: 3px; color: var(--accent-ink); text-decoration: none; }
.mf-dot {
    display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
    font-weight: 800; font-size: .82rem;
    border: 2px solid color-mix(in srgb, var(--accent-ink) 55%, transparent);
    background: color-mix(in srgb, var(--accent) 60%, #000);
    transition: transform .12s ease;
}
.mf-step.done .mf-dot { background: var(--metal-gold); border-color: var(--metal-gold); color: #1B1305; }
.mf-step.here .mf-dot { background: var(--accent-ink); color: var(--accent); border-color: var(--metal-gold); box-shadow: 0 0 0 3px color-mix(in srgb, var(--metal-gold) 45%, transparent); transform: scale(1.08); }
.mf-step a:hover .mf-dot { transform: scale(1.12); }
.mf-name { font-size: .72rem; font-weight: 700; letter-spacing: .04em; opacity: .85; }
.mf-step.here .mf-name { opacity: 1; text-decoration: underline; text-decoration-color: var(--metal-gold); text-underline-offset: 4px; }

@media (max-width: 640px) {
    .mf-hero { padding: 10px 12px; }
    .mf-hero h1 { font-size: 1.15rem; }
    .mf-hero-side { align-items: flex-start; }
    .mf-dot { width: 24px; height: 24px; font-size: .75rem; }
    .mf-step + .mf-step::before { top: 11px; }
    .mf-name { font-size: .68rem; }
}
@media print { .mf-hero { display: none; } }

/*  THE SHOP BEING WORKED IN, in the top bar beside the user menu (28 Sep 2026,
    the owner: "show company name for which working is going on").  */
.shopchip {
    display: inline-flex; align-items: center; gap: 6px;
    margin-right: 8px; padding: 5px 12px; max-width: 22rem;
    border: 1px solid var(--accent); border-radius: 999px;
    background: var(--accent-soft); color: var(--ink);
    font-size: .85rem; white-space: nowrap;
}
.shopchip svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--accent); }
.shopchip b { overflow: hidden; text-overflow: ellipsis; }
.shopchip-k { color: var(--ink-soft); font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; }
.shopchip[data-open-usermenu] { cursor: pointer; }
@media (max-width: 700px) { .shopchip-k { display: none; } .shopchip { max-width: 11rem; } }
@media print { .shopchip { display: none; } }

/*  Back to the owner's dashboard - owners only (29 Sep 2026).  */
.ownerback {
    display: inline-flex; align-items: center; gap: 6px;
    margin-right: 8px; padding: 5px 12px;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--raised); color: var(--ink);
    font-size: .85rem; white-space: nowrap; text-decoration: none;
}
.ownerback:hover { border-color: var(--accent); color: var(--accent); }
.ownerback svg { width: 16px; height: 16px; flex: 0 0 auto; }
@media (max-width: 700px) { .ownerback span { display: none; } .ownerback { padding: 5px 8px; } }
@media print { .ownerback { display: none; } }

/*  THE MANUFACTURING DASHBOARD'S TWO PANELS (28 Sep 2026, the owner: "reduce
    width of right panel karigars"). By stage carries five columns and the
    links, Karigars three - so the wider side is the stages, and the stage
    table no longer scrolls sideways.  */
.panes.mf-dash-panes { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .panes.mf-dash-panes { grid-template-columns: minmax(0, 1fr); } }

/*  THE SUMMARY KEEPS ITS WIDTH ON A SAVED BILL (30 Sep 2026: "layout changes
    when click previous next"). The column is max-content, and a reopened
    bill adds Preview, WhatsApp and Cancel bill beside Save - one unbroken row
    that widened the panel over the grid. The row now takes no part in the
    panel's width (width 0, then the panel's full width) and wraps inside it.  */
.rs-layout #totals .actions {
    width: 0; min-width: 100%; box-sizing: border-box;
    flex-wrap: wrap; justify-content: flex-end; gap: 6px;
}
.rs-layout #totals .actions > .spacer { display: none; }
.rs-layout #totals .actions > #save-said { flex: 1 1 100%; }
.rs-layout #totals .actions > #save-said:empty { display: none; }
