/* ============================================================================
   DESIGN SYSTEM — the whole look of the desk, in one file.

   The tokens are the operator's own, lifted from murrja.vercel.app: pine and
   gold on sand. The app a client glances over the counter should look like the
   site they booked from, so nothing here invents a new palette.

   Three rules the desk imposes on every choice below:
     1. The device is held in one hand, often in sunlight at the airport, so
        contrast is high and touch targets are never under 48px.
     2. Nothing may depend on hover: a finger has no hover state.
     3. The primary action of a screen sits at the bottom, inside the thumb's
        reach, as a full-width pill.
   ========================================================================= */

:root {
  /* PINE, in enough steps to build with. One flat brand colour is why an
     interface ends up looking printed rather than made: a dark surface needs a
     floor to sit on, a lift to catch light, and a hairline that is neither. */
  --pine-950: #0D1A1C; --pine-900: #142629; --pine-deep: #172A2D;
  --pine: #23393D; --pine-2: #2E4A4F; --pine-3: #3D5F64;
  --pine-300: #7C989B; --pine-tint: #E4ECEA; --pine-50: #EFF5F3;

  /* GOLD is the operator's accent and it is used like one: a number that
     matters, one primary action, the mark on a dark ground. Everywhere it
     appears twice on a screen it has stopped meaning anything. */
  --gold: #F0C540; --gold-2: #E4B62F; --gold-lift: #FFD86B;
  --gold-soft: #FBF3D6; --gold-ink: #6E5300;

  --ink: #16211F; --mute: #5A6968; --faint: #7E8B8B;
  /* Secondary text on a DARK ground. It cannot share --faint: on a light ground
     tertiary text must get darker to be read, on pine it must get lighter. */
  --on-dark: rgba(255, 255, 255, .92);
  --on-dark-dim: #A9B9B7;

  --line: #DCE4E1; --hair: #E9EEEB; --mist: #F4F7F5; --mist-2: #EAF0EE;
  /* The page is sand; anything raised off it is a shade WARMER and lighter, not
     stark white. White on cream reads as a hole punched in the page. */
  --sand: #FAF6EA; --sand-2: #F3EAD2; --card: #FFFDF8; --sea: #DDEBEA;
  --eco: #2C7355; --red: #AE3B36; --white: #fff;

  --r-card: 20px; --r-input: 13px; --r-panel: 26px; --r-tile: 24px; --r-pill: 999px;

  /* Elevation in three steps, tinted with the brand hue rather than black.
     Every level is TWO shadows: a tight one that gives the edge a seat, and a
     wide soft one that gives it height. A single blur is what flat looks like. */
  --e1: 0 1px 2px rgba(20, 38, 41, .05), 0 1px 3px rgba(20, 38, 41, .04);
  --e2: 0 1px 2px rgba(20, 38, 41, .05), 0 6px 14px -4px rgba(20, 38, 41, .07), 0 14px 30px -12px rgba(20, 38, 41, .09);
  --e3: 0 1px 3px rgba(20, 38, 41, .06), 0 12px 26px -8px rgba(20, 38, 41, .11), 0 34px 64px -22px rgba(20, 38, 41, .16);
  /* The old names, kept so a hundred call sites need not be rewritten. */
  --shadow: var(--e3); --shadow-sm: var(--e2);

  /* Both faces are served from this machine (css/fonts.css) and precached with
     the shell, so the desk looks like itself in aeroplane mode. The serif is
     for display only — a greeting, a screen title, a total. It is not a UI
     face and must never be asked to set a form label. */
  --display: "Instrument Serif", ui-serif, Georgia, "Times New Roman", serif;
  --sans: "Inter", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  --ease: cubic-bezier(.2, .8, .3, 1);

  --rail: 264px;
  --gap: 16px;
  --pad: 20px;
}

* { box-sizing: border-box; }
/* The shell is hidden until we know who is signed in; the flex rules below
   would otherwise win over the attribute. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: none;
}

body { min-height: 100dvh; }

/* Inter is drawn a little wide for display sizes. Every heading here pulls the
   tracking in; without it large type looks set by a word processor. */
h1, h2, h3, h4 { margin: 0; font-weight: 640; letter-spacing: -.022em; line-height: 1.16; }
h1 { font-size: 28px; letter-spacing: -.03em; }
h2 { font-size: 20px; }
h3 { font-size: 17px; }

/* The display face. Reserved for the few places the app is allowed to have a
   voice — the greeting, a screen title, a figure somebody is about to be told.
   Instrument Serif has one weight, so size and tracking do all the work. */
.serif, .display {
  font-family: var(--display); font-weight: 400;
  letter-spacing: -.012em; line-height: 1.08;
}
p { margin: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; border-radius: 8px; }

/* ------------------------------------------------------------- layout ---- */

#shell { display: flex; min-height: 100dvh; flex-direction: column; }

#view {
  flex: 1;
  width: 100%;
  max-width: 940px;
  margin: 0 auto;
  padding: 12px var(--pad) 132px;
  /* clip, not hidden: clip does not make a scroll container, so the sticky
     header above still sticks. Nothing may make the page scroll sideways. */
  overflow-x: clip;
}

.section { margin-top: 28px; }
.section:first-child { margin-top: 8px; }
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 12px; padding: 0 4px;
}
.section-head h2 { font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--mute); font-weight: 620; }
.section-head .count { font-size: 15px; color: var(--mute); font-variant-numeric: tabular-nums; }
.section-head .count.late { color: var(--red); font-weight: 700; }

/* minmax(0, 1fr), never 1fr: a grid item's default min-width is its own
   content, so one long unbreakable line (a plate, a price) widens the column
   past the screen and the card runs off the right edge of the phone. */
.stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.rowline { display: flex; align-items: center; gap: 10px; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* A flex child will not shrink below its own text unless it is told it may, and
   one long customer name then makes the whole page scroll sideways on a phone. */
.spread > *, .rowline > * { min-width: 0; }
.grow { flex: 1; min-width: 0; }
.wrap { display: flex; flex-wrap: wrap; gap: 8px; }
.muted { color: var(--mute); }
/* Tertiary TEXT still has to be read on a tablet in daylight: --faint is an
   icon tone and does not clear 4.5:1 on any of our grounds. */
.faint { color: var(--mute); }
.tabular { font-variant-numeric: tabular-nums; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.center { text-align: center; }

/* --------------------------------------------------------- app header ---- */

#top {
  position: sticky; top: 0; z-index: 40;
  background: rgba(250, 246, 234, .82);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  padding: env(safe-area-inset-top) 0 0;
  /* A hairline, not a border: it fades in only once the page has moved under
     the bar. A permanent rule across the top of a screen that has not scrolled
     is a line for its own sake. */
  box-shadow: 0 1px 0 rgba(20, 38, 41, 0);
  transition: box-shadow .2s ease;
}
body.scrolled #top { box-shadow: 0 1px 0 var(--hair), 0 8px 24px -18px rgba(20, 38, 41, .5); }
#top .bar {
  max-width: 940px; margin: 0 auto;
  display: flex; align-items: center; gap: 10px;
  padding: 10px var(--pad);
  min-height: 58px;
}
/* The spacer may collapse to nothing, but never below nothing. */
#top .bar .grow { flex: 1 1 8px; min-width: 8px; }
/* The name is the one thing in this bar that may be sacrificed. On a phone the
   company name, the language switch and the sync chip do not all fit, and the
   two on the right both have to be readable — one is a control and the other is
   the only place the app admits it is offline. So the name truncates. min-width
   on BOTH the flex item and its wrapper: without it on the inner span the text
   sets its own floor and pushes the chip off the edge instead of shortening. */
.brandmark { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 0 1 auto; }
.brandmark > span { min-width: 0; }
.brandmark .mark {
  width: 36px; height: 36px; border-radius: 12px; flex: none;
  background: var(--pine); color: var(--gold);
  display: grid; place-items: center; font-weight: 750; font-size: 17px;
  box-shadow: var(--e1);
}
.brandmark .name { font-weight: 600; font-size: 16px; letter-spacing: -.017em; }
.brandmark .where { font-size: 12px; color: var(--mute); }

/* the sync chip: the agent must be able to tell at a glance whether the work
   in their hand has left the device. It never spins and never blocks. */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 13px; border-radius: var(--r-pill);
  font-size: 13px; font-weight: 600; border: 1px solid transparent;
  white-space: nowrap;
}
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
.chip.ok { background: #E7F2EC; color: var(--eco); border-color: #CBE4D8; }
.chip.wait { background: var(--gold-soft); color: #8A6A05; border-color: #EEDFA8; }
.chip.off { background: var(--mist-2); color: var(--mute); border-color: var(--line); }
.chip.bad { background: #FBEBEA; color: var(--red); border-color: #F0D2D0; }

/* --------------------------------------------------------------- cards --- */

/* A raised surface is warm ivory rather than white, carries a hairline that is
   darker at the foot than at the head (which is what a lit edge looks like),
   and sits on two shadows. Those three details together are the difference
   between a panel and a rectangle. */
.card {
  position: relative;
  max-width: 100%;
  background: var(--card);
  border: 1px solid var(--hair);
  border-bottom-color: var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--e2);
  padding: 18px;
}
.card.flat { box-shadow: var(--e1); }
.card.tint { background: var(--mist); border-color: var(--line); box-shadow: none; }
.card.sand { background: var(--sand-2); border-color: #E8DCBC; box-shadow: none; }
.card.pine {
  background: linear-gradient(168deg, var(--pine-2), var(--pine) 42%, var(--pine-900));
  color: var(--white); border-color: var(--pine-950);
  box-shadow: var(--e3), inset 0 1px 0 rgba(255, 255, 255, .07);
}
.card.pine .muted, .card.pine .faint { color: var(--on-dark-dim); }
.card.alert { border-color: #EBC9C7; background: #FDF4F3; box-shadow: none; }

/* a tappable card is a button, so it works with a keyboard and reads as one to
   a screen reader; it just does not look like one */
button.card, a.card { display: block; width: 100%; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
button.card:active, a.card:active { transform: scale(.985); box-shadow: var(--e1); }
button.card, a.card { transition: transform .14s var(--ease), box-shadow .14s var(--ease); }

/* .job is the two-line list row: a .who line and a .spread line under it. The
   ROW is what .job describes; the pieces inside it are used on their own all
   over the app — the car and customer cards on a rental, the customer box and
   the car picker in the new-rental flow — and scoping them to .job left every
   one of those as unstyled stacked divs with a chevron adrift below the text. */
.job { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.who { display: flex; align-items: center; gap: 13px; }
.job .who { align-items: flex-start; }
/* The plate is the one thing an agent reads across a car park, so it is set
   like a plate: monospaced, letter-spaced, on its own dark ground. Deliberately
   NOT scoped to .job — six screens render one outside a job row, and on the home
   screen's late-car block it came out as plain text on white. */
.plate {
  font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: .05em;
  background: linear-gradient(180deg, var(--pine-2), var(--pine));
  color: var(--white);
  padding: 7px 10px; border-radius: 8px; flex: none; white-space: nowrap;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
}
.job.late .plate, .plate.late { background: linear-gradient(180deg, #C4514C, var(--red)); }
.title { font-weight: 600; font-size: 17px; letter-spacing: -.019em; line-height: 1.3; }
.sub { font-size: 14px; color: var(--mute); }
.who .sub, .spread .sub { margin-top: 2px; }
.when { font-size: 14px; font-weight: 600; color: var(--pine); white-space: nowrap; flex: none; }

/* On a narrow phone the model name matters more than one tidy line. Shrink the
   plate a little and let the name wrap rather than truncating "Volkswagen Golf
   7" to "Volkswagen Go…", which tells the agent in the car park nothing. */
@media (max-width: 430px) {
  .plate { font-size: 12px; padding: 6px 9px; }
  .title.truncate { white-space: normal; overflow: visible; }
}
.when.late { color: var(--red); }

/* --------------------------------------------------------------- stats --- */

.stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.stat {
  background: var(--card); border: 1px solid var(--hair); border-bottom-color: var(--line);
  border-radius: 17px; padding: 15px 14px; box-shadow: var(--e2);
}
.stat .n { font-size: 27px; font-weight: 660; letter-spacing: -.038em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat .k { font-size: 12.5px; color: var(--mute); margin-top: 3px; font-weight: 500; letter-spacing: .005em; }
.stat.gold { background: var(--gold-soft); border-color: #EEDFA8; }
.stat.gold .n { color: #7A5C00; }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 50px; padding: 13px 22px;
  border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--card); color: var(--pine);
  font-size: 16px; font-weight: 580; letter-spacing: -.011em; cursor: pointer;
  box-shadow: var(--e1);
  -webkit-tap-highlight-color: transparent;
  transition: transform .14s var(--ease), box-shadow .14s var(--ease), opacity .12s ease;
}
.btn:active { transform: scale(.972); box-shadow: none; }
.btn[disabled] { opacity: .42; pointer-events: none; box-shadow: none; }
.btn svg { width: 19px; height: 19px; }
/* The primary action gets a lit top edge and a shadow in its own colour, so it
   reads as a raised key rather than a filled rectangle. */
.btn.primary {
  background: linear-gradient(180deg, var(--pine-2), var(--pine));
  border-color: var(--pine-900); color: var(--white); font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 2px 4px rgba(20, 38, 41, .14), 0 10px 22px -10px rgba(20, 38, 41, .5);
}
.btn.gold {
  background: linear-gradient(180deg, var(--gold-lift), var(--gold));
  border-color: var(--gold-2); color: var(--pine-deep); font-weight: 650;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 2px 4px rgba(140, 104, 8, .18), 0 10px 22px -10px rgba(140, 104, 8, .45);
}
.btn.ghost { background: transparent; border-color: transparent; color: var(--mute); box-shadow: none; }
.btn.danger { color: var(--red); border-color: #EBC9C7; background: #FDF4F3; }
.btn.block { display: flex; width: 100%; }
.btn.sm { min-height: 42px; padding: 9px 16px; font-size: 14.5px; }

/* The screen's main action, pinned where the thumb already is. On a tablet it
   sits inline at the end of the content instead of floating. */
.thumb {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 44;
  padding: 12px var(--pad) calc(12px + env(safe-area-inset-bottom));
  background: linear-gradient(to top, var(--sand) 62%, rgba(251, 247, 236, 0));
  pointer-events: none;
}
.thumb > * { pointer-events: auto; }
.thumb .inner { max-width: 940px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }


/* ------------------------------------------------------------ the bar ---
   The only chrome there is. On home it carries the brand; everywhere else it is
   a single way back to home, because everywhere else is a job you entered from
   there. The rail and the tab bar that used to live here are gone: a permanent
   menu is what made this read as a website, and it is an invitation to wander
   off mid-handover. */

.homebtn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 8px 14px 8px 8px; margin-left: -6px;
  border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 15.5px; font-weight: 650; color: var(--pine);
  border-radius: var(--r-pill);
  -webkit-tap-highlight-color: transparent;
}
.homebtn svg { width: 20px; height: 20px; stroke-width: 2; }
.homebtn:hover { background: var(--pine-tint); }
.homebtn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

@media (min-width: 860px) {
  #main { flex: 1; min-width: 0; }
  #view { padding-bottom: 72px; max-width: 940px; margin: 0 auto; }
  #top .bar { max-width: 940px; margin: 0 auto; }
  #top { background: rgba(251, 247, 236, .92); }
}

.thumb { bottom: 0; padding-bottom: calc(12px + env(safe-area-inset-bottom)); }
@media (min-width: 860px) {
  .thumb { position: static; padding: 22px 0 0; background: none; }
  .thumb .inner { max-width: 420px; margin: 0; }
}

/* --------------------------------------------------------------- pills --- */

.tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 580; letter-spacing: .004em;
  background: var(--mist-2); color: var(--mute); white-space: nowrap;
  box-shadow: inset 0 0 0 1px rgba(20, 38, 41, .05);
}
.tag.ok { background: #E7F2EC; color: var(--eco); }
.tag.out { background: var(--sea); color: #1E5A5E; }
.tag.late { background: #FBEBEA; color: var(--red); }
.tag.warn { background: var(--gold-soft); color: #8A6A05; }
.tag.pine { background: var(--pine); color: var(--white); }

/* horizontal filter row: scrolls rather than wrapping, so the header height
   never jumps as filters change */
.filters { display: flex; gap: 8px; overflow-x: auto; padding: 2px 4px 6px; scrollbar-width: none; margin: 0 -4px; }
.filters::-webkit-scrollbar { display: none; }
.filters button {
  min-height: 44px; padding: 10px 17px; border-radius: var(--r-pill);
  border: 1px solid var(--line); background: var(--card); color: var(--mute);
  font-size: 14.5px; font-weight: 540; letter-spacing: -.005em; white-space: nowrap; cursor: pointer;
  box-shadow: var(--e1); transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.filters button[aria-pressed="true"] {
  background: linear-gradient(180deg, var(--pine-2), var(--pine));
  border-color: var(--pine-900); color: var(--white); font-weight: 580;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), var(--e1);
}

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

.field { display: grid; grid-template-columns: minmax(0, 1fr); gap: 7px; }
.field > label { font-size: 13px; font-weight: 580; letter-spacing: .01em; color: var(--mute); padding-left: 4px; }
.field .hint { font-size: 13px; color: var(--mute); padding-left: 4px; }
.field .bad { font-size: 13.5px; color: var(--red); padding-left: 4px; font-weight: 550; }

/* 16px minimum, always: anything smaller makes iOS Safari zoom the page on
   focus and the agent then has to pinch back out one-handed. */
input, select, textarea {
  width: 100%; min-height: 50px;
  padding: 13px 15px; font-size: 16px; font-family: inherit; color: var(--ink);
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-input);
  appearance: none;
  /* A field is a well, not a card: the shadow goes inwards. */
  box-shadow: inset 0 1px 2px rgba(20, 38, 41, .045);
  transition: border-color .15s ease, box-shadow .15s ease;
}
textarea { min-height: 96px; resize: vertical; line-height: 1.45; }
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%235F6E6E' stroke-width='1.8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 16px center; background-size: 12px;
  padding-right: 42px;
}
input:focus, select:focus, textarea:focus { border-color: var(--pine-2); outline: none; box-shadow: inset 0 1px 2px rgba(20, 38, 41, .04), 0 0 0 3.5px rgba(46, 74, 79, .13); }
input[aria-invalid="true"] { border-color: var(--red); }
.two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
@media (max-width: 420px) { .two { grid-template-columns: 1fr; } }

.search { position: relative; }
.search input { padding-left: 46px; }
.search svg { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); width: 19px; height: 19px; stroke: var(--faint); }

.check {
  display: flex; align-items: center; gap: 12px; min-height: 52px;
  padding: 8px 14px; border: 1px solid var(--line); border-radius: var(--r-input);
  background: var(--white); cursor: pointer; font-weight: 550;
}
.check input { width: 22px; height: 22px; min-height: 0; flex: none; accent-color: var(--pine); }
.check[data-on="true"] { border-color: var(--pine-2); background: var(--mist); }

/* ---------------------------------------------------------------- rows --- */

.rows { display: grid; grid-template-columns: minmax(0, 1fr); }
.rows > * { border-bottom: 1px solid var(--hair); }
.rows > *:last-child { border-bottom: 0; }
.kv { display: flex; justify-content: space-between; gap: 16px; padding: 12px 2px; font-size: 15px; }
.kv dt, .kv .k { color: var(--mute); flex: none; }
.kv dd, .kv .v { min-width: 0; }
.kv dd, .kv .v { margin: 0; font-weight: 600; text-align: right; }
.kv.total { font-size: 17px; padding-top: 15px; }
.kv.total .v { font-weight: 700; }
.kv .v.neg { color: var(--eco); }

.listitem {
  display: flex; align-items: center; gap: 13px; width: 100%;
  padding: 15px 4px; min-height: 62px; background: none; border: 0;
  text-align: left; cursor: pointer; border-bottom: 1px solid var(--hair);
}
.listitem:last-child { border-bottom: 0; }
.listitem:active { background: var(--mist); }
/* An inline SVG with no width fills whatever space it is given, and a chevron
   the size of the card is what that looks like. Every icon dropped into a row
   gets a size here rather than at each call site. */
.listitem > svg, .who > svg, .spread > svg { width: 19px; height: 19px; stroke: var(--faint); flex: none; }

.avatar {
  width: 42px; height: 42px; border-radius: 50%; flex: none;
  background: linear-gradient(160deg, var(--pine-50), var(--pine-tint));
  color: var(--pine); box-shadow: inset 0 0 0 1px rgba(20, 38, 41, .06);
  display: grid; place-items: center; font-weight: 620; font-size: 15px; letter-spacing: -.01em;
}

/* --------------------------------------------------------------- empty --- */

.empty {
  display: grid; gap: 8px; justify-items: center; text-align: center;
  padding: 34px 24px; border: 1px dashed var(--line); border-radius: var(--r-card);
  background: rgba(255, 255, 255, .5); color: var(--mute);
}
.empty .big { font-size: 16px; font-weight: 600; color: var(--ink); }
.empty svg { width: 30px; height: 30px; stroke: var(--faint); }

.skeleton { display: grid; gap: 12px; }
.skeleton > i {
  display: block; height: 84px; border-radius: var(--r-card);
  background: linear-gradient(100deg, var(--mist) 30%, var(--mist-2) 50%, var(--mist) 70%);
  background-size: 300% 100%; animation: sweep 1.4s linear infinite;
}
@keyframes sweep { from { background-position: 140% 0; } to { background-position: -40% 0; } }
@media (prefers-reduced-motion: reduce) { .skeleton > i { animation: none; } }

/* ------------------------------------------------------- sheet & toast --- */

.scrim {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(23, 42, 45, .42);
  display: flex; align-items: flex-end; justify-content: center;
  animation: fade .16s ease;
}
@keyframes fade { from { opacity: 0; } }
.sheet {
  background: var(--sand); width: 100%; max-width: 620px;
  border-radius: var(--r-panel) var(--r-panel) 0 0;
  padding: 10px var(--pad) calc(20px + env(safe-area-inset-bottom));
  max-height: 92dvh; overflow-y: auto;
  animation: rise .22s cubic-bezier(.2, .8, .3, 1);
  box-shadow: var(--shadow);
}
@keyframes rise { from { transform: translateY(24px); } }
.sheet .grip { width: 40px; height: 4px; border-radius: 2px; background: var(--line); margin: 6px auto 14px; }
.sheet h2 { margin-bottom: 14px; }
.sheet .body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.sheet .actions { display: grid; gap: 10px; margin-top: 20px; }
@media (min-width: 620px) {
  .scrim { align-items: center; }
  .sheet { border-radius: var(--r-panel); max-height: 86dvh; }
  @keyframes rise { from { transform: scale(.97); } }
}

#toasts {
  position: fixed; left: 0; right: 0; bottom: calc(72px + env(safe-area-inset-bottom));
  z-index: 70; display: grid; gap: 8px; justify-items: center; pointer-events: none; padding: 0 16px;
}
.toast {
  background: var(--pine-900); color: var(--white);
  padding: 13px 19px; border-radius: var(--r-pill); font-size: 14.5px; font-weight: 520;
  box-shadow: var(--e3), inset 0 1px 0 rgba(255, 255, 255, .08);
  max-width: 480px; animation: rise .2s var(--ease);
}
.toast.bad { background: var(--red); }
.toast.ok { background: var(--eco); }

/* a banner, not a dialogue: a new version or a stale read must never stop the
   agent mid-handover */
.banner {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 13px 16px; border-radius: 16px; font-size: 14px; font-weight: 550;
  background: var(--gold-soft); color: #6E5300; border: 1px solid #EEDFA8;
  margin-bottom: 14px;
}
.banner .btn { min-height: 40px; padding: 8px 15px; font-size: 14px; margin-left: auto; }

/* --------------------------------------------------------------- login --- */

/* The first screen anyone sees, including a client leaning over the counter
   while an agent signs in. It is the whole product in one impression, so it
   gets the light source, the serif and the real mark rather than a form on a
   coloured background. */
.login {
  position: relative;
  min-height: 100dvh; display: grid; place-items: center;
  padding: 28px 20px calc(28px + env(safe-area-inset-bottom));
  background:
    radial-gradient(90% 70% at 50% -10%, rgba(240, 197, 64, .16), transparent 60%),
    radial-gradient(80% 60% at 50% 115%, rgba(46, 74, 79, .8), transparent 60%),
    linear-gradient(168deg, var(--pine-2), var(--pine) 45%, var(--pine-950));
}
.login .box { width: 100%; max-width: 392px; display: grid; gap: 20px; animation: settle .45s var(--ease) both; }
.login .mark {
  width: 68px; height: 68px; border-radius: 22px; margin: 0 auto;
  background: var(--gold); color: var(--pine);
  display: grid; place-items: center; font-size: 32px; font-weight: 750;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 255, 255, .4);
}
.login h1 {
  font-family: var(--display); font-weight: 400; font-size: 34px;
  letter-spacing: -.014em; line-height: 1.1;
  color: #fff; text-align: center; margin-top: 2px;
}
.login .panel {
  background: var(--card); border-radius: var(--r-panel); padding: 24px;
  display: grid; gap: 15px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 30px 70px -20px rgba(0, 0, 0, .5);
}
.login .foot { text-align: center; color: rgba(255, 255, 255, .5); font-size: 13px; letter-spacing: .01em; }

/* Absolutely positioned so it cannot disturb the centring of the card. It has
   to be here: a device signing in for the first time has no stored preference
   and opens in English, so without a switch on THIS screen the one person who
   needs Albanian is the one person who cannot reach it. */
.login-lang {
  position: absolute; top: calc(env(safe-area-inset-top) + 10px); right: 14px;
}
.login-lang .langswitch .on { background: rgba(255, 255, 255, .16); color: #fff; }
.login-lang .langswitch .off { color: rgba(255, 255, 255, .55); }
.login-lang .langswitch:hover .off { color: #fff; background: rgba(255, 255, 255, .1); }

/* -------------------------------------------------------------- misc ----- */

.hr { height: 1px; background: var(--hair); border: 0; margin: 18px 0; }
.back { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 8px 12px 8px 6px; margin-left: -6px; color: var(--mute); font-weight: 600; font-size: 15px; background: none; border: 0; cursor: pointer; }
.back svg { width: 18px; height: 18px; }
/* Every screen opens the way home does: the eyebrow in small caps, then the
   title in the display face. It is the one thread that ties fifteen screens
   into one product rather than fifteen pages — a customer's name set like this
   reads as a guest record, which is what it is. */
.headline { display: grid; gap: 6px; margin-bottom: 20px; }
.headline h1 {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(30px, 4.6vw, 38px); letter-spacing: -.014em; line-height: 1.07;
}
.headline .muted { font-size: 15px; }
.headline .eyebrow { font-size: 11.5px; font-weight: 620; letter-spacing: .13em; text-transform: uppercase; color: var(--mute); }
.money-big { font-family: var(--display); font-weight: 400; font-size: 46px; letter-spacing: -.018em; line-height: 1.05; font-variant-numeric: tabular-nums; }
.pending { opacity: .72; }
.pending .tag { background: var(--gold-soft); color: #8A6A05; }


/* ---------------------------------------------------------------- flows ----
   A focused flow (handover, return, signing) takes the whole screen. The tab bar
   is hidden rather than merely covered: on a phone it overlapped the wizard's own
   primary button, and a bottom bar during a signature is an invitation to lose
   the work. app.js sets .flow from the route. */
/* A wizard already carries its own Cancel and Back. Hiding the way home during
   one leaves exactly one way out of a half-signed inspection. */
body.flow .homebtn { display: none; }
body.flow #view { padding-bottom: 0; }

/* ------------------------------------------------------- language switch ----
   Two letters in the corner of the header: the one you are reading, then the one
   you would get. Big enough for a thumb on a tablet held in one hand, quiet
   enough that it never competes with the work. */
.langswitch {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 6px 4px; min-height: 44px; min-width: 44px;
  border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  -webkit-tap-highlight-color: transparent;
}
.langswitch .on,
.langswitch .off {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px; padding: 0 6px; border-radius: var(--r-pill);
  transition: background-color .15s ease, color .15s ease;
}
.langswitch .on { background: var(--pine); color: #fff; }
.langswitch .off { color: var(--mute); }
.langswitch:hover .off { color: var(--pine); background: var(--pine-tint); }
.langswitch:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--r-pill); }

/* The rail is the one dark ground in the app, so its secondary text takes the
   on-dark tone. Set after the base rule so it wins without an id selector. */
/* the rail is gone; the on-dark tone is kept for anything else on pine */

/* ============================================================================
   THE LAUNCHER

   Home is a set of jobs, not a dashboard. Three bands, in the order the day is
   actually read:

     THE HERO is the desk itself — a dark panel carrying the date, a greeting
     and the three numbers the owner glances at. Putting the figures INSIDE it
     rather than in a strip of their own is what stops the screen reading as a
     stack of unrelated widgets, and it gives the app the weight that a page of
     white cards on cream never has.

     THE TILES are the work. Each one is a whole tap target with a title in the
     words an agent would use and one line saying what happens next, because the
     alternative is an icon and a noun that everybody reads differently.

     THE CHIPS are the rest. Fleet, money, customers, settings: opened a few
     times a day, never mid-handover, and given a permanent menu is exactly what
     made this read as a website.
   ========================================================================= */

.home { display: grid; gap: 20px; }

/* ------------------------------------------------------------- the hero ----
   Two gradients doing separate jobs. The linear one is the material — a dark
   panel is never one flat colour, or it looks like a hole. The radial is a
   light source at the top left, which is what stops a large dark rectangle
   looking like a swatch. */
.hero {
  position: relative; overflow: hidden;
  border-radius: var(--r-panel);
  padding: 26px 26px 22px;
  color: var(--white);
  background:
    radial-gradient(120% 100% at 8% -10%, rgba(240, 197, 64, .13), transparent 52%),
    linear-gradient(158deg, var(--pine-2) 0%, var(--pine) 46%, var(--pine-950) 100%);
  box-shadow: var(--e3), inset 0 1px 0 rgba(255, 255, 255, .09);
}

.hero-date {
  font-size: 11.5px; font-weight: 600; letter-spacing: .15em; text-transform: uppercase;
  color: var(--gold); opacity: .92;
}
/* The one place the app speaks. A serif at this size on a dark ground is the
   whole difference between a tool and a front desk. */
.hero h1 {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(30px, 5.4vw, 42px); letter-spacing: -.015em; line-height: 1.06;
  margin: 7px 0 0; color: #fff;
}
.hero-sub { margin: 8px 0 0; font-size: 15px; color: var(--on-dark-dim); letter-spacing: -.005em; }

/* The day in three figures. A hairline rule above rather than a box: they
   belong to the greeting, they are not a separate panel. */
.hero-figs {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 8px; margin-top: 22px; padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, .11);
}
.hero-figs b {
  display: block; font-family: var(--display); font-weight: 400;
  font-size: 30px; letter-spacing: -.01em; line-height: 1;
  font-variant-numeric: tabular-nums; color: #fff;
}
.hero-figs .gold b { color: var(--gold); }
.hero-figs span {
  display: block; margin-top: 6px; font-size: 11.5px; font-weight: 550;
  letter-spacing: .085em; text-transform: uppercase; color: var(--on-dark-dim);
}

/* How much of the fleet is earning, as a line rather than a percentage nobody
   reads. It is the only chart in the app and it is four pixels tall. */
.hero-bar { margin-top: 20px; }
.hero-bar .track {
  height: 5px; border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, .12);
}
.hero-bar .fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--gold-2), var(--gold-lift));
  box-shadow: 0 0 12px rgba(240, 197, 64, .45);
  transition: width .6s var(--ease);
}
.hero-bar .cap {
  margin-top: 9px; font-size: 12.5px; color: var(--on-dark-dim);
  display: flex; justify-content: space-between; gap: 12px;
}

/* --------------------------------------------------------------- tiles -----
   Two up from 620px. Sized so a thumb finds them on a tablet held in one hand,
   and so the four of them fill the frame instead of floating in the top third
   of it — a screen that stops two thirds of the way down looks unfinished
   whatever is on it. */
.tiles { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 620px) { .tiles { grid-template-columns: 1fr 1fr; gap: 14px; } }

.tile {
  position: relative; overflow: hidden;
  display: flex; align-items: flex-start; gap: 16px; width: 100%;
  padding: 22px; min-height: 124px; text-align: left;
  background: var(--card);
  border: 1px solid var(--hair); border-bottom-color: var(--line);
  border-radius: var(--r-tile);
  box-shadow: var(--e2); cursor: pointer; font: inherit; color: inherit;
  transition: transform .16s var(--ease), box-shadow .16s var(--ease), border-color .16s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.tile:hover { box-shadow: var(--e3); border-color: var(--line); transform: translateY(-1px); }
.tile:active { transform: scale(.988); box-shadow: var(--e1); }
.tile:focus-visible { outline: 2.5px solid var(--gold); outline-offset: 3px; }

.tile-ic {
  display: grid; place-items: center; flex: none;
  width: 48px; height: 48px; border-radius: 15px;
  background: linear-gradient(160deg, var(--pine-50), var(--pine-tint));
  color: var(--pine);
  box-shadow: inset 0 0 0 1px rgba(20, 38, 41, .06);
}
.tile-ic svg { width: 24px; height: 24px; }
.tile-txt { display: grid; gap: 5px; min-width: 0; }
.tile-t {
  display: flex; align-items: center; gap: 9px;
  font-size: 18px; font-weight: 600; letter-spacing: -.024em;
}
.tile-b { font-size: 14px; line-height: 1.45; color: var(--mute); letter-spacing: -.002em; }
.tile-badge {
  display: inline-grid; place-items: center; min-width: 23px; height: 23px; padding: 0 7px;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--gold-lift), var(--gold)); color: var(--pine-deep);
  font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
}

/* The first job of the day is the one you came here to do, so it is the one
   tile that is not the same as the others. */
.tile-go {
  background:
    radial-gradient(100% 90% at 100% 0%, rgba(240, 197, 64, .12), transparent 55%),
    linear-gradient(160deg, var(--pine-2), var(--pine) 55%, var(--pine-900));
  border-color: var(--pine-950); color: #fff;
  box-shadow: var(--e3), inset 0 1px 0 rgba(255, 255, 255, .08);
}
.tile-go .tile-ic {
  background: rgba(255, 255, 255, .1); color: var(--gold);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
}
.tile-go .tile-b { color: var(--on-dark-dim); }
.tile-go:hover { border-color: var(--pine-950); }

/* ---------------------------------------------------------- late cars ------
   A late car costs money by the hour, so it sits above everything with its own
   button rather than waiting to be found inside a list. */
.urgent {
  background: linear-gradient(180deg, #FEF6F5, #FDF0EE);
  border: 1px solid #F2D3D0; border-radius: var(--r-card);
  padding: 16px; box-shadow: var(--e1);
}
.urgent-h {
  display: flex; align-items: center; gap: 9px; font-size: 11.5px; font-weight: 620;
  letter-spacing: .13em; text-transform: uppercase; color: var(--red);
}
.urgent-h svg { width: 17px; height: 17px; }
.urgent-n { margin-left: auto; font-variant-numeric: tabular-nums; }
.urgent-row {
  display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 11px;
  padding: 13px 14px; min-height: 62px; text-align: left; cursor: pointer;
  background: var(--white); border: 1px solid #F0D2D0; border-radius: var(--r-input);
  font: inherit; color: inherit; box-shadow: var(--e1);
  transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}
.urgent-row:active { transform: scale(.99); box-shadow: none; }
.urgent-who { display: grid; gap: 1px; min-width: 0; flex: 1; }
.urgent-who b { font-size: 15.5px; font-weight: 600; letter-spacing: -.018em; }
.urgent-who small { font-size: 13px; color: var(--mute); }
.urgent-go { flex: none; font-size: 14px; font-weight: 600; color: var(--red); letter-spacing: -.01em; }

/* --------------------------------------------------------------- chips -----
   Quiet on purpose. These are not the work. */
.homechips { display: flex; flex-wrap: wrap; gap: 9px; padding-top: 2px; }
.homechip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 17px; min-height: 46px; cursor: pointer;
  background: var(--card); border: 1px solid var(--hair); border-bottom-color: var(--line);
  border-radius: var(--r-pill);
  font: inherit; font-size: 14.5px; font-weight: 540; letter-spacing: -.01em; color: var(--ink);
  box-shadow: var(--e1);
  transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}
.homechip svg { width: 18px; height: 18px; stroke: var(--faint); }
.homechip:hover { box-shadow: var(--e2); }
.homechip:active { transform: scale(.982); box-shadow: none; }
.homechip:focus-visible { outline: 2.5px solid var(--gold); outline-offset: 2px; }

.stalebar {
  background: var(--gold-soft); border: 1px solid #EEDFA8; border-radius: var(--r-input);
  padding: 11px 14px; font-size: 14px; color: var(--gold-ink);
}

/* ------------------------------------------------------------ entrance -----
   The launcher settles in rather than appearing. It is 260ms and it happens
   once per visit to home; anything longer is a thing to wait through. The
   stagger is what makes it read as one movement instead of four. */
@keyframes settle { from { opacity: 0; transform: translateY(10px); } }
.home > * { animation: settle .3s var(--ease) both; }
.home > *:nth-child(2) { animation-delay: .04s; }
.home > *:nth-child(3) { animation-delay: .08s; }
.home > *:nth-child(4) { animation-delay: .12s; }
.home > *:nth-child(5) { animation-delay: .16s; }
@media (prefers-reduced-motion: reduce) {
  .home > * { animation: none; }
  .hero-bar .fill { transition: none; }
}

/* ============================================================================
   THE PICK LIST — a whole rental on one screen.

   The new-rental form used to be a page: a customer search with its results,
   four date fields, a filter row, nineteen cars, four extras, the quote and a
   notes box, stacked. Three and a half thousand pixels of scrolling, done by an
   agent with somebody standing in front of them.

   It is five lines now. Each says what has been chosen and opens a sheet to
   change it, and the price sits underneath in view the whole time — so the
   screen never moves, and the agent looks at the same five lines from the first
   tap to the last.
   ========================================================================= */

.picklist {
  display: grid; grid-template-columns: minmax(0, 1fr);
  background: var(--card);
  border: 1px solid var(--hair); border-bottom-color: var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--e2);
  overflow: hidden;
}

.pickrow {
  display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 15px 17px; min-height: 68px;
  background: none; border: 0; border-bottom: 1px solid var(--hair);
  text-align: left; cursor: pointer; font: inherit; color: inherit;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .12s ease;
}
.picklist > .pickrow:last-child { border-bottom: 0; }
.pickrow:active { background: var(--mist); }
.pickrow:focus-visible { outline: 2.5px solid var(--gold); outline-offset: -3px; }
.pickrow > svg { width: 18px; height: 18px; stroke: var(--faint); flex: none; }

/* The label is fixed width so all five values start on the same line down the
   card. A ragged left edge is what makes a form look like a list of unrelated
   questions rather than one thing being described. */
.pick-k {
  flex: none; width: 96px;
  font-size: 12.5px; font-weight: 580; letter-spacing: .02em;
  color: var(--mute);
}
@media (max-width: 430px) { .pick-k { width: 76px; font-size: 12px; } }

.pick-v { display: flex; align-items: center; gap: 11px; flex: 1; min-width: 0; }
.pick-text { display: grid; gap: 1px; min-width: 0; }
.pick-main {
  font-size: 16px; font-weight: 550; letter-spacing: -.014em; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pick-sub {
  font-size: 13px; color: var(--mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Nothing chosen yet reads as a prompt, not as an answer. */
.pickrow.is-empty .pick-main { color: var(--mute); font-weight: 500; }
/* A row that leads somewhere else rather than opening a sheet. */
.pickrow.is-locked > svg { stroke: var(--line); }

.avatar.sm { width: 34px; height: 34px; font-size: 13px; }
.pick-v .plate { font-size: 12px; padding: 6px 8px; }

/* The car list inside its sheet: the chosen one carries a ring rather than a
   tick in the corner, because at a glance the ring is the faster read. */
.carpick { padding: 14px 15px; }
.carpick.on {
  border-color: var(--pine);
  box-shadow: inset 0 0 0 2px var(--pine), var(--e1);
}

/* ============================================================================
   THE OVERVIEW

   An information screen, so information design leads rather than decoration.
   Three rules it is built on:

     THE SUMMARY COMES BEFORE THE DETAIL. The till is the first thing and it is
     the only thing given a dark ground; everything under it is quieter by
     construction, so the eye lands in the right place without being told.

     STATE IS CARRIED BY FORM, NOT ONLY BY NUMBER. A late car and a stale
     inspection are both "one row", and if they look identical the owner has to
     read all of them to triage any of them. The stripe down the left edge does
     that job before a single word is read.

     SEMANTIC COLOUR IS NOT THE ACCENT. Gold is the brand and it means "money".
     Red and amber mean "wrong", and they are never spent on anything that is
     merely important.
   ========================================================================= */

.admin { display: grid; gap: 22px; }

/* ------------------------------------------------------------- the till ----
   The one dark surface on the page. Everything the owner opened this screen to
   see is inside it: what came in, which way, and the shape of the fortnight. */
.till {
  position: relative; overflow: hidden;
  border-radius: var(--r-panel); padding: 24px 24px 18px; color: #fff;
  background:
    radial-gradient(120% 100% at 12% -10%, rgba(240, 197, 64, .14), transparent 55%),
    linear-gradient(158deg, var(--pine-2) 0%, var(--pine) 46%, var(--pine-950) 100%);
  box-shadow: var(--e3), inset 0 1px 0 rgba(255, 255, 255, .09);
}
.till-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.till-k {
  font-size: 11.5px; font-weight: 600; letter-spacing: .15em;
  text-transform: uppercase; color: var(--gold); opacity: .92;
}
.till-v {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(38px, 6.5vw, 56px); line-height: 1; letter-spacing: -.018em;
  font-variant-numeric: tabular-nums; margin-top: 8px;
}
/* How the money came in. Zero-value methods are not drawn at all: a row of
   three zeroes beside one real number is three things to read and one to know. */
.till-split { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 6px; }
.till-chip {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 7px 12px; border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .08);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
}
.till-chip i {
  font-style: normal; font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--on-dark-dim);
}
.till-chip b { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }

.spark { display: block; width: 100%; height: 132px; margin: 18px 0 6px; overflow: visible; }
/* Bars, because a day of takings is an amount and not a reading on a curve.
   preserveAspectRatio is none, so the bars stretch to the panel width and the
   rounded corners have to be drawn small enough to survive it. */
.bar { fill: var(--gold); }
.bar-out { fill: #C4514C; }
/* A day that traded nothing still gets a slot, so a quiet fortnight looks
   like one. */
.bar-empty { fill: rgba(255, 255, 255, .2); }
/* Where zero actually is, so a day the desk paid a deposit back drops below it
   rather than being flattened into "nothing happened". */
.spark-zero { stroke: rgba(255, 255, 255, .16); stroke-width: 1; vector-effect: non-scaling-stroke; }

.till-foot {
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  font-size: 12px; color: var(--on-dark-dim);
}

/* --------------------------------------------------------- three figures ---
   Deliberately not tiles. These are consequences of the number above, so they
   share one surface and are separated by hairlines rather than by air. */
.figs3 {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  background: var(--card); border: 1px solid var(--hair); border-bottom-color: var(--line);
  border-radius: var(--r-card); box-shadow: var(--e2); overflow: hidden;
}
@media (max-width: 620px) { .figs3 { grid-template-columns: 1fr; } }
.fig { padding: 17px 18px; border-left: 1px solid var(--hair); display: grid; gap: 3px; align-content: start; }
.fig:first-child { border-left: 0; }
@media (max-width: 620px) {
  .fig { border-left: 0; border-top: 1px solid var(--hair); }
  .fig:first-child { border-top: 0; }
}
.fig-k { font-size: 11.5px; font-weight: 600; letter-spacing: .11em; text-transform: uppercase; color: var(--mute); }
.fig-v { font-size: 25px; font-weight: 650; letter-spacing: -.032em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.fig-n { font-size: 12.5px; color: var(--mute); }
.fig-warn .fig-v { color: var(--red); }

/* -------------------------------------------------------------- panels -----*/
.panel { display: grid; gap: 12px; }
.panel-head { display: flex; align-items: baseline; gap: 12px; padding: 0 4px; }
.panel-head h2 {
  font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--mute); font-weight: 620;
}
.panel-aside {
  margin-left: auto; font-size: 12.5px; color: var(--mute); font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- alerts ------
   The point of the screen. The stripe does the triage before a word is read. */
.alerts {
  display: grid; grid-template-columns: minmax(0, 1fr);
  background: var(--card); border: 1px solid var(--hair); border-bottom-color: var(--line);
  border-radius: var(--r-card); box-shadow: var(--e2); overflow: hidden;
}
.alert {
  display: flex; align-items: center; gap: 13px; width: 100%;
  padding: 14px 16px 14px 0; min-height: 64px;
  background: none; border: 0; border-top: 1px solid var(--hair);
  text-align: left; cursor: pointer; font: inherit; color: inherit;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .12s ease;
}
.alerts > .alert:first-child { border-top: 0; }
.alert::before {
  content: ''; flex: none; align-self: stretch; width: 4px; margin-right: 12px;
  border-radius: 0 3px 3px 0; background: var(--line);
}
.alert-bad::before { background: var(--red); }
.alert-warn::before { background: var(--gold-2); }
.alert-quiet::before { background: var(--pine-300); }
.alert:active { background: var(--mist); }
.alert:focus-visible { outline: 2.5px solid var(--gold); outline-offset: -3px; }
.alert-body { display: grid; gap: 2px; flex: 1; min-width: 0; }
.alert-what { font-size: 15.5px; font-weight: 580; letter-spacing: -.015em; }
.alert-bad .alert-what { color: var(--red); }
.alert-detail { font-size: 13px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alert-amt { font-size: 15px; font-weight: 620; flex: none; }
.alert > svg { width: 18px; height: 18px; stroke: var(--faint); flex: none; }

/* Nothing wrong is worth saying out loud, once, and then getting out of the way. */
.allclear {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px; border-radius: var(--r-card);
  background: #EDF5F0; border: 1px solid #CFE5DA; color: #23543F;
  font-size: 14.5px; line-height: 1.45;
}
.allclear svg { width: 20px; height: 20px; stroke: var(--eco); stroke-width: 2.2; flex: none; }

/* ------------------------------------------------------------ the fleet ----*/
.util { display: grid; gap: 10px; }
.util-nums { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.util-nums b {
  font-family: var(--display); font-weight: 400; font-size: 30px;
  letter-spacing: -.01em; line-height: 1; font-variant-numeric: tabular-nums;
}
.util-nums span { font-size: 14px; color: var(--mute); }
.util-track { height: 8px; border-radius: 999px; background: var(--mist-2); overflow: hidden; }
.util-fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--pine-2), var(--pine));
  transition: width .6s var(--ease);
}
.util-legend { display: flex; align-items: center; gap: 14px; font-size: 12.5px; color: var(--mute); }
.util-legend .is-bad { color: var(--red); }

.mini-k {
  font-size: 11px; font-weight: 620; letter-spacing: .11em; text-transform: uppercase;
  color: var(--mute); margin-bottom: 6px;
}
.kv-sub { display: block; margin-top: 2px; font-size: 12.5px; color: var(--mute); }
.kv .k .plate { font-size: 11.5px; padding: 4px 7px; }

/* A row that goes somewhere looks like it does. */
.kvlink {
  width: 100%; background: none; border: 0; font: inherit; color: inherit;
  cursor: pointer; text-align: left; -webkit-tap-highlight-color: transparent;
}
.kvlink:active { background: var(--mist); }
.kvlink:focus-visible { outline: 2.5px solid var(--gold); outline-offset: -2px; border-radius: 8px; }

@media (prefers-reduced-motion: reduce) { .util-fill { transition: none; } }
