/* The kitchen display.
   ────────────────────────────────────────────────────────────────────────────
   A 1280 × 800 tablet on a wall, read across a room, through steam, by somebody
   holding a pan. It is the one screen in this product that does not wear the
   restaurant's colours: a brasserie's warm paper and brass is exactly the wrong
   palette for a surface whose whole job is to make four states distinguishable
   at three metres. The roadmap records that exception deliberately.

   Two themes, and they are not a light/dark pair of the same design. Dark is for
   a service; light is high-visibility, for a kitchen with a window behind the
   screen — so it does not just swap the background, it thickens every border and
   widens every status stripe, because glare eats thin lines first. */

:root,
[data-kds="dark"] {
    --kds-bg: #14171a;
    --kds-panel: #1c2126;
    --kds-card: #232a30;
    --kds-ink: #f2f5f7;
    --kds-mut: #9aa7b1;
    --kds-line: #333c44;

    /* One hue per column, and the same hue on the card's stripe. The colour is
       the index: a cook finds the column by colour before reading its title. */
    --kds-new: #5980a6;
    --kds-cooking: #d99a2b;
    --kds-ready: #4a9d5f;
    --kds-late: #c2413a;
    --kds-due: #7dd3fc;

    --kds-border: 1px;
    --kds-stripe: 4px;
}

[data-kds="light"] {
    --kds-bg: #eef1f3;
    --kds-panel: #ffffff;
    --kds-card: #ffffff;
    --kds-ink: #14171a;
    --kds-mut: #55616b;
    --kds-line: #b9c3cb;

    /* Darkened against a white ground: the dark theme's steel and amber are set
       for contrast against near-black and go pale and washed out on paper. */
    --kds-new: #2f5d8a;
    --kds-cooking: #9a6a05;
    --kds-ready: #2f7a44;
    --kds-late: #a52b24;
    --kds-due: #0b5d8a;

    --kds-border: 2px;
    --kds-stripe: 6px;
}

.kds {
    background: var(--kds-bg);
    color: var(--kds-ink);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    font-family: 'Barlow', system-ui, sans-serif;
}

/* The same board, set underneath something.
   ────────────────────────────────────────────────────────────────────────────
   The till shows it in a tab, below its own bar. Claiming the whole window
   height is right for a wall display whose only content it is; under a banner it
   pushes a windowful of board downwards and makes the page scroll to find the
   third column.

   The subtraction is an ALLOWANCE, not a measurement: the till's bar wraps onto
   two lines on a narrow screen, and no CSS rule can read the height it takes
   that day. Being wrong costs a few pixels of scrolling, never a cut-off column
   — this is a minimum, and the board stretches past it when its content asks. */
.kds-inset {
    min-height: calc(100vh - 4.25rem);
}

/* ── Top bar ─────────────────────────────────────────────────────────────── */

.kds-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 18px;
    padding: 10px 18px;
    background: var(--kds-panel);
    border-bottom: var(--kds-border) solid var(--kds-line);
}

.kds-place {
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 600;
    font-size: 21px;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* Counters and clock. Tabular figures throughout: a number that changes width as
   it counts is a number that makes the whole bar twitch every few seconds. */
.kds-stat {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
}

.kds-stat-value {
    font-size: 22px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.kds-stat-label {
    font-size: 11px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--kds-mut);
}

.kds-clock {
    font-size: 26px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.kds-toggle {
    border: var(--kds-border) solid var(--kds-line);
    background: transparent;
    color: var(--kds-ink);
    border-radius: 4px;
    min-height: 44px;
    padding: 8px 14px;
    cursor: pointer;
    font-size: 13px;
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* ── Columns ─────────────────────────────────────────────────────────────── */

.kds-columns {
    flex: 1 1 auto;
    display: flex;
    gap: 12px;
    padding: 12px;
    overflow: hidden;
}

.kds-column {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--kds-panel);
    border: var(--kds-border) solid var(--kds-line);
    border-radius: 6px;
    overflow: hidden;
}

/* The middle column is where a ticket spends most of its life, and it is the one
   a cook is reading. The handoff gives it the extra width for that reason. */
.kds-column-cooking {
    flex: 1.3 1 0;
}

/* Unless the ready column is the one being read — on a till, it is where the
   money changes hands. The bar's own button flips this for the service. */
.kds-column-ready-wide {
    flex: 1.7 1 0;
}

.kds-column-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    border-bottom: var(--kds-border) solid var(--kds-line);
}

.kds-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex: none;
}

.kds-column-title {
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 600;
    font-size: 15px;
    letter-spacing: .1em;
    text-transform: uppercase;
}

.kds-column-count {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.kds-column-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.kds-empty {
    color: var(--kds-mut);
    font-size: 13px;
    padding: 8px 2px;
}

/* ── Order card ──────────────────────────────────────────────────────────── */

.kds-card {
    background: var(--kds-card);
    border: var(--kds-border) solid var(--kds-line);
    border-left: var(--kds-stripe) solid var(--kds-line);
    border-radius: 5px;
    /* No text selection: every gesture on this card is a command, and a long press
       that highlights the dish name instead of cancelling is a long press wasted. */
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
}

.kds-card-new { border-left-color: var(--kds-new); }
.kds-card-cooking { border-left-color: var(--kds-cooking); }
.kds-card-ready { border-left-color: var(--kds-ready); }

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

/* Late flips the whole header rather than adding a badge to it. A badge is
   something you find; a red header is something you cannot miss from the pass. */
.kds-card-late .kds-card-head {
    background: var(--kds-late);
    color: #fff;
}

.kds-card-late {
    border-left-color: var(--kds-late);
}

.kds-order-no {
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 700;
    font-size: calc(28px * var(--kds-scale, 1));
    letter-spacing: .02em;
}

/* The code beside the table: what the customer reads off their ticket. Smaller
   than the table, which is still where the plate goes. */
.kds-order-code {
    font-size: calc(14px * var(--kds-scale, 1));
    letter-spacing: .06em;
    color: var(--kds-mut);
    font-variant-numeric: tabular-nums;
}

/* The second axis on a ticket — does somebody still owe. Amber while they do,
   because it is the customer's money and the kitchen's colour for "somebody
   said something"; outlined green once the till has recorded it. */
.kds-money {
    font-size: calc(12px * var(--kds-scale, 1));
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: 2px 7px;
    border-radius: 3px;
    white-space: nowrap;
}

.kds-money-owed {
    background: var(--kds-cooking);
    color: #14171a;
    font-weight: 700;
}

.kds-money-paid {
    border: 1px solid var(--kds-ready);
    color: var(--kds-ready);
}

.kds-card-late .kds-money-paid {
    border-color: #fff;
    color: #fff;
}

/* A ready ticket folds its dishes: the number and the money are what this
   column is read for. The count opens them again. */
.kds-card-folded .kds-lines {
    display: none;
}

.kds-fold {
    border: 0;
    background: transparent;
    color: var(--kds-mut);
    font-size: 12px;
    letter-spacing: .06em;
    text-transform: uppercase;
    text-decoration: underline;
    cursor: pointer;
    min-height: 44px;
    padding: 10px 12px 4px;
    text-align: left;
}

/* "Paid" — the one button on this board that is about money rather than food.
   Outlined rather than filled, so the filled green "collected" below it stays
   the gesture the hand goes to. */
.kds-settle {
    display: block;
    width: 100%;
    border: 2px solid var(--kds-ready);
    background: transparent;
    color: var(--kds-ready);
    min-height: 48px;
    padding: 10px;
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 700;
    font-size: 16px;
    letter-spacing: .1em;
    text-transform: uppercase;
    cursor: pointer;
}

.kds-settle:disabled {
    opacity: .5;
    cursor: default;
}

/* Paid how: three equal targets, one tap each, and a way back. */
.kds-tenders {
    display: flex;
    gap: 6px;
    padding: 8px 12px;
}

.kds-tender {
    flex: 1 1 0;
    border: var(--kds-border) solid var(--kds-ready);
    background: var(--kds-ready);
    color: #fff;
    min-height: 48px;
    padding: 10px 4px;
    border-radius: 4px;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: .06em;
    text-transform: uppercase;
    cursor: pointer;
}

.kds-tender-back {
    flex: 0 0 auto;
    background: transparent;
    color: var(--kds-ink);
    border-color: var(--kds-line);
}

.kds-tender:disabled {
    opacity: .5;
    cursor: default;
}

.kds-service {
    font-size: calc(12px * var(--kds-scale, 1));
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: 2px 7px;
    border: 1px solid currentColor;
    border-radius: 3px;
    opacity: .85;
}

.kds-timer {
    margin-left: auto;
    font-size: calc(26px * var(--kds-scale, 1));
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* FOR WHAT TIME — a ticket ordered ahead.

   Large rather than discreet: two tickets side by side, one for now and one for eight o'clock, are
   not cooked in the same order, and this screen is read from a metre and a half with full hands.
   Absent from the great majority of tickets, which are wanted straight away. */
.kds-due {
    margin: 6px 12px 0;
    font-size: calc(20px * var(--kds-scale, 1));
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--kds-due);
}

.kds-lines {
    padding: 8px 12px;
}

.kds-line {
    display: grid;
    grid-template-columns: minmax(2.4em, auto) 1fr;
    column-gap: 8px;
    align-items: baseline;
    margin-bottom: 6px;
}

.kds-qty {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-size: calc(22px * var(--kds-scale, 1));
    color: var(--kds-ink);
}

.kds-name {
    font-size: calc(22px * var(--kds-scale, 1));
    line-height: 1.25;
}

/* Two channels that must never be confused. Options are what the kitchen builds
   the plate from; a note is the customer talking. Same size, different colour and
   different voice — a cook reading amber knows somebody wrote it by hand. */
.kds-options {
    display: block;
    font-size: calc(16px * var(--kds-scale, 1));
    color: var(--kds-new);
}

.kds-note {
    display: block;
    font-size: calc(16px * var(--kds-scale, 1));
    font-weight: 600;
    font-style: italic;
    color: var(--kds-cooking);
}

.kds-action {
    display: block;
    width: 100%;
    border: 0;
    min-height: 52px;
    padding: 12px;
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 700;
    font-size: calc(17px * var(--kds-scale, 1));
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #fff;
    cursor: pointer;
    border-radius: 0 0 3px 3px;
}

.kds-action-new { background: var(--kds-new); }
.kds-action-cooking { background: var(--kds-cooking); }
.kds-action-ready { background: var(--kds-ready); }

.kds-action:disabled {
    opacity: .5;
    cursor: default;
}

/* ── Bottom help bar ─────────────────────────────────────────────────────── */

.kds-help {
    display: flex;
    gap: 20px;
    padding: 7px 18px;
    background: var(--kds-panel);
    border-top: var(--kds-border) solid var(--kds-line);
    font-size: 12px;
    color: var(--kds-mut);
}

.kds-help kbd {
    font-family: inherit;
    border: 1px solid var(--kds-line);
    border-radius: 3px;
    padding: 1px 5px;
    margin-right: 5px;
    color: var(--kds-ink);
}

/* The cancel confirmation, on the card rather than in a dialog: a modal over a wall display is a
   modal somebody else walks up to and cannot read the context of. */
.kds-confirm {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    background: var(--kds-late);
    color: #fff;
    font-size: 13px;
    border-radius: 0 0 3px 3px;
}

.kds-confirm span {
    flex: 1 1 auto;
}

.kds-confirm-no,
.kds-confirm-yes {
    border: 1px solid rgba(255, 255, 255, .7);
    background: transparent;
    color: #fff;
    border-radius: 3px;
    min-height: 44px;
    padding: 8px 14px;
    cursor: pointer;
    font-size: 12px;
    letter-spacing: .06em;
    text-transform: uppercase;
}

/* The destructive one is the filled one. Reversed from the usual, because here the safe answer is
   the one you reach for without looking and "no" must be the easy target. */
.kds-confirm-yes {
    background: #fff;
    color: var(--kds-late);
    font-weight: 700;
}

/* ── Rupture immédiate ────────────────────────────────────────────────────────

   A panel rather than the handoff's permanent side rail: on a 1280-wide tablet a rail costs a whole
   column, and a kitchen looks at its shortages twice a service. */

.kds-toggle-on {
    background: var(--kds-ink);
    color: var(--kds-bg);
}

.kds-rail {
    background: var(--kds-panel);
    border-bottom: var(--kds-border) solid var(--kds-line);
    padding: 10px 18px 14px;
}

.kds-rail-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.kds-rail-head .kds-column-title {
    flex: 1 1 auto;
}

/* Wrapping chips, not a list: a carte is forty dishes and a column of forty rows would be the panel
   eating the board it is supposed to sit above. */
.kds-rail-items {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    max-height: 30vh;
    overflow-y: auto;
}

.kds-switch {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: var(--kds-border) solid var(--kds-line);
    border-radius: 4px;
    background: transparent;
    color: var(--kds-ink);
    min-height: 44px;
    padding: 8px 12px;
    font-size: 15px;
    cursor: pointer;
    user-select: none;
}

/* Off reads as off at a glance: struck through here for the same reason it is struck through on the
   client's carte, so the two screens are describing the same fact in the same way. */
.kds-switch-off {
    border-color: var(--kds-late);
    color: var(--kds-late);
    text-decoration: line-through;
}

.kds-switch-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--kds-ready);
    flex: none;
}

.kds-switch-off .kds-switch-dot {
    background: var(--kds-late);
}

.kds-switch:disabled {
    opacity: .5;
    cursor: default;
}

/* A line the kitchen took back. Struck through rather than removed, so a cook who had already
   started it knows which one to stop — and so the ticket still matches what the customer ordered. */
.kds-line-gone .kds-name,
.kds-line-gone .kds-qty {
    text-decoration: line-through;
    opacity: .45;
}

/* "We've run out": a real target on its own line, asked twice. It was a 12 px underlined link beside
   the dish name, the first thing a thumb scrolling the column landed on. */
/* "We've run out": a small red ring pinned to the end of the line, out of the way of the double tap
   and the long press the card itself takes (2026-10-07). The line keeps room for it on the right. */
.kds-line {
    position: relative;
    padding-right: 40px;
}

.kds-drop {
    position: absolute;
    top: 0;
    right: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 2px solid var(--kds-late);
    border-radius: 50%;
    background: transparent;
    color: var(--kds-late);
    font-size: 18px;
    line-height: 1;
    opacity: .7;
    cursor: pointer;
}

.kds-drop:hover {
    opacity: 1;
}

.kds-drop:disabled {
    opacity: .4;
    cursor: default;
}

/* Why a dish appeared on a ticket the kitchen had already started. */
.kds-replacement {
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--kds-ready);
    padding-left: 8px;
}

/* Somebody in the room decided this ticket goes first. Off it is a hairline outline that reads as an
   affordance; on it is filled, because a priority nobody can spot from the pass is not a priority. */
.kds-star {
    border: 0;
    background: transparent;
    color: var(--kds-line);
    font-size: calc(24px * var(--kds-scale, 1));
    line-height: 1;
    cursor: pointer;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    margin: -8px 0;
}

.kds-star-on {
    color: var(--kds-cooking);
}

.kds-star:disabled {
    opacity: .5;
    cursor: default;
}

/* ── What the board learned since the last look ──────────────────────────── */

/* The board's own pieces, without a box of their own: the host's `.kds` lays out the bar, rails and
   columns as direct flex children, and this wrapper only carries the station's text size. */
.kds-scope {
    display: contents;
}

.kds-spacer {
    flex: 1 1 auto;
}

.kds-dot-new { background: var(--kds-new); }
.kds-dot-cooking { background: var(--kds-cooking); }
.kds-dot-ready { background: var(--kds-ready); }

/* Amber before red. Fifteen minutes straight to red made red the first warning, and the first
   warning is the one a kitchen can still act on. */
.kds-card-warn .kds-card-head {
    background: var(--kds-cooking);
    color: #14171a;
}

.kds-card-warn {
    border-left-color: var(--kds-cooking);
}

/* Nobody has taken it yet: the stripe breathes until somebody does. */
.kds-card-fresh {
    animation: kds-fresh 1.6s ease-in-out infinite;
}

@keyframes kds-fresh {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    50% { box-shadow: 0 0 0 4px var(--kds-new); }
}

/* A dish arrived on a ticket the kitchen had already started. */
.kds-card-changed {
    outline: 3px solid var(--kds-cooking);
    outline-offset: -1px;
}

.kds-changed {
    padding: 6px 12px;
    background: var(--kds-cooking);
    color: #14171a;
    font-weight: 700;
    font-size: calc(14px * var(--kds-scale, 1));
    letter-spacing: .06em;
    text-transform: uppercase;
}

/* The diner's note about the whole meal — an allergy, more often than not. Filled, first, and in
   the late colour's neighbour so nobody reads it as an option. */
.kds-order-note {
    margin: 8px 12px 0;
    padding: 8px 10px;
    border-radius: 4px;
    background: var(--kds-cooking);
    color: #14171a;
    font-weight: 700;
    font-size: calc(17px * var(--kds-scale, 1));
    line-height: 1.3;
}

/* Cancelled elsewhere: struck through, red, and gone on a tap or after a moment. */
.kds-card-ghost {
    border-left-color: var(--kds-late);
    opacity: .85;
    cursor: pointer;
}

.kds-card-ghost .kds-card-head {
    background: var(--kds-late);
    color: #fff;
}

.kds-ghost-label {
    margin-left: auto;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.kds-ghost-hint {
    padding: 0 12px 8px;
    font-size: 12px;
    color: var(--kds-mut);
}

.kds-drop-confirm {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    padding: 6px 10px;
    border-radius: 4px;
    background: var(--kds-late);
    color: #fff;
    font-size: 14px;
}

.kds-drop-confirm span {
    flex: 1 1 auto;
}

/* The tap is waiting its few seconds; the whole bar undoes it. The bar drains over the same 5 s as
   UndoWindow in KitchenBoard.razor. */
.kds-action-pending {
    position: relative;
    overflow: hidden;
    background: var(--kds-panel);
    color: var(--kds-ink);
    border-top: var(--kds-border) solid var(--kds-line);
}

.kds-pending-bar {
    position: absolute;
    inset: 0;
    background: var(--kds-line);
    transform-origin: left;
    animation: kds-drain 5s linear forwards;
}

.kds-pending-text {
    position: relative;
}

@keyframes kds-drain {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
    .kds-card-fresh { animation: none; box-shadow: 0 0 0 3px var(--kds-new); }
    .kds-pending-bar { animation: none; }
}

/* The board has not heard the kitchen for a minute. */
.kds-offline {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 18px;
    background: var(--kds-late);
    color: #fff;
    font-weight: 700;
    font-size: 15px;
}

.kds-offline span {
    flex: 1 1 auto;
}

.kds-offline .kds-toggle {
    border-color: #fff;
    color: #fff;
}

.kds-sync-stale {
    color: var(--kds-late);
    font-weight: 700;
}

.kds-allday {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    border: var(--kds-border) solid var(--kds-line);
    border-radius: 4px;
    padding: 8px 12px;
    font-size: calc(16px * var(--kds-scale, 1));
}

.kds-allday b {
    font-size: calc(20px * var(--kds-scale, 1));
    font-variant-numeric: tabular-nums;
}

/* ── Views and density (2026-10-06) ───────────────────────────────────────

   One pile alone gets the whole screen, so its tickets sit side by side instead of in one tall
   column nobody can read to the bottom of. Condensed does the same in every pile, with smaller
   type and tighter cards: a busy service on one screen, read from close up. */

.kds-columns-1 .kds-column-body,
.kds-compact .kds-column-body {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
    align-content: start;
}

.kds-compact {
    --kds-scale: .78;
}

.kds-compact .kds-column-body {
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 8px;
    padding: 8px;
}

.kds-compact .kds-card-head {
    padding: 5px 8px;
    gap: 6px;
}

.kds-compact .kds-lines {
    padding: 4px 8px;
}

.kds-compact .kds-line {
    margin-bottom: 2px;
}

.kds-compact .kds-action {
    min-height: 40px;
    padding: 8px;
}

/* The four views, as a strip under the bar while it is open. */
.kds-views {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 8px;
    padding: 10px 18px;
    background: var(--kds-panel);
    border-bottom: var(--kds-border) solid var(--kds-line);
}

.kds-view {
    min-height: 52px;
    border: var(--kds-border) solid var(--kds-line);
    border-radius: 5px;
    background: var(--kds-card);
    color: var(--kds-ink);
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 700;
    font-size: 17px;
    letter-spacing: .08em;
    text-transform: uppercase;
    cursor: pointer;
}

.kds-view-on {
    background: var(--kds-new);
    border-color: var(--kds-new);
    color: #fff;
}

/* "Next", on the cooking-only screen: the whole width, in the new colour, with how many are
   still waiting — a button and a counter in one, read from the stove. */
.kds-take-next {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    min-height: 60px;
    border: 0;
    border-radius: 5px;
    background: var(--kds-new);
    color: #fff;
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 700;
    font-size: calc(22px * var(--kds-scale, 1));
    letter-spacing: .1em;
    text-transform: uppercase;
    cursor: pointer;
}

.kds-take-next:disabled {
    opacity: .45;
    cursor: default;
}

.kds-take-next-count {
    min-width: 1.8em;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .25);
    font-variant-numeric: tabular-nums;
}

/* ── A narrow screen ─────────────────────────────────────────────────────── */

/* A tablet turned to portrait, or a phone at the pass: three columns side by side become three
   panes the finger swipes between, each nearly the width of the screen. */
@media (max-width: 900px) {
    .kds-columns {
        overflow-x: auto;
        scroll-snap-type: x mandatory;
    }

    .kds-column,
    .kds-column-cooking,
    .kds-column-ready-wide {
        flex: 0 0 86vw;
        scroll-snap-align: start;
    }

    /* A single pile is the screen: nothing to swipe to. */
    .kds-columns-1 .kds-column {
        flex: 1 1 auto;
    }

    .kds-columns-1 .kds-column-body {
        grid-template-columns: 1fr;
    }

    .kds-bar {
        gap: 10px;
        padding: 8px 12px;
    }
}

/* What the plate holds. Red outlined pills under the dish: the late colour, because an allergen
   missed is the one mistake on this board that harms somebody, and outlined rather than filled so a
   ticket with five of them does not read as a late ticket. */
.kds-allergens {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
}

.kds-allergen {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border: var(--kds-border) solid var(--kds-late);
    border-radius: 999px;
    color: var(--kds-late);
    font-size: calc(14px * var(--kds-scale, 1));
    font-weight: 700;
    line-height: 1.3;
}

[data-kds="dark"] .kds-allergen {
    /* The dark theme's red is set for a header fill; as text on a dark card it needs lifting. */
    color: #ff8a80;
    border-color: #ff8a80;
}

/* No sound yet: across the whole board, until somebody touches it. A new ticket must ring, and in a
   browser the first tap is the only thing that makes that possible. */
.kds-sound-off {
    display: block;
    width: 100%;
    min-height: 64px;
    padding: 14px 18px;
    border: 0;
    background: var(--kds-late);
    color: #fff;
    font-family: 'Barlow Condensed', system-ui, sans-serif;
    font-weight: 700;
    font-size: calc(22px * var(--kds-scale, 1));
    letter-spacing: .06em;
    text-transform: uppercase;
    cursor: pointer;
    animation: kds-sound-off 1.4s ease-in-out infinite;
}

@keyframes kds-sound-off {
    0%, 100% { opacity: 1; }
    50% { opacity: .75; }
}

@media (prefers-reduced-motion: reduce) {
    .kds-sound-off { animation: none; }
}

/* ── No-show protection (2026-10-21) ─────────────────────────────────────────
   A bug on the ticket: red when the diner left an unpaid order here, orange when reported
   elsewhere (a count only). Fixed colours rather than the palette's: they must read the same on
   every restaurant's board, whatever its theme. */
.kds-flag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 2px solid currentColor;
    border-radius: 999px;
    background: transparent;
    font-weight: 700;
    min-height: 32px;
    padding: 0 10px;
    cursor: pointer;
}

.kds-flag-here {
    color: #d32f2f;
    background: rgba(211, 47, 47, .12);
}

.kds-flag-elsewhere {
    color: #ef6c00;
    background: rgba(239, 108, 0, .12);
}

/* Why a kiosk ticket waits (2026-11-07): the money first, said above "Encaisser". */
.kds-hold-reason {
    margin: 6px 12px 0;
    padding: 6px 10px;
    border-left: 3px solid var(--kds-cooking);
    color: var(--kds-cooking);
    font-weight: 700;
    font-size: 14px;
}

.kds-hold {
    border: 1px dashed var(--kds-late);
    color: var(--kds-late);
    border-radius: 4px;
    padding: 2px 6px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .08em;
}

.kds-flag-panel {
    margin: 8px 0;
    padding: 10px;
    border-radius: 6px;
    border-left: 4px solid #ef6c00;
    background: rgba(239, 108, 0, .08);
}

.kds-flag-panel-here {
    border-left-color: #d32f2f;
    background: rgba(211, 47, 47, .08);
}

.kds-flag-line {
    font-weight: 700;
    margin-bottom: 4px;
}

.kds-flag-past {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 4px 0;
}

.kds-flag-past-lines {
    padding-left: 12px;
    font-size: 13px;
    opacity: .85;
}

.kds-flag-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.kds-flag-message {
    width: 100%;
    box-sizing: border-box;
    font: inherit;
    padding: 6px;
    border-radius: 4px;
}

/* "Did not come / did not pay": small, in the card's right corner, above the money (2026-10-22).
   The rare gesture, so not a full-width bar beside the ones the hand goes to. */
.kds-noshow-row {
    display: flex;
    justify-content: flex-end;
    padding: 4px 8px;
}

.kds-noshow {
    min-height: 32px;
    padding: 4px 10px;
    border: 1px solid #d32f2f;
    background: transparent;
    color: #d32f2f;
    border-radius: 4px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: .06em;
    font-size: 11px;
}

[data-kds="dark"] .kds-noshow {
    /* The same lift as the allergen pills: #d32f2f as text on a dark card is too dim. */
    color: #ff8a80;
    border-color: #ff8a80;
}

.kds-noshow:disabled {
    opacity: .5;
    cursor: default;
}

.kds-flag-icon {
    width: 1.1em;
    height: 1.1em;
}

/* In the till, the unpaid order's number in the panel is the way to its ticket (2026-10-23). */
.kds-flag-past-link {
    border: 0;
    background: transparent;
    color: var(--kds-ink);
    min-height: 32px;
    padding: 0 2px;
    cursor: pointer;
    font: inherit;
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* A flagged ticket's frame takes the alert's colour instead of the new ticket's blue (2026-10-22). */
.kds-card-flag-here { --kds-flag: #d32f2f; }
.kds-card-flag-elsewhere { --kds-flag: #ef6c00; }

.kds-card-flag-here,
.kds-card-flag-elsewhere {
    border: 2px solid var(--kds-flag);
    border-left: var(--kds-stripe) solid var(--kds-flag);
}

.kds-card-fresh.kds-card-flag-here,
.kds-card-fresh.kds-card-flag-elsewhere {
    animation-name: kds-fresh-flag;
}

@keyframes kds-fresh-flag {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    50% { box-shadow: 0 0 0 4px var(--kds-flag); }
}

@media (prefers-reduced-motion: reduce) {
    .kds-card-fresh.kds-card-flag-here,
    .kds-card-fresh.kds-card-flag-elsewhere { animation: none; box-shadow: 0 0 0 3px var(--kds-flag); }
}

/* ── On hold (2026-10-22) ────────────────────────────────────────────────────
   A column of its own, only while something is held; it folds into a strip that keeps its title and
   count in sight. */
.kds-dot-hold { background: var(--kds-mut); }
.kds-card-hold { border-left-color: var(--kds-mut); }
.kds-action-hold { background: var(--kds-new); }

.kds-column-hold {
    flex: .9 1 0;
}

.kds-collapse {
    border: var(--kds-border) solid var(--kds-line);
    background: transparent;
    color: var(--kds-ink);
    border-radius: 4px;
    min-width: 36px;
    min-height: 36px;
    padding: 0;
    cursor: pointer;
    font-size: 16px;
}

.kds-column-collapsed {
    flex: 0 0 56px;
    align-items: center;
    gap: 10px;
    padding: 12px 0;
    color: var(--kds-ink);
    font: inherit;
    cursor: pointer;
}

.kds-column-collapsed .kds-column-count {
    margin-left: 0;
}

.kds-vertical {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    white-space: nowrap;
}

@media (max-width: 900px) {
    .kds-column-collapsed {
        flex: 0 0 56px;
    }
}

/* A line's choices grouped by step (2026-10-22): bold ink, then regular in the "due" blue, and
   again — two styles that read apart at a glance. Both ≥ 7:1 on the card in either theme
   (ink on card; #7dd3fc on #232a30 ≈ 8.7:1, #0b5d8a on white ≈ 7.1:1). */
.kds-options .line-opt-0 { color: var(--kds-ink); font-weight: 700; }
.kds-options .line-opt-1 { color: var(--kds-due); font-weight: 500; }
.kds-options .line-opt-sep { color: var(--kds-mut); }

/* PRINT, on every ticket (2026-10-23): a quiet target in the header, like the star. */
.kds-print {
    border: 0;
    background: transparent;
    color: var(--kds-mut);
    font-size: calc(20px * var(--kds-scale, 1));
    line-height: 1;
    cursor: pointer;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    margin: -8px 0;
}

/* WHILE THE PRINTER IS BEING REACHED (2026-11-05, the owner: "no feedback, you don't know whether
   you pressed"). The pressed button turns into a spinner and every print button waits; a
   Bluetooth connect takes a second, and up to twenty when the printer is off. */
.kds-print:disabled,
.kds-toggle:disabled {
    opacity: .55;
    cursor: progress;
}

.kds-busy {
    display: inline-block;
    width: .85em;
    height: .85em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    vertical-align: -.1em;
    animation: kds-spin .8s linear infinite;
}

@keyframes kds-spin {
    to { transform: rotate(360deg); }
}

/* THE CUSTOMER IN FRONT OF THE TILL (2026-10-23): the ticket being served, framed thick in the
   ready colour and first in its column, with what is owed in large type. */
.kds-card-focus {
    outline: 4px solid var(--kds-ready);
    outline-offset: 2px;
    box-shadow: 0 0 0 8px color-mix(in srgb, var(--kds-ready) 25%, transparent);
}

.kds-focus-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding: 8px 12px;
    border-top: var(--kds-border) solid var(--kds-line);
    border-bottom: var(--kds-border) solid var(--kds-line);
}

.kds-focus-label {
    font-size: calc(14px * var(--kds-scale, 1));
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--kds-ready);
    font-weight: 700;
}

.kds-focus-amount {
    flex: 1 1 auto;
    font-size: calc(28px * var(--kds-scale, 1));
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--kds-ink);
}

.kds-focus-owed { color: var(--kds-cooking); }
/* Beside "Encaisser" on the ticket being served: the till's "Libérer la table" (2026-10-24). */
.kds-focus-actions {
    margin-top: 6px;
}

.kds-free-table {
    border-color: var(--kds-ink);
    color: var(--kds-ink);
}

