/*
 * Tenvelo, at a desk.
 *
 * "Gruff, in daylight" — the house signage system with the concessions a dark bar needs
 * taken out, because a back office is read at a desk. The amber stays: it is the colour
 * of this product at work, and a manager finds the one thing that acts on a dense screen
 * because it is the only warm thing on it.
 *
 * What went is the HAZARD BAND. Alternating black and amber on the diagonal is a real
 * signal with a real meaning — keep out, not finished, mind the step — and a shop owner
 * reads it before they read the word next to it. It sat ten pixels above a mark that says
 * the opposite: a receipt, torn off, the sale done. So the band is gone and the mark took
 * its place.
 *
 * The rules of the system:
 *
 *   - THE PERFORATION IS THE DEVICE. A receipt's tear line, and a broken connection: the
 *     product's whole argument is that the line breaks and the sale carries on. It
 *     separates things. Nothing else does. (`../tender-web`, where it is `.perf`.)
 *   - AMBER MARKS WHAT ACTS. Nothing else is amber, and it never repeats into a pattern.
 *   - RED MARKS WHAT STOPS. The only other colour with a meaning.
 *   - SHADOWS ARE HARD OFFSETS, NEVER BLURRED. A blur is the first thing to go on a bad
 *     monitor, and it takes the layout's structure with it.
 *   - EVERY NUMBER IS MONOSPACED. A column of takings has to align on the decimal or it
 *     cannot be read down.
 *   - SURFACES ARE PAPER, NOT WHITE. #ffffff on a screen full of cards is glare, and it
 *     made two dozen screens read as a different product from Today.
 */

@font-face {
  font-family: 'ArchivoBlack';
  src: url('/static/fonts/ArchivoBlack-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('/static/fonts/Archivo-Variable.ttf') format('truetype');
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'PlexMono';
  src: url('/static/fonts/IBMPlexMono-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'PlexMono';
  src: url('/static/fonts/IBMPlexMono-SemiBold.ttf') format('truetype');
  font-weight: 600;
  font-display: swap;
}

:root {
  --field: #f2efe6;
  /* Surfaces are warm paper, not #ffffff. That one value is most of why two dozen screens
     read as a different product from Today: a grid of pure-white cards on cream is glare
     with a layout behind it, and the amber has nothing to be warm against. */
  --paper: #fbf9f4;
  --ink: #17150f;
  --ink-muted: #4a463c;
  --hair: #c9c2b0;
  --stone: #ddd8c8;

  /* The accent, and the only one. */
  --amber: #ffb000;
  --amber-deep: #d99500;
  --red: #9e1a0f;

  /* Rail internals: warm near-black steps, so the dark column has structure without a
     second hue creeping in. */
  --rail-line: #332f24;
  --rail-hover: #221f18;
  --rail-quiet: #8d8676;

  --rule: 3px solid var(--ink);
  --hair-rule: 1px solid var(--hair);
  --offset: 6px 6px 0 var(--ink);
  --display: 'ArchivoBlack', 'Arial Black', sans-serif;
  --sans: 'Archivo', 'Helvetica Neue', sans-serif;
  --mono: 'PlexMono', ui-monospace, 'SF Mono', monospace;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--field);
  /* Paper grain. A flat fill reads as a screenshot of a design; a little tooth reads as a
     surface. Inline so it costs no request and cannot fail to load. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.45;
}

::selection { background: var(--amber); color: var(--ink); }

/* There was no focus ring in this stylesheet at all. Every control below is reachable by
   keyboard and none of them said so. Ink rather than amber on the light field: amber on
   cream is about 1.8:1, which is under the 3:1 a focus indicator has to clear, and a ring
   nobody can see is the same as no ring. */
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.on-ink :focus-visible, .on-ink:focus-visible { outline-color: var(--amber); }

/* Announced to a screen reader, absent from the page. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- the perforation -------------------------------------------------------
   The brand device, and the only separator in the system. Decorative, so anything
   carrying it is aria-hidden. */
.perf {
  height: 0;
  border-top: 2px dashed var(--ink);
}

.perf--faint { border-top-color: var(--hair); }
.perf--lit { border-top-color: var(--amber); }
.perf--rail { border-top-color: var(--rail-line); }

/* The torn edge itself, for the bottom of a receipt block. Drawn as a mask so the paper
   is genuinely absent rather than covered by a shape in the ground colour, which would
   show as a seam over any other surface. */
.torn-bottom {
  --tooth: 18px;
  mask-image:
    linear-gradient(#000 0 0),
    conic-gradient(from -45deg at 50% 100%, #000 0deg 90deg, #0000 90deg);
  mask-size:
    100% calc(100% - var(--tooth) / 2),
    var(--tooth) calc(var(--tooth) / 2);
  mask-position: top left, bottom left;
  mask-repeat: no-repeat, repeat-x;
}

/* A border would be clipped by the mask, so the outline is drawn as hard drop-shadows on
   the parent, which follow the teeth. */
.receipt-outline {
  filter:
    drop-shadow(2px 0 0 var(--ink)) drop-shadow(-2px 0 0 var(--ink))
    drop-shadow(0 2px 0 var(--ink)) drop-shadow(0 -2px 0 var(--ink));
}

/* ---- instrument labelling -------------------------------------------------- */
.label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.label--ruled {
  display: block;
  border-bottom: var(--rule);
  padding-bottom: 6px;
  margin-bottom: 14px;
  color: var(--ink);
}

/* ---- structure -------------------------------------------------------------- */
.shell {
  display: grid;
  grid-template-columns: 248px minmax(0, 1fr);
  min-height: 100vh;
}

.rail {
  background: var(--ink);
  color: var(--field);
  border-right: var(--rule);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

/* ---- the receipt stub ------------------------------------------------------
   The rail's head is the mark at size: paper, the name, the merchant, one green total
   line, and a torn edge where it leaves the rail. It replaces a black-and-amber hazard
   band that belonged to another company and read as roadworks. */
.rail__head {
  background: var(--paper);
  color: var(--ink);
  padding: 20px 20px 26px;
  --tooth: 16px;
}

.rail__mark {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--display);
  font-size: 24px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.rail__merchant {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-top: 6px;
  overflow-wrap: anywhere;
}

/* A sandbox merchant wears its marker under the name, so a back office acting on one
   never mistakes it for live trading. */
.rail__sandbox {
  display: inline-block;
  margin-top: 4px;
  padding: 1px 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* A checkbox field on the gates: the label is a plain sentence next to the box, not a
   caption above a control. */
.field--check {
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  color: var(--ink-muted);
}

/* The mark's own total line, at the width of the stub. A single solid rule, which is what
   a total is — the thing the hazard band was not. */
.rail__total {
  height: 7px;
  background: var(--amber);
  margin-top: 12px;
  width: 56%;
}

/* ---- the rail's nav --------------------------------------------------------
   Twenty-six destinations did not fit a 100vh sticky column and nothing here said
   `overflow`, so everything past the twelfth was unreachable on a laptop — not clipped,
   not scrollable, simply gone. `min-height: 0` is what lets a flex child shrink far
   enough to scroll; `flex: 1` alone does not. */
.rail__nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px 0 14px;
  scrollbar-width: thin;
  scrollbar-color: var(--rail-line) transparent;
}

.rail__nav::-webkit-scrollbar { width: 8px; }
.rail__nav::-webkit-scrollbar-track { background: transparent; }
.rail__nav::-webkit-scrollbar-thumb { background: var(--rail-line); }

.rail__group { padding: 0; margin: 0; border: 0; }
.rail__list { list-style: none; margin: 0; padding: 0; }

/* The group's name. Quiet: it is a signpost, not a destination. */
.rail__grouphead {
  display: block;
  padding: 16px 20px 6px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--rail-quiet);
}

.rail__group + .rail__group .rail__grouphead { border-top: 2px dashed var(--rail-line); margin-top: 10px; padding-top: 18px; }

.rail__link {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  padding: 8px 20px;
  color: #d5d2c6;
  text-decoration: none;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-left: 5px solid transparent;
  transition: color 90ms linear, border-color 90ms linear, background-color 90ms linear;
}

.rail__link:hover {
  color: var(--paper);
  background: var(--rail-hover);
  border-left-color: var(--amber);
}

/* One loud thing in the column, and it is where you are. */
.rail__link[aria-current='page'] {
  color: var(--ink);
  background: var(--amber);
  border-left-color: var(--ink);
  font-weight: 600;
}

.rail__count {
  font-size: 11px;
  color: var(--rail-quiet);
  font-variant-numeric: tabular-nums;
}

.rail__link[aria-current='page'] .rail__count { color: var(--ink); opacity: 0.7; }

.rail__foot {
  padding: 14px 20px;
  border-top: 2px dashed var(--rail-line);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  /* --rail-quiet is 5:1 on the rail, short of AAA for text this small. */
  color: var(--hair);
  display: grid;
  gap: 14px;
}

.rail__foot form { margin: 0; }

/* Who is signed in and the way out, on one line. The name wraps as words, never a letter
   at a time, which is what a flex row sharing its width with two selects did to it. */
.rail__who {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.rail__who span { min-width: 0; overflow-wrap: break-word; }

/* A labelled select with its button beside it, the select taking the rail's width so a
   long business name is readable rather than clipped. */
.rail__switch {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 6px 10px;
}

.rail__switch-label {
  grid-column: 1 / -1;
  text-transform: uppercase;
}

.rail__switch select {
  width: 100%;
  min-width: 0;
  min-height: 36px;
  padding: 4px 8px;
  font: inherit;
  letter-spacing: normal;
  color: var(--field);
  background: var(--rail-hover);
  border: 1px solid var(--rail-line);
  border-radius: 0;
}

.rail__signout {
  background: none;
  border: 0;
  padding: 0;
  color: var(--amber);
  font: inherit;
  letter-spacing: 0.1em;
  cursor: pointer;
  text-transform: uppercase;
  white-space: nowrap;
}
.rail__signout:hover { text-decoration: underline; }

.main { padding: 0 0 64px; min-width: 0; }

.masthead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding: 30px 40px 18px;
  border-bottom: var(--rule);
  flex-wrap: wrap;
}

.masthead h1 {
  font-family: var(--display);
  font-size: clamp(28px, 3.4vw, 44px);
  letter-spacing: -0.01em;
  margin: 4px 0 0;
  text-transform: uppercase;
}

.masthead__when {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.section { padding: 34px 40px 0; }

/* ---- the headline figure ----------------------------------------------------
   Deliberately out of scale with everything else. A manager opens this screen to read one
   number, and the design should not make them hunt for it among five of equal weight. */
.takings {
  display: grid;
  grid-template-columns: minmax(320px, 1.4fr) minmax(280px, 1fr);
  gap: 28px;
  align-items: start;
}

/* Sized off the column it sits in rather than the viewport: at 9vw a five-figure day ran
   out through the side of its grid cell and under the stat slabs. */
.takings__figure {
  container-type: inline-size;
  font-family: var(--mono);
  font-weight: 600;
  font-size: clamp(40px, 13cqw, 104px);
  line-height: 0.9;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin: 0;
  overflow-wrap: anywhere;
}

/* The mark's total line again, at the width of the day's takings. */
.takings__rule {
  height: 12px;
  background: var(--amber);
  border: var(--rule);
  border-bottom: 0;
  margin-bottom: -2px;
  max-width: 520px;
}

/* ---- the host stand --------------------------------------------------------
   Who is due and where they sit, read together at the door. Two columns so a host sees
   the whole night at a glance; one column on a narrow screen, like takings. */
.host {
  display: grid;
  grid-template-columns: minmax(320px, 1.1fr) minmax(300px, 1fr);
  gap: 24px;
  align-items: start;
}

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 18px;
}

.slab {
  background: var(--paper);
  border: var(--rule);
  box-shadow: var(--offset);
  padding: 16px 18px;
}

.slab__value {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 26px;
  font-variant-numeric: tabular-nums;
  margin-top: 6px;
  overflow-wrap: anywhere;
}

.slab__note {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-muted);
  margin-top: 2px;
}

/* A form is one column of a readable width, not a field stretched to the monitor. */
.slab--form { max-width: 620px; }

/* ---- the trading day -------------------------------------------------------- */
.hours {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 190px;
  border-bottom: var(--rule);
  padding-bottom: 0;
}

.hours__bar {
  flex: 1;
  min-width: 0;
  background: var(--amber);
  border: 2px solid var(--ink);
  border-bottom: 0;
  position: relative;
  transform-origin: bottom;
  animation: grow 420ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

.hours__bar--empty { background: var(--stone); }

.hours__bar:hover::after {
  content: attr(data-tip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translate(-50%, -8px);
  background: var(--ink);
  color: var(--field);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  padding: 5px 8px;
  white-space: nowrap;
  z-index: 2;
}

.hours__axis {
  display: flex;
  gap: 4px;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-muted);
  letter-spacing: 0.06em;
}

.hours__axis span { flex: 1; text-align: center; min-width: 0; }

/* ---- the trend -------------------------------------------------------------
   A range day by day. Each column is a bar for the day and, where the period before took
   anything, a dashed tick at that day's height: the comparison is carried by shape, so it
   reads without the amber and in print. */
.takings__compare {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink-muted);
  margin: 14px 0 0;
}

.change {
  display: inline-block;
  font-weight: 600;
  color: var(--ink);
  border: 2px solid var(--ink);
  padding: 1px 8px;
  margin-right: 4px;
  background: var(--paper);
}

.change--up { background: var(--amber); }

.trend__stats { margin-bottom: 26px; }

.trend__frame { position: relative; }

.trend__empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  margin: 0;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  pointer-events: none;
}

.trend__legend {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-bottom: 14px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.trend__key { display: inline-block; width: 18px; }
.trend__key--bar { height: 12px; background: var(--amber); border: 2px solid var(--ink); }
.trend__key--prev { height: 0; border-top: 3px dashed var(--ink); margin-left: 12px; }

.trend {
  display: flex;
  align-items: stretch;
  gap: 4px;
  height: 220px;
  border-bottom: var(--rule);
}

.trend--dense { gap: 1px; }

.trend__day {
  flex: 1;
  min-width: 0;
  position: relative;
  display: flex;
  align-items: flex-end;
}

.trend__bar {
  width: 100%;
  background: var(--amber);
  border: 2px solid var(--ink);
  border-bottom: 0;
  transform-origin: bottom;
  animation: grow 420ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

.trend--dense .trend__bar { border-width: 1px; }
.trend__bar--empty { background: var(--stone); }

.trend__prev {
  position: absolute;
  left: -2px;
  right: -2px;
  height: 0;
  border-top: 3px dashed var(--ink);
  pointer-events: none;
}

.trend--dense .trend__prev { border-top-width: 2px; left: 0; right: 0; }

.trend__day:hover .trend__bar { background: var(--amber-deep); }
.trend__day:hover .trend__bar--empty { background: var(--hair); }

.trend__day:hover::after {
  content: attr(data-tip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translate(-50%, -8px);
  background: var(--ink);
  color: var(--field);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  padding: 5px 8px;
  white-space: nowrap;
  z-index: 2;
}

.trend__day:first-child:hover::after { left: 0; transform: translate(0, -8px); }
.trend__day:last-child:hover::after { left: auto; right: 0; transform: translate(0, -8px); }

.trend__axis {
  display: flex;
  gap: 4px;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-muted);
  letter-spacing: 0.06em;
}

.trend__axis--dense { gap: 1px; }
.trend__axis span { flex: 1; min-width: 0; text-align: center; white-space: nowrap; }
.trend__axis--dense span { text-align: left; overflow: visible; }

.trend__table { margin-top: 22px; }

.trend__table summary {
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 12px;
}

/* ---- the period controls ----------------------------------------------------
   One row: the presets, then the location and dates, then the actions. Stacked, the
   inputs ran the width of the page and pushed the figures below the fold. */
.masthead__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px 18px;
}

.masthead__form .field__input { width: auto; min-width: 0; }

.presets {
  display: inline-flex;
  border: var(--rule);
  background: var(--paper);
  box-shadow: var(--offset);
}

.presets__link {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 10px 14px;
  color: var(--ink);
  text-decoration: none;
}

.presets__link + .presets__link { border-left: 3px solid var(--ink); }
.presets__link:hover { background: var(--field); }
.presets__link[aria-current='page'] { background: var(--ink); color: var(--paper); }

/* ---- the ledger -------------------------------------------------------------
   A back office is a place for reading a column of things down. Two dozen screens used
   to be grids of white cards, which is why they read as a different product from Today:
   you cannot compare two tax rates or two suppliers that are side by side in boxes. Every
   list is a ledger now, and only a detail screen is a slab. */
.ledger__wrap {
  overflow-x: auto;
  /* The shadow is outside the table's box, so the scroller needs room for it or it is
     clipped on the first paint. */
  padding: 0 6px 8px 0;
}

.ledger {
  width: 100%;
  border-collapse: collapse;
  background: var(--paper);
  border: var(--rule);
  box-shadow: var(--offset);
}

.ledger caption {
  text-align: left;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-bottom: 10px;
}

.ledger th {
  text-align: left;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 12px 18px;
  border-bottom: var(--rule);
  white-space: nowrap;
}

.ledger td {
  padding: 12px 18px;
  border-bottom: var(--hair-rule);
  font-family: var(--mono);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  vertical-align: baseline;
}

.ledger tbody tr:last-child td { border-bottom: 0; }
.ledger tbody tr:hover td { background: #f2eee3; }

.ledger .num { text-align: right; }
.ledger .name { font-family: var(--sans); font-weight: 600; font-size: 15px; }
.ledger .quiet { color: var(--ink-muted); }

/* The row's own actions, kept to the right and kept small. A full offset-shadow button
   on every row of forty is a wall, not an affordance. */
.ledger .acts { text-align: right; white-space: nowrap; }

.ledger .acts form { display: inline; margin: 0; }

.act {
  display: inline-block;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 5px 10px;
  border: 2px solid var(--ink);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  margin-left: 6px;
}

.act:hover { background: var(--ink); color: var(--paper); }
.act--stop { border-color: var(--red); color: var(--red); }
.act--stop:hover { background: var(--red); color: var(--paper); border-color: var(--red); }

/* An empty screen is an invitation to act, so it is set like a sentence and not like a
   failed query. */
.ledger__empty {
  background: var(--paper);
  border: 2px dashed var(--hair);
  padding: 26px 22px;
  font-size: 15px;
  color: var(--ink-muted);
  max-width: 62ch;
}

/* ---- devices ---------------------------------------------------------------- */
.tills {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 22px;
}

.till__name {
  font-family: var(--display);
  font-size: 20px;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin: 8px 0 2px;
}

.till__line {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-muted);
  letter-spacing: 0.04em;
  margin-top: 4px;
}

/* A line that wants reading rather than scanning: a missed break on a timesheet. The
   block is deliberately quiet (muted, small), so a modifier that only restated it would
   be invisible — this takes the full ink and the red, because the point of flagging a
   missed break is that a manager does not scroll past it. */
.till__line--flag {
  color: var(--red);
  font-weight: 600;
}

/* Approved, and nothing to do. It shared the flag modifier, which would have rendered an
   approval in the same red as a missed break the moment either got a rule — one is a
   problem and the other is the absence of one. */
.till__line--done {
  color: var(--ink);
}

/* The line a row adds up to. Emphasis without colour: a total is not an exception. */
.till__line--total {
  color: var(--ink);
  font-weight: 600;
}

.till__agent { display: block; margin-top: 4px; overflow-wrap: anywhere; }

.till__error { font-family: var(--mono); font-size: 12px; color: var(--red); margin-top: 4px; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 3px 8px;
  border: 2px solid var(--ink);
  white-space: nowrap;
}

/* Colour never carries the meaning on its own — each of these has a word in it. */
.pill--live { background: var(--amber); }
.pill--waiting { background: var(--stone); }
.pill--behind { background: var(--red); color: var(--paper); border-color: var(--red); }

/* The code is read aloud across a room, so it is set like something to be read aloud. */
.code {
  font-family: var(--mono);
  font-weight: 600;
  font-size: clamp(28px, 4vw, 40px);
  letter-spacing: 0.28em;
  padding: 18px 20px;
  background: var(--ink);
  color: var(--amber);
  border: var(--rule);
  word-break: break-all;
}

/* ---- forms and actions ------------------------------------------------------ */
.btn {
  display: inline-block;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 14px 22px;
  border: 3px solid var(--ink);
  background: var(--amber);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--offset);
  transition: transform 70ms linear, box-shadow 70ms linear;
}

.btn:hover { transform: translate(2px, 2px); box-shadow: 4px 4px 0 var(--ink); }
.btn:active { transform: translate(6px, 6px); box-shadow: 0 0 0 var(--ink); }

.btn--quiet { background: var(--paper); color: var(--ink); }
.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
  box-shadow: none;
}
.btn--ghost:hover { background: var(--ink); color: var(--paper); transform: none; box-shadow: none; }

.row { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; }
.field--grow { flex: 1 1 220px; }
.field--narrow { flex: 0 1 140px; }
.field--inline { display: inline-block; margin-right: 16px; }
.field-row { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; }

.field { display: block; margin-bottom: 22px; }

.field__label {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 6px;
}

/* The tag set as checkboxes, wrapping. A merchant's vocabulary is short and flat, so a
   row of labels reads faster than a multi-select and needs nothing to learn. */
.tag-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding: 6px 0;
}

.tag-picker__option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
}

/* Underlines rather than boxes. A box inside a slab inside a border is three nested
   rectangles saying the same thing; the rule under the text is enough. */
.field__input {
  width: 100%;
  font-family: var(--mono);
  font-size: 18px;
  padding: 8px 2px;
  border: 0;
  border-bottom: var(--rule);
  background: transparent;
  color: var(--ink);
}

.field__input:focus {
  outline: 0;
  border-bottom-color: var(--amber-deep);
  background: #fdf7e6;
}

.field__hint, .field__help {
  display: block;
  margin-top: 6px;
  font-size: 14px;
  color: var(--ink-muted);
}

/* A guest search on the booking and waitlist forms: a type-to-find picker that narrows the
   directory instead of loading it all into a select. The field keeps a hidden customer_id
   when a result is chosen, so the form still links the guest it needs. */
.guest-picker {
  position: relative;
}

.guest-results {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 10;
  background: var(--paper);
  border: var(--rule);
  border-top: 0;
  max-height: 220px;
  overflow-y: auto;
}

.guest-results--show {
  display: block;
}

.guest-result {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--mono);
  font-size: 15px;
  color: var(--ink);
  padding: 9px 12px;
  border: 0;
  border-bottom: var(--rule);
  background: transparent;
  cursor: pointer;
}

.guest-result:hover,
.guest-result:focus {
  background: #fdf7e6;
}

/* Errors do not apologise and are never vague about what happened. */
.notice {
  border: var(--rule);
  border-left-width: 10px;
  border-left-color: var(--red);
  background: var(--paper);
  padding: 12px 16px;
  font-family: var(--mono);
  font-size: 13px;
  margin-bottom: 22px;
}

.notice--good { border-left-color: var(--amber); }

/* ---- sign in ----------------------------------------------------------------
   The same receipt as the rail's head, at the size of a whole page: this is the first
   Tenvelo surface anyone sees, so it is the mark and nothing else. */
.gate {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

/* The outline has to be drawn as drop-shadows, because a border would be clipped by the
   mask that makes the teeth. */
.gate__paper {
  width: min(440px, 100%);
  filter:
    drop-shadow(3px 0 0 var(--ink)) drop-shadow(-3px 0 0 var(--ink))
    drop-shadow(0 3px 0 var(--ink)) drop-shadow(0 -3px 0 var(--ink));
}

.gate__slab {
  background: var(--paper);
  --tooth: 22px;
}

.gate__body { padding: 30px 34px 44px; }

.gate__mark {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--display);
  font-size: 32px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0;
}

.brand-icon { flex: none; }

.gate__sub {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 4px 0 0;
}

.gate__total { height: 8px; background: var(--amber); width: 46%; margin: 16px 0 26px; }

.gate__alt { font-size: 14px; color: var(--ink-muted); margin-top: 20px; }

/* ---- one orchestrated entrance ---------------------------------------------
   Staggered on load and nowhere else. Motion on a screen somebody reads forty times a day
   stops being delightful by the third time. */
.rise {
  animation: rise 420ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
  animation-delay: calc(var(--i, 0) * 55ms);
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@keyframes grow {
  from { transform: scaleY(0); }
  to { transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
  .rise, .hours__bar, .trend__bar { animation: none; }
  .btn, .rail__link, .act { transition: none; }
  .btn:hover, .btn:active { transform: none; }
}

@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  /* Above the content rather than beside it, so the nav scrolls with the page and needs
     no scroller of its own. */
  .rail {
    position: static;
    height: auto;
    border-right: 0;
    border-bottom: var(--rule);
  }
  .rail__nav { overflow-y: visible; max-height: none; }
  .takings { grid-template-columns: 1fr; }
  .host { grid-template-columns: 1fr; }
  .section, .masthead { padding-left: 20px; padding-right: 20px; }
}

/* ---- kitchen display --------------------------------------------------------
   The KDS is read at arm's length across a room, so a ticket is a slab whose item lines
   are large and whose note is set apart. The board is not a table: quantity, item and
   note sit on one line, because that is how a ticket is actually read. */
/* The left edge was #e4572e, a third hue nothing in the system ever set. */
.kds {
  border-left: 10px solid var(--amber);
}

.kds__head {
  display: flex;
  gap: 12px;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.kds__lines {
  list-style: none;
  margin: 0 0 10px;
  padding: 0;
  display: grid;
  gap: 8px;
}

.kds__line {
  display: flex;
  gap: 10px;
  align-items: baseline;
  font-size: 17px;
}

.kds__qty {
  font-family: var(--mono);
  font-weight: 700;
  min-width: 2ch;
  color: var(--ink-muted);
}

.kds__item { font-weight: 600; }

/* A held course line: the server has rung it but not yet fired it, so it is coming,
   not up. Drawn dimmed so a runner never mistakes it for food ready to run. */
.kds__line.kds__held { opacity: 0.45; }

.kds__note {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-muted);
  margin-left: auto;
}

/* An allergen clash: the line's product bears something the guest declared. Flagged in
   words and colour, set apart from a note, so a cook cannot miss "nuts" at the pass. */
.kds__allergen {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  color: #a12f00;
  background: #fff1e0;
  padding: 0 6px;
  border-radius: 4px;
}

/* Printed pages are the report, not the app: hide the rail and the screen chrome and let
   the report fill the paper. A manager printing the Z report wants the figures, not the
   rail or the filters. The Print button itself hides too, since it is the thing being
   pressed. */
@media print {
  .rail,
  .masthead,
  main form,
  [data-print] {
    display: none;
  }

  body {
    background: #fff;
  }

  .main {
    max-width: none;
    padding: 0;
    margin: 0;
  }
}

/* A short word in a box: what channel an order came from, or what state a setting is in.
   The word carries the meaning; the fill only repeats it, so it reads without colour. */
.badge {
  display: inline-block;
  padding: 2px 8px;
  border: 2px solid var(--ink);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: var(--paper);
  color: var(--ink);
}
.badge--on { background: var(--amber); }
.badge--stop { background: var(--ink); color: var(--paper); }
.badge--off { color: var(--ink-muted); border-color: var(--ink-muted); }
/* A cancelled ticket: the same red-on-paper pairing .pill--behind already uses, so no new
   colour and no new contrast question. */
.badge--danger { background: var(--red); color: var(--paper); border-color: var(--red); }

.online-state { display: flex; flex-wrap: wrap; gap: 12px 24px; align-items: center; justify-content: space-between; }
.online-state__line { margin: 0; }
.online-count { font-family: var(--mono); }
.online-late { color: var(--red); font-weight: 700; }

/* A QR code on the table screen and the printable sheet. The sheet is a print surface:
   white cards on cream, grid-spaced, with the table's name under the code. */
.qr { display: block; background: #fff; padding: 8px; image-rendering: pixelated; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
.qr-card { text-align: center; }
.qr-card img { margin: 0 auto; }
