/* ==========================================================================
   BusinessOS counter screen.

   Built for a shop: large hit targets, one accent colour, numbers in a
   tabular font so columns line up, and enough contrast to read under a tube
   light. No framework, no build step - the file you edit is the file served.
   ========================================================================== */

:root {
  /* ------------------------------------------------------------------
     Dark is the default because a counter screen is usually the brightest
     thing in a small shop after dark, and a white page at the till is a
     lamp pointed at the cashier.

     Three states, deliberately:

       :root                                  dark, the default
       @media (prefers-color-scheme: light)   follow the machine
       :root[data-theme="..."]                the person has chosen

     A choice must beat the system in *both* directions, which is why the
     media query is guarded: without `:not([data-theme="dark"])`, someone
     on a light laptop who picks dark would flip back the moment the OS
     re-evaluated the query.
     ------------------------------------------------------------------ */
  --bg:        #0f1419;
  --surface:   #161c23;
  --surface-2: #1d252e;
  --surface-3: #232d38;
  --line:      #2a3441;
  --line-soft: #202834;
  --text:      #e8edf2;
  --text-2:    #b9c6d4;
  --muted:     #8b9aab;
  --accent:    #35b07a;
  --accent-dk: #2a9366;
  --accent-sf: #14312a;
  /* What goes ON an accent-filled surface. A bright accent is right for text
     and icons against a dark page (6.2:1) and wrong underneath white text
     (2.75:1, which fails outright) - so the button uses this instead of
     assuming white. */
  --on-accent: #08150f;
  --danger:    #e26558;
  --danger-sf: #331e1c;
  --warn:      #d9a441;
  --warn-sf:   #322a17;
  --info:      #4d9fd6;

  --radius:    10px;
  --radius-sm: 7px;
  --shadow-1:  0 1px 2px rgba(0,0,0,.35);
  --shadow-2:  0 6px 20px rgba(0,0,0,.4);
  --ring:      0 0 0 2px var(--bg), 0 0 0 4px var(--accent);

  --mono: ui-monospace, "Cascadia Mono", "Consolas", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  color-scheme: dark;
}

/* The light palette, written once and referenced twice. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg:        #f6f8fa;
    --surface:   #ffffff;
    --surface-2: #f0f4f8;
    --surface-3: #e6edf4;
    --line:      #dae2ea;
    --line-soft: #eaf0f5;
    --text:      #14202b;
    --text-2:    #3d4d5c;
    --muted:     #606e80;
    --accent:    #16794f;
    --accent-dk: #0f5c3b;
    --accent-sf: #e6f5ee;
    --danger:    #c5372a;
    --danger-sf: #fdecea;
    --warn:      #a86a00;
    --warn-sf:   #fdf3e2;
    --info:      #2470a8;
    --on-accent: #ffffff;
    --shadow-1:  0 1px 2px rgba(16,32,48,.07);
    --shadow-2:  0 8px 24px rgba(16,32,48,.10);
    color-scheme: light;
  }
}

:root[data-theme="light"] {
  --bg:        #f6f8fa;
  --surface:   #ffffff;
  --surface-2: #f0f4f8;
  --surface-3: #e6edf4;
  --line:      #dae2ea;
  --line-soft: #eaf0f5;
  --text:      #14202b;
  --text-2:    #3d4d5c;
  --muted:     #606e80;
  --accent:    #16794f;
  --accent-dk: #0f5c3b;
  --accent-sf: #e6f5ee;
  --danger:    #c5372a;
  --danger-sf: #fdecea;
  --warn:      #a86a00;
  --warn-sf:   #fdf3e2;
  --info:      #2470a8;
  --on-accent: #ffffff;
  --shadow-1:  0 1px 2px rgba(16,32,48,.07);
  --shadow-2:  0 8px 24px rgba(16,32,48,.10);
  color-scheme: light;
}

* { box-sizing: border-box; }

/*
 * The browser hides `[hidden]` with a display rule of its own, and any class
 * here that sets `display` silently outranks it. Every panel in this file is
 * shown and hidden by that attribute, so without this line the sign-in screen,
 * the receipt and the return panel all stay on top of each other for ever.
 */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
}

.muted { color: var(--muted); }
.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); }

kbd {
  font-family: var(--mono);
  font-size: 11px;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 4px;
  padding: 1px 5px;
  color: var(--muted);
  background: var(--surface-2);
}

.icon {
  width: 18px; height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon--xl { width: 44px; height: 44px; stroke-width: 1.2; }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.btn:hover { border-color: var(--muted); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn--primary:hover:not(:disabled) { background: var(--accent-dk); }
.btn--primary kbd { color: var(--on-accent); border-color: currentColor; opacity: .8; background: transparent; }
.btn--ghost { background: none; border-color: transparent; padding: 7px; }
.btn--ghost:hover { background: var(--surface-2); border-color: var(--line); }
.btn--tiny { padding: 3px; }
.btn--block { width: 100%; }
.btn--tall { padding: 15px; font-size: 17px; }

/* --- sign in ------------------------------------------------------------ */

.signin { display: grid; place-items: center; min-height: 100%; padding: 24px; }
.signin__card { width: min(360px, 100%); }
.signin__brand { margin: 0; font-size: 26px; letter-spacing: -.02em; }
.signin__sub { margin: 2px 0 22px; color: var(--muted); }
.signin__error { color: var(--danger); min-height: 1.2em; margin: 12px 0 0; font-size: 14px; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 26px;
}

.field { display: block; margin-bottom: 14px; }
.field > span { display: block; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 5px; }
.field input, .cart input {
  width: 100%;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
}
.field input:focus, .cart input:focus, .searchbar input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* --- shell -------------------------------------------------------------- */

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

.topbar {
  display: flex; align-items: center; gap: 20px;
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.topbar__brand { display: flex; align-items: center; gap: 10px; min-width: 220px; }
.topbar__brand strong { display: block; line-height: 1.2; }
.topbar__brand span { font-size: 12px; }
.topbar__user { margin-left: auto; display: flex; align-items: center; gap: 10px; font-size: 13px; }

/* The bar scrolls inside itself. Without `min-width: 0` a flex child refuses
   to shrink below its content, so an eighth tab widened the whole document and
   put a horizontal scrollbar under every screen instead of under the tabs. */
.tabs {
  display: flex;
  gap: 4px;
  min-width: 0;
  /* Wrap onto a second line rather than scroll.
     The office has ten tabs and they have never fitted on one row, so the
     strip always carried a horizontal scrollbar - which hides half the
     navigation behind a drag nobody thinks to try, and puts a scrollbar
     across the top of every page. Wrapping shows all ten at once and costs a
     few pixels of height only on the widths where they genuinely do not fit. */
  flex-wrap: wrap;
  row-gap: 4px;
}
.tab {
  display: inline-flex; align-items: center; gap: 6px;
  flex: 0 0 auto; white-space: nowrap;
  /* 14px of side padding x 10 tabs was most of the overflow on its own. */
  padding: 8px 11px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: none; color: var(--muted);
  font: inherit; cursor: pointer;
}
.tab:hover { color: var(--text); }
.tab--on { background: var(--surface-2); border-color: var(--line); color: var(--text); }

.view { flex: 1; display: grid; grid-template-columns: 1fr 360px; gap: 12px; padding: 12px; min-height: 0; }
#view-bills { grid-template-columns: 1fr; }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 14px;
  min-height: 0;
  display: flex; flex-direction: column;
}
.panel__title { margin: 0 0 12px; font-size: 15px; }

/* --- search ------------------------------------------------------------- */

.searchbar {
  display: flex; align-items: center; gap: 10px;
  padding: 0 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.searchbar input { flex: 1; padding: 13px 0; background: none; border: 0; color: var(--text); font: inherit; font-size: 16px; }

.results {
  list-style: none; margin: 6px 0 0; padding: 4px;
  max-height: 300px; overflow-y: auto;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.results--inline { max-height: 200px; }
.results li {
  display: flex; align-items: baseline; gap: 10px;
  padding: 9px 10px; border-radius: 7px; cursor: pointer;
}
.results li:hover, .results li.on { background: var(--accent); color: var(--on-accent); }
.results li:hover .muted, .results li.on .muted { color: rgba(255,255,255,.8); }
.results__name { flex: 1; }
.results__meta { font-size: 12px; font-family: var(--mono); }

/* --- cart --------------------------------------------------------------- */

.cart { width: 100%; border-collapse: collapse; margin-top: 12px; }
.cart thead th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); font-weight: 600; padding: 6px 8px; border-bottom: 1px solid var(--line);
}
.cart thead th.num { text-align: right; }
.cart td { padding: 5px 8px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.cart__item { width: 40%; }
.cart__name { display: block; }
.cart__hsn { font-size: 11px; }
.cart input { padding: 7px 8px; text-align: right; font-family: var(--mono); }
.cart input.qty { width: 74px; }
.cart input.rate, .cart input.disc { width: 88px; }
.cart__amount { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.cart__tax { font-family: var(--mono); font-size: 12px; text-align: right; color: var(--muted); }

.cart__empty { flex: 1; display: grid; place-content: center; justify-items: center; gap: 10px; color: var(--muted); }

/* --- checkout ----------------------------------------------------------- */

.panel--checkout { gap: 4px; }
.customer__chosen {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; margin-bottom: 12px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
}
.customer__chosen span { flex: 1; }

.totals { margin: 6px 0 0; border-top: 1px solid var(--line); padding-top: 10px; }
.totals > div { display: flex; justify-content: space-between; padding: 3px 0; }
.totals dt { color: var(--muted); font-size: 14px; }
.totals dd { margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.totals__grand { margin-top: 8px; padding-top: 10px !important; border-top: 1px solid var(--line); }
.totals__grand dt { color: var(--text); font-size: 17px; font-weight: 600; }
.totals__grand dd { font-size: 24px; font-weight: 700; color: var(--accent); }

.supply-note { margin: 6px 0 0; font-size: 11px; color: var(--muted); min-height: 1em; }

/* The figure on screen belongs to the previous cart until the server answers. */
.totals.is-stale { opacity: .4; }
.totals.is-stale .totals__grand dd { color: var(--muted); }

.pay { margin-top: auto; padding-top: 14px; }
.pay__modes { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 12px; }
.mode {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 10px 4px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--muted); font: inherit; font-size: 12px; cursor: pointer;
}
.mode:hover { color: var(--text); }
.mode--on { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }

.change { margin: 8px 0 0; font-size: 15px; color: var(--warn); font-family: var(--mono); }
.error { color: var(--danger); font-size: 13px; margin: 10px 0 0; min-height: 1.1em; }

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

.list { width: 100%; border-collapse: collapse; }
.list th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); padding: 8px; border-bottom: 1px solid var(--line);
}
.list th.num { text-align: right; }
.list td { padding: 9px 8px; border-bottom: 1px solid var(--line); }
.list td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.pill { font-size: 11px; padding: 2px 8px; border-radius: 20px; border: 1px solid var(--line); color: var(--muted); }
.pill--paid { color: var(--accent); border-color: var(--accent); }
.pill--part { color: var(--warn); border-color: var(--warn); }
.pill--void { color: var(--danger); border-color: var(--danger); text-decoration: line-through; }

/* --- receipt ------------------------------------------------------------ */

.overlay {
  position: fixed; inset: 0; z-index: 20;
  background: rgba(0,0,0,.6);
  display: grid; place-items: center; align-content: center; gap: 14px;
  padding: 20px; overflow-y: auto;
}
.overlay__actions { display: flex; gap: 10px; }

.receipt {
  width: 320px;
  background: #fff; color: #111;
  padding: 20px 18px;
  border-radius: 6px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
}
.receipt__head { text-align: center; border-bottom: 1px dashed #999; padding-bottom: 10px; margin-bottom: 10px; }
.receipt__head h2 { margin: 0; font-size: 16px; letter-spacing: .04em; }
.receipt__head p { margin: 2px 0; color: #555; }
.receipt__title { margin-top: 8px !important; font-weight: 700; color: #111 !important; letter-spacing: .1em; text-transform: uppercase; }
.receipt__meta { display: flex; justify-content: space-between; gap: 10px; margin: 2px 0; }
.receipt__lines { width: 100%; border-collapse: collapse; margin: 10px 0; }
.receipt__lines th { text-align: left; border-bottom: 1px dashed #999; padding: 4px 2px; font-weight: 600; }
.receipt__lines th.num, .receipt__lines td.num { text-align: right; }
.receipt__lines td { padding: 3px 2px; vertical-align: top; }
.receipt__lines tr.disc td { color: #777; font-size: 11px; padding-top: 0; }
.receipt__totals { margin: 0; border-top: 1px dashed #999; padding-top: 8px; }
.receipt__totals > div { display: flex; justify-content: space-between; }
.receipt__totals dt { color: #555; }
.receipt__totals dd { margin: 0; }
.receipt__totals .grand { border-top: 1px solid #111; margin-top: 6px; padding-top: 6px; font-weight: 700; font-size: 14px; }
.receipt__totals .grand dt { color: #111; }
.receipt__foot { text-align: center; color: #666; border-top: 1px dashed #999; margin-top: 10px; padding-top: 8px; font-size: 11px; }

/* The pay code. The receipt is always light, in both themes, because it is a
   picture of a piece of paper - so the QR needs no special handling here. */
.receipt__pay { text-align: center; border-top: 1px dashed #999; margin-top: 10px; padding-top: 10px; }
.receipt__qr { line-height: 0; }
.receipt__qr svg { display: inline-block; width: 148px; height: 148px; }
.receipt__paytext { margin: 6px 0 0; font-size: 12px; color: #333; }

/* --- returns ------------------------------------------------------------ */

.return { width: min(620px, 100%); max-height: 88vh; overflow-y: auto; }
.return__head { margin-bottom: 12px; }
.return__head h2 { margin: 0; font-size: 18px; }
.return__head p { margin: 3px 0 0; font-size: 13px; }
.return .cart { margin-bottom: 16px; }
.return .cart input.qty { width: 90px; }
.return .pay__modes { grid-template-columns: repeat(3, 1fr); }
.return .totals { margin-bottom: 4px; }
.return .overlay__actions { margin-top: 16px; justify-content: flex-end; }

/* --- toast -------------------------------------------------------------- */

.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  z-index: 40;
  padding: 11px 18px;
  background: var(--surface); border: 1px solid var(--accent); border-radius: 30px;
  box-shadow: 0 8px 30px rgba(0,0,0,.35);
}

/* --- printing ----------------------------------------------------------- */

@media print {
  body { background: #fff; }
  .app, .signin, .overlay__actions, .toast { display: none !important; }
  .overlay { position: static; background: none; padding: 0; display: block; }
  .receipt { width: auto; max-width: 76mm; border: 0; padding: 0; }
}

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

/* A table wider than its panel scrolls inside this box, so the page itself
   never scrolls sideways. The office screen relies on the same class; it lives
   here because this file is the design system both screens load. */
.table-wrap { overflow-x: auto; min-height: 0; }

/* ==========================================================================
   Small screens.
   ==========================================================================
   The desktop shell is deliberately viewport-height: `html, body` are 100%,
   `.app` is a column flex of that height, and the panels carry `min-height: 0`
   so each one scrolls its own list rather than the page scrolling as a whole.
   That is right for a counter with a keyboard and a fixed screen.

   On a phone it is wrong, and not merely cramped: `min-height: 0` lets a panel
   be laid out *shorter than its own content*, so the Save bill button was
   escaping the checkout panel by 34px and landing on top of the search box.
   Below 900px the document goes back to scrolling normally and the panels size
   to what is in them.
   ========================================================================== */
@media (max-width: 900px) {
  html, body { height: auto; }
  .app { height: auto; min-height: 100%; }
  .view {
    grid-template-columns: 1fr;
    /* No longer a fixed-height flex child: it is as tall as its panels. */
    flex: none;
    min-height: 0;
    padding: 10px;
    gap: 10px;
  }
  /* `min-height` lets the panel size to its content; `min-width` lets the grid
     track shrink below it. A grid item is min-width:auto by default, so without
     this the Bills panel stayed 394px wide inside a 320px column. */
  .panel { min-height: auto; min-width: 0; padding: 12px; }
  .view > .panel { min-width: 0; }

  /* The cart comes first, because scanning is the action repeated fifty times
     an hour and the totals are read once at the end. The previous order put
     the whole payment panel between the cashier and the search box. */
  .panel--cart { order: -1; }
  .panel--checkout { order: 0; }

  .topbar { gap: 10px; padding: 8px 12px; }
  .topbar__brand { min-width: 0; }
  /* The person's name goes, to buy width for the tabs. Anything else in the
     bar stays - this used to be a bare `span` selector, which also swallowed
     the theme control the moment the screen got narrow. */
  .topbar__user > span:not([data-theme-toggle]) { display: none; }
  /* The tabs are the one thing that must stay reachable, so they slide rather
     than being clipped - "Today" was being cut off mid-word. */
  .tabs { flex-wrap: wrap; }
  .tab { white-space: nowrap; padding: 7px 9px; }
}

@media (max-width: 560px) {
  /* Two rows, and only ever two: the shop above, the controls below.
     The office has ten tabs, so a naive wrap put the brand, the tab strip and
     the user on three separate lines - a 163px header on a 667px screen. The
     tab strip and the user share the second row instead: the strip takes the
     space that is left and scrolls inside it, and the user stays pinned right
     where sign-out has to be findable. */
  .topbar { flex-wrap: wrap; }
  .topbar__brand { flex: 1 0 100%; }
  /* Basis 0, not auto. A flex item wraps when its *base* size exceeds the
     space left on the line, and shrinking only happens afterwards - so a strip
     whose content is 1220px wide always claimed a line of its own no matter how
     shrinkable it was. Starting from zero, it takes what is left and scrolls. */
  .tabs { flex: 1 1 0; min-width: 0; }
  .period { flex: 1 0 100%; order: 3; }
  .topbar__user { flex: 0 0 auto; margin-left: auto; }
  /* Shop and branch side by side rather than stacked: the same two facts in
     half the height, on the screen where height is the scarce thing. */
  .topbar__brand > div {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
  }
  .topbar__brand strong,
  .topbar__brand span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tabs { order: 2; }
  .pay__modes { grid-template-columns: repeat(2, 1fr); }
  /* A thumb, not a mouse. */
  .btn, .tab { min-height: 42px; }
  .cart thead th, .cart td { padding: 8px 6px; }
}

/* --- the theme control --------------------------------------------------- */

.theme-toggle { color: var(--muted); }
.theme-toggle:hover { color: var(--text); }
/* Visible focus, because this is reached by keyboard more than by mouse on a
   till where the hands are on the scanner. */
.theme-toggle:focus-visible { outline: none; box-shadow: var(--ring); }

/* Colour changes are instant on the element that matters and eased on the
   large flat areas, so switching theme reads as a change of light rather than
   a page reload. Anyone who has asked for less motion gets neither. */
@media (prefers-reduced-motion: no-preference) {
  html, body, .topbar, .panel, .card { transition: background-color .18s ease, border-color .18s ease; }
}

/* On the sign-in card, because the top bar does not exist until somebody is
   in - and the first thing a cashier sees at 7am should not be a white flash
   they cannot do anything about. */
.signin__theme { float: right; margin: -6px -6px 0 0; }

/* The slot is a bare <span> the script fills. Inside a flex row it inherits
   `flex-shrink: 1` and collapses to nothing the moment the bar is tight -
   which is exactly when the tabs are widest, so the control vanished on the
   office screen at 800px while still being in the DOM. */
[data-theme-toggle] { display: inline-flex; flex: none; }

/* An <a class="btn"> is a button to look at and a link to the browser, which
   underlines it. Three of them on the office screen read as underlined
   buttons. */
a.btn { text-decoration: none; }

/* --- the keyboard sheet --------------------------------------------------- */

.keys-sheet { z-index: 60; }
.keys-sheet__card { width: min(760px, 94vw); max-height: 86vh; overflow-y: auto; }
.keys-sheet__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.keys-sheet__head h2 { margin: 0; font-size: 19px; }
.keys-sheet__groups { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 32px; }
.keys-group h3 {
  margin: 0 0 8px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted);
}
.keys-group dl { margin: 0; }
.keys-group dl > div {
  display: flex; align-items: baseline; gap: 12px;
  padding: 6px 0; border-bottom: 1px solid var(--line-soft);
}
.keys-group dt { flex: none; display: flex; gap: 3px; }
.keys-group dd { margin: 0; font-size: 13.5px; color: var(--text-2); }
.keys-sheet__foot { margin: 20px 0 0; font-size: 12.5px; color: var(--muted); }

@media (max-width: 680px) {
  .keys-sheet__groups { grid-template-columns: 1fr; }
}

.keys-hint { color: var(--muted); }
.keys-hint:hover { color: var(--text); }
.keys-hint:focus-visible { outline: none; box-shadow: var(--ring); }

/* ==========================================================================
   The design system, made explicit
   ==========================================================================
   The tokens above grew where they were needed. These are the ones that were
   implied but never written down: a type scale, a spacing scale, and the
   rules that make a screen usable rather than merely correct.

   Everything here is additive and low-specificity, so it raises the floor for
   all four surfaces - counter, office, portal and the public page - without
   overriding a single decision any of them has already made.
   ========================================================================== */

:root {
  /* A scale, so sizes are chosen from a set rather than typed. The ratio is
     a shade under 1.2: enough to separate two levels, small enough that six
     of them still fit on a phone. */
  --text-xs:  11px;
  --text-sm:  12.5px;
  --text-md:  14px;
  --text-lg:  16px;
  --text-xl:  20px;
  --text-2xl: 26px;
  --text-3xl: 33px;

  /* Multiples of 4. Half-steps exist because 6px is genuinely the right gap
     between an icon and its label and 8px is not. */
  --space-1: 4px;
  --space-2: 6px;
  --space-3: 8px;
  --space-4: 12px;
  --space-5: 16px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 48px;

  /* What a finger is. 44px is the figure both Apple and Google publish, and
     it is not a suggestion on a counter screen operated at speed. */
  --tap: 44px;

  --ease: cubic-bezier(.2, 0, .2, 1);
  --fast: 120ms;
  --slow: 220ms;
}

/* --- focus you can actually see ------------------------------------------- */
/* One ring, everywhere, and only for keyboard users. `:focus-visible` rather
   than `:focus` so a mouse click does not leave a halo behind - which is why
   people used to remove focus rings altogether and break keyboard use. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --- touch ---------------------------------------------------------------- */
/* Applied by input type rather than by screen width: a 13in touchscreen till
   needs a thumb-sized target and a 6in phone attached to a mouse does not.
   `pointer: coarse` asks the question that actually matters. */
@media (pointer: coarse) {
  .btn,
  .tab,
  button,
  select,
  input:not([type="checkbox"]):not([type="radio"]):not([type="color"]) {
    min-height: var(--tap);
  }
  /* A checkbox is hit by its label, so the label is what has to be big. */
  label.check { min-height: var(--tap); align-items: center; }
}

/* --- motion --------------------------------------------------------------- */
/* Someone who has asked their machine for less movement has usually asked for
   a reason - vestibular disorders are the common one. Transitions become
   instant rather than merely quick; nothing is removed, so no state is lost. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- text that has to stay readable --------------------------------------- */
/* A table of Indian names and a column of rupees have opposite needs: prose
   wants to wrap, figures want to stay on one line and line up. */
.num, .grid td.num, .cart .num { font-variant-numeric: tabular-nums; }
p, li { text-wrap: pretty; }
h1, h2, h3, .panel__title { text-wrap: balance; }

/* Anything wide gets its own scroller rather than pushing the page sideways.
   A page that scrolls horizontally on a phone feels broken even when every
   figure on it is right. */
.table-wrap, .scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
img, svg, video { max-width: 100%; }

/* --- states that are usually forgotten ------------------------------------ */
[disabled], .is-disabled {
  opacity: .55;
  cursor: not-allowed;
}
/* A button mid-request should say so, or it gets pressed again - and a second
   invoice is a real consequence of a missing spinner. */
.btn[aria-busy="true"] { position: relative; color: transparent; }
.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  color: var(--on-accent);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Somewhere to say "nothing here yet" that does not look like a failure. */
.empty {
  padding: var(--space-7) var(--space-5);
  text-align: center;
  color: var(--muted);
  font-size: var(--text-md);
}
.empty strong { display: block; color: var(--text-2); margin-bottom: var(--space-2); }

/* --- printing ------------------------------------------------------------- */
/* Somebody will print a register. Ink is expensive and a dark background is
   the fastest way to waste it. */
@media print {
  .topbar, .sidenav, .navtoggle, .tabs, .btn, #toast { display: none !important; }
  :root { --bg: #fff; --surface: #fff; --surface-2: #fff; --text: #000; --muted: #444; --line: #bbb; }
  body { background: #fff; color: #000; }
  .panel { border: 1px solid #bbb; box-shadow: none; }
}

/* ==========================================================================
   The start-up mark
   ==========================================================================
   Shown once per session while the screen behind it is already loading, and
   dismissed by any key or click. It is a curtain being lifted, not a door
   being held shut: a splash a person has to *wait* through gets resented by
   the third day, so this one never blocks and never repeats within a session.

   Someone who has asked for reduced motion gets the same mark, held still.
   ========================================================================== */

.splash {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--bg);
  animation: splash-out .45s var(--ease, ease) 1.35s forwards;
}
.splash[hidden] { display: none; }

.splash__inner { text-align: center; padding: 24px; }

.splash__mark { width: min(260px, 64vw); height: auto; overflow: visible; }
.splash__mark rect { fill: var(--surface-3); }
.splash__mark text {
  font-family: var(--mono);
  font-size: 11px;
  fill: var(--text-2);
}
.sp-rule { stroke: var(--accent); stroke-width: 1.5; }
.sp-total {
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 700;
  fill: var(--accent);
}

/* Each row is written in turn, then the rule is drawn under them, then the
   total appears - the order the arithmetic actually happens in. */
.sp-row { opacity: 0; animation: sp-write .34s var(--ease, ease) forwards; }
.sp-row--1 { animation-delay: .05s; }
.sp-row--2 { animation-delay: .19s; }
.sp-row--3 { animation-delay: .33s; }
.sp-row--4 { animation-delay: .47s; }

.sp-rule {
  stroke-dasharray: 150;
  stroke-dashoffset: 150;
  animation: sp-rule .38s var(--ease, ease) .66s forwards;
}
.sp-total { opacity: 0; animation: sp-total .4s var(--ease, ease) .92s forwards; }

.splash__name {
  margin: 18px 0 2px;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.01em;
  opacity: 0;
  animation: sp-fade .4s var(--ease, ease) .82s forwards;
}
.splash__by {
  margin: 0 0 6px;
  font-size: 13px;
  color: var(--muted);
  opacity: 0;
  animation: sp-fade .4s var(--ease, ease) .96s forwards;
}
.splash__by strong { color: var(--accent); font-weight: 600; }
.splash__hint {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
  opacity: 0;
  animation: sp-fade .4s var(--ease, ease) 1.08s forwards;
}

@keyframes sp-write {
  from { opacity: 0; transform: translateX(-10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes sp-rule  { to { stroke-dashoffset: 0; } }
@keyframes sp-total { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes sp-fade  { to { opacity: 1; } }
@keyframes splash-out { to { opacity: 0; visibility: hidden; } }

/* Reduced motion: the same mark, arrived at rather than animated to. Nothing
   is hidden and nothing moves, and it still gets out of the way on time. */
@media (prefers-reduced-motion: reduce) {
  .splash,
  .splash * {
    animation: none !important;
  }
  .splash { animation: splash-out .01s linear 1.2s forwards !important; }
  .sp-row, .splash__name, .splash__by, .splash__hint, .sp-total { opacity: 1; }
  .sp-rule { stroke-dashoffset: 0; }
}
