/*  KashGenie back office
    ---------------------
    Big type, high contrast, wide targets. The person using this may be billing
    with one hand and counting change with the other, on a phone, in a shop with
    sunlight on the screen. Nothing here is decorative.

    The geometry - card radius, row rhythm, the sidebar, the shape of a KPI
    tile - comes from mockup/*.html. The colour does not: those mockups were
    drawn in green before the decision to run the product in the company's
    blue, so every green in them is read here as "brand" and rendered blue.

    No web fonts. The mockups call for Bricolage Grotesque and Geist, and both
    would be a CDN request that has to succeed before a shopkeeper in a patchy
    signal area can read their own sales figure - and neither has Devanagari,
    so the Hindi half of a bilingual product would fall back anyway. The system
    stack below covers both scripts and costs nothing.                        */

:root {
    --ink: #0f1828;
    --ink-soft: #3b4863;
    --muted: #697794;
    --line: #e7ebf3;
    --line-strong: #d6ddea;
    --bg: #f4f6fb;
    --panel: #ffffff;

    /*  Professional blue, taken from the hero gradient on kashgenie.com so the
        product and the marketing site are recognisably the same company. The
        site runs #274685 into #3db3c5; the back office uses the deep end for
        anything a shopkeeper has to read against, and keeps the teal for
        accents on dark surfaces like the sidebar and the till.

        White on --brand is 8.9:1 and --brand on white is the same, so every
        combination below clears AAA - which matters more here than usual,
        because this is read on a phone in a shop with sun on the screen.     */
    --brand: #274685;
    --brand-dark: #1b3160;
    --brand-tint: #eef3fb;
    --brand-line: #c7d3e8;
    --accent: #3db3c5;

    /*  The sidebar is its own surface with its own scale, the way the mockups
        have it: one dark column that never moves, so the shop's eye learns
        where things are and stops reading the menu.                          */
    --sidebar: #0e1e3c;
    --sidebar-deep: #0a1527;
    --sidebar-text: #afbcd3;
    --sidebar-bright: #ffffff;

    /*  The quiet end of the sidebar scale: group headings, counts, anything
        that has to be legible without competing with a link.                */
    --sidebar-muted: #65769a;
    --sidebar-line: rgba(255, 255, 255, .07);
    --sidebar-mark: #3db3c5;

    /*  Status colours. Three, not more: fine, watch this, wrong.             */
    --ok: #0a6b45;
    --ok-tint: #e6f5ec;
    --warn: #8a4b06;
    --warn-tint: #fdf2de;
    --danger: #a4232b;
    --danger-tint: #fdeceb;

    --radius: 10px;
    --radius-card: 14px;
    --tap: 46px;
    --shadow-card: 0 1px 2px rgba(18, 24, 38, .04), 0 1px 3px rgba(18, 24, 38, .03);
    --shadow-pop: 0 10px 28px rgba(27, 49, 96, .14);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: "Segoe UI", system-ui, -apple-system, "Noto Sans Devanagari", sans-serif;
    font-size: 16px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/*  Figures line up in columns everywhere, not only in the tables that remember
    to ask. A rupee figure that jitters as its digits change is the single most
    common way a well-built ledger screen still looks amateur.                */
body { font-variant-numeric: tabular-nums; }

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

.app { min-height: 100vh; display: flex; flex-direction: column; }

/*  ---------------------------------------------------------- the shell ----
    Sidebar on the left, work on the right. The sidebar is fixed: it does not
    scroll with the page, because losing the menu on a long day book is how a
    shopkeeper ends up scrolling to the top to get anywhere.                  */

/*  The sidebar itself is sticky, so it is only ever one screen tall. The
    column it sits in has to stay dark all the way down a long day book, and
    the cheapest way to say that is to paint the stripe on the shell.        */
.shell {
    display: flex;
    min-height: 100vh;
    align-items: stretch;
    background-image: linear-gradient(to right, var(--sidebar-deep) 0 244px, transparent 244px);
}

.sidebar {
    width: 244px;
    flex-shrink: 0;
    /*  A shade deeper at the foot than the head. Barely visible on its own,
        but it stops a 900px column of flat navy reading as a painted wall,
        and it costs nothing.                                                */
    background: linear-gradient(180deg, var(--sidebar), var(--sidebar-deep));
    color: var(--sidebar-text);
    padding: 18px 12px 20px;
    display: flex;
    flex-direction: column;
    gap: 18px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.sidebar-brand { display: block; padding: 2px 8px 0; }
.sidebar-brand img { height: 34px; width: auto; display: block; }

.app-nav { display: flex; flex-direction: column; gap: 3px; }

.nav-group { display: flex; flex-direction: column; gap: 2px; }

/*  ------------------------------------------------- the collapsing groups ---
    <details> rather than a script: it opens on the first paint, with the
    keyboard, and with a screen reader, and this app is static SSR - every
    click is a full page load, so a menu that needs JavaScript to open is a
    menu that is shut for as long as the page takes to arrive.

    display:block on the element matters. A <details> set to flex loses the
    browser's own hide-the-contents behaviour and stays open for ever.        */
details.nav-fold { display: block; }

details.nav-fold > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    margin-bottom: 1px;
    border-radius: 8px;
    cursor: pointer;
    list-style: none;
}

/*  Both spellings: WebKit still wants the pseudo-element, everything else
    takes ::marker. Without them the group heading carries a stray triangle. */
details.nav-fold > summary::-webkit-details-marker { display: none; }
details.nav-fold > summary::marker { content: ""; }
details.nav-fold > summary:hover { background: rgba(255, 255, 255, .05); }
details.nav-fold > summary:focus-visible { outline: 3px solid var(--sidebar-mark); outline-offset: -3px; }

.nav-group-title {
    margin: 0;
    padding: 0;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--sidebar-muted);
}

/*  What is inside a group you have closed. A plain count, because the layout
    knows how many links it rendered and can say so for nothing - anything
    that needed a query would put a database round trip on every page.       */
.nav-roll {
    margin-left: auto;
    font-size: 10.5px;
    font-weight: 600;
    color: #4e5f80;
    font-variant-numeric: tabular-nums;
}

details.nav-fold[open] > summary .nav-roll { display: none; }

.nav-chev { margin-left: auto; display: flex; color: var(--sidebar-muted); }
details.nav-fold[open] > summary .nav-roll + .nav-chev { margin-left: 0; }
.nav-chev .ico { width: 13px; height: 13px; stroke-width: 2.2; transform: rotate(-90deg); transition: transform .15s ease; }
details.nav-fold[open] > summary .nav-chev .ico { transform: rotate(0); }

.nav-links { display: flex; flex-direction: column; gap: 1px; padding-bottom: 7px; }

.app-nav a {
    position: relative;
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: 36px;
    padding: 6px 12px;
    border-radius: 8px;
    color: var(--sidebar-text);
    text-decoration: none;
    font-size: 14px;
    font-weight: 500;
}

/*  One 24x24 grid and one stroke weight for every glyph in the product, in
    currentColor so a row that turns white or teal takes its icon with it.   */
.ico {
    width: 17px;
    height: 17px;
    flex: 0 0 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .85;
}

.app-nav a:hover { background: rgba(255, 255, 255, .055); color: #e8eef8; }

/*  The active row gets a filled plate and a bright rule down its left edge -
    two signals rather than one, so it still reads on a dim phone screen.    */
/*  An inset rule rather than an absolutely positioned one: the sidebar
    scrolls, and anything hanging outside its box gets clipped away.        */
.app-nav a.active {
    background: rgba(255, 255, 255, .10);
    box-shadow: inset 3px 0 0 var(--sidebar-mark);
    color: var(--sidebar-bright);
    font-weight: 600;
}

.app-nav a.active .ico { opacity: 1; stroke: var(--sidebar-mark); }

.sidebar-foot { margin-top: auto; padding-top: 10px; }

.sidebar-note {
    display: block;
    padding: 12px 12px 13px;
    border-radius: 10px;
    background: rgba(255, 255, 255, .05);
    font-size: 12px;
    line-height: 1.45;
    color: #9fb0cc;
}

.sidebar-note strong { display: block; color: #fff; font-size: 12.5px; margin-bottom: 2px; }

.app-nav a.platform-link {
    margin-top: 6px;
    color: var(--sidebar-mark);
    font-weight: 700;
}

/*  ---------------------------------------------------------- the topbar ---
    Deliberately thin and quiet. Everything a shopkeeper actually does is in
    the page below it; this strip only answers "who am I, and in which
    language".                                                                */

.work { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 60px;
    padding: 8px 28px;
    background: rgba(255, 255, 255, .92);
    backdrop-filter: saturate(150%) blur(6px);
    border-bottom: 1px solid var(--line);
}

.topbar .spacer { flex-grow: 1; }

/*  The mark only appears when the sidebar is folded away, so the shop always
    has one thing on screen that says which product this is.                 */
.topbar-mark { display: none; }
.topbar .who { color: var(--ink-soft); font-size: 14px; font-weight: 600; }

/*  The initials disc. A shopkeeper with two staff logins needs to see at a
    glance which one is billing, and a name in 14px does not do that.        */
.avatar {
    width: 34px; height: 34px; flex-shrink: 0;
    border-radius: 50%;
    background: var(--brand-tint);
    color: var(--brand-dark);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; font-weight: 700;
}

.topbar form { margin: 0; }

.topbar .link, .topbar .language button {
    color: var(--muted);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    padding: 8px 10px;
    border-radius: 8px;
}

.topbar .link:hover, .topbar .language button:hover { background: var(--bg); color: var(--ink); }

/*  The mobile menu button, and the checkbox that drives it. No script: this
    has to work on the day the shop's connection drops halfway through
    loading, which is the same day they most need to look something up.     */
.nav-toggle { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.nav-button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--line-strong);
    border-radius: 10px;
    background: #fff;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}

.nav-toggle:focus-visible + .nav-button { outline: 3px solid var(--brand); outline-offset: 2px; }
.nav-button .bars { display: inline-block; width: 16px; border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink); height: 10px; }

/*  ------------------------------------------------- collapsing the nav ---
    The same checkbox that opens the sidebar on a phone closes it on a desktop.
    One control, and in both cases pressing it flips whether the sidebar is
    there - which is the only thing a person pressing it means.

    An entry grid with eight columns on it wants the width, and a shopkeeper
    who knows their way around does not need thirty links in view to type a
    purchase bill. Still a checkbox and a label rather than a script, so it
    works on the morning the connection is down and the page came off the
    service worker.                                                          */
@media (min-width: 1001px) {
    .nav-toggle:checked ~ .shell { background-image: none; }

    .nav-toggle:checked ~ .shell .sidebar {
        width: 0;
        padding-left: 0;
        padding-right: 0;
        overflow: hidden;
    }

    .sidebar { transition: width 140ms ease, padding 140ms ease; }
}

/*  Somebody who has asked their system not to animate things meant it.      */
@media (prefers-reduced-motion: reduce) {
    .sidebar { transition: none; }
}

.app-main { flex: 1; width: 100%; max-width: 74rem; margin: 0 auto; padding: 26px 28px 56px; }

.app-footer { padding: 18px 28px 24px; color: var(--muted); font-size: 13px; text-align: center; }

/*  ---------------------------------------------------------- page head ----
    Every screen opens the same way: what this is, one line of why, and the
    single action most people came to do.                                    */

h1 { font-size: 27px; line-height: 1.2; letter-spacing: -.02em; margin: 0 0 4px; }
h2 { font-size: 17px; letter-spacing: -.01em; margin: 28px 0 10px; }
h3 { font-size: 15px; margin: 0 0 6px; }

.lead { color: var(--muted); margin: 0 0 20px; font-size: 14.5px; }
.muted { color: var(--muted); }
.hint { color: var(--muted); font-size: 13px; margin: -4px 0 8px; }

.page-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}

.page-head .lead { margin-bottom: 0; }
.page-head .button { margin-top: 0; }

/*  ------------------------------------------------------------- surfaces --
    One card shape, used everywhere. A screen that invents a second one makes
    the reader work out whether the difference means something.              */

.panel, .narrow, .wide, .card, .tile, .lists section, .feature, table.grid {
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-card);
}

.narrow { max-width: 30rem; margin: 0 auto; padding: 28px; }
.wide { max-width: 50rem; margin: 0 auto; padding: 26px; }
.panel { padding: 20px 22px; margin-bottom: 18px; }

/*  A fieldset used as a panel: the browser's own border is replaced by the
    card shape above, and the legend sits on the card rather than through it. */
fieldset.panel { border: 1px solid var(--line); margin-top: 18px; }
fieldset.panel legend { font-weight: 600; font-size: 13.5px; color: var(--ink-soft); padding: 0 6px; }
fieldset.panel > p.muted { margin-top: 2px; margin-bottom: 10px; }

/*  An opening balance sits inside the body of a report rather than in its
    head, because it is a figure the reader counts from, not a column name.  */
table.grid tr.subtotal td { background: var(--brand-tint); font-weight: 600; }

/*  A figure the row was told rather than asked for - the item's own GST rate,
    read off its master. Styled as a fact rather than a box, so nobody tries to
    type in it and nobody wonders why they cannot.                           */
input.readonly {
    background: var(--brand-tint);
    border-color: transparent;
    color: var(--ink-soft);
    font-weight: 600;
    cursor: default;
}

/*  A form with a line grid in it needs more than the 30rem a login card wants,
    and less than the full width the tables get - otherwise the eye has to
    travel the width of a monitor to match a quantity to its item.           */
.line-form { margin-bottom: 28px; }
.line-form h2 { margin-top: 0; margin-bottom: 4px; }

.stack { display: flex; flex-direction: column; gap: 4px; }
.stack label, .field label { font-weight: 600; font-size: 13.5px; color: var(--ink-soft); margin-top: 14px; }

/*  A row of fields.

    Two rules, both learned from a form that looked crooked: the row owns the
    space above it rather than each label doing it (otherwise the gap doubles
    on the first row and disappears on the rest), and the control is pinned to
    the BOTTOM of its column - so a label long enough to wrap onto two lines
    lifts itself rather than pushing its box below the boxes beside it. That
    one is what makes "Or stop after this many bills" line up with two date
    fields whose labels fit on one line.                                    */
/*  The hidden attribute is nothing but `display: none` in the browser's own
    stylesheet, so any author rule that sets display at all beats it. `.row >
    div` below sets display:flex, which meant a field marked hidden stayed on
    screen: the cheque-or-reference box sat there for a cash account, and a box
    on screen is a box somebody fills in - then the bank reconciliation carries
    a reference that ties to nothing. One !important here is worth more than
    remembering the trap at each call site, and it costs nothing: an element
    carrying `hidden` is meant to be gone, with no exceptions anywhere.       */
[hidden] { display: none !important; }

.row { --row-gap: 16px; display: flex; gap: var(--row-gap); align-items: stretch; }
.row > div { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }

/*  A row whose cells keep their half width even when only one of them is
    there. Without it a lone date box stretches the width of the dialog while
    the Amount box above it is half that, and the form looks like two forms.
    Half the gap comes off so the box lands on exactly the same edge as the
    one above it - a cell that is seven pixels wider than its neighbour is not
    a layout, it is a near miss, and those are what the eye catches.        */
.row.half > div { flex: 0 1 calc(50% - var(--row-gap) / 2); }

.stack > .row, .dialog-body .row { margin-top: 14px; }
.row > div > label { margin-top: 0; }

.row > div > input,
.row > div > select,
.row > div > textarea { margin-top: auto; }
.actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

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

input, select, textarea {
    min-height: var(--tap);
    padding: 9px 12px;
    font: inherit;
    color: inherit;
    background: #fff;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
}

input::placeholder { color: #9aa4b2; }
input:hover, select:hover { border-color: #b9c6d8; }

input:focus, select:focus, textarea:focus {
    border-color: var(--brand);
    outline: 3px solid rgba(39, 70, 133, .22);
    outline-offset: 0;
}

button:focus-visible, a:focus-visible, summary:focus-visible {
    outline: 3px solid var(--brand);
    outline-offset: 2px;
}

.check { display: flex; align-items: center; gap: 10px; margin-top: 14px; font-weight: 600; }
.check input { min-height: auto; width: 20px; height: 20px; accent-color: var(--brand); }

/*  ------------------------------------------------------------- buttons ---  */

.button, button.primary, .button.primary {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    min-height: var(--tap); padding: 0 18px; margin-top: 14px;
    font: inherit; font-size: 15px; font-weight: 600; text-decoration: none;
    border: 1px solid var(--line-strong); border-radius: var(--radius);
    background: #fff; color: var(--ink); cursor: pointer;
    box-shadow: var(--shadow-card);
}

.button:hover { background: #f7f9fc; border-color: #b9c6d8; }

.button.primary, button.primary {
    background: var(--brand); border-color: var(--brand); color: #fff;
    box-shadow: 0 1px 2px rgba(27, 49, 96, .3);
}

.button.primary:hover, button.primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }

.button.small { min-height: 34px; padding: 0 12px; font-size: 13.5px; margin-top: 0; }
.button.danger, button.danger { border-color: #e3b6b6; color: var(--danger); background: #fff; }
.button.danger:hover, button.danger:hover { background: var(--danger-tint); }

button.link {
    background: none; border: none; color: inherit; font: inherit;
    text-decoration: underline; cursor: pointer; padding: 4px;
    min-height: auto; box-shadow: none;
}

.language { display: inline; }

/*  The dashboard's shortcut row. Wraps rather than scrolls, because a row that
    scrolls sideways on a phone hides whatever is past the edge.              */
.quick { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 0; }
.quick .button { flex: 1 1 auto; text-align: center; min-width: 9rem; margin-top: 0; }

/*  ------------------------------------------------------------- filters ---
    The strip above a table. It is a form, but it should not look like data
    entry - so it sits on its own quiet plate and keeps its controls short.  */

.search {
    display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
    margin: 0 0 16px; padding: 12px 14px;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--radius-card); box-shadow: var(--shadow-card);
}

.search input, .search select { min-height: 40px; }
.search input[type="search"], .search input[name="search"] { flex: 1; min-width: 12rem; }
.search .button { margin-top: 0; min-height: 40px; }
.search label { font-size: 13.5px; font-weight: 600; color: var(--ink-soft); margin: 0 2px 0 0; }
.search.period { align-items: flex-end; }

form.inline { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
form.inline input { flex: 1; min-width: 6rem; }
form.inline .button { margin-top: 0; }
/*  Invoice numbering: one real form per row, laid out on a shared grid so the
    prefix boxes line up like a table without pretending to be one - a <form>
    cannot wrap a <tr>, and every row here has to post on its own.           */
.numbering-head, form.numbering {
    display: grid;
    grid-template-columns: minmax(8rem, 1.6fr) 8rem 8rem minmax(8rem, 1.3fr) 6rem;
    gap: 12px; align-items: center;
}

.numbering-head {
    padding-bottom: 8px; border-bottom: 1px solid var(--line);
    font-size: 12px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted);
}

form.numbering { padding: 12px 0; border-bottom: 1px solid var(--line); }
form.numbering:last-child { border-bottom: 0; padding-bottom: 0; }
form.numbering .doc { font-weight: 600; }
form.numbering input { margin-top: 0; width: 100%; }
form.numbering .sample { color: var(--muted); font-size: 13.5px; }
form.numbering .sample strong { color: var(--ink); font-variant-numeric: tabular-nums; }
form.numbering .button { margin-top: 0; width: 100%; }
form.numbering .col-label { display: none; }

/*  A heading that divides one form into parts - the address block inside the
    business card - rather than starting a new card.                         */
.stack .group { margin: 22px 0 0; font-size: 13px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted); }
.stack .group + label { margin-top: 8px; }
.stack .group + .row { margin-top: 8px; }

/*  -------------------------------------------------------------- tables ---
    The heart of the product. Everything here is in service of one thing:
    finding your own row quickly and reading the figure on it correctly.     */

table.grid { width: 100%; border-collapse: separate; border-spacing: 0; overflow: hidden; }

table.grid th, table.grid td { padding: 12px 16px; text-align: left; border-bottom: 1px solid var(--line); }

/*  A heading is a label for the column, not a second row of data: smaller,
    quieter, and separated by the same hairline as every other row. The heavy
    rule under it was doing the work of a border on a table that already has
    one.                                                                     */
table.grid thead th {
    background: #fbfcfe;
    font-size: 10.5px; font-weight: 600; letter-spacing: .075em; text-transform: uppercase;
    color: var(--muted); white-space: nowrap;
    border-bottom: 1px solid var(--line);
}

table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid tbody tr:hover td { background: #f9fbfe; }
table.grid td a { font-weight: 600; text-decoration: none; }
table.grid td a:hover { text-decoration: underline; }

table.grid td.right, table.grid th.right { text-align: right; font-variant-numeric: tabular-nums; }

/*  .right was only ever defined for cells, so the class every quantity and
    rate box in the entry grids already carries did nothing: the numbers sat
    left while their headings sat right. Figures line up under each other when
    they are right-aligned, which is the whole reason to align a column.    */
input.right { text-align: right; font-variant-numeric: tabular-nums; }
table.grid td.mono, .mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: 13.5px; }
table.grid td.bad, .bad { color: var(--danger); }
.strong { font-weight: 700; }
.centre { text-align: center; }
.struck { opacity: .5; text-decoration: line-through; }
.danger { color: var(--danger); }

/*  The totals line. A ledger that puts its total in the same weight as its
    rows makes the reader count for themselves to be sure.                  */
table.grid tfoot th, table.grid tfoot td {
    background: #f7f9fc;
    border-top: 2px solid var(--line-strong);
    border-bottom: 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    text-transform: none;
    letter-spacing: 0;
}

table.grid tfoot th.right, table.grid tfoot td.right { text-align: right; font-variant-numeric: tabular-nums; }

tr.opening td { background: #f7f9fc; font-style: italic; }
tr.overdue td { background: #fff7f6; }
tr.total td, tr.grand td { font-weight: 700; border-top: 2px solid var(--line-strong); background: #f7f9fc; }

/*  A line grid inside a form. The inputs fill their cell so a thumb on a phone
    lands on the field and not on the gap beside it.                          */
.grid.lines td, table.grid.entry td { padding: 6px 8px; }
.grid.lines input, .grid.lines select,
table.grid.entry input, table.grid.entry select { width: 100%; min-width: 0; margin: 0; min-height: 42px; }

/*  A tick is not a text box, and the rule above was stretching it into one -
    a 42px-tall checkbox filling its whole cell, which read as a button
    somebody had got wrong. Sized to itself and centred in the column.      */
table.grid.entry input[type="checkbox"] {
    width: 18px;
    height: 18px;
    min-height: 0;
    margin: 0 auto;
    display: block;
    accent-color: var(--brand);
}

/*  The heading of a narrow column may wrap. thead th is nowrap everywhere
    else, which is right for a table that sizes to its content and wrong for
    this one, where the widths are fixed and the text has to fit them.      */
table.grid.entry thead th.col-tick { white-space: normal; }

/*  ------------------------------------------------ the entry grid's shape --
    Space where the reading happens.

    An item's name is the only thing on a line a person has to read to know
    what the line is; a quantity is at most four digits and a rate six. Left to
    itself the table gave the name whatever the shrink-to-fit select happened
    to want and split the rest evenly, so "Cement bag (18%)" sat truncated in a
    narrow box beside a quantity box wide enough for a phone number.

    The widths are by class rather than by column position because the two
    grids do not have the same columns - the sales bill has an Inclusive tick
    where the purchase bill has an ITC picker, and either may grow batch and
    serial cells. Naming what a cell holds survives that; nth-child does not. */
table.grid.entry { table-layout: fixed; width: 100%; }

table.grid.entry .col-item  { width: auto; }
table.grid.entry .col-qty   { width: 7.5rem; }
table.grid.entry .col-rate  { width: 8.5rem; }
table.grid.entry .col-small { width: 6.5rem; }
table.grid.entry .col-tick  { width: 5.5rem; }
table.grid.entry .col-pick  { width: 10rem; }
table.grid.entry .col-amount { width: 9rem; }

/*  The running count under an entry grid. Right-aligned under the amount
    column it is adding up, because that is where the eye already is.       */
.totals-strip {
    display: flex;
    justify-content: flex-end;
    gap: 28px;
    flex-wrap: wrap;
    padding: 12px 10px 0;
    font-variant-numeric: tabular-nums;
}

.totals-label { color: var(--muted); font-size: 13px; margin-right: 6px; }
.totals-strip b { font-weight: 600; }
.totals-grand b { font-size: 18px; color: var(--brand); }

/*  The item select may now be as wide as its cell, which is the point. Its
    text is ellipsised rather than clipped so a long name ends legibly.      */
table.grid.entry .col-item select {
    min-width: 0;
    text-overflow: ellipsis;
}

/*  Below a tablet the fixed widths stop helping: the grid scrolls sideways
    instead, with the name column wide enough to still be a name.            */
@media (max-width: 860px) {
    table.grid.entry { table-layout: auto; }
    table.grid.entry .col-item { min-width: 14rem; }
}

/*  Nothing here, drawn rather than stated. An empty list is a normal state -
    a shop that has not billed anything yet this morning - so it should look
    like an answer, not like a failure.                                     */
.empty {
    display: flex; flex-direction: column; align-items: center;
    padding: 40px 20px 44px; text-align: center; color: var(--muted);
    background: var(--panel); border: 1px dashed var(--line-strong); border-radius: var(--radius-card);
}

.empty-art { width: 168px; height: 120px; display: block; margin-bottom: 6px; }
.empty-art .sheet { fill: var(--bg); stroke: var(--line-strong); stroke-width: 2; }
.empty-art .line { fill: var(--line); }
.empty-art .line.head { fill: var(--brand-line); }
.empty-art .glass-lens { fill: var(--panel); opacity: .92; }
.empty-art .glass-rim { fill: none; stroke: var(--brand); stroke-width: 3; }
.empty-art .glass-grip { fill: none; stroke: var(--brand); stroke-width: 4.5; stroke-linecap: round; }
.empty-art .glass-none { fill: none; stroke: var(--brand); stroke-width: 3; stroke-linecap: round; }

.empty-title { margin: 6px 0 0; font-size: 16px; font-weight: 600; color: var(--ink); }
.empty-hint { margin: 6px 0 0; font-size: 14px; max-width: 26rem; }
.empty-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: 16px; }
.empty-actions .button { margin-top: 0; }

/*  A row that goes somewhere says so. The link inside it still works on its
    own, so this is a bigger target rather than the only one.               */
tr[data-href] { cursor: pointer; }

/*  --------------------------------------------------------------- chips ---
    A word that carries a state - paid, overdue, cancelled - reads faster with
    a shape around it than as one more piece of grey text in a wall of rows.  */

.chip {
    display: inline-flex; align-items: center; gap: 5px;
    min-height: 24px; padding: 2px 9px; border-radius: 999px;
    font-size: 12.5px; font-weight: 600; white-space: nowrap;
    background: #eef1f6; color: var(--ink-soft);
}

.chip.ok { background: var(--ok-tint); color: var(--ok); }
.chip.warn { background: var(--warn-tint); color: var(--warn); }
.chip.bad { background: var(--danger-tint); color: var(--danger); }
/*  Modifiers are named for the chip, never borrowed from a word the
    stylesheet already uses for something else. This one was ".chip.brand"
    until ".brand" - the header logo lockup, 20px and bold, defined further
    down the file - won on source order and turned every party-type chip into
    a blob twice the size of the row it sat in.                             */
.chip.info { background: var(--brand-tint); color: var(--brand-dark); }

/*  --------------------------------------------------------------- tiles ---
    The figures an owner opens the product to see. One number per tile, the
    largest type on the screen, with its own supporting line underneath.     */

.tiles, .cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 14px;
    margin: 0 0 22px;
}

.tile, .card { padding: 18px 20px; display: flex; flex-direction: column; gap: 6px; }

.tile-label, .card-label {
    font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted);
}

.tile-value, .card-value {
    font-size: 28px; font-weight: 700; line-height: 1.15; letter-spacing: -.02em;
    font-variant-numeric: tabular-nums; margin: 0;
}

.tile-note { font-size: 13px; color: var(--muted); }
.tile-note a { font-weight: 600; }

/*  Amber, not red. "Six items need reordering" is a job for this afternoon,
    not an emergency, and a screen that shouts at a shopkeeper every morning
    gets ignored by the end of the week.                                     */
.tile.warn { border-color: #e8cfa4; background: #fffcf5; }
.tile.warn .tile-value { color: var(--warn); }

/*  ---------------------------------------------------------- dashboard ----
    The owner's screen, drawn from mockup/dashboard.html: a strip of figures
    across the top, then the two things the figures make you want to do -
    look at the month, and chase who has not paid.                          */

.eyebrow {
    margin: 0 0 2px;
    font-size: 13px; font-weight: 600; color: var(--muted);
}

.tile-head { display: flex; align-items: center; gap: 10px; }

/*  The plate is what makes a row of six figures scannable rather than a wall
    of numbers - the eye finds the shape before it reads the label.         */
.tile-icon {
    width: 32px; height: 32px; flex-shrink: 0;
    border-radius: 9px;
    background: var(--brand-tint); color: var(--brand);
    display: inline-flex; align-items: center; justify-content: center;
}

.tile-icon svg { width: 17px; height: 17px; }
.tile.warn .tile-icon { background: var(--warn-tint); color: var(--warn); }
.tile-note { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
a.chip { text-decoration: none; }
a.chip:hover { filter: brightness(.95); }

.panel-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; margin-bottom: 14px;
}

.panel-head h2 { margin: 0; }
.panel-head .hint { margin: 2px 0 0; }
.panel-head a { font-size: 14px; font-weight: 600; text-decoration: none; white-space: nowrap; }

/*  The leaves of one cheque book, opened under the list of books. The table
    inside it is already a panel of its own, so it loses its frame here and
    keeps only the ruled lines.                                              */
.leaf-panel { margin-top: 22px; }
.leaf-panel table.grid { border: 0; box-shadow: none; border-radius: 0; margin-bottom: 0; }

/*  Cancelling a leaf is a different act from listing them, so the form is
    fenced off rather than running on from the rows above it.                */
.leaf-form-title {
    margin: 22px 0 0; padding-top: 16px; border-top: 1px solid var(--line);
    font-size: 15px;
}

/*  A box that cannot be typed in has to look it. On the return screen a line
    that has already come back in full still shows its box, in line with every
    other row, and without this it invites a click that does nothing.       */
input:disabled, select:disabled, textarea:disabled {
    background: var(--bg);
    color: var(--muted);
    cursor: not-allowed;
}

.button:disabled, button:disabled { opacity: .5; cursor: not-allowed; }

/*  The allocation grid and the strip under it. The strip is the one place a
    shopkeeper finds out that money they meant to put against a bill is about
    to go on account instead, so it is legible rather than subtle.          */
.allocations input[type="number"] { max-width: 9rem; margin-left: auto; }

/*  A bill number and a date that wrap turn a two-line grid into a six-line one,
    and the shopkeeper is scanning down the outstanding column.              */
.allocations td:nth-child(-n+3) { white-space: nowrap; }

/*  The reconciliation is read down the status and the tax, so those two and the
    dates hold their line; the remark is the column allowed to wrap.        */
.recon td:nth-child(-n+5) { white-space: nowrap; }
.recon td:last-child { white-space: normal; min-width: 16rem; }

/*  A ledger sitting under the cost centre it belongs to. Indent rather than a
    second table, so the eye reads one column of money down the page.       */
td.indent { padding-left: 32px; }

/*  A heading inside a table, for statements read top to bottom rather than
    scanned across - the cash flow and anything else with sub-totals.       */
table.grid tr.section th {
    background: var(--brand-tint);
    border-top: 1px solid var(--line-strong);
    padding-top: 12px;
}
.allocations tr.overdue td { background: var(--warn-tint); }

.allocation-strip { margin: 10px 0 0; font-variant-numeric: tabular-nums; }
.allocation-strip.warn { color: var(--warn); font-weight: 600; }

/*  Buttons that act on the form rather than submitting it. */
.actions.secondary { margin-top: 8px; gap: 8px; }

form.inline { display: inline; }

/*  Drawn as markup on the server. preserveAspectRatio is off so the month
    stretches to the card; only the vertical scale carries meaning here, and
    the exact figures are two clicks away in the day book.                  */
.chart { display: block; width: 100%; height: 180px; }
.chart-fill { fill: rgba(39, 70, 133, .10); }
.chart-line { fill: none; stroke: var(--brand); stroke-width: 2; vector-effect: non-scaling-stroke; }

.chart-axis {
    display: flex; justify-content: space-between;
    margin-top: 6px; font-size: 12.5px; color: var(--muted);
}

/*  -------------------------------------------------------- the card ------
    Entering a value happens over the page, not under it.

    Nothing here needs script. The dialog is in the markup because the URL
    said so, and every way out of it - the scrim, the cross, Cancel - is a
    link back to the same page without that query. The scrim being an anchor
    is what makes clicking away work.                                       */

.dialog-layer {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.dialog-scrim {
    position: fixed;
    inset: 0;
    background: rgba(10, 20, 42, .55);
    backdrop-filter: blur(2px);
}

.dialog {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 36rem;
    max-height: calc(100vh - 48px);
    background: var(--panel);
    border-radius: 16px;
    box-shadow: var(--shadow-pop);
}

.dialog-head {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    padding: 18px 22px;
    border-bottom: 1px solid var(--line);
}

.dialog-head h2 { margin: 0; font-size: 18px; }

.dialog-close {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; flex-shrink: 0;
    border-radius: 9px;
    color: var(--muted); text-decoration: none;
    font-size: 24px; line-height: 1;
}

.dialog-close:hover { background: var(--bg); color: var(--ink); }

/*  Its own scroll, so a long card scrolls inside itself and the page behind
    it stays where the shopkeeper left it.                                  */
.dialog-body { padding: 18px 22px 22px; overflow-y: auto; }
.dialog-body > :first-child { margin-top: 0; }
.dialog-body .row { --row-gap: 14px; gap: var(--row-gap); }
.dialog-body .actions { margin-top: 20px; }
.dialog-body .actions .button { margin-top: 0; }
.dialog-body .stack label:first-child { margin-top: 0; }

@media (max-width: 620px) {
    /*  On a phone it is a sheet: full width, off the bottom, tall enough to
        type into with a keyboard up.                                       */
    .dialog-layer { padding: 0; align-items: flex-end; }
    .dialog { max-width: none; max-height: 92vh; border-radius: 16px 16px 0 0; }
}

/*  ------------------------------------------------------ report actions --
    Print and download, in the page head next to the title. Print is also how
    a PDF is made - every browser's print dialogue saves one - so there is no
    separate PDF button promising something this does not do differently. */

.report-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-start; }
.report-actions .button { margin-top: 0; }
.report-actions form { margin: 0; }

/*  The masthead and the mark exist only on paper. On screen they would be a
    second copy of the business name that is already in the corner.        */
.print-masthead, .print-foot { display: none; }

/*  -------------------------------------------------------------- notices --  */

.notice {
    background: var(--brand-tint);
    border: 1px solid var(--brand-line);
    border-left: 3px solid var(--brand);
    color: var(--brand-dark);
    padding: 12px 16px;
    border-radius: var(--radius);
    margin: 0 0 16px;
}

.error, .notice.error {
    background: var(--danger-tint); border-color: #f0c2c0; border-left-color: var(--danger);
    color: #8c1d18;
}

/*  This one means "it worked", and a success panel that matches the brand is
    a success panel nobody notices.                                          */
.notice.ok { background: var(--ok-tint); border-color: #bcdfc8; border-left-color: var(--ok); color: var(--ok); }

/*  ---------------------------------------------------------------- tabs ---
    A screen that holds five unrelated short lists is not five screens and it
    is not one long one either. Tabs say "these belong together, look at one
    at a time", which is the thing a shopkeeper who has never used accounting
    software needs told.

    Radio buttons and labels, no script. Switching is instant and costs no
    round trip, and because the radio is a real focusable control the arrow
    keys move between tabs the way a keyboard user expects - which is what a
    hand-rolled div-and-JS version usually gets wrong.

    The server still decides which tab opens, by writing `checked` on one
    radio from ?tab= in the URL. That is what brings you back to Units after
    adding a unit, instead of dropping you on the first tab every time.

    Generic on purpose: the rules are positional, so any page can use this by
    putting N radios, then a .tab-bar of N labels, then a .tab-panels of N
    panels. Eight is the ceiling; a screen that wants nine tabs wants to be
    two screens.                                                             */

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

.tab-bar {
    display: flex; gap: 4px; flex-wrap: wrap;
    padding: 5px; margin: 0 0 20px;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: 12px; box-shadow: var(--shadow-card);
}

.tab-bar > label {
    display: inline-flex; align-items: center; gap: 8px;
    min-height: 40px; padding: 0 16px;
    border: 1px solid transparent; border-radius: 9px;
    font-size: 14.5px; font-weight: 600; color: var(--muted);
    cursor: pointer; white-space: nowrap;
}

.tab-bar > label:hover { background: var(--bg); color: var(--ink); }

/*  How many rows are behind the tab, so nobody has to open all five to find
    out that four of them are already stocked from provisioning.             */
.tab-count {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 22px; height: 20px; padding: 0 6px; border-radius: 999px;
    background: var(--bg); color: var(--muted);
    font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}

/*  The card under a list. One card, two jobs: empty it adds a row, and with
    a row loaded into it it saves over that row. It sits on a tinted plate so
    that "the list" and "the thing you type into" are never mistaken for each
    other, and it gets a brand edge while it is holding somebody's row, so a
    shopkeeper who scrolled past can see they are editing and not adding.   */
.entry-card {
    margin-top: 22px;
    padding: 18px 20px 20px;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 12px;
}

.entry-card.editing { background: var(--brand-tint); border-color: var(--brand-line); }
.entry-card h3 { margin: 0 0 4px; font-size: 15px; color: var(--brand-dark); }
.entry-card .row { --row-gap: 14px; gap: var(--row-gap); }
.entry-card .actions { margin-top: 16px; }
.entry-card .actions .button { margin-top: 0; }
.entry-card .stack label:first-child { margin-top: 10px; }

/*  What sits at the right-hand end of a list row: the short form or code, a
    retired mark, and on price lists the link into its own screen.          */
.row-end { display: inline-flex; align-items: center; gap: 10px; }
ul.simple li.struck a { text-decoration: line-through; }
ul.simple li a { font-weight: 600; text-decoration: none; }
ul.simple li a:hover { text-decoration: underline; }

.tab-panel { display: none; }
.tab-panel > h2:first-child { margin-top: 0; }

/*  One list, one form, at a width the eye can cross. Stretching a two-column
    list of units across a monitor puts a metre of nothing between the name
    and its short form. The cap is on the whole block so the strip and the
    panel under it are the same width; .tabs.full takes it off for a page
    whose tabs hold tables.                                                  */
.tabs { max-width: 54rem; }
.tabs.full { max-width: none; }

.tab-radio:nth-of-type(1):checked ~ .tab-bar > label:nth-child(1) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(2):checked ~ .tab-bar > label:nth-child(2) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(3):checked ~ .tab-bar > label:nth-child(3) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(4):checked ~ .tab-bar > label:nth-child(4) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(5):checked ~ .tab-bar > label:nth-child(5) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(6):checked ~ .tab-bar > label:nth-child(6) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(7):checked ~ .tab-bar > label:nth-child(7) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(8):checked ~ .tab-bar > label:nth-child(8) { background: var(--brand); border-color: var(--brand); color: #fff; }
.tab-radio:nth-of-type(1):checked ~ .tab-bar > label:nth-child(1) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(2):checked ~ .tab-bar > label:nth-child(2) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(3):checked ~ .tab-bar > label:nth-child(3) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(4):checked ~ .tab-bar > label:nth-child(4) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(5):checked ~ .tab-bar > label:nth-child(5) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(6):checked ~ .tab-bar > label:nth-child(6) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(7):checked ~ .tab-bar > label:nth-child(7) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(8):checked ~ .tab-bar > label:nth-child(8) .tab-count { background: rgba(255, 255, 255, .22); color: #fff; }
.tab-radio:nth-of-type(1):checked ~ .tab-panels > .tab-panel:nth-child(1) { display: block; }
.tab-radio:nth-of-type(2):checked ~ .tab-panels > .tab-panel:nth-child(2) { display: block; }
.tab-radio:nth-of-type(3):checked ~ .tab-panels > .tab-panel:nth-child(3) { display: block; }
.tab-radio:nth-of-type(4):checked ~ .tab-panels > .tab-panel:nth-child(4) { display: block; }
.tab-radio:nth-of-type(5):checked ~ .tab-panels > .tab-panel:nth-child(5) { display: block; }
.tab-radio:nth-of-type(6):checked ~ .tab-panels > .tab-panel:nth-child(6) { display: block; }
.tab-radio:nth-of-type(7):checked ~ .tab-panels > .tab-panel:nth-child(7) { display: block; }
.tab-radio:nth-of-type(8):checked ~ .tab-panels > .tab-panel:nth-child(8) { display: block; }
.tab-radio:nth-of-type(1):focus-visible ~ .tab-bar > label:nth-child(1) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(2):focus-visible ~ .tab-bar > label:nth-child(2) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(3):focus-visible ~ .tab-bar > label:nth-child(3) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(4):focus-visible ~ .tab-bar > label:nth-child(4) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(5):focus-visible ~ .tab-bar > label:nth-child(5) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(6):focus-visible ~ .tab-bar > label:nth-child(6) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(7):focus-visible ~ .tab-bar > label:nth-child(7) { outline: 3px solid var(--brand); outline-offset: 2px; }
.tab-radio:nth-of-type(8):focus-visible ~ .tab-bar > label:nth-child(8) { outline: 3px solid var(--brand); outline-offset: 2px; }

@media (max-width: 620px) {
    /*  Below this the tabs stop wrapping and scroll, because a tab strip that
        wraps to three lines pushes the list itself off the screen.          */
    .tab-bar { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .tab-bar > label { padding: 0 12px; }
}

/*  --------------------------------------------------------------- lists ---  */

.lists { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); margin-top: 8px; }
.lists section { padding: 20px 22px; }
.lists h2 { margin-top: 0; }

ul.simple { list-style: none; padding: 0; margin: 0 0 14px; }
ul.simple li { display: flex; justify-content: space-between; gap: 16px; padding: 9px 0; border-bottom: 1px solid var(--line); }
ul.simple li:last-child { border-bottom: 0; }

ul.plain { list-style: none; padding: 0; margin: 8px 0 0; }
ul.plain li { padding: 3px 0; }

.ready { list-style: none; padding: 0; margin: 8px 0 0; }
.ready li { display: flex; align-items: center; gap: 10px; padding: 11px 0; border-bottom: 1px solid var(--line); }
.ready li:last-child { border-bottom: 0; }
.tick { color: var(--ok); font-weight: 700; }
.count { margin-left: auto; color: var(--muted); }

.row-actions { display: flex; flex-direction: column; gap: 7px; min-width: 15rem; }
.row-actions form { display: flex; gap: 6px; align-items: center; margin: 0; }
.row-actions input { max-width: 11rem; min-height: 34px; }

/*  ------------------------------------------------------------- the tree --  */

.tree, .tree ul { list-style: none; padding-left: 0; margin: 0; }
.tree ul { padding-left: 18px; border-left: 2px solid var(--line); margin-left: 7px; }
.tree li { padding: 2px 0; }
.tree summary { cursor: pointer; padding: 8px 0; font-weight: 600; display: flex; gap: 12px; align-items: baseline; }
.tree .ledger .name { display: inline-block; padding: 6px 0; }
.tree .nature { color: var(--muted); font-size: 12.5px; font-weight: 400; text-transform: lowercase; }

/*  -------------------------------------------------------------- totals ---
    Right-aligned against the right edge of the sheet, because that is where
    every bill book and every ledger in India puts them.                     */

.totals dl {
    display: grid; grid-template-columns: auto 9rem; gap: 4px 24px;
    justify-content: end; margin: 18px 0 0;
}

.totals dt { text-align: right; color: var(--muted); }
.totals dd { text-align: right; margin: 0; font-variant-numeric: tabular-nums; font-weight: 600; }

/*  -------------------------------------------------------------- Hindi ----
    Small caps with letter-spacing is a Latin typographic trick. Devanagari
    has no capitals to set, and spacing the letters out pulls conjuncts apart
    into something a reader has to reassemble - so in Hindi these labels stay
    as written, and get a size back to make up for the extra height the script
    needs. <html lang> is set from the chosen language in App.razor.         */

html[lang="hi"] .nav-group-title,
html[lang="hi"] .tile-label,
html[lang="hi"] .card-label,
html[lang="hi"] table.grid thead th {
    text-transform: none;
    letter-spacing: 0;
    font-size: 13px;
}

html[lang="hi"] .lead { font-size: 15px; }

/*  ---------------------------------------------------------- the phone ----
    Under 1000px the sidebar folds behind one button. It is a checkbox and a
    label, not a script, so it still opens on a page that was served from the
    service worker with no network at all.                                   */

@media (max-width: 1000px) {
    .shell { display: block; }

    .sidebar {
        display: none;
        position: static;
        width: auto;
        height: auto;
        padding: 14px 12px 18px;
    }

    .shell { background-image: none; }

    .nav-toggle:checked ~ .shell .sidebar {
        display: flex;
        position: fixed;
        top: 60px; left: 0; right: 0; bottom: 0;
        z-index: 30;
        overflow-y: auto;
    }

    .nav-button { display: inline-flex; }
    .nav-toggle:checked ~ .shell .work .topbar { border-bottom-color: var(--sidebar); }
    .sidebar-brand { display: none; }
    .sidebar-foot { display: none; }
    .topbar-mark { display: block; height: 30px; width: auto; }

    .topbar { padding: 8px 16px; }
    .topbar .who { display: none; }
    .app-main { padding: 20px 16px 48px; }
}

@media (max-width: 620px) {
    body { font-size: 15.5px; }
    h1 { font-size: 23px; }
    .narrow, .wide { padding: 20px 16px; border-radius: var(--radius-card); }
    .page-head { gap: 10px; }

    /*  A page whose head holds one action gives it the full width. A page
        with four - the dashboard's strip - puts them two to a row instead,
        because four full-width buttons push the figures off the screen.   */
    .page-head > .button { width: 100%; }
    .page-head .actions { width: 100%; }
    .page-head .actions .button { flex: 1 1 8rem; }

    /*  A ledger row has more columns than a phone has width. It scrolls
        sideways inside its own card rather than having columns hidden: a
        missing column on a tax figure is worse than a swipe.                */
    table.grid { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    table.grid th, table.grid td { padding: 11px 12px; white-space: nowrap; }

    .search { padding: 10px 12px; }
    .tiles, .cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
    .tile-value, .card-value { font-size: 24px; }
    .row { flex-direction: column; gap: 0; }

    /*  Stacked, the second field of a pair needs the breathing room the label
        gives every other field - otherwise it reads as part of the first.   */
    .row > div + div > label { margin-top: 14px; }

    /*  On a phone the numbering grid drops its header and stacks: the bill
        type and the sample take a full line, prefix and number share one.  */
    .numbering-head { display: none; }
    form.numbering { grid-template-columns: 1fr 1fr; gap: 8px; }
    form.numbering .doc,
    form.numbering .sample,
    form.numbering .button { grid-column: 1 / -1; }
    form.numbering .button { justify-self: start; width: auto; }
    form.numbering .col-label { display: inline; }
}

/*  -------------------------------------------------- the public header ----
    What a visitor who is not signed in sees. This is the marketing chrome, so
    it keeps the full-bleed brand bar; the back office behind the sign-in does
    not have one, because a shopkeeper does not need to be sold to twice.    */

.app-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; padding: 12px 24px;
    background: var(--brand); color: #fff;
}

.brand { color: #fff; font-size: 20px; font-weight: 700; text-decoration: none; display: inline-flex; align-items: center; }

/*  Height drives the size and width follows, so a different lockup can be
    dropped in without touching this.                                        */
.brand img { height: 32px; width: auto; display: block; }

/*  Sign-in sits on white, and a reversed wordmark on white is invisible - so
    it gets a brand plate to sit on, the same blue as the header.            */
.sign-in-brand {
    margin: 0 0 24px; padding: 18px 20px;
    background: var(--brand); border-radius: var(--radius-card);
    display: flex; justify-content: center;
}

.sign-in-brand img { height: 38px; width: auto; display: block; }

.header-actions { display: flex; align-items: center; gap: 14px; }
.app-header .who { opacity: .9; font-size: 14px; }
.app-header .link, .app-header .language button { color: #fff; }
/* ------------------------------------------------------------ the sheet --
   A printed invoice is a legal document, so the print styles are not a
   nicety: the sheet must carry the same figures with none of the chrome.  */

.print-sheet {
    max-width: 210mm;
    margin: 0 auto;
    padding: 12mm;
    background: #fff;
    color: #000;
    font-size: 12px;
}

.invoice.a5 { font-size: 10px; }

.invoice-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    border-bottom: 2px solid #000;
    padding-bottom: 8px;
}

.invoice-head h1 { font-size: 1.4em; margin: 0 0 4px; }
.invoice-head .title h2 { font-size: 1.2em; margin: 0; text-align: right; }
.invoice-head .stamp { color: #b3261e; font-weight: 700; text-align: right; margin: 4px 0 0; }

.invoice-meta {
    display: flex;
    justify-content: space-between;
    gap: 2rem;
    margin: 10px 0;
}

.invoice-meta table.meta th { text-align: left; padding-right: 10px; font-weight: 600; }

.invoice table.lines { width: 100%; border-collapse: collapse; margin-top: 8px; }
.invoice table.lines th,
.invoice table.lines td { border: 1px solid #999; padding: 4px 6px; }
.invoice table.lines thead th { background: #eee; }

.invoice-foot { display: flex; justify-content: space-between; gap: 2rem; margin-top: 10px; }
.invoice-foot table { border-collapse: collapse; }
.invoice-foot th, .invoice-foot td { padding: 3px 8px; }
.invoice-foot .tax-summary table th,
.invoice-foot .tax-summary table td { border: 1px solid #999; }
.invoice-foot .totals table tr.grand th,
.invoice-foot .totals table tr.grand td { border-top: 2px solid #000; font-weight: 700; }

.invoice .words { margin-top: 10px; }
.invoice .terms { margin-top: 8px; font-size: 0.9em; color: #333; }

.invoice footer.sign { margin-top: 30px; text-align: right; }
.invoice footer.sign .line { border-top: 1px solid #000; width: 180px; margin: 40px 0 0 auto; }

@media print {
    /*  What a report looks like on paper.

        This list used to name the old chrome only - .app-header, .app-nav,
        .app-footer - and then the shell was rewritten around a sidebar and a
        topbar that it had never heard of. Every report printed since has had
        a navy column down the left and the date pickers across the top. A
        print rule that names elements has to be revisited whenever the shell
        changes; this one now covers the shell, the filters and the buttons,
        because none of them mean anything on paper.                        */
    .app-header, .app-nav, .app-footer, .site-nav, .site-footer,
    .sidebar, .topbar, .nav-button, .dialog-layer,
    .search, .tabs .tab-bar, .quick, .actions, .page-head .button,
    .report-actions { display: none !important; }

    .shell { display: block; background: none; }
    .app-main, .site-main { max-width: none; padding: 0; }
    .site-main > *:not(.landing) { max-width: none; padding: 0; }
    .print-sheet { padding: 0; max-width: none; }

    /*  Ink is expensive and a shopkeeper's printer is usually a cheap laser.
        Panels lose their fill and their shadow; the table keeps its rules,
        because a ledger without lines is unreadable.                       */
    body { background: #fff; font-size: 11pt; }
    .panel, table.grid, .tile, .card { box-shadow: none; border-color: #999; background: #fff; }
    table.grid thead th { background: #eee; color: #000; }

    /*  A long report breaks across pages, and a header row that does not
        repeat leaves page two a wall of unlabelled numbers.                */
    table.grid { display: table; overflow: visible; }
    table.grid thead { display: table-header-group; }
    table.grid tr { break-inside: avoid; }

    h1 { font-size: 16pt; margin: 0 0 2mm; }
    .lead { color: #333; }
    a { color: #000; text-decoration: none; }

    /*  Whose books, and which days. Without the period a printed report says
        what it is and not what it covers, which is the one thing somebody
        reading it in three months actually needs.                         */
    .print-masthead {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 8mm;
        padding-bottom: 2mm;
        margin-bottom: 4mm;
        border-bottom: 1pt solid #333;
    }

    .print-business { font-size: 13pt; font-weight: 700; }
    .print-period { font-size: 10pt; color: #333; }

    /*  The mark, once, at the end of the report rather than on every page:
        a browser cannot repeat an element per sheet, and pretending it can
        by faking a footer is how you get it printed halfway down page one. */
    .print-foot {
        display: block;
        margin-top: 6mm;
        padding-top: 2mm;
        border-top: 1pt solid #999;
        font-size: 8pt;
        color: #555;
    }
}

/*  Paper size. Named page rules rather than a style tag in the component, so
    the sheet size is a class on the article and the Razor stays free of CSS
    at-rules - which the Razor parser reads as code blocks.                 */
@page sheet-a4 { size: A4; margin: 10mm; }
@page sheet-a5 { size: A5; margin: 8mm; }

.invoice.a4 { page: sheet-a4; }
.invoice.a5 { page: sheet-a5; }
/*  ------------------------------------------------------ the public site --
    kashgenie.com: the landing page at / and the pages behind the nav -
    /features, /pricing, /why, /partners, /contact, /faq.

    It shares the product's tokens rather than inventing a second brand, so a
    visitor who signs up lands somewhere that looks like the page that sold it
    to them. What it does not share is the width cap: the back office keeps a
    table of figures inside 74rem so the eye does not have to travel a monitor,
    while a hero band wants the whole viewport and re-centres its own content.  */

.site-main { flex: 1; width: 100%; }
.landing { width: 100%; }

/*  Sign in, sign up and first run share this chrome but are not marketing
    pages: they need the breathing room the back office's page frame gives
    every screen, while a marketing page runs its bands to the edge.

    Only the offsets are set here. An earlier version of this rule matched
    every child that was not a .landing and gave it a width - which beat
    .narrow on specificity and stretched the sign-in card the full width of
    the monitor. A card's width is the card's own business.                   */
.site-main > .narrow, .site-main > .wide { margin-top: 26px; margin-bottom: 56px; }

/*  ------- the brand bar ----- */

.site-nav { display: flex; gap: 1.4rem; margin-left: 2rem; flex: 1; }
.site-nav a { color: #fff; opacity: 0.9; text-decoration: none; font-weight: 500; white-space: nowrap; }
.site-nav a:hover { opacity: 1; text-decoration: underline; text-underline-offset: 6px; }

/*  NavLink marks the page you are on. Without it a five-page site feels like
    five unrelated pages.                                                     */
.site-nav a.active { opacity: 1; font-weight: 700; text-decoration: underline; text-underline-offset: 6px; }

.link-button { color: #fff; text-decoration: none; font-weight: 600; padding: 0.25rem 0.5rem; }
.link-button:hover { text-decoration: underline; }
.button.light { background: #fff; color: var(--brand); border-color: #fff; font-weight: 700; }
.button.light:hover { background: #eef2f9; }

/*  ------- hero ----- */

.hero {
    background: linear-gradient(120deg, var(--brand) 0%, var(--accent) 100%);
    color: #fff;
    padding: 3.75rem 1.25rem 4rem;
}

.hero-inner { max-width: 46rem; margin: 0 auto; text-align: center; }

/*  Words on one side, the product on the other: a shopkeeper deciding whether
    this is for them wants to see the screen before they read the sentence.   */
.hero-split {
    max-width: 72rem; margin: 0 auto;
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: 3rem; align-items: center;
}

.hero-words h1 { font-size: clamp(1.9rem, 4vw, 2.8rem); line-height: 1.15; margin: 0 0 1rem; }
.hero-sub { font-size: clamp(1rem, 2.2vw, 1.15rem); opacity: 0.95; margin: 0 0 2rem; max-width: 34rem; }
.hero-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin: 0; }
.hero-actions.centre { justify-content: center; }
.hero-inner .hero-actions { justify-content: center; }
.hero-note { margin-top: 1.25rem; opacity: 0.9; font-size: 0.95rem; }

.hero-shot img {
    width: 100%; height: auto; display: block;
    border-radius: 14px; box-shadow: 0 26px 60px rgba(8, 22, 50, 0.38);
}

.button.big { padding: 0.85rem 1.75rem; font-size: 1.05rem; font-weight: 700; }
.button.ghost { background: transparent; color: #fff; border: 2px solid rgba(255, 255, 255, 0.75); }
.button.ghost:hover { background: rgba(255, 255, 255, 0.12); }
.button.wide { display: block; width: 100%; text-align: center; margin-top: 1rem; }

/*  The head of every page that is not the home page: same family as the hero,
    quieter, because the reader has already been sold the headline once.      */
.page-hero {
    background: var(--brand-tint);
    border-bottom: 1px solid var(--line);
    padding: 3rem 1.25rem 2.5rem;
}

/*  FocusOnNavigate gives the page's h1 tabindex="-1" and focuses it, so a
    screen reader starts at the right place. The browser then draws its focus
    ring around the headline, which on a hero band reads as a rendering fault.
    Only the heading loses the ring - every control a keyboard can actually
    reach keeps it.                                                           */
h1[tabindex="-1"]:focus { outline: none; }

.page-hero h1 { font-size: clamp(1.7rem, 3.6vw, 2.4rem); margin: 0.25rem 0 0.75rem; }
.page-hero .lead { margin-bottom: 0; }

/*  ------- bands ----- */

.band { padding: 3.5rem 1.25rem; }
.band.tinted { background: var(--brand-tint); }
.band.closing { background: var(--brand-dark); color: #fff; }
.band.closing h2 { color: #fff; }
.band.closing .hint { color: rgba(255, 255, 255, 0.85); }
.band-inner { max-width: 62rem; margin: 0 auto; }
.band-inner.narrow-band { max-width: 42rem; }
.band h2 { text-align: center; font-size: clamp(1.4rem, 3.2vw, 2rem); margin: 0 0 0.5rem; }
.band h2.left { text-align: left; }
.band-more { margin-top: 2rem; }
.centre-text { text-align: center; }
.centre { justify-content: center; }

.visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/*  ------- trust strip ----- */

.trust-band { padding: 2.5rem 1.25rem; background: var(--panel); border-bottom: 1px solid var(--line); }
.trust-grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
.trust { border-top: 3px solid var(--accent); padding-top: 0.9rem; }
.trust h3 { margin: 0 0 0.3rem; font-size: 1rem; color: var(--brand-dark); }
.trust p { margin: 0; color: var(--muted); font-size: 0.92rem; line-height: 1.5; }

/*  ------- how it works ----- */

.steps {
    list-style: none; padding: 0; margin: 2.25rem 0 0;
    display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.step {
    background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--radius-card); padding: 1.5rem 1.25rem 1.25rem;
    position: relative;
}

.step-number {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; border-radius: 50%;
    background: var(--brand); color: #fff; font-weight: 700; font-size: 0.95rem;
    margin-bottom: 0.75rem;
}

.step h3 { margin: 0 0 0.35rem; font-size: 1.05rem; color: var(--brand-dark); }
.step p { margin: 0; color: var(--muted); line-height: 1.55; }

/*  ------- features ----- */

.feature-grid {
    display: grid; gap: 1.25rem; margin-top: 2.25rem;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.feature-grid.two { grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }
.feature { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.25rem; }
.band.tinted .feature { background: #fff; }
.feature h3 { margin: 0 0 0.4rem; font-size: 1.05rem; color: var(--brand-dark); }
.feature p { margin: 0; color: var(--muted); line-height: 1.5; }

/*  A chapter on /features: the words and the screen they describe, side by
    side, swapping sides down the page.                                       */
.chapter {
    display: grid; gap: 2.5rem; align-items: center;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
}

.chapter:only-child { margin: 0; }
.chapter .chapter-words { min-width: 0; }
.chapter.shot-first .chapter-words { order: 2; }
.chapter.no-shot { grid-template-columns: 1fr; }
.chapter.no-shot .lead { max-width: 46rem; }
.chapter.no-shot .ticks { display: grid; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); gap: 0 2rem; }
.chapter .lead { margin-bottom: 1rem; }

.ticks { list-style: none; padding: 0; margin: 0; }
.ticks li { display: flex; gap: 0.6rem; padding: 0.4rem 0; color: var(--ink-soft); line-height: 1.5; }
.tick { color: var(--accent); font-weight: 700; }

/*  ------- screens ----- */

.shot-grid { display: grid; gap: 1.75rem; margin-top: 2.25rem; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
.shot { margin: 0; }
.shot img {
    width: 100%; height: auto; display: block;
    border: 1px solid var(--line); border-radius: 12px;
    box-shadow: 0 14px 34px rgba(16, 38, 76, 0.12); background: #fff;
}
.shot figcaption { margin-top: 0.75rem; color: var(--muted); font-size: 0.9rem; line-height: 1.5; }
.shot figcaption strong { color: var(--ink); display: block; }

/*  ------- pricing ----- */

.plan-grid {
    display: grid; gap: 1.25rem; margin-top: 2.25rem; align-items: stretch;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.plan {
    background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
    padding: 1.5rem 1.25rem; height: 100%;
    display: flex; flex-direction: column;
}

/*  Whatever each plan lists, the buttons finish on one line - four Choose
    buttons at four different heights makes the cheapest look like an
    afterthought.                                                             */
.plan .button.wide { margin-top: auto; }
.plan-features + .button.wide { margin-top: 1.25rem; }

/*  One plan is marked, because a pricing table with four equal columns makes
    the reader do the choosing and most of them will not.                     */
.plan.featured { border: 2px solid var(--brand); box-shadow: 0 8px 24px rgba(39, 70, 133, 0.12); }
.plan h3 { margin: 0 0 0.25rem; color: var(--brand-dark); }
.plan-price { font-size: 2rem; font-weight: 700; margin: 0.75rem 0 0.15rem; line-height: 1; }
.plan-price .rupee { font-size: 1.2rem; margin-right: 0.1rem; }
.plan-per { font-size: 0.85rem; font-weight: 400; color: var(--muted); }
.plan-quote { font-size: 1.3rem; color: var(--brand); }
.plan-note { font-size: 0.85rem; color: var(--muted); margin: 0.15rem 0; }
.plan-note .save { color: var(--brand); font-weight: 600; }
.plan-trial { font-size: 0.85rem; font-weight: 600; color: var(--brand); margin: 0.5rem 0 0; }
.plan-features { list-style: none; padding: 0; margin: 1rem 0 0; font-size: 0.92rem; }
.plan-features li { padding: 0.3rem 0; border-bottom: 1px solid var(--line); }
.plan-features li:last-child { border-bottom: 0; }
.price-note { margin-top: 1.75rem; }

.price-teaser { font-size: 2.6rem; font-weight: 700; color: var(--brand-dark); margin: 1.25rem 0 0.25rem; line-height: 1; }
.price-teaser .rupee { font-size: 1.4rem; }

/*  ------- the comparison ----- */

.compare-wrap { overflow-x: auto; margin-top: 2rem; }

.compare {
    width: 100%; border-collapse: collapse; background: var(--panel);
    border: 1px solid var(--line); border-radius: var(--radius-card); overflow: hidden;
}

.compare th, .compare td {
    text-align: left; padding: 0.9rem 1rem; vertical-align: top;
    border-bottom: 1px solid var(--line); font-size: 0.93rem; line-height: 1.45;
}

.compare thead th { background: var(--brand-tint); color: var(--brand-dark); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; }
.compare tbody th { font-weight: 700; color: var(--ink); width: 11rem; }
.compare td { color: var(--muted); }

/*  Our own column carries the weight, and says so quietly rather than with a
    row of ticks against a row of crosses.                                    */
.compare .ours { background: #f4fbfc; color: var(--ink); font-weight: 600; }
.compare thead .ours { background: var(--brand); color: #fff; }
.compare tbody tr:last-child th, .compare tbody tr:last-child td { border-bottom: 0; }

.honest { margin-top: 1.75rem; }
ul.plain.honest li, .honest li {
    background: var(--panel); border: 1px solid var(--line); border-left: 4px solid var(--warn);
    border-radius: var(--radius); padding: 0.9rem 1.1rem; margin-bottom: 0.75rem;
    color: var(--ink-soft); line-height: 1.55;
}

/*  ------- questions ----- */

.faq-list { margin-top: 1.75rem; }

.faq {
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 0.9rem 1.1rem; margin-bottom: 0.75rem;
}

.faq summary {
    cursor: pointer; font-weight: 600; color: var(--ink); list-style: none;
    display: flex; justify-content: space-between; align-items: center; gap: 1rem;
}

.faq summary::-webkit-details-marker { display: none; }

/*  A plus that becomes a minus: the only state this page has, and it needs no
    script to carry it.                                                       */
.faq summary::after { content: "+"; color: var(--brand); font-size: 1.3rem; line-height: 1; font-weight: 700; }
.faq[open] summary::after { content: "\2212"; }
.faq p { margin: 0.75rem 0 0; color: var(--muted); line-height: 1.6; }

/*  ------- talking to a person ----- */

.contact-strip {
    display: grid; gap: 1rem; margin-top: 2rem; justify-content: center;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 20rem));
}

.contact-strip.compact { margin-top: 1.5rem; }

.contact-card {
    display: flex; align-items: center; gap: 0.9rem; text-decoration: none;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 1rem 1.1rem; color: var(--ink);
}

.contact-card:hover { border-color: var(--brand-line); box-shadow: var(--shadow-card); }
.contact-card strong { display: block; color: var(--brand-dark); }
.contact-value { color: var(--muted); font-size: 0.9rem; }

.contact-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.5rem; height: 2.5rem; border-radius: 50%;
    background: var(--brand-tint); color: var(--brand); flex: none;
}

.contact-icon svg { width: 1.3rem; height: 1.3rem; }
.contact-card.whatsapp .contact-icon { background: #e6f6ec; color: #1f8a56; }

.enquiry { margin-top: 1.5rem; }

/*  ------- the footer ----- */

.site-footer { background: var(--sidebar); color: var(--sidebar-text); padding: 3rem 1.25rem 1.5rem; }

.footer-inner {
    max-width: 62rem; margin: 0 auto;
    display: grid; gap: 2rem;
    grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
}

.footer-brand img { height: 30px; width: auto; display: block; margin-bottom: 1rem; }
.footer-brand p { margin: 0 0 0.75rem; font-size: 0.9rem; line-height: 1.6; max-width: 26rem; }
.footer-made { color: var(--sidebar-mark); font-weight: 600; }

.footer-links { display: flex; flex-direction: column; gap: 0.5rem; }
.footer-title { margin: 0 0 0.25rem; color: #fff; font-weight: 700; font-size: 0.95rem; }
.footer-links a { color: var(--sidebar-text); text-decoration: none; font-size: 0.9rem; }
.footer-links a:hover { color: #fff; text-decoration: underline; }
.footer-note { font-size: 0.82rem; opacity: 0.75; }

.footer-legal {
    max-width: 62rem; margin: 2rem auto 0; padding-top: 1.25rem;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    display: flex; gap: 1rem; flex-wrap: wrap; justify-content: space-between;
    font-size: 0.82rem; opacity: 0.8;
}

@media (max-width: 900px) {
    .hero-split { grid-template-columns: 1fr; gap: 2rem; }
    .hero-words { text-align: center; }
    .hero-sub { margin-left: auto; margin-right: auto; }
    .hero-actions { justify-content: center; }
    .chapter { grid-template-columns: 1fr; gap: 1.5rem; }
    .chapter.shot-first .chapter-words { order: 0; }
    .footer-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .footer-brand { grid-column: 1 / -1; }
}

@media (max-width: 720px) {
    /*  The nav drops under the brand bar and scrolls sideways rather than
        disappearing: a five-page site whose pages cannot be reached on a phone
        is a one-page site.                                                    */
    .app-header { flex-wrap: wrap; row-gap: 10px; }
    .site-nav {
        order: 3; flex: 0 0 100%; width: 100%; margin-left: 0; gap: 1.1rem;
        overflow-x: auto; padding-bottom: 2px; -webkit-overflow-scrolling: touch;
        font-size: 0.95rem;
    }
    .hero { padding: 2.75rem 1.25rem; }
    .band { padding: 2.5rem 1.25rem; }
    .page-hero { padding: 2.25rem 1.25rem 2rem; }
    .band-more { margin-top: 1.5rem; }
    .footer-inner { grid-template-columns: 1fr; gap: 1.5rem; }
    .site-main > .narrow, .site-main > .wide { margin: 18px 16px 40px; }

    /*  The comparison stops being a table and becomes three labelled answers
        per question, because four columns on a phone is four unreadable ones. */
    .compare, .compare tbody, .compare tr, .compare th, .compare td { display: block; width: auto; }
    .compare thead { display: none; }
    .compare tbody tr { border-bottom: 1px solid var(--line); padding: 0.5rem 0; }
    .compare tbody tr:last-child { border-bottom: 0; }
    .compare tbody th { width: auto; padding-bottom: 0.25rem; border-bottom: 0; font-size: 1rem; }
    .compare td { border-bottom: 0; padding: 0.35rem 1rem; }
    .compare td::before {
        content: attr(data-label) ": "; font-weight: 700; color: var(--ink-soft);
    }
    .compare .ours { border-radius: var(--radius); }
}


/*  ==========================================================================
    CONTROL SIZING
    --------------------------------------------------------------------------
    Two rules, and most form alignment stops being a judgement call.

    1. A control is as wide as the content it holds, stated in characters. A
       date is ten characters, so the box is 12ch. A GSTIN is exactly fifteen,
       so the box is 17ch - and a box that fits it exactly is a box that shows
       a typo. Percentages are what produced a 400px field holding "25-09-2026"
       next to a 90px field holding a party name.

    2. A label occupies a fixed row, so every control on a line starts at the
       same height whatever the labels say. The old way - margin-top:auto on
       the input - only lines boxes up by accident, and drops one to the floor
       of the row the moment a cell holds two fields.

    The 24px added to each width is the two paddings and the two borders, so
    6ch really does hold six digits.
    ========================================================================== */

.fld { display: grid; grid-template-rows: 18px auto; row-gap: 6px; align-content: start; }

/*  Ellipsis rather than wrap on purpose: a label that needs two lines is a
    label that needs rewording, and letting it wrap moves the box under it.  */
.fld > label {
    margin: 0;
    font-size: 12px; font-weight: 600; line-height: 18px;
    color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.fld > .help { grid-column: 1 / -1; margin-top: 5px; font-size: 11.5px; color: var(--muted); }

/*  A form row is a line of intrinsically sized fields, never a set of equal
    columns: the fields that must be wide are wide, and the slack collects at
    the end of the line instead of being shared out among boxes that did not
    ask for it.                                                              */
.formrow { display: flex; gap: 16px; align-items: start; flex-wrap: wrap; }
.formrow > .fld { flex: 0 0 auto; }
.formrow > .fld.grow { flex: 1 1 calc(18ch + 24px); min-width: calc(18ch + 24px); width: auto; }
.formrow + .formrow { margin-top: 18px; }

/*  The scale. The number is characters of content.                          */
.w4  { width: calc(4ch  + 24px); }
.w6  { width: calc(6ch  + 24px); }
.w8  { width: calc(8ch  + 24px); }
.w10 { width: calc(10ch + 24px); }
.w12 { width: calc(12ch + 24px); }
.w15 { width: calc(15ch + 24px); }
.w17 { width: calc(17ch + 24px); }
.w20 { width: calc(20ch + 24px); }

/*  A date box holds ten characters and the browser's own picker glyph, which
    is not free: without the extra room the glyph sits on the last digit.    */
.w-date { width: calc(12ch + 42px); }

/*  Applied to the control itself rather than the field, so a field can grow
    without its box claiming the whole line.                                 */
.fld > input.grow, .fld > select.grow, .fld > textarea.grow { width: 100%; }

/*  Money and quantities read right to left: the units column has to be in the
    same place on every row or the eye cannot compare two figures at all.    */
input.num, .fld > input.num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }


/*  A one-control form sitting beside a page heading - a year picker, a period
    switch. The button lines up with the box, not with the label above it, so
    the row reads as one control rather than two.                            */
.inline-form { display: flex; align-items: end; gap: 10px; flex-wrap: wrap; }
.inline-form .fld { min-width: 0; }
.inline-form .button { margin-top: 0; height: var(--h-ctl); }

/*  A destructive action offered quietly beside the thing it destroys: the
    sentence explains it, the link opens the confirmation. Not a button,
    because a button here would compete with Save.                          */
.reset-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 18px; }
