/*  ═══════════════════════════════════════════════════════════════════════════
    The signed-in shell - owner surface, working screens, operators' panel.

    Loaded ON TOP of site.css, which owns the tokens. Nothing here declares a
    colour of its own: a component with a hard-coded colour is the bug that
    makes a theme change need a component edit.

    What a till needs from a page and what a sales page needs are not the same
    thing, which is why this is a second stylesheet and a second layout rather
    than more classes in the first.
    ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════ shell === */

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

.appbar {
    background: var(--ink);
    color: var(--on-ink);
    border-bottom: 1px solid var(--ink-rule);
    position: sticky; top: 0; z-index: 40;
}
.appbar-in { display: flex; align-items: center; gap: 1rem; min-height: 3.5rem; }
.appbar a { color: var(--on-ink); text-decoration: none; }

.appbar .where {
    display: flex; flex-direction: column; line-height: 1.2; margin-left: .5rem;
    padding-left: 1rem; border-left: 1px solid var(--ink-rule);
}
.appbar .where .company { font-family: var(--display); font-size: .98rem; font-weight: 600; }
.appbar .where .who   { font-size: .78rem; color: var(--on-ink-2); }

.appbar-right { margin-left: auto; display: flex; align-items: center; gap: .6rem; }
.appbar-right .name { font-size: .88rem; color: var(--on-ink-2); }

.linkbtn {
    font: inherit; font-size: .88rem; background: none;
    border: 1px solid var(--ink-rule); color: var(--on-ink);
    padding: .35rem .8rem; border-radius: var(--radius-sm); cursor: pointer;
}
.linkbtn:hover { border-color: var(--brass); }

.appmain { flex: 1; padding-block: 2rem 4rem; }

/* ═════════════════════════════════════════════════════════ page heading === */

.page-head {
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: 1rem;
    margin-bottom: 1.6rem;
    padding-bottom: 1rem; border-bottom: 1px solid var(--rule);
}
.page-head .titles { display: flex; flex-direction: column; gap: .3rem; }
.page-head h1 { font-size: clamp(1.6rem, 3vw, 2.1rem); }
.page-head p  { color: var(--text-2); font-size: .98rem; max-width: 46rem; }
.page-head .actions { margin-left: auto; display: flex; gap: .5rem; }

/* ══════════════════════════════════════════════════════════════ cards === */

.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: 1rem; }

.card {
    background: var(--card); border: 1px solid var(--rule);
    border-radius: var(--radius); padding: 1.2rem;
    display: flex; flex-direction: column; gap: .6rem;
}
.card h3 { font-size: 1.15rem; }
.card .meta { font-family: var(--mono); font-size: .76rem; color: var(--text-3); letter-spacing: .04em; }
.card .foot { margin-top: auto; padding-top: .6rem; display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
/*  Buttons that must stay inside a narrow card: two to a row, a third
    across the full width.  */
.card .foot-grid { display: grid; grid-template-columns: 1fr 1fr; }
.card .foot-grid > :nth-child(3) { grid-column: 1 / -1; }
.card .foot-grid .btn { padding-left: .6rem; padding-right: .6rem; }

/*  The chain currently being worked in. One card lifted, not all of them.  */
.card-here { border-color: var(--brass); box-shadow: var(--shadow-md); }
.card-blocked { border-color: var(--danger); }

/* ══════════════════════════════════════════════════════════════ chips === */

.chip {
    display: inline-flex; align-items: center; gap: .35rem;
    font-family: var(--mono); font-size: .68rem; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase;
    padding: .16rem .5rem; border-radius: 3px; white-space: nowrap;
}
.chip::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.chip-live    { color: #1B8A4C; background: color-mix(in srgb, #1B8A4C 14%, transparent); }
.chip-blocked { color: #C62828; background: color-mix(in srgb, #C62828 12%, transparent); }
.chip-here    { color: var(--text-2); background: var(--card-2); }

/* ══════════════════════════════════════════════════════════════ forms === */

.panel {
    background: var(--card); border: 1px solid var(--rule);
    border-radius: var(--radius); padding: 1.6rem;
    max-width: 34rem;
}
.panel-wide { max-width: 52rem; }
.panel-full { max-width: none; }

/*  No up/down arrows on a number box: amounts and percentages are typed,
    and the arrows only invite a stray click to change one.  */
input[type=number] { -moz-appearance: textfield; appearance: textfield; }
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

.validation {
    background: color-mix(in srgb, var(--danger) 12%, transparent);
    border-left: 3px solid var(--danger);
    padding: .8rem 1rem; margin-bottom: 1.2rem; font-size: .93rem;
}
.validation ul { display: flex; flex-direction: column; gap: .25rem; margin: 0; padding: 0; list-style: none; }
.validation.validation-summary-valid { display: none; }
.field-error { color: var(--danger); font-size: .82rem; }

.form-foot { display: flex; align-items: center; gap: .8rem; margin-top: 1.3rem; }
.form-foot .aside { font-size: .88rem; color: var(--text-3); margin-left: auto; }

/* ════════════════════════════════════════════════════════ empty states === */

.empty {
    border: 1px dashed var(--rule);
    border-radius: var(--radius);
    padding: 2.5rem 1.5rem;
    text-align: center;
    display: flex; flex-direction: column; gap: .8rem; align-items: center;
}
.empty h3 { font-size: 1.2rem; }
.empty p { color: var(--text-2); max-width: 32rem; }

/* ════════════════════════════════════════════════════ the module tiles === */

.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 1px;
         background: var(--rule); border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; }

.tile {
    background: var(--card); padding: 1.15rem 1.2rem 1.25rem;
    display: flex; flex-direction: column; gap: .35rem;
    text-decoration: none; color: inherit;
}
.tile:hover { background: var(--card-2); }
.tile .code { font-family: var(--mono); font-size: .7rem; letter-spacing: .1em; color: var(--text-3); text-transform: uppercase; }
.tile h3 { font-size: 1.06rem; }
.tile p { font-size: .89rem; color: var(--text-2); line-height: 1.5; }
.tile .rights { margin-top: .35rem; display: flex; gap: .3rem; }
.tile .r {
    font-family: var(--mono); font-size: .62rem; font-weight: 600;
    padding: .1rem .35rem; border-radius: 2px;
    background: var(--card-2); color: var(--text-3);
}
.tile .r-on { background: color-mix(in srgb, var(--brass) 18%, transparent); color: var(--brass); }

/* ══════════════════════════════════════════════════════════ stop pages === */

.stop {
    max-width: 38rem; margin-inline: auto; text-align: center;
    display: flex; flex-direction: column; gap: 1rem; padding-block: 3rem;
}
.stop .big {
    font-family: var(--display); font-size: 1.6rem; font-weight: 600;
}
.stop .why {
    background: var(--card-2); border-left: 3px solid var(--ember);
    padding: 1rem 1.2rem; text-align: left; font-size: .95rem;
}
.stop .need { font-family: var(--mono); font-weight: 600; }

/* ══════════════════════════════════════════════════════ chain sub-nav === */

.chainnav {
    display: flex; flex-wrap: wrap; gap: .3rem;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 1.6rem;
}
.chainnav a {
    padding: .55rem .9rem; font-size: .93rem; text-decoration: none;
    color: var(--text-2); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.chainnav a:hover { color: var(--text); }
.chainnav a.on { color: var(--text); border-bottom-color: var(--ember); font-weight: 500; }

/* ══════════════════════════════════════════════════════════════ tables === */

.tablewrap { overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--card); }

table.grid { border-collapse: collapse; width: 100%; font-size: .93rem; }
table.grid th, table.grid td { text-align: left; padding: .65rem .85rem; border-bottom: 1px solid var(--rule-soft); vertical-align: middle; }
table.grid th {
    font-family: var(--mono); font-size: .7rem; font-weight: 600;
    letter-spacing: .09em; text-transform: uppercase;
    color: var(--text-3); background: var(--card-2); white-space: nowrap;
}
table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid tbody tr.off td { opacity: .55; }
table.grid td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
table.grid td.acts { text-align: right; white-space: nowrap; }
table.grid td.acts form { display: inline; }

.iconbtn {
    font: inherit; font-size: .82rem; background: none; cursor: pointer;
    border: 1px solid var(--rule); color: var(--text-2);
    padding: .28rem .6rem; border-radius: var(--radius-sm); text-decoration: none;
    display: inline-flex; align-items: center;
}
.iconbtn:hover { border-color: var(--text-3); color: var(--text); }
.iconbtn-warn:hover { border-color: var(--danger); color: var(--danger); }
.iconbtn-go:hover { border-color: #2E7D32; color: #2E7D32; }
/*  A square button holding only an icon; its title is the tooltip.  */
.iconbtn-sq { padding: .4rem; }
.iconbtn svg { width: 1rem; height: 1rem; display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
table.grid td.acts > * + * { margin-left: .3rem; }

.strong { font-weight: 500; color: var(--text); }
.subtle { color: var(--text-3); font-size: .86rem; }

/* ═════════════════════════════════════════════════════ permission grid === */
/*
    View is the floor, and the browser ticks it the moment any other right is
    ticked - so the person SEES what they are about to save. The procedure
    normalises it again on the way in; this copy exists for the eyes, not for
    correctness.
*/
.permgrid th.right, .permgrid td.right { text-align: center; width: 4.5rem; }
.permgrid td.right label { display: block; cursor: pointer; padding: .2rem 0; }
.permgrid input[type=checkbox] { width: 1.05rem; height: 1.05rem; accent-color: var(--ember); cursor: pointer; }
.permgrid tr:hover td { background: var(--card-2); }
.permgrid .modname { display: flex; flex-direction: column; gap: .15rem; }
.permgrid .modname .code { font-family: var(--mono); font-size: .68rem; letter-spacing: .09em; color: var(--text-3); text-transform: uppercase; }
.permgrid .modname .sum { font-size: .84rem; color: var(--text-3); max-width: 34rem; }

.gridbar {
    display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
    position: sticky; bottom: 0; z-index: 10;
    background: var(--paper); border-top: 1px solid var(--rule);
    padding: .9rem 0; margin-top: 1rem;
}
.gridbar .aside { margin-left: auto; font-size: .88rem; color: var(--text-3); }

/* ════════════════════════════════════════════════════ issued password === */

.issued {
    background: var(--card-2); border-left: 3px solid var(--brass);
    padding: 1rem 1.2rem; margin-bottom: 1.4rem;
    display: flex; flex-direction: column; gap: .5rem;
}
.issued code {
    font-family: var(--mono); font-size: 1.15rem; font-weight: 600;
    letter-spacing: .06em; background: var(--card); padding: .3rem .6rem;
    border-radius: var(--radius-sm); display: inline-block;
}

/* ══════════════════════════════════════════════════════════ dialog.ask === */
/*
    Built from a native <dialog>, not window.confirm - which cannot be styled,
    shows the hostname to a customer's staff, and can be suppressed by a
    browser checkbox, at which point a destructive action stops asking.
*/
dialog.ask {
    border: 1px solid var(--rule); border-radius: var(--radius);
    background: var(--card); color: var(--text);
    padding: 0; max-width: 26rem; width: calc(100% - 2rem);
    box-shadow: var(--shadow-md);
}
dialog.ask::backdrop { background: rgb(14 26 22 / .5); }
dialog.ask .in { padding: 1.4rem; display: flex; flex-direction: column; gap: .7rem; }
dialog.ask h3 { font-size: 1.15rem; }
dialog.ask p { color: var(--text-2); font-size: .95rem; }
dialog.ask .row { display: flex; gap: .5rem; justify-content: flex-end; margin-top: .6rem; }

/* ═══════════════════════════════════════════════════ operators' panel === */
/*
    Numbers first, then the rows behind them. Every tile here is something
    somebody acts on this morning - a count of chains is a vanity figure and
    is not on the front page for that reason.
*/
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 1px;
         background: var(--rule); border: 1px solid var(--rule); border-radius: var(--radius);
         overflow: hidden; margin-bottom: 2rem; }

.stat { background: var(--card); padding: 1rem 1.1rem 1.15rem; display: flex; flex-direction: column; gap: .2rem;
        text-decoration: none; color: inherit; }
a.stat:hover { background: var(--card-2); }
.stat .n { font-family: var(--display); font-size: 1.9rem; font-weight: 700; line-height: 1;
           font-variant-numeric: tabular-nums; }
.stat .l { font-size: .84rem; color: var(--text-2); }
.stat .s { font-size: .78rem; color: var(--text-3); }

/*  Severity in FORM as well as number, so what needs attention reads at a
    glance rather than being counted.  */
.stat-warn .n { color: var(--danger); }
.stat-note .n { color: var(--brass); }

.filterbar { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-bottom: 1.2rem; }
.filterbar input[type=search] {
    font: inherit; font-size: .93rem; padding: .5rem .7rem; min-width: 16rem;
    background: var(--card); color: var(--text);
    border: 1px solid var(--rule); border-radius: var(--radius-sm);
}

details.trace { margin-top: .4rem; }
details.trace summary { cursor: pointer; font-size: .84rem; color: var(--text-3); }
details.trace pre {
    font-family: var(--mono); font-size: .76rem; line-height: 1.5;
    background: var(--card-2); padding: .8rem; border-radius: var(--radius-sm);
    overflow-x: auto; max-height: 22rem; margin: .5rem 0 0;
}

.inline-form { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.inline-form input[type=text] {
    font: inherit; font-size: .86rem; padding: .3rem .5rem; min-width: 12rem;
    background: var(--paper); color: var(--text);
    border: 1px solid var(--rule); border-radius: var(--radius-sm);
}
.inline-form select {
    font: inherit; font-size: .86rem; padding: .3rem .5rem;
    background: var(--paper); color: var(--text);
    border: 1px solid var(--rule); border-radius: var(--radius-sm);
}

/* ═══════════════════════════════════════════════════ the owner's dashboard === */
/*
    A sentence and a button, each. The kind of thing is encoded in a stripe on
    the left edge as well as in the words, so what needs attention reads at a
    glance before it is read at all - and urgency is in the stripe's weight.

    Semantic colour here is separate from the accent: ember is "stop", brass
    is "soon", the neutral rule is "when you get to it".
*/
.todo { list-style: none; padding: 0; display: flex; flex-direction: column; gap: .5rem; }

.todo-item {
    display: flex; align-items: center; gap: 1rem;
    background: var(--card); border: 1px solid var(--rule);
    border-left: 4px solid var(--rule);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    padding: .85rem 1rem;
}
.todo-item.u0 { border-left-color: var(--danger); }
.todo-item.u1 { border-left-color: var(--brass); }
.todo-item.u2 { border-left-color: var(--text-3); }

.todo-text { display: flex; flex-direction: column; gap: .15rem; flex: 1 1 auto; min-width: 0; }
.todo-text .what { font-weight: 500; color: var(--text); }
.todo-text .why  { font-size: .88rem; color: var(--text-2); }

.todo-item .btn { flex: none; }

@media (max-width: 40rem) {
    .todo-item { flex-wrap: wrap; }
    .todo-item .btn { width: 100%; }
}

/*  The three counts on a chain card, as one line rather than three tiles - a
    card is a summary and three tiles inside a card is a dashboard inside a
    dashboard.  */
.company-facts { display: flex; gap: 1.1rem; font-size: .9rem; color: var(--text-2); flex-wrap: wrap; }
.company-facts b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

.company-plan { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }

/* ════════════════════════════════════════════════════════ the branch bar === */
/*
    Which branch a per-branch screen is about. Sits above the tabs because
    every tab under it changes meaning when it changes. Staff see a name; an
    owner with more than one branch gets the picker.
*/
.branchbar {
    display: flex; align-items: center; gap: .75rem;
    margin-bottom: .6rem;
}
.branchbar select {
    font: inherit; font-size: .93rem; font-weight: 500;
    padding: .35rem .6rem;
    background: var(--card); color: var(--text);
    border: 1px solid var(--rule); border-radius: var(--radius-sm);
}

/* ══════════════════════════════════════════════════════════ the diet mark === */
/*
    The green dot and the red dot - and the brown one for egg, which the FSSAI
    added in 2021. Drawn as the square-with-a-dot the law actually specifies,
    not a coloured word, so it reads on a card at arm's length. Colours are
    the legal ones and are NOT palette tokens on purpose: a veg mark is green
    whatever the page looks like.
*/
.diet {
    display: inline-block; width: .85rem; height: .85rem;
    border: 1.5px solid; border-radius: 1px; vertical-align: -.1rem; margin-right: .45rem;
    position: relative; flex: none;
}
.diet::after { content: ""; position: absolute; inset: 2px; border-radius: 50%; background: currentColor; }
.diet-veg    { color: #1E8E3E; }
.diet-vegan  { color: #1E8E3E; }
.diet-nonveg { color: #B3261E; }
.diet-egg    { color: #8B5A00; }
.diet-nonveg::after { border-radius: 0; clip-path: polygon(50% 0, 100% 100%, 0 100%); }

/* ═══════════════════════════════════════════════════════ editable grids === */

table.gridedit td { padding: .35rem .5rem; }
table.gridedit input:not([type=radio]):not([type=checkbox]) {
    font: inherit; font-size: .92rem; width: 100%;
    padding: .4rem .55rem;
    background: var(--paper); color: var(--text);
    border: 1px solid var(--rule); border-radius: var(--radius-sm);
}
table.gridedit input[type=number] { text-align: right; font-variant-numeric: tabular-nums; }
table.gridedit input:focus { border-color: var(--ember); outline: none; }

/* ═══════════════════════════════════════════════════════ orders and KOT === */
/*
    THE FLOOR. One tile per table, coloured by state - the colour IS the
    information, read from across the room. Free is paper; seated is a pale
    ember; cooking is the full ember; served is ink, because the next thing
    that happens to it is the bill.
*/
.floor { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: .7rem; }
.ftile {
    display: flex; flex-direction: column; gap: .15rem; text-align: left;
    min-height: 6.4rem; padding: .8rem .9rem;
    border: 1px solid var(--rule); border-radius: var(--radius);
    background: var(--card); color: var(--text); text-decoration: none;
    font: inherit; cursor: pointer; transition: transform .08s ease, box-shadow .08s ease;
}
.ftile:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.ftile-code  { font-family: var(--mono); font-size: 1.35rem; font-weight: 700; letter-spacing: .04em; }
.ftile-sub   { font-size: .8rem; color: var(--text-3); }
.ftile-amt   { font-size: 1.05rem; font-weight: 600; margin-top: auto; font-variant-numeric: tabular-nums; }
.ftile-state { font-family: var(--mono); font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; }
.ftile-free    { background: var(--paper); border-style: dashed; }
.ftile-free .ftile-code { color: var(--text-3); }
.ftile-seated  { background: color-mix(in srgb, var(--ember) 14%, var(--paper)); border-color: color-mix(in srgb, var(--ember) 40%, var(--rule)); }
.ftile-kotsent { background: var(--ember); color: var(--ember-ink); border-color: var(--ember); }
.ftile-kotsent .ftile-sub, .ftile-kotsent .ftile-state { color: var(--ember-ink); opacity: .8; }
.ftile-served, .ftile-billed { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.ftile-served .ftile-sub, .ftile-served .ftile-state, .ftile-billed .ftile-sub, .ftile-billed .ftile-state { color: var(--paper); opacity: .7; }

/*  THE TICKET. What is keyed on the left, the card on the right, the card
    wider because it has more on it. Stacks on a phone, ticket first.  */
.ticket-page { display: grid; grid-template-columns: minmax(20rem, 2fr) 3fr; gap: 1.4rem; align-items: start; }
@media (max-width: 1150px) { .ticket-page { grid-template-columns: 1fr; } .card-pane { position: static; } }  /* the sidebar takes 15.5rem of the width above 62rem */
.ticket-pane { min-width: 0; }
.card-pane   { min-width: 0; position: sticky; top: 1rem; }

table.tlines td { padding: .45rem .5rem; vertical-align: top; }
table.tlines td.qty { font-family: var(--mono); font-size: 1.1rem; font-weight: 700; width: 2.5rem; }
table.tlines tr.off td { text-decoration: line-through; color: var(--text-3); }
table.tlines tr.off td .subtle { text-decoration: none; }
.ticket-total {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-top: 1rem; padding-top: .8rem; border-top: 2px solid var(--ink);
    font-size: 1.15rem; font-variant-numeric: tabular-nums;
}
.btn-big { font-size: 1.05rem; padding: .8rem 1.4rem; width: 100%; }

/*  THE CARD. Category tabs across the top, dishes as big buttons - a finger
    on a tablet at a table, not a mouse.  */
.card-tabs { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .8rem; align-items: center; }
.card-find {
    flex: 1 1 12rem; font: inherit; font-size: .95rem; padding: .5rem .7rem;
    border: 1px solid var(--rule); border-radius: var(--radius-sm); background: var(--paper); color: var(--text);
}
.card-find:focus { border-color: var(--ember); outline: none; }
.card-tab {
    font: inherit; font-size: .85rem; padding: .45rem .8rem; cursor: pointer;
    border: 1px solid var(--rule); border-radius: 999px; background: var(--paper); color: var(--text);
}
.card-tab.on { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: .55rem; }
.dish {
    display: flex; flex-direction: column; align-items: flex-start; gap: .1rem; text-align: left;
    min-height: 5.6rem; padding: .7rem .8rem; cursor: pointer;
    font: inherit; border: 1px solid var(--rule); border-radius: var(--radius);
    background: var(--card); color: var(--text);
}
.dish:hover { border-color: var(--ember); }
.dish:active { background: color-mix(in srgb, var(--ember) 18%, var(--card)); }
.dish[hidden] { display: none; }
.dish-off { opacity: .45; cursor: not-allowed; }
.dish-name  { font-weight: 600; line-height: 1.2; }
.dish-sub   { font-size: .75rem; color: var(--text-3); }
.dish-sub code { font-family: var(--mono); background: var(--card-2); padding: 0 .3rem; border-radius: 3px; }
.dish-price { margin-top: auto; font-weight: 600; font-variant-numeric: tabular-nums; }

/*  Dialogs that carry a form directly.  */
dialog.ask > form, dialog.pick > form { padding: 1.4rem; }
dialog.pick { max-width: 30rem; }
.pick-group { margin: .6rem 0; }
.pick-q { font-family: var(--mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; color: var(--text-3); margin-bottom: .3rem; }
.pick-opt {
    display: flex; align-items: center; gap: .6rem; padding: .45rem .6rem; cursor: pointer;
    border: 1px solid var(--rule); border-radius: var(--radius-sm); margin-bottom: .3rem;
}
.pick-opt:has(input:checked) { border-color: var(--ember); background: color-mix(in srgb, var(--ember) 10%, var(--card)); }
.pick-opt input { accent-color: var(--ember); width: 1.05rem; height: 1.05rem; }
.pick-opt span { flex: 1; }
.pick-opt b { font-variant-numeric: tabular-nums; font-weight: 600; }

/*  THE KITCHEN WALL. Tickets as cards, oldest first, going amber then
    ember as they age. Big type - read from the pass, not from a chair.  */
.kds { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: .8rem; align-items: start; }
.kds-ticket {
    border: 1px solid var(--rule); border-top: 5px solid var(--ink); border-radius: var(--radius);
    background: var(--card); padding: .8rem .9rem;
}
.kds-slow  { border-top-color: var(--brass); }
.kds-late  { border-top-color: var(--ember); }
.kds-ready { background: color-mix(in srgb, var(--ember) 10%, var(--card)); }
.kds-head  { display: flex; align-items: center; gap: .6rem; }
.kds-no    { font-family: var(--mono); font-size: 1.15rem; font-weight: 700; }
.kds-min   { margin-left: auto; font-family: var(--mono); font-size: .85rem; color: var(--text-3); }
.kds-late .kds-min { color: var(--brass); font-weight: 700; }
.kds-where { margin: .3rem 0 .5rem; font-weight: 600; }
.kds-lines { list-style: none; margin: 0; padding: 0; }
.kds-lines li { display: flex; gap: .6rem; padding: .35rem 0; border-top: 1px dashed var(--rule); font-size: 1.02rem; }
.kds-lines li b { font-family: var(--mono); font-size: 1.25rem; min-width: 1.6rem; }
.kds-lines li.off { text-decoration: line-through; color: var(--text-3); }
.kds-acts { display: flex; gap: .5rem; margin-top: .7rem; }
.kds-acts form { flex: 1; }
.kds-acts .btn { width: 100%; }
.pill {
    display: inline-block; min-width: 1.3rem; padding: 0 .35rem; margin-left: .3rem;
    border-radius: 999px; background: var(--ink); color: var(--paper);
    font-family: var(--mono); font-size: .7rem; text-align: center; line-height: 1.3rem;
}
.btn-solid .pill { background: var(--ink); color: var(--paper); }

/* ═══════════════════════════════════════════════════════════════ the till === */
table.sums { margin-top: .6rem; }
table.sums td { padding: .25rem .5rem; border: 0; }
.pay-quick { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin: .6rem 0; }
.pay-quick .btn { padding: .4rem .7rem; }
.pay-modes { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.pay-modes .btn-big { width: auto; padding: 1rem .5rem; font-size: 1.1rem; }
.pay-modes .btn:disabled { opacity: .45; cursor: not-allowed; }
.tender { display: grid; grid-template-columns: 7rem 1fr 1fr auto; gap: .4rem; margin-bottom: .4rem; align-items: center; }
.tender select, .tender input {
    font: inherit; font-size: .95rem; padding: .5rem .6rem; width: 100%;
    border: 1px solid var(--rule); border-radius: var(--radius-sm); background: var(--paper); color: var(--text);
}
.tender input[type=number] { text-align: right; font-variant-numeric: tabular-nums; }
.quick-done { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.quick .ticket-pane { position: sticky; top: 1rem; }
.quick table.tlines td.qty { white-space: nowrap; width: auto; font-size: 1rem; }
.quick table.tlines td.qty .iconbtn { padding: .1rem .5rem; }

/*  Editable grids with a select in a cell.  */
table.gridedit select {
    font: inherit; font-size: .92rem; width: 100%;
    padding: .4rem .55rem;
    background: var(--paper); color: var(--text);
    border: 1px solid var(--rule); border-radius: var(--radius-sm);
}
table.gridedit select:focus { border-color: var(--ember); outline: none; }
table.grid tfoot td { border-top: 1px solid var(--rule); padding: .45rem .5rem; }

/*  Bars for the reports: a label, a track, a value. No chart library.  */
.bars { display: grid; gap: .3rem; }
.bar { display: grid; grid-template-columns: 4.5rem 1fr 8rem; gap: .6rem; align-items: center; font-size: .88rem; }
.bar-l { font-family: var(--mono); font-size: .75rem; color: var(--text-3); }
.bar-t { height: .8rem; background: var(--card-2); border-radius: 999px; overflow: hidden; }
.bar-f { display: block; height: 100%; background: var(--ember); border-radius: 999px; }
.bar-v { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ═════════════════════════════════════════════ the tick bar (split/move) === */
/*  Appears under the ticket once a line is ticked: how many, how much, and
    the two things you can do with them. Sticky at the foot on a phone.  */
.tickbar {
    display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
    margin-top: .8rem; padding: .7rem .9rem;
    background: var(--ink); color: var(--paper); border-radius: var(--radius);
    font-size: .92rem;
}
.tickbar b { font-family: var(--mono); font-size: 1.05rem; }
.tickbar select {
    font: inherit; font-size: .9rem; padding: .4rem .5rem; margin-left: auto;
    border: 1px solid var(--ink-rule); border-radius: var(--radius-sm); background: var(--paper); color: var(--text);
}
.tickbar .btn-quiet { color: var(--paper); border-color: var(--ink-rule); }

/* ═══════════════════════════════════════════════ a phone in the steward's hand === */
/*
    The screens were drawn for a till and a tablet. On a phone the same
    screens must still work with a thumb: the card first (a steward keys
    before reading), the ticket under it, the send button and the tick bar
    pinned to the foot, every button at least a fingertip tall, and no
    table wider than the glass - it scrolls inside its own box instead.
*/
@media (max-width: 40rem) {
    .appmain { padding-block: 1rem 6rem; }
    .appbar-in { gap: .6rem; min-height: 3rem; }
    .appbar .where { padding-left: .6rem; margin-left: 0; }
    .appbar .where { flex: 1 1 0; min-width: 0; }
    .appbar .where .company, .appbar .where .who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .appbar .where .chain { font-size: .88rem; }
    .appbar-right { gap: .3rem; flex: none; }
    .appbar-right .name { display: none; }
    .linkbtn { padding: .35rem .5rem; font-size: .8rem; white-space: nowrap; }
    .page-head { margin-bottom: 1rem; gap: .6rem; }
    .page-head p { display: none; }
    .page-head .actions { margin-left: 0; width: 100%; flex-wrap: wrap; }
    .page-head .actions .btn { flex: 1 1 auto; }
    .chainnav a { padding: .5rem .6rem; font-size: .88rem; }
    .panel { padding: 1rem; }

    .btn { min-height: 2.75rem; }
    .btn-big { font-size: 1.1rem; padding: .9rem 1rem; }

    /*  The ticket: card on top, ticket below, nothing sticky on the side.  */
    .ticket-page { display: flex; flex-direction: column-reverse; gap: 1rem; }
    .card-pane { position: static; }
    .card-grid { grid-template-columns: repeat(2, 1fr); gap: .45rem; }
    .dish { min-height: 4.6rem; padding: .6rem .65rem; }
    .card-tabs { overflow-x: auto; flex-wrap: nowrap; padding-bottom: .3rem; -webkit-overflow-scrolling: touch; }
    .card-tab { white-space: nowrap; }
    .card-find { flex-basis: 100%; }

    /*  What must always be reachable: the send button and the tick bar.  */
    .ticket-pane form:has(> .btn-big), .ticket-pane .btn-big { position: sticky; bottom: .6rem; z-index: 5; box-shadow: var(--shadow-md); }
    .tickbar { position: sticky; bottom: .6rem; z-index: 6; box-shadow: var(--shadow-md); }
    .tickbar select { margin-left: 0; flex: 1 1 8rem; }
    .tickbar .btn { flex: 1 1 8rem; }

    /*  Tables scroll inside their box; the page never scrolls sideways.
        (Not the ticket pane: a scroll box would un-stick the tick bar.)  */
    .panel { overflow-x: auto; }
    table.grid { min-width: 32rem; }
    table.tlines { min-width: 0; }
    table.tlines td { padding: .4rem .3rem; }

    /*  The counts in one row, small, so the floor is above the fold.  */
    .stats { grid-template-columns: repeat(3, 1fr); margin-bottom: 1rem; }
    .stat { padding: .6rem .6rem .7rem; }
    .stat .n { font-size: 1.4rem; }
    .stat .l { font-size: .78rem; }

    /*  The floor: bigger tiles, two across.  */
    .floor { grid-template-columns: repeat(2, 1fr); gap: .5rem; }
    .ftile { min-height: 5.5rem; }

    /*  The kitchen wall on a phone: one ticket wide, buttons a thumb tall.  */
    .kds { grid-template-columns: 1fr; }
    .kds-acts .btn { min-height: 3rem; }
}

/* ═══════════════════════════════════════════════════════ salon screens === */
.pickbranch { display: inline; }
.pickbranch select {
    font: inherit; font-size: .78rem; padding: .1rem .3rem; margin-left: .3rem;
    background: var(--ink-soft); color: var(--on-ink); border: 1px solid var(--ink-rule); border-radius: 4px;
}
.filterbar label.subtle { display: inline-flex; align-items: center; gap: .3rem; }
.filterbar input[type=date], .filterbar select {
    font: inherit; font-size: .9rem; padding: .4rem .5rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); background: var(--paper); color: var(--text);
}
.filterbar .check { display: inline-flex; align-items: center; gap: .35rem; font-size: .9rem; }
table.grid tfoot td { font-weight: 600; border-top: 2px solid var(--ink); }
table.grid tr.off td { color: var(--text-3); text-decoration: line-through; }
table.grid tr.off td .chip, table.grid tr.off td.acts { text-decoration: none; }
.low { color: var(--danger); font-weight: 600; }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: .3rem 1.2rem; font-size: .93rem; }
.kv dt { color: var(--text-3); }
.kv dd { margin: 0; }
.pl { max-width: 34rem; }
.pl .row { display: flex; justify-content: space-between; padding: .45rem 0; border-bottom: 1px dashed var(--rule); font-variant-numeric: tabular-nums; }
.pl .row.sum { border-bottom: 2px solid var(--ink); font-weight: 600; }
.pl .row.net { font-size: 1.25rem; font-weight: 700; border: 0; padding-top: .8rem; }
.pl .row.net.loss { color: var(--danger); }
.pl .row .sub { color: var(--text-3); font-size: .85rem; }

/*  The till: services and products on the right, the bill on the left.  */
.till-line { display: grid; grid-template-columns: 1fr auto; gap: .3rem .6rem; padding: .5rem 0; border-bottom: 1px dashed var(--rule); }
.till-line .name { font-weight: 600; }
/*  Under the name AND the amount: in the first column alone the controls
    wrapped a line early.  */
.till-line .ctl { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; font-size: .84rem; color: var(--text-2); }
.till-line .ctl select, .till-line .ctl input { font: inherit; font-size: .84rem; padding: .2rem .35rem; border: 1px solid var(--rule); border-radius: 4px; width: auto; }
.till-line .ctl input[type=number] { width: 4.2rem; }
.till-line .amt { font-variant-numeric: tabular-nums; font-weight: 600; text-align: right; }
.till-line .rm { background: none; border: 0; color: var(--text-3); cursor: pointer; font-size: 1rem; }
.till-line .rm:hover { color: var(--danger); }
/*  minmax(0, 1fr), not 1fr: a text box will not shrink below its own default
    width, and two of them side by side ran out of the pane.  */
.till-cust { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; margin-bottom: .6rem; position: relative; }
.till-cust input { font: inherit; padding: .5rem .6rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); width: 100%; min-width: 0; box-sizing: border-box; }
.till-sugg { position: absolute; top: 100%; left: 0; right: 0; z-index: 5; background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-sm); box-shadow: var(--shadow-md); }
.till-sugg button { display: block; width: 100%; text-align: left; background: none; border: 0; padding: .5rem .7rem; font: inherit; cursor: pointer; }
.till-sugg button:hover { background: var(--card-2); }
/*  No column gap, so the rule over Bill and To pay runs unbroken under both
    cells; the space between label and amount is the amount's own padding.  */
.till-sums { display: grid; grid-template-columns: 1fr auto; gap: .2rem 0; margin-top: .8rem; font-variant-numeric: tabular-nums; font-size: .95rem; align-items: center; }
.till-sums > span:nth-child(even) { text-align: right; padding-left: .8rem; }
.till-sums .grand { font-size: 1.35rem; font-weight: 700; border-top: 2px solid var(--ink); padding-top: .4rem; margin-top: .3rem; }
.till-sums input { width: 5rem; font: inherit; padding: .15rem .3rem; border: 1px solid var(--rule); border-radius: 4px; text-align: right; }
.dish-stock { font-size: .72rem; color: var(--text-3); }
.dish-stock.low { color: var(--danger); }
.dayboard { display: flex; gap: 1rem; flex-wrap: wrap; font-size: .85rem; color: var(--text-2); margin-bottom: .8rem; }
.dayboard b { color: var(--text); font-variant-numeric: tabular-nums; }

/*  The printed bill: 80mm receipt, plain, no colour.  */
.bill { max-width: 22rem; margin: 0 auto; background: #fff; color: #000; padding: 1rem; font-family: var(--mono); font-size: .8rem; border: 1px solid var(--rule); }
.bill h2 { text-align: center; font-family: var(--sans); font-size: 1.1rem; margin: 0; }
.bill .c { text-align: center; }
.bill .r { text-align: right; }
.bill table { width: 100%; border-collapse: collapse; }
.bill td, .bill th { padding: .15rem 0; vertical-align: top; }
.bill th { text-align: left; border-bottom: 1px dashed #000; }
.bill .rule { border-top: 1px dashed #000; margin: .4rem 0; }
.bill .tot td { font-weight: 700; }
.bill .void { text-align: center; font-size: 1.2rem; font-weight: 700; border: 2px solid #000; padding: .3rem; margin: .5rem 0; }
/*  On paper only the page's content: none of the shell (side menu, top bar,
    sub-nav), so a printed bill is the bill and nothing else.  */
@media print {
    .appbar, .chainnav, .notice, .page-head, .no-print,
    .side, .topbar, .side-scrim { display: none !important; }
    .shell { display: block; min-height: 0; }
    .shell .appmain { padding: 0; }
    .shell .wrap { width: auto; margin: 0; }
    .bill { border: 0; max-width: none; padding: 0; }
    body { background: #fff; }
    /*  A bill prints on a page of its own kind (below) with no margin, which
        is also what stops the browser stamping its date, title and address
        across the top and bottom. The bill keeps a small margin of its own.  */
    .rcpt, .bill { page: bill; }
    .shell .rcpt, .shell .bill { padding: 3mm 3mm 5mm; }
}
@page bill { margin: 0; }

/*  The appointment board: time down the side, a column per stylist.  */
table.board td.slot { vertical-align: top; min-width: 11rem; padding: .25rem .3rem; height: 2.6rem; }
table.board .ap { display: block; padding: .35rem .5rem; margin-bottom: .25rem; border-radius: var(--radius-sm); border: 1px solid var(--rule); border-left-width: 4px; text-decoration: none; color: var(--text); font-size: .85rem; line-height: 1.3; background: var(--card); }
table.board .ap .sub { display: block; font-size: .74rem; color: var(--text-3); }
table.board .ap:hover { box-shadow: var(--shadow-md); }
table.board .ap-booked    { border-left-color: var(--text-3); }
table.board .ap-confirmed { border-left-color: var(--ember); }
table.board .ap-arrived   { border-left-color: #E09B00; background: color-mix(in srgb, #E09B00 10%, var(--card)); }
table.board .ap-inservice { border-left-color: var(--ember); background: color-mix(in srgb, var(--ember) 12%, var(--card)); }
table.board .ap-done      { border-left-color: #1B8A4C; opacity: .75; }
table.board .ap-off       { border-left-color: var(--danger); opacity: .5; text-decoration: line-through; }
table.board .slot-add { display: block; text-align: center; color: var(--rule); text-decoration: none; font-size: 1.1rem; }
table.board td.slot:hover .slot-add { color: var(--ember); }

/*  ═══════════════════════════════════════════════════════════════════════════
    THE SHELL, SECOND FORM (14 Sep 2026): a sidebar of screens on the left, a
    top bar that says where you are, the page on the right. The owner's
    "layout standard". The old top-only .appbar rules above are kept for the
    public pages; the signed-in layout uses these.
    ═══════════════════════════════════════════════════════════════════════════ */

.shell { min-height: 100vh; display: grid; grid-template-columns: 15.5rem 1fr; }
.shell .body { min-width: 0; display: flex; flex-direction: column; }

.side {
    background: var(--ink); color: var(--on-ink);
    display: flex; flex-direction: column; gap: .2rem;
    padding: 1rem .8rem; position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.side-brand { display: flex; align-items: center; gap: .5rem; text-decoration: none; color: var(--on-ink); padding: .2rem .5rem .8rem; }
.side-brand .brand-logo { height: 1.7rem; width: auto; }
.side-company { padding: .5rem .6rem .8rem; border-top: 1px solid var(--ink-rule); border-bottom: 1px solid var(--ink-rule); margin-bottom: .5rem; line-height: 1.25; }
.side-company .company { display: block; font-family: var(--display); font-weight: 600; font-size: 1rem; }
.side-company .who { display: block; font-size: .76rem; color: var(--on-ink-2); }
.side-group { font-family: var(--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; color: var(--on-ink-2); padding: .9rem .6rem .3rem; }
.side-nav { display: flex; flex-direction: column; gap: 2px; }
.side-nav a {
    display: flex; align-items: center; gap: .65rem;
    padding: .5rem .6rem; border-radius: var(--radius-sm);
    color: var(--on-ink); text-decoration: none; font-size: .9rem; line-height: 1.2;
}
.side-nav a:hover { background: var(--ink-soft); }
.side-nav a.on { background: var(--ember); color: var(--ember-ink); font-weight: 500; }
.side-nav svg { width: 1.1rem; height: 1.1rem; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; opacity: .9; }
.side-foot { margin-top: auto; padding: .8rem .6rem 0; border-top: 1px solid var(--ink-rule); display: flex; align-items: center; justify-content: space-between; gap: .5rem; font-size: .8rem; color: var(--on-ink-2); }
.side-person b { color: var(--on-ink); font-weight: 500; }

.topbar {
    display: flex; align-items: center; gap: 1rem; min-height: 3.4rem;
    padding: 0 1.25rem; background: var(--card); border-bottom: 1px solid var(--rule);
    position: sticky; top: 0; z-index: 30;
}
/*  At every width: on a phone it slides the menu in, on a desktop it hides
    and shows it (the choice is remembered in the browser).  */
.menubtn { display: block; font: inherit; background: none; border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: .3rem; cursor: pointer; color: var(--text); }
.menubtn:hover { border-color: var(--text-3); }
.menubtn svg { width: 1.3rem; height: 1.3rem; display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.topbar-where { display: flex; align-items: center; gap: .6rem; min-width: 0; }
.topbar-where .company { font-family: var(--display); font-weight: 600; font-size: 1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-where .branch { font-size: .88rem; color: var(--text-2); }
.topbar .pickbranch select { background: var(--paper); color: var(--text); border: 1px solid var(--rule); font-size: .88rem; padding: .3rem .5rem; margin: 0; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 1rem; font-size: .86rem; color: var(--text-2); white-space: nowrap; }
.topbar-right .name { color: var(--text); font-weight: 500; }

.shell .appmain { padding-block: 1.5rem 4rem; }
.shell .wrap { width: min(var(--wrap), 100% - 2.5rem); }
.side-scrim { position: fixed; inset: 0; background: rgb(0 0 0 / .4); z-index: 39; }

@media (min-width: 62.01rem) {
    .shell.side-hidden { grid-template-columns: 1fr; }
    .shell.side-hidden .side { display: none; }
}

@media (max-width: 62rem) {
    .shell { grid-template-columns: 1fr; }
    .side { position: fixed; left: 0; top: 0; bottom: 0; width: 16rem; z-index: 40; transform: translateX(-100%); transition: transform .18s ease; }
    .shell.side-open .side { transform: none; }
    .menubtn { display: block; }
    .topbar-right .today { display: none; }
    .shell .wrap { width: min(var(--wrap), 100% - 1.6rem); }
}

/* ══════════════════════════════════════════════════════════ dashboard === */

.dash-head { display: flex; flex-wrap: wrap; align-items: center; gap: .8rem; margin-bottom: 1.2rem; }
.dash-head h1 { font-size: clamp(1.5rem, 2.6vw, 1.9rem); }
.dash-head .sub { color: var(--text-2); font-size: .92rem; }
.dash-head form { margin-left: auto; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }

.tiles-x { display: grid; grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)); gap: .8rem; margin-bottom: 1.2rem; }
.tile-x {
    border-radius: var(--radius); padding: .9rem 1rem 1rem; color: #fff; text-decoration: none;
    display: flex; flex-direction: column; gap: .15rem; min-height: 5.6rem; box-shadow: var(--shadow-sm);
    background: var(--ink);
}
.tile-x .n { font-family: var(--display); font-size: 1.75rem; font-weight: 700; line-height: 1.05; font-variant-numeric: tabular-nums; }
.tile-x .l { font-size: .8rem; opacity: .9; }
.tile-x .s { font-size: .74rem; opacity: .75; margin-top: auto; }
.tile-x.t-blue   { background: var(--ember); }
.tile-x.t-green  { background: #1B8A4C; }
.tile-x.t-amber  { background: #C77B00; }
.tile-x.t-red    { background: var(--danger); }
.tile-x.t-teal   { background: #0F7C8C; }
.tile-x.t-plum   { background: #6A2C91; }
.tile-x.t-slate  { background: #3C4A63; }
a.tile-x:hover { filter: brightness(1.08); }

.dash-grid { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: 1rem; align-items: start; }
@media (max-width: 70rem) { .dash-grid { grid-template-columns: 1fr; } }
.dash-col { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }

.dash-panel { background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius); padding: 1rem 1.1rem; }
.dash-panel h3 { font-size: 1rem; margin-bottom: .6rem; display: flex; align-items: baseline; gap: .6rem; }
.dash-panel h3 .more { margin-left: auto; font-family: var(--sans); font-weight: 400; font-size: .82rem; color: var(--ember); text-decoration: none; }
.dash-panel h3 .more:hover { text-decoration: underline; }

/*  Charts are plain SVG drawn by the view. No library: a stylesheet or a
    script that fails to load must cost the look, not the numbers.  */
.chart { width: 100%; height: auto; display: block; font-family: var(--sans); }
.chart .bar { fill: var(--ember); }
.chart .bar.today { fill: var(--brass); }
.chart .bar:hover { opacity: .8; }
.chart .axis { stroke: var(--rule); stroke-width: 1; }
.chart .lbl { font-size: 10px; fill: var(--text-3); }
.chart .val { font-size: 10px; fill: var(--text-2); font-variant-numeric: tabular-nums; }
.chart .hbar { fill: var(--ember); }
.chart .hbar-bg { fill: var(--card-2); }

/*  The day grid: one column per stylist, one row per half hour. Bookings
    sit in the slot where they start and tell how long they run.  */
.daygrid-wrap { overflow-x: auto; }
table.daygrid { border-collapse: collapse; width: 100%; font-size: .8rem; }
table.daygrid th { font-family: var(--mono); font-size: .66rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); padding: .3rem .4rem; text-align: left; border-bottom: 1px solid var(--rule); white-space: nowrap; }
table.daygrid th.st { font-family: var(--sans); font-size: .82rem; letter-spacing: 0; text-transform: none; color: var(--text); font-weight: 600; min-width: 9rem; }
table.daygrid th.st .sub { display: block; font-weight: 400; font-size: .72rem; color: var(--text-3); }
table.daygrid td { border-bottom: 1px solid var(--rule-soft); border-left: 1px solid var(--rule-soft); vertical-align: top; padding: .15rem .25rem; height: 1.9rem; }
table.daygrid td.t { font-family: var(--mono); font-size: .68rem; color: var(--text-3); white-space: nowrap; border-left: 0; width: 3.2rem; }
table.daygrid tr.hour td { border-bottom-color: var(--rule); }
table.daygrid tr.now td.t { color: var(--ember); font-weight: 700; }
table.daygrid .ap { display: block; padding: .25rem .4rem; border-radius: 4px; border-left: 3px solid var(--text-3); background: var(--card-2); text-decoration: none; color: var(--text); line-height: 1.25; margin-bottom: .15rem; }
table.daygrid .ap .sub { display: block; font-size: .7rem; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
table.daygrid .ap-confirmed { border-left-color: var(--ember); }
table.daygrid .ap-arrived   { border-left-color: #E09B00; background: color-mix(in srgb, #E09B00 12%, var(--card)); }
table.daygrid .ap-inservice { border-left-color: var(--ember); background: color-mix(in srgb, var(--ember) 12%, var(--card)); }
table.daygrid .ap-done      { border-left-color: #1B8A4C; opacity: .7; }
table.daygrid .ap-noshow    { border-left-color: var(--danger); opacity: .55; text-decoration: line-through; }

.upcoming { display: flex; flex-direction: column; gap: .5rem; }
.upcoming a { display: grid; grid-template-columns: 3.4rem 1fr; gap: .5rem; align-items: start; text-decoration: none; color: inherit; padding: .45rem .5rem; border-radius: var(--radius-sm); border: 1px solid var(--rule-soft); }
.upcoming a:hover { background: var(--card-2); }
.upcoming .when { font-family: var(--mono); font-size: .8rem; font-weight: 600; color: var(--ember); line-height: 1.3; }
.upcoming .when .d { display: block; font-weight: 400; font-size: .66rem; color: var(--text-3); }
.upcoming .who { font-size: .88rem; font-weight: 500; line-height: 1.25; }
.upcoming .what { font-size: .76rem; color: var(--text-3); }

.kv { display: grid; grid-template-columns: 1fr auto; gap: .35rem .8rem; font-size: .9rem; }
.kv .k { color: var(--text-2); }
.kv .v { font-variant-numeric: tabular-nums; text-align: right; font-weight: 500; }
.kv .v.strong { font-family: var(--display); font-size: 1.05rem; }

/*  A slot the stylist is not there for: shaded, no "+", the reason on hover.  */
table.board td.slot-off, table.board td.slot-leave { background: repeating-linear-gradient(135deg, var(--card-2) 0 6px, var(--paper) 6px 12px); }
table.board td.slot-closed { background: var(--card-2); }
table.board td.slot-break  { background: color-mix(in srgb, #E09B00 10%, var(--paper)); }

/*  Parked bills on the till, and the coupon row.  */
.held-strip { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: .8rem; }
.held-chip { display: inline-flex; align-items: center; gap: .3rem; border: 1px solid var(--rule); border-radius: 999px; padding: .2rem .4rem .2rem .8rem; font-size: .85rem; background: var(--card); }
.held-chip a { text-decoration: none; color: var(--text); }
.held-chip form { display: inline; }
.held-chip .rm { font: inherit; background: none; border: 0; color: var(--text-3); cursor: pointer; padding: 0 .3rem; font-size: 1rem; }
.coupon-row { display: flex; gap: .4rem; align-items: center; margin: .4rem 0; }
.coupon-row input { font: inherit; padding: .4rem .6rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); width: 11rem; }
.coupon-row .low { color: var(--danger); }
.till-sums input[type=number] { font: inherit; font-size: .9rem; padding: .15rem .3rem; border: 1px solid var(--rule); border-radius: 4px; }

/*  The week: seven columns, a day each, bookings stacked.  */
.week { display: grid; grid-template-columns: repeat(7, minmax(9.5rem, 1fr)); gap: .5rem; overflow-x: auto; }
.week-day { background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius); padding: .5rem; min-height: 12rem; display: flex; flex-direction: column; gap: .3rem; }
.week-day.today { border-color: var(--ember); box-shadow: inset 0 3px 0 var(--ember); }
.week-head { display: flex; justify-content: space-between; align-items: baseline; padding-bottom: .3rem; border-bottom: 1px solid var(--rule-soft); }
.week-head a { text-decoration: none; color: var(--text); font-size: .9rem; }
.week-away { font-size: .72rem; color: var(--danger); }
.week .ap { display: block; padding: .3rem .45rem; border-radius: 4px; border: 1px solid var(--rule); border-left-width: 4px; text-decoration: none; color: var(--text); font-size: .8rem; line-height: 1.25; }
.week .ap .sub { display: block; font-size: .7rem; color: var(--text-3); }
.week .ap-booked    { border-left-color: var(--text-3); }
.week .ap-confirmed { border-left-color: var(--ember); }
.week .ap-arrived   { border-left-color: #E09B00; }
.week .ap-inservice { border-left-color: var(--ember); background: color-mix(in srgb, var(--ember) 12%, var(--card)); }
.week .ap-done      { border-left-color: #1B8A4C; opacity: .7; }
.week .ap-off       { border-left-color: var(--danger); opacity: .5; text-decoration: line-through; }
.week-add { margin-top: auto; font-size: .8rem; color: var(--ember); text-decoration: none; }
@media (max-width: 62rem) { .week { grid-template-columns: 1fr; } }

/*  ── product pictures: the edit panel, the list thumb, the till tile ── */
.pic-row { display: flex; gap: 1.2rem; align-items: flex-start; flex-wrap: wrap; }
.pic-box { width: 160px; height: 160px; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--card-2); display: grid; place-items: center; overflow: hidden; }
.pic-box img { width: 100%; height: 100%; object-fit: cover; }
.thumb { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; border: 1px solid var(--rule); vertical-align: middle; margin-right: .5rem; background: var(--card-2); }
.thumb-none { display: inline-grid; place-items: center; color: var(--text-3); font-size: .7rem; }
.dish-pic { width: 100%; height: 64px; object-fit: cover; border-radius: 6px; margin-bottom: .3rem; background: var(--card-2); }

/* ── the doors: sign in / register, on _AuthLayout ─────────────────────── */
.auth-body { margin: 0; min-height: 100vh; background: linear-gradient(160deg, #0B2049 0%, #163A7A 55%, #2F7BFF 100%); }
.auth { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.2rem; padding: 2rem 1rem; }
.auth-row { width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.2rem; }
.auth-brand { flex: none; }
.auth-brand img { display: block; width: 7.5rem; height: 7.5rem; object-fit: contain; background: #fff; border-radius: 1.4rem; padding: .45rem; box-shadow: 0 16px 40px rgba(0,0,0,.35); }
@media (min-width: 48rem) {
    .auth-row { flex-direction: row; gap: 3rem; }
    .auth-brand img { width: 11rem; height: 11rem; border-radius: 2rem; padding: .7rem; }
}
.auth-card { width: 100%; max-width: 26rem; background: var(--paper); border-radius: var(--radius); box-shadow: 0 24px 60px rgba(0,0,0,.35); padding: 1.6rem 1.6rem 1.4rem; }
.auth-card .page-head { margin: 0 0 1rem; padding: 0; border: 0; }
.auth-card .page-head h1 { font-size: 1.7rem; }
.auth-card .page-head p { font-size: .92rem; }
.auth-card .panel { background: none; border: 0; box-shadow: none; padding: 0; max-width: none; }
.auth-card .fields { grid-template-columns: 1fr !important; }
.auth-card .fields > * { grid-column: 1 / -1 !important; }
.auth-card .form-foot { flex-wrap: wrap; }
.auth-card .form-foot .btn { width: 100%; }
.auth-card .form-foot .aside { margin-left: 0; width: 100%; text-align: center; }
.auth-foot { color: rgba(255,255,255,.75); font-size: .85rem; }
.auth-foot a { color: #fff; }
.auth-card .field input, .auth-card .field select, .auth-card .field textarea { width: 100%; box-sizing: border-box; }
.auth-card .hint { display: block; }
.setup-cmd { white-space: pre-wrap; word-break: break-all; font-size: .82rem; background: var(--card-2); padding: .8rem; border-radius: var(--radius-sm); }
.chip-wait { background: #FFF4D6; color: #7A5200; }
.approve-form { flex-wrap: wrap; }
.field label.check { display: flex; align-items: center; gap: .5rem; font-weight: 500; }
.field label.check input { width: 1.05rem; height: 1.05rem; padding: 0; flex: none; accent-color: var(--ember); cursor: pointer; }
/*  A tick dressed as an input, so it lines up with the boxes beside it.  */
.field label.check-tile { padding: .55rem .7rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); background: var(--paper); font-size: .95rem; color: var(--text); cursor: pointer; }
.f3 { grid-column: auto / span 3; }
.f2 { grid-column: auto / span 2; }
/*  Repeated here because the .f3 above comes after site.css's phone rule
    and would otherwise win it back.  */
@media (max-width: 42rem) { .f2, .f3 { grid-column: auto / span 12; } }
.share { display: inline-flex; gap: .4rem; margin-left: .5rem; }
.booklink { margin: 0 0 1rem; }
.booklink-in { display: flex; flex-wrap: wrap; gap: .8rem 1.2rem; align-items: center; justify-content: space-between; }
.booklink-url { display: inline-block; margin-top: .35rem; font-size: .9rem; word-break: break-all; }
.booklink-acts { display: flex; flex-wrap: wrap; gap: .4rem; }
.form-part { margin: 1.2rem 0 .2rem; font-size: 1rem; color: var(--text-2); border-top: 1px solid var(--rule); padding-top: .9rem; }
.dayoffs { display: flex; flex-wrap: wrap; gap: .5rem .9rem; }
.dayoff { display: inline-flex; align-items: center; gap: .35rem; font-weight: 500; }
/* ═══════════════════════════════════════════════════════════════ compact === */
/*  The working screens are used all day at a counter: dense, full width, no
    prose. Everything here overrides the roomier values above, so deleting
    this block puts them back.  */

.appmain, .shell .appmain { padding-block: 1rem 2rem; }
.shell .wrap { width: min(100rem, 100% - 2rem); }

.page-head { margin-bottom: .9rem; padding-bottom: .6rem; gap: .6rem; }
.page-head .titles { gap: .1rem; }
.page-head h1 { font-size: clamp(1.25rem, 2vw, 1.5rem); }
.page-head p { font-size: .88rem; }
.chainnav { margin-bottom: .9rem; }
.chainnav a { padding: .4rem .75rem; font-size: .88rem; }

/*  Every panel takes the page's width. It is also the container the field
    grid below measures itself against.  */
.panel { max-width: none; padding: 1rem 1.1rem; container-type: inline-size; }
.panel h3 { font-size: 1.02rem; }
.fields { gap: .6rem .8rem; }
.field { gap: .2rem; }
.field label { font-size: .78rem; }
.field input, .field select, .field textarea { padding: .4rem .6rem; font-size: .9rem; }
.field textarea { min-height: 3.2rem; }
.field label.check-tile { padding: .4rem .6rem; font-size: .9rem; }
.form-foot { margin-top: .6rem; }
.btn { padding: .45rem .9rem; font-size: .88rem; }
.validation { padding: .55rem .8rem; margin-bottom: .8rem; }

/*  On a wide panel every form is the same even grid: six columns, a short
    field (a phone, a date, an amount, a choice) in one, a long one (a name,
    an email, an address, notes) in two, and the buttons and headings across
    the row. Forms stay in their written order, so Enter still walks them
    left to right. A form laid out for the full width by hand opts out with
    .fields-wide.  */
@container (min-width: 56rem) {
    .fields:not(.fields-wide) { grid-template-columns: repeat(6, minmax(0, 1fr)); }
    .fields:not(.fields-wide) > :is(.f2, .f3, .f4, .f5) { grid-column: auto / span 1; }
    .fields:not(.fields-wide) > :is(.f6, .f8, .f9, .field.f12) { grid-column: auto / span 2; }
    .fields:not(.fields-wide) > .f12:not(.field) { grid-column: 1 / -1; }
}

.cards { gap: .7rem; }
.card { padding: .85rem; gap: .4rem; }
.card h3 { font-size: 1.05rem; }
.tile { padding: .8rem .9rem; }
.empty { padding: 1.4rem 1rem; gap: .4rem; }
.empty h3 { font-size: 1.05rem; }
table.grid { font-size: .88rem; }
table.grid th, table.grid td { padding: .4rem .65rem; }

/*  The till.  */
.ticket-page { grid-template-columns: minmax(22rem, 5fr) 7fr; gap: 1rem; }
.dayboard { margin-bottom: .5rem; }
.till-cust input { padding: .4rem .55rem; font-size: .9rem; }
.till-line { padding: .35rem 0; }
.till-line .ctl input[type=number] { width: 3.4rem; }
.till-sums { font-size: .88rem; margin-top: .5rem; }
.till-sums .grand { font-size: 1.12rem; padding-top: .3rem; margin-top: .2rem; }
.till-sums input, .till-sums select { font-size: .85rem; padding: .12rem .3rem; }
.coupon-row input { flex: 1; width: auto; min-width: 0; padding: .35rem .55rem; font-size: .88rem; }
.pay-quick { margin: .4rem 0; }
.pay-quick .btn { padding: .3rem .6rem; }
.btn-big { padding: .6rem 1rem; font-size: .98rem; }
.card-tabs { gap: .3rem; margin-bottom: .6rem; }
.card-find { padding: .4rem .6rem; font-size: .9rem; }
.card-tab { padding: .32rem .7rem; font-size: .82rem; }
.card-grid { grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: .45rem; }
.dish { min-height: 4.4rem; padding: .5rem .65rem; }
.dish-name { font-size: .9rem; }
/*  A destructive button that does its thing once confirmed.  */
.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-danger:hover { filter: brightness(.92); }

/*  The bill in a window over the Bills list.  */
dialog.bill-preview { max-width: 30rem; }
dialog.bill-preview .pv-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
dialog.bill-preview .pv-body { max-height: 65vh; overflow-y: auto; border: 1px solid var(--rule); border-radius: var(--radius-sm); background: #fff; }
dialog.bill-preview .row { margin-top: 0; }
dialog.ask .cx-in { font: inherit; font-size: .9rem; padding: .45rem .6rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); width: 100%; box-sizing: border-box; }
/* ═════════════════════════════════════════════════════════ every list === */
/*  The list-ui skill: the header row in the logo navy, a click on a header
    sorts (site.js marks the sortable ones), and row actions are icons.  */
table.grid thead th { background: var(--ink); color: var(--on-ink); border-bottom: 0; }
table.grid thead th.num { text-align: right; }
table.grid thead th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
table.grid thead th.sortable:hover, table.grid thead th.sortable:focus-visible { background: var(--ink-soft); outline: none; }
table.grid thead th.sortable::after { content: "\2195"; margin-left: .3rem; opacity: .35; font-family: var(--sans); }
table.grid thead th[aria-sort="ascending"]::after { content: "\25B2"; opacity: .9; font-size: .6rem; }
table.grid thead th[aria-sort="descending"]::after { content: "\25BC"; opacity: .9; font-size: .6rem; }
