/* =====================================================================
   Pushpa Chicken ERP v2.0.0 - design system
   Infinite Option Web Solutions
   Mobile-first, app-like shell. Bottom nav on phones, sidebar on desktop.
   ===================================================================== */

/* ---------------------------------------------------------------------
   0. Fonts - served from this site, not from Google
   Loading them from fonts.googleapis.com held up every first page view by
   up to a second (two extra servers to reach before anything was drawn).
   Same files Google serves, variable weight, so one file covers every
   weight used. latin-ext carries the rupee sign. Google's copy stays as a
   second source, used only if the local file is missing.
   --------------------------------------------------------------------- */
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url('../fonts/outfit-latin-ext.woff2') format('woff2'),
       url('https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJuktqQ4E.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url('../fonts/outfit-latin.woff2') format('woff2'),
       url('https://fonts.gstatic.com/s/outfit/v15/QGYvz_MVcBeNP4NJtEtq.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/jakarta-latin-ext.woff2') format('woff2'),
       url('https://fonts.gstatic.com/s/plusjakartasans/v12/LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko40yyygA.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/jakarta-latin.woff2') format('woff2'),
       url('https://fonts.gstatic.com/s/plusjakartasans/v12/LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko20yw.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------------------------------------------------------------------
   1. Tokens
   --------------------------------------------------------------------- */
:root {
  /* Brand - warm amber against deep charcoal */
  --brand-50:  #FEF4E6;
  --brand-100: #FCE4C0;
  --brand-300: #F3B057;
  --brand-500: #E8871E;
  --brand-600: #C96A0C;
  --brand-700: #A15408;

  /* Neutrals */
  --ink-900: #10141C;
  --ink-800: #1A2130;
  --ink-700: #2A3140;
  --ink-600: #414A5C;
  --ink-500: #5B6472;
  --ink-400: #7C8595;
  --ink-300: #9AA3B2;
  --ink-200: #C6CDD8;
  --line:    #E4E8EE;
  --line-soft: #EEF1F5;
  --bg:      #F4F6F9;
  --surface: #FFFFFF;
  --surface-2: #FAFBFD;

  /* Semantic */
  --success:   #12855A;
  --success-bg:#E4F5ED;
  --danger:    #CF3636;
  --danger-bg: #FCEAEA;
  --warning:   #C97A0C;
  --warning-bg:#FDF2DF;
  --info:      #2563EB;
  --info-bg:   #E8EFFE;

  /* Type */
  --font-display: 'Outfit', 'Segoe UI', sans-serif;
  --font-body: 'Plus Jakarta Sans', 'Segoe UI', sans-serif;

  /* Shape & depth */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-pill: 999px;

  --sh-1: 0 1px 2px rgba(16, 20, 28, .06);
  --sh-2: 0 2px 8px rgba(16, 20, 28, .07);
  --sh-3: 0 8px 24px rgba(16, 20, 28, .10);
  --sh-fab: 0 6px 20px rgba(232, 135, 30, .40);

  /* Layout */
  --appbar-h: 58px;
  --bottomnav-h: 64px;
  --sidebar-w: 252px;
  --safe-b: env(safe-area-inset-bottom, 0px);

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* ---------------------------------------------------------------------
   2. Reset
   --------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-800);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}

h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.015em;
  margin: 0 0 .5rem;
  color: var(--ink-900);
}
h1 { font-size: 1.5rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.05rem; }

p { margin: 0 0 .75rem; }

a { color: var(--brand-600); text-decoration: none; }
a:hover { color: var(--brand-700); }

img, svg { max-width: 100%; vertical-align: middle; }

hr { border: 0; border-top: 1px solid var(--line); margin: 1.25rem 0; }

::selection { background: var(--brand-100); color: var(--ink-900); }

:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------------------------------------------------------------------
   3. App shell
   --------------------------------------------------------------------- */
.app { min-height: 100vh; }

/* --- Top app bar --- */
.appbar {
  position: sticky;
  top: 0;
  z-index: 60;
  height: var(--appbar-h);
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: 0 .9rem;
  background: var(--ink-900);
  color: #fff;
  box-shadow: var(--sh-2);
}

.appbar__back,
.appbar__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border: 0;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .08);
  color: #fff;
  cursor: pointer;
  transition: background .18s var(--ease);
}
.appbar__back:hover,
.appbar__action:hover { background: rgba(255, 255, 255, .18); }

.appbar__title {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.appbar__sub {
  display: block;
  font-family: var(--font-body);
  font-size: .72rem;
  font-weight: 500;
  color: var(--ink-300);
  letter-spacing: .02em;
}

.appbar__brand {
  display: flex;
  align-items: center;
  gap: .55rem;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 700;
  color: #fff;
}
.appbar__logo {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 9px;
  background: linear-gradient(140deg, var(--brand-500), var(--brand-700));
  font-size: 1rem;
}

/* --- Page canvas --- */
.page {
  padding: 1rem .9rem calc(var(--bottomnav-h) + var(--safe-b) + 84px);
  max-width: 1180px;
  margin: 0 auto;
}

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}
.page-head h1 { margin: 0; }
.page-head__sub {
  font-size: .85rem;
  color: var(--ink-500);
  margin: .15rem 0 0;
}

/* --- Sidebar (desktop only) --- */
.sidebar { display: none; }

/* --- Bottom navigation (mobile) --- */
.bottomnav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 70;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  height: calc(var(--bottomnav-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  /* Solid, not frosted: a blur under a fixed bar is redrawn on every
     scroll frame, which is what made lists judder on cheaper phones. */
  background: #fff;
  border-top: 1px solid var(--line);
  box-shadow: 0 -2px 14px rgba(16, 20, 28, .06);
}

.bottomnav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 48px;
  border: 0;
  background: none;
  font-family: var(--font-body);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink-400);
  cursor: pointer;
  transition: color .18s var(--ease);
}
.bottomnav__item svg { width: 22px; height: 22px; }
.bottomnav__item.is-active { color: var(--brand-600); }
.bottomnav__item.is-active svg { transform: translateY(-1px); }

/* --- Floating action button --- */
.fab {
  position: fixed;
  right: 1rem;
  bottom: calc(var(--bottomnav-h) + var(--safe-b) + 16px);
  z-index: 65;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  height: 52px;
  padding: 0 1.25rem;
  border: 0;
  border-radius: var(--r-pill);
  background: linear-gradient(140deg, var(--brand-500), var(--brand-600));
  color: #fff;
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 600;
  box-shadow: var(--sh-fab);
  cursor: pointer;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
.fab:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(232,135,30,.48); }
.fab:active { transform: translateY(0); }
.fab svg { width: 20px; height: 20px; }

/* --- "More" sheet --- */
.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(16, 20, 28, .5);
  opacity: 0;
  visibility: hidden;
  transition: opacity .22s var(--ease), visibility .22s;
}
.sheet-backdrop.is-open { opacity: 1; visibility: visible; }

.sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 85;
  max-height: 82vh;
  overflow-y: auto;
  padding: .5rem 1rem calc(1.25rem + var(--safe-b));
  background: var(--surface);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  transform: translateY(100%);
  transition: transform .26s var(--ease);
  box-shadow: 0 -8px 30px rgba(16, 20, 28, .18);
}
.sheet.is-open { transform: translateY(0); }

.sheet__grip {
  width: 44px; height: 4px;
  margin: .5rem auto 1rem;
  border-radius: var(--r-pill);
  background: var(--ink-200);
}
.sheet__title {
  font-family: var(--font-display);
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-400);
  margin: 1rem 0 .5rem;
}
.sheet__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: .6rem;
}
.sheet__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .45rem;
  padding: .9rem .4rem;
  border-radius: var(--r-md);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  font-size: .74rem;
  font-weight: 600;
  color: var(--ink-700);
  text-align: center;
  transition: background .18s var(--ease), border-color .18s var(--ease), transform .18s var(--ease);
}
.sheet__link:hover {
  background: var(--brand-50);
  border-color: var(--brand-100);
  color: var(--brand-700);
  transform: translateY(-2px);
}
.sheet__link svg { width: 22px; height: 22px; color: var(--brand-600); }


/* Sign out is a POST button now (a GET link let any page sign the admin
   out), so it has to be dressed as the sidebar link it replaced. */
.sidebar__link--button {
  width: 100%;
  border: 0;
  background: none;
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
}
.sheet__grid > form { display: contents; }
.sheet__link[type="submit"] {
  border: 1px solid var(--line-soft);
  font-family: var(--font-body);
  cursor: pointer;
  width: 100%;
}

/* ---------------------------------------------------------------------
   4. Cards & stat tiles
   --------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
}
.card + .card { margin-top: .9rem; }

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .85rem 1rem;
  border-bottom: 1px solid var(--line-soft);
}
.card__head h2, .card__head h3 { margin: 0; font-size: .98rem; }
.card__body { padding: 1rem; }
.card__foot {
  padding: .75rem 1rem;
  border-top: 1px solid var(--line-soft);
  background: var(--surface-2);
}

/* Section label */
.section-label {
  font-family: var(--font-display);
  font-size: .74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--ink-400);
  margin: 1.1rem 0 .45rem;
}
.section-label:first-child { margin-top: 0; }

/* A "View all" / "CSV" link sitting beside a section heading must not
   inherit the heading's uppercase tracking. */
.section-label a,
.section-label__link {
  font-size: .78rem;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: var(--brand-600);
}
.section-label a:hover { color: var(--brand-700); }

/* Small print inside a card or row - replaces one-off font-size overrides. */
.text-sm { font-size: .82rem; }
.text-xs { font-size: .74rem; }
.fw-500  { font-weight: 500; }
.maxw-sm { max-width: 520px; }

/* --- Stat tiles --- */
.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: .7rem;
}
.stats--3 { grid-template-columns: repeat(2, 1fr); }
/* Two tiles side by side at every width - two classes, so it outranks the
   wider .stats grids set for tablet and desktop further down. */
.stats.stats--2 { grid-template-columns: repeat(2, 1fr); }

.stat {
  position: relative;
  padding: .9rem .95rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
  animation: rise .4s var(--ease) both;
}
.stat::after {
  content: '';
  position: absolute;
  inset: auto auto -28px -28px;
  width: 78px; height: 78px;
  border-radius: 50%;
  background: var(--brand-50);
  opacity: .7;
}
.stat > * { position: relative; z-index: 1; }

.stat__label {
  display: flex;
  align-items: center;
  gap: .35rem;
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-400);
  margin-bottom: .3rem;
}
.stat__label svg { width: 14px; height: 14px; }

.stat__value {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.02em;
  color: var(--ink-900);
  word-break: break-word;
}
.stat__meta {
  font-size: .74rem;
  color: var(--ink-500);
  margin-top: .2rem;
}

.stat--success .stat__value { color: var(--success); }
.stat--success::after { background: var(--success-bg); }
.stat--danger .stat__value { color: var(--danger); }
.stat--danger::after { background: var(--danger-bg); }
.stat--brand .stat__value { color: var(--brand-600); }
.stat--info .stat__value { color: var(--info); }
.stat--info::after { background: var(--info-bg); }
.stat--warning .stat__value { color: var(--warning); }
.stat--warning::after { background: var(--warning-bg); }

/* A stat tile can also be a link. */
a.stat {
  color: inherit;
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
a.stat:hover {
  color: inherit;
  transform: translateY(-2px);
  border-color: var(--brand-300);
  box-shadow: var(--sh-2);
}

/* stagger */
.stat:nth-child(1) { animation-delay: .02s; }
.stat:nth-child(2) { animation-delay: .07s; }
.stat:nth-child(3) { animation-delay: .12s; }
.stat:nth-child(4) { animation-delay: .17s; }
.stat:nth-child(5) { animation-delay: .22s; }
.stat:nth-child(6) { animation-delay: .27s; }

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* --- Quick action grid --- */
.quick {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .55rem;
}
.quick__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .45rem;
  padding: .85rem .3rem;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: .7rem;
  font-weight: 600;
  color: var(--ink-700);
  text-align: center;
  line-height: 1.25;
  transition: transform .18s var(--ease), border-color .18s var(--ease);
}
.quick__item:hover { transform: translateY(-3px); border-color: var(--brand-300); color: var(--brand-700); }
.quick__icon {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  background: var(--brand-50);
  color: var(--brand-600);
}
.quick__icon svg { width: 20px; height: 20px; }

/* Stock actions, told apart by colour.
   Birds coming in and a count that puts the book right are green; birds lost
   and the record of past losses are red. On the Stock page these four sit in
   a row and the owner is often in a hurry - the colour should say which way
   the birds are going before the words are read.
   The fill is deep enough to read as a button rather than a tinted card, and
   the icon sits on the full colour so it carries at arm's length. The label
   stays near-black: on these fills that is better than 8:1, where the text
   colour matching the tile would have been barely half that. */
.quick__item--add {
  background: #BFE6D2;
  border-color: #8FCFB3;
}
.quick__item--add:hover { background: #ACDFC5; border-color: var(--success); }
.quick__item--add .quick__icon { background: var(--success); color: #fff; }

.quick__item--loss {
  background: #F5C4C4;
  border-color: #E6A0A0;
}
.quick__item--loss:hover { background: #F1B2B2; border-color: var(--danger); }
.quick__item--loss .quick__icon { background: var(--danger); color: #fff; }

/* The third kind: a tile that only takes you somewhere to look, rather than
   opening a form. Blue keeps it out of the green/red argument entirely, so
   the eye can skip it when the job is to enter something. */
.quick__item--look {
  background: #C7D9FB;
  border-color: #9DBBF7;
}
.quick__item--look:hover { background: #B4CCF9; border-color: var(--info); }
.quick__item--look .quick__icon { background: var(--info); color: #fff; }

/* ---------------------------------------------------------------------
   5. Data lists  (cards on mobile, table on desktop)
   --------------------------------------------------------------------- */
.list { display: flex; flex-direction: column; gap: .6rem; }

.row-card {
  display: block;
  padding: .85rem .95rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-1);
  color: inherit;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.row-card:hover { border-color: var(--brand-300); box-shadow: var(--sh-2); color: inherit; }

.row-card__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: .35rem;
}
.row-card__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .98rem;
  color: var(--ink-900);
  line-height: 1.3;
}
.row-card__amount {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  white-space: nowrap;
  color: var(--ink-900);
}
.row-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem .8rem;
  font-size: .78rem;
  color: var(--ink-500);
}
.row-card__meta span { display: inline-flex; align-items: center; gap: .25rem; }

/* Responsive table */
.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--r-lg);
}
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: .88rem;
  background: var(--surface);
  min-width: 600px;
}
table.data th {
  position: sticky;
  top: 0;
  padding: .7rem .8rem;
  text-align: left;
  font-family: var(--font-display);
  font-size: .74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-500);
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.data td {
  padding: .7rem .8rem;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: middle;
}
table.data tbody tr:hover { background: var(--brand-50); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.data tfoot td {
  padding: .75rem .8rem;
  font-weight: 700;
  background: var(--surface-2);
  border-top: 2px solid var(--line);
}

/* ---------------------------------------------------------------------
   6. Badges, chips, pills
   --------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  padding: .18rem .55rem;
  border-radius: var(--r-pill);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .01em;
  white-space: nowrap;
}
.badge--success { background: var(--success-bg); color: var(--success); }
.badge--danger  { background: var(--danger-bg);  color: var(--danger); }
.badge--warning { background: var(--warning-bg); color: var(--warning); }
.badge--info    { background: var(--info-bg);    color: var(--info); }
.badge--muted   { background: var(--line-soft);  color: var(--ink-500); }
.badge--brand   { background: var(--brand-50);   color: var(--brand-700); }

.text-success { color: var(--success) !important; }
.text-info    { color: var(--info) !important; }
.text-danger  { color: var(--danger)  !important; }
.text-warning { color: var(--warning) !important; }
.text-muted   { color: var(--ink-500) !important; }
.text-right   { text-align: right; }
.text-center  { text-align: center; }
.nowrap       { white-space: nowrap; }
.tabular      { font-variant-numeric: tabular-nums; }

/* Segmented control - one track, the selected segment lifts out of it.
   Reads as an app toggle rather than a row of loose web buttons. */
.chips {
  display: inline-flex;
  gap: 2px;
  max-width: 100%;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
  vertical-align: middle;
}
.chips::-webkit-scrollbar { display: none; }

.chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  min-height: 34px;
  padding: .3rem .9rem;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  font-family: var(--font-body);
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink-500);
  white-space: nowrap;
  cursor: pointer;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.chip:hover { background: rgba(16, 20, 28, .05); color: var(--ink-800); }
.chip.is-active {
  background: var(--ink-900);
  color: #fff;
  box-shadow: 0 1px 3px rgba(16, 20, 28, .2);
}
.chip.is-active:hover { background: var(--ink-800); color: #fff; }

/* ---------------------------------------------------------------------
   7. Forms - big touch targets, numeric keypads
   --------------------------------------------------------------------- */
.form-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: .9rem;
}

.field { display: flex; flex-direction: column; gap: .35rem; }
.field--span2 { grid-column: 1 / -1; }

.field label,
.label {
  font-size: .8rem;
  font-weight: 600;
  color: var(--ink-600);
  letter-spacing: .01em;
}
.field label .req { color: var(--danger); }

.input,
input[type="text"],
input[type="number"],
input[type="date"],
input[type="tel"],
input[type="email"],
input[type="password"],
input[type="search"],
select,
textarea {
  width: 100%;
  min-height: 48px;
  padding: .7rem .85rem;
  font-family: var(--font-body);
  font-size: 16px; /* 16px stops iOS zoom-on-focus */
  color: var(--ink-900);
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
  appearance: none;
  -webkit-appearance: none;
}
textarea { min-height: 90px; resize: vertical; line-height: 1.5; }

.input:focus,
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(232, 135, 30, .16);
}

input:disabled, select:disabled, textarea:disabled,
.input[readonly], input[readonly] {
  background: var(--surface-2);
  color: var(--ink-500);
  cursor: not-allowed;
}

select {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235B6472' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .7rem center;
  background-size: 18px;
  padding-right: 2.4rem;
}

.field__hint { font-size: .74rem; color: var(--ink-400); }
.field__error { font-size: .78rem; color: var(--danger); font-weight: 600; }
.field.has-error .input,
.field.has-error input,
.field.has-error select { border-color: var(--danger); }

/* ---------------------------------------------------------------------
   Filter bars
   Every filter form is method="get"; every entry form is method="post".
   That one distinction lets the filters be dense everywhere at once, so the
   records below them stay on the first screen instead of being pushed off it.
   --------------------------------------------------------------------- */
form[method="get"].form-grid {
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: .5rem .6rem;
  align-items: end;
}

form[method="get"].form-grid .field { gap: .2rem; }

form[method="get"].form-grid .field > label,
form[method="get"].form-grid .label {
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-400);
}

form[method="get"].form-grid input,
form[method="get"].form-grid select,
form[method="get"].form-grid .input {
  min-height: 40px;
  padding: .4rem .6rem;
  border-width: 1px;
  border-radius: var(--r-sm);
}
form[method="get"].form-grid .searchbar input { padding-left: 2.2rem; }
form[method="get"].form-grid .searchbar svg { left: .65rem; width: 16px; height: 16px; }
form[method="get"].form-grid select { background-position: right .5rem center; padding-right: 2rem; }

/* Hints belong on entry forms, not on a filter the admin uses every day. */
form[method="get"].form-grid .field__hint { display: none; }

/* --- App-style controls -------------------------------------------
   Filled, borderless fields on a soft ground, pill buttons - the shape
   language of a phone app rather than a web form. */
form[method="get"].form-grid input,
form[method="get"].form-grid select {
  background-color: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
}
form[method="get"].form-grid input:hover,
form[method="get"].form-grid select:hover { border-color: var(--ink-200); }
form[method="get"].form-grid input:focus,
form[method="get"].form-grid select:focus {
  background-color: var(--surface);
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(232, 135, 30, .14);
}

/* Search reads as a search: pill, icon inside, soft ground. */
form[method="get"].form-grid .searchbar input {
  border-radius: var(--r-pill);
  padding-left: 2.4rem;
  background-color: var(--surface-2);
}
form[method="get"].form-grid .searchbar svg { left: .85rem; }

/* Buttons sit at their natural width on one line, not stretched thirds. */
form[method="get"].form-grid .btn-row {
  grid-column: 1 / -1;
  gap: .4rem;
  margin-top: .15rem;
}
form[method="get"].form-grid .btn-row .btn {
  flex: 0 0 auto;
  min-height: 40px;
  padding: .45rem 1.05rem;
  font-size: .86rem;
  border-radius: var(--r-pill);
}

/* A secondary filter button is a soft filled pill, not an outlined box. */
form[method="get"].form-grid .btn-row .btn--ghost {
  background: var(--surface-2);
  border-color: transparent;
  color: var(--ink-600);
}
form[method="get"].form-grid .btn-row .btn--ghost:hover {
  background: var(--line-soft);
  color: var(--ink-900);
}

/* The export link is tinted like the spreadsheet it produces, wherever it
   appears - no page markup needed to single it out. */
.btn[href*="export=csv"] {
  background: var(--success-bg) !important;
  border-color: transparent !important;
  color: var(--success) !important;
}
.btn[href*="export=csv"]:hover {
  background: #D5EFE3 !important;
  color: #0E6E4A !important;
}

/* Phone: the primary action takes the full width, the way an app does. */
@media (max-width: 599px) {
  form[method="get"].form-grid .btn-row .btn {
    flex: 1 1 auto;
    min-height: 44px;
  }
  form[method="get"].form-grid .btn-row .btn--primary { flex: 1 1 100%; }
}

/* --- Toolbar layout, built by main.js -------------------------------
   One slim bar: status toggle left, search / Filters / export right.
   Everything else waits inside the panel until it is asked for. */
form[method="get"].form-grid { display: block; }

.filterbar {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}
.filterbar__left  { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.filterbar__right {
  display: flex;
  align-items: center;
  gap: .45rem;
  margin-left: auto;
  min-width: 0;
  flex: 1 1 260px;
  justify-content: flex-end;
}

.filterbar__search { flex: 1 1 auto; max-width: 340px; min-width: 150px; }
.filterbar__search .searchbar input { min-height: 40px; }

.filterbar__toggle,
.filterbar__export { flex: 0 0 auto; white-space: nowrap; }

.filterbar__toggle.is-on { color: var(--brand-700); }
.filterbar__toggle.is-open { background: var(--line-soft); }

.filterbar__count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  margin-left: .1rem;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--brand-500);
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  line-height: 1;
}
/* `display` on the class beats the browser's [hidden] rule, so restate it -
   without this the badge shows as an empty dot when no filter is active. */
.filterbar__count[hidden] { display: none; }

/* The panel that opens under the bar.
   Flex, not grid: grid columns stretch to fill the row, which left no room
   for the buttons and pushed them onto a line of their own. With capped
   field widths the buttons simply follow the last field. */
.filterpanel {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: .7rem .7rem;
  margin-top: .8rem;
  padding-top: .8rem;
  border-top: 1px solid var(--line-soft);
}
.filterpanel[hidden] { display: none; }

.filterpanel > .field {
  flex: 0 1 185px;
  min-width: 145px;
}

/* Apply and Reset sit right after the last field, on the same line. */
.filterpanel .btn-row {
  flex: 0 0 auto;
  align-self: flex-end;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: .4rem;
  margin: 0;
}
.filterpanel .btn-row .btn { flex: 0 0 auto; }

/* On a phone the bar stacks: toggle row first, then search full width,
   and the panel's buttons go full width the way an app's do. */
@media (max-width: 599px) {
  .filterbar__right { flex: 1 1 100%; justify-content: flex-start; }
  .filterbar__search { max-width: none; }
  .filterpanel > .field { flex: 1 1 145px; }
  .filterpanel .btn-row {
    flex: 1 1 100%;
    flex-wrap: wrap;
  }
  .filterpanel .btn-row .btn { flex: 1 1 auto; }

/* Inside a table row the buttons must stay on ONE line. The default row lets
   them grow and wrap, which in a narrow Actions cell stacks Edit under Bill
   and makes every row three times as tall. The table already scrolls
   sideways when it needs to, so widening the cell is the right answer. */

table.data td .btn-row { flex-wrap: nowrap; gap: .4rem; }
table.data td .btn-row .btn { flex: 0 0 auto; white-space: nowrap; }
table.data td .btn-row form { flex: 0 0 auto; }
  .filterpanel .btn-row .btn--primary { flex: 1 1 100%; }
}

@media (min-width: 1024px) {
  .card:has(> .card__body > form[method="get"]) > .card__body { padding: .8rem .9rem; }

  /* Hiding the "FILTER" heading also removed the breathing room it gave,
     so the bar has to carry that gap itself. */
  .card:has(> .card__body > form[method="get"]) {
    margin-top: 1.1rem;
    margin-bottom: .85rem;
  }

  /* A heading over an obvious toolbar is a wasted band.
     Browsers without :has simply keep the heading - no harm done. */
  .section-label:has(+ .card > .card__body > form[method="get"]) { display: none; }
}

/* A filter card carries less padding than a content card. */
.card:has(> .card__body > form[method="get"]) > .card__body { padding: .8rem .85rem; }

@media (min-width: 600px) {
  form[method="get"].form-grid input,
  form[method="get"].form-grid select { font-size: 14px; }
}

/* ---------------------------------------------------------------------
   Entry forms - compact on anything bigger than a phone
   A voucher has a lot of fields. On a mouse-driven screen they are tightened
   so the whole form is visible at once; the phone keeps its full-size
   touch targets, where scrolling is natural and mis-taps are not.
   --------------------------------------------------------------------- */
@media (min-width: 600px) {
  form[method="post"].form-grid { gap: .55rem .7rem; }

  form[method="post"] .field { gap: .18rem; }
  form[method="post"] .field > label,
  form[method="post"] .label { font-size: .76rem; }

  form[method="post"] input[type="text"],
  form[method="post"] input[type="number"],
  form[method="post"] input[type="date"],
  form[method="post"] input[type="tel"],
  form[method="post"] input[type="password"],
  form[method="post"] select {
    min-height: 40px;
    padding: .4rem .7rem;
    font-size: 14px;
  }
  form[method="post"] textarea { min-height: 58px; font-size: 14px; padding: .45rem .7rem; }
  form[method="post"] .field__hint { font-size: .7rem; line-height: 1.35; }
  form[method="post"] .input-affix__unit { font-size: .76rem; }

  .calc-box { padding: .45rem .7rem; font-size: .78rem; }
  .calc-box strong { font-size: .95rem; }

  form[method="post"] .form-actions { margin-top: .8rem; }
}

/* The lightbox is ~940px wide, below the 1024px breakpoint, so it would
   otherwise get only two columns. Three fit comfortably. */
@media (min-width: 760px) {
  body.is-modal .form-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  body.is-modal .page--modal { padding: .9rem 1rem 1.2rem; }
  body.is-modal .card__body { padding: .8rem .9rem; }

  /* An entry form in the lightbox is worked through in one sitting, so the
     whole of it wants to be in view at once. Everything here only tightens
     spacing - no figure, label or control is taken away. */
  body.is-modal .form-grid { gap: .65rem; }
  body.is-modal .field { gap: .2rem; }
  body.is-modal .section-label { margin: .7rem 0 .3rem; }
  body.is-modal .bill__row { padding: .3rem .55rem; }
  body.is-modal .bill__row--head { padding-top: .3rem; padding-bottom: .3rem; }
  body.is-modal .bill__linefoot { padding: .35rem .6rem; }
  body.is-modal .alert { padding: .5rem .7rem; font-size: .78rem; }
  body.is-modal .field__hint { font-size: .72rem; }
  body.is-modal input,
  body.is-modal select { padding-top: .38rem; padding-bottom: .38rem; }
}

/* Computed / read-only result box */
.calc-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .7rem .85rem;
  background: var(--brand-50);
  border: 1.5px dashed var(--brand-300);
  border-radius: var(--r-md);
  font-size: .88rem;
  font-weight: 600;
  color: var(--brand-700);
}
.calc-box strong {
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------
   Calculated summary strip
   Several running totals on one band, at the end of the section they belong
   to, rather than a full-width box per figure interrupting the fields.
   --------------------------------------------------------------------- */
.calc-strip {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .5rem;
  padding: .5rem .8rem;
  background: var(--brand-50);
  border: 1px dashed var(--brand-300);
  border-radius: var(--r-md);
}
.calc-strip--half { grid-column: span 2; }

.calc-strip__item {
  flex: 1 1 130px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .6rem;
  min-width: 0;
}
.calc-strip__item + .calc-strip__item {
  padding-left: .8rem;
  border-left: 1px solid var(--brand-100);
}
.calc-strip__label {
  font-size: .76rem;
  font-weight: 600;
  color: var(--brand-700);
  white-space: nowrap;
}
.calc-strip__value {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  color: var(--brand-700);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The figure the operator acts on - the balance owed. */
.calc-strip--result {
  background: var(--surface-2);
  border-style: solid;
  border-color: var(--line);
}
.calc-strip--result .calc-strip__label { color: var(--ink-600); }
.calc-strip--result .calc-strip__value { font-size: 1.2rem; color: var(--ink-900); }

@media (max-width: 599px) {
  .calc-strip--half { grid-column: 1 / -1; }
  .calc-strip__item + .calc-strip__item { border-left: 0; padding-left: 0; }
}

/* =====================================================================
   Bill layout
   An entry screen shaped like the document it produces: who it is for at
   the top, one priced line, then the money ladder on the right. It reads
   the way the owner's own sale register reads.
   ===================================================================== */
.bill { display: block; }

/* --- Who and when --- */
.bill__head {
  display: grid;
  grid-template-columns: 1fr;
  gap: .7rem;
  padding-bottom: .9rem;
  margin-bottom: .9rem;
  border-bottom: 2px solid var(--ink-900);
}
.bill__party > label,
.bill__meta label {
  display: block;
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-400);
  margin-bottom: .2rem;
}
.bill__meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem; }

@media (min-width: 720px) {
  .bill__head { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); align-items: start; gap: 1.2rem; }
}

/* --- The priced line --- */
.bill__lines {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}

.bill__row {
  display: grid;
  grid-template-columns: .8fr 1.1fr 1fr 1.2fr;
  gap: .5rem;
  align-items: center;
  padding: .55rem .7rem;
}
.bill__row--head {
  background: var(--ink-900);
  color: #fff;
  font-size: .72rem;
  font-weight: 600;
  /* Left in normal case on purpose. Set in capitals with letter-spacing,
     "WEIGHT OF ONE BIRD (KG)" was wide enough to push the last two headings
     onto a second line inside the modal, which made the black bar read as two
     broken rows instead of one header. */
  letter-spacing: .01em;
  line-height: 1.25;
  padding-top: .4rem;
  padding-bottom: .4rem;
}
.bill__row--head .num { text-align: right; }

/* A size line used to be four cells; with a price per bird and a line total it
   is six, and on the four-column grid above each line wrapped onto two rows.
   The wide variant lays all six out in one line on a desktop; the phone keeps
   the stacked layout, where wrapping is what you want anyway.
   It MUST stay below .bill__row: both are a single class, so they carry the
   same weight and the one written later wins. Placed earlier in the file, this
   whole block was silently overridden and the six columns never took effect.
   Starts at 820px, not 900px, because the desktop lightbox is narrower than
   the window it sits in. The typed cells give way first; the two read-only
   figures and the Clear button take only what they need. */
@media (min-width: 820px) {
  .bill__row--wide {
    grid-template-columns: .7fr 1fr 1fr minmax(0, .8fr) minmax(0, .9fr) auto;
    gap: .4rem;
    padding: .4rem .6rem;
  }
  .bill__row--wide > * { min-width: 0; }
  .bill__row--wide input,
  .bill__row--wide .input-affix { width: 100%; min-width: 0; }
  .bill__row--wide .btn { padding-left: .6rem; padding-right: .6rem; }
}

.bill__cell { min-width: 0; }
.bill__cell.has-error input { border-color: var(--danger); }

.bill__amount {
  font-family: var(--font-display);
  /* 12px. These two cells are not typed into - they only confirm what the
     line comes to - so they support the row rather than compete with the
     boxes the operator is actually filling in. At 1.05rem they were the
     loudest thing on the screen and forced the row wider than it needed. */
  font-size: .75rem;
  font-weight: 700;
  color: var(--ink-900);
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Live "that average looks wrong" note under the line. */
.bill__sanity {
  display: flex;
  align-items: flex-start;
  gap: .35rem;
  padding: .45rem .7rem;
  background: var(--warning-bg);
  border-top: 1px solid rgba(201, 122, 12, .25);
  font-size: .78rem;
  font-weight: 600;
  color: var(--warning);
}

.bill__rowerror {
  display: flex;
  align-items: center;
  gap: .3rem;
  padding: 0 .7rem .4rem;
  font-size: .76rem;
  font-weight: 600;
  color: var(--danger);
}

.bill__linefoot {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 1.2rem;
  padding: .5rem .7rem;
  background: var(--brand-50);
  border-top: 1px dashed var(--brand-300);
  font-size: .8rem;
  color: var(--brand-700);
}
.bill__linefoot strong {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
}

.bill__lines .optional-group {
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
}

/* --- Money ladder --- */
.bill__foot {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin-top: 1rem;
}
@media (min-width: 720px) {
  .bill__foot { grid-template-columns: minmax(0, 1fr) minmax(320px, 380px); }
}

.bill__side { display: grid; gap: .6rem; align-content: start; }

.bill__totals {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}

.bill__trow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .45rem .8rem;
  border-bottom: 1px solid var(--line-soft);
}
.bill__trow:last-child { border-bottom: 0; }

.bill__tlabel {
  font-size: .84rem;
  font-weight: 600;
  color: var(--ink-600);
  margin: 0;
  white-space: nowrap;
}
.bill__tvalue {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* An editable line in the ladder: label left, the box right. Wide enough
   for a lakh-plus figure - a clipped amount is a misread amount. */
.bill__trow--input input,
.bill__trow--input select {
  width: 185px;
  min-height: 36px;
  padding: .3rem .6rem;
  font-size: 14px;
  text-align: right;
}
.bill__trow--input select { text-align: left; }
.bill__trow--input .input-affix { width: 185px; }
.bill__trow--input .input-affix input { width: 100%; }
.bill__trow--input.has-error input { border-color: var(--danger); }

.bill__trow--net {
  background: var(--surface-2);
  border-top: 1px solid var(--line);
}
.bill__trow--net .bill__tvalue { font-size: 1.1rem; }

.bill__trow--due {
  background: var(--ink-900);
  padding-top: .6rem;
  padding-bottom: .6rem;
}
.bill__trow--due .bill__tlabel { color: #fff; }
.bill__trow--due .bill__tvalue { color: var(--brand-300); font-size: 1.25rem; }

@media (max-width: 599px) {
  .bill__row { grid-template-columns: 1fr 1fr; }
  .bill__row--head { display: none; }
  .bill__amount { grid-column: 1 / -1; text-align: left; }
  .bill__trow--input input,
  .bill__trow--input select,
  .bill__trow--input .input-affix { width: 130px; }
}

/* ---------------------------------------------------------------------
   Optional field group
   Fields most entries never need, folded away so the common case stays
   short. Opens by itself when it holds a value or an error.
   --------------------------------------------------------------------- */
.optional-group {
  grid-column: 1 / -1;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.optional-group > summary {
  padding: .5rem .8rem;
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink-600);
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .4rem;
}
.optional-group > summary::-webkit-details-marker { display: none; }
.optional-group > summary::before {
  content: '';
  width: 7px;
  height: 7px;
  border-right: 2px solid var(--ink-400);
  border-bottom: 2px solid var(--ink-400);
  transform: rotate(-45deg);
  transition: transform .18s var(--ease);
}
.optional-group[open] > summary::before { transform: rotate(45deg); }
.optional-group > summary:hover { color: var(--ink-900); }

.optional-group__body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: .6rem .7rem;
  padding: 0 .8rem .8rem;
}

/* Input with a unit suffix */
.input-affix { position: relative; }
.input-affix input { padding-right: 3rem; }
.input-affix__unit {
  position: absolute;
  right: .85rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink-400);
  pointer-events: none;
}

/* A small action living inside the field, e.g. "Full" on an amount box -
   it belongs to that input, so it should not float below it as a button. */
.input-affix__action {
  position: absolute;
  right: .25rem;
  top: 50%;
  transform: translateY(-50%);
  min-height: 26px;
  padding: 0 .5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  font-family: var(--font-body);
  font-size: .74rem;
  font-weight: 700;
  color: var(--ink-600);
  cursor: pointer;
  transition: background .16s var(--ease), color .16s var(--ease), border-color .16s var(--ease);
}
.input-affix__action:hover {
  background: var(--brand-50);
  border-color: var(--brand-300);
  color: var(--brand-700);
}
/* Keep the typed figure clear of the button. */
.input-affix:has(> .input-affix__action) input { padding-right: 4.4rem; }

/* Search bar */
.searchbar { position: relative; }
.searchbar input { padding-left: 2.6rem; }
.searchbar svg {
  position: absolute;
  left: .85rem; top: 50%;
  transform: translateY(-50%);
  width: 18px; height: 18px;
  color: var(--ink-400);
  pointer-events: none;
}

/* Checkbox / radio */
.check {
  display: flex;
  align-items: center;
  gap: .6rem;
  min-height: 44px;
  font-size: .9rem;
  cursor: pointer;
}
.check input { width: 20px; height: 20px; min-height: 0; accent-color: var(--brand-500); }

/* ---------------------------------------------------------------------
   8. Buttons
   --------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  min-height: 48px;
  padding: .65rem 1.15rem;
  border: 1.5px solid transparent;
  border-radius: var(--r-md);
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  text-align: center;
  transition: transform .15s var(--ease), background .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.btn svg { width: 18px; height: 18px; }
.btn:active { transform: scale(.985); }
.btn:disabled, .btn.is-loading { opacity: .6; pointer-events: none; }

/* --- Day Book: the notebook list --- */
.dbk-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: .3rem;
  border-radius: 50%;
  vertical-align: middle;
}
.dbk-dot--in  { background: var(--success); }
.dbk-dot--out { background: var(--danger); }
.dbk-table th.dbk-in,  .dbk-table td.dbk-in  { background: var(--success-bg); }
.dbk-table th.dbk-out, .dbk-table td.dbk-out { background: var(--danger-bg); }
.dbk-table th.dbk-in  { color: var(--success); }
.dbk-table th.dbk-out { color: var(--danger); }
.dbk-table tr.dbk-open td { background: var(--warning-bg); }
.dbk-bal { font-size: 1rem; }
.dbk-was { margin-top: .15rem; font-size: .75rem; color: var(--ink-500); white-space: nowrap; }
.row-card.dbk-open { background: var(--warning-bg); }
.row-card.dbk-card--in  { border-left: 4px solid var(--success); }
.row-card.dbk-card--out { border-left: 4px solid var(--danger); }
.row-card .dbk-was { text-align: right; }

/* --- Day Book: end-of-day tally (main.js fills in the right-hand box) --- */
.tally { display: grid; gap: .9rem; }
.tally__col {
  padding: .9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
}
/* One boxed row: label left, amount right - the same in both columns. */
.tally__line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: .5rem;
  padding: .6rem .8rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 9px;
}
.tally__line--input {
  min-height: 48px;
  cursor: text;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.tally__line--input:focus-within {
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(232, 135, 30, .16);
}
.tally__entry { display: flex; align-items: center; gap: .3rem; font-weight: 700; }
/* Two classes so this outranks the app-wide input[type="number"] box. */
.tally__line .tally__input,
.tally__line .tally__input:focus {
  width: 7.5rem;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  text-align: right;
  font-weight: 700;
  -moz-appearance: textfield;
}
.tally__line .tally__input::-webkit-outer-spin-button,
.tally__line .tally__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.tally__tick { display: inline-flex; color: var(--success); visibility: hidden; }
.tally__line.is-filled .tally__tick { visibility: visible; }
.tally__total.tally__total--counted { color: var(--success); }
.tally__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: .2rem;
  border-radius: 50%;
  color: #fff;
  background: var(--ink-500);
}
.tally__icon-ok { display: none; }
.tally__result--ok .tally__icon      { background: var(--success); }
.tally__result--ok .tally__icon-ok   { display: inline-flex; }
.tally__result--ok .tally__icon-warn { display: none; }
.tally__result--short .tally__icon   { background: var(--danger); }
.tally__result--extra .tally__icon   { background: var(--warning); }
.tally__head {
  margin-bottom: .5rem;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-500);
}
.tally__row {
  display: flex;
  justify-content: space-between;
  gap: .75rem;
  padding: .5rem 0;
  border-bottom: 1px dashed var(--line);
}
.tally__total {
  border-bottom: 0;
  margin-top: .25rem;
  font-weight: 700;
  color: var(--brand-600);
}
.tally__col .field { margin-bottom: .6rem; }
.tally__result {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: .35rem;
  padding: 1.1rem 1rem;
  border: 2px solid var(--line);
  border-radius: 12px;
  text-align: center;
  transition: background .2s, border-color .2s;
}
.tally__title { font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; }
.tally__note  { font-size: .85rem; color: var(--ink-500); }
.tally__diff  { margin-top: .35rem; padding: .3rem .7rem; border-radius: 8px; background: #fff; font-size: .9rem; }
.tally__result--ok    { border-color: var(--success); background: var(--success-bg); }
.tally__result--ok .tally__title    { color: var(--success); }
.tally__result--short { border-color: var(--danger);  background: var(--danger-bg); }
.tally__result--short .tally__title { color: var(--danger); }
.tally__result--extra { border-color: var(--warning); background: var(--warning-bg); }
.tally__result--extra .tally__title { color: var(--warning); }
@media (min-width: 1024px) {
  .tally { grid-template-columns: 1fr 1fr 1fr; }
}

/* Saving loader - shown by main.js while a form is being sent, so nothing
   can be tapped twice. Above the lightbox and the confirm box. */
.busy {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: none;
  place-items: center;
  background: rgba(16, 20, 28, .35);
}
.busy.is-on { display: grid; }
.busy__box {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .9rem 1.25rem;
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 10px 30px rgba(16, 20, 28, .18);
  font-weight: 600;
  color: var(--ink-900);
}
.busy__spin {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 3px solid var(--brand-100);
  border-top-color: var(--brand-500);
  animation: busySpin .7s linear infinite;
}
@keyframes busySpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .busy__spin { animation-duration: 2s; } }

.btn--primary {
  background: linear-gradient(140deg, var(--brand-500), var(--brand-600));
  color: #fff;
  box-shadow: 0 2px 10px rgba(232, 135, 30, .28);
}
.btn--primary:hover { color: #fff; box-shadow: 0 5px 16px rgba(232, 135, 30, .36); }

.btn--dark { background: var(--ink-900); color: #fff; }
.btn--dark:hover { background: var(--ink-800); color: #fff; }

.btn--ghost {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink-700);
}
.btn--ghost:hover { border-color: var(--brand-300); color: var(--brand-700); }

.btn--danger { background: var(--danger); color: #fff; }
.btn--danger:hover { background: #B62E2E; color: #fff; }

/* Switching something off is NOT the same as deleting it: one is a decision
   you can take back tomorrow, the other is gone for good. Painting them the
   same red invites the wrong click.
   Amber was tried first and was still confused with red - side by side the two
   were the same darkness, so they read as "two red buttons". Slate is a muted
   grey with a fifth of red's saturation and nearly twice its distance in
   colour, so the pair cannot be mistaken for each other. Solid with white
   text, so it still reads as a live button rather than a disabled one. */
/* The show-password eye. Sits inside the field, 48px so a thumb can hit it,
   and the slash across the eye means "hidden" - it disappears once the
   password is on screen. */
.lg__pw { position: relative; }
.lg__pw input { width: 100%; padding-right: 3.2rem; }
.pw-eye {
  position: absolute;
  top: 50%;
  right: .35rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  border-radius: var(--r-md);
  color: var(--ink-500);
  cursor: pointer;
}
.pw-eye:hover { color: var(--brand-700); background: var(--surface-2); }
.pw-eye:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
.pw-eye svg { width: 20px; height: 20px; }
.lg__pw.is-shown .pw-eye { color: var(--brand-700); }
.lg__pw.is-shown .pw-eye__slash { display: none; }

.btn--off { background: #5B6472; border-color: #5B6472; color: #fff; }
.btn--off:hover { background: #454D59; border-color: #454D59; color: #fff; }

.btn--success { background: var(--success); color: #fff; }
.btn--success:hover { background: #0E6E4A; color: #fff; }

/* Sending a bill on WhatsApp. WhatsApp's own green, because the owner looks
   for the colour rather than reading the label. */
/* The "New ..." button in the top bar. Phones get the floating button
   instead, so this only shows once there is room for it. */
.appbar__new { display: none; white-space: nowrap; margin-left: auto; }
.appbar__new svg { width: 18px; height: 18px; }
@media (min-width: 900px) {
  .appbar__new { display: inline-flex; }
}

/* "Show details" - a ghost button that goes deeper into a record. Given a
   firmer border than a plain ghost so it reads as the row's main way in,
   without competing with the orange buttons that create something. */
.btn--detail { border-color: var(--ink-300, #9aa3b0); color: var(--ink-700, #3d4757); }
.btn--detail:hover { border-color: var(--ink-500, #6b7480); background: var(--surface-2, #f4f6f9); }
.btn--detail svg:last-child { margin-left: .1rem; opacity: .7; }

.btn--whatsapp { background: #25D366; color: #06301A; }
.btn--whatsapp:hover { background: #1EB755; color: #06301A; }
/* The paper copy has no button on it. */
@media print { .btn--whatsapp { display: none; } }

/* Two buttons found by colour before they are read: Edit is blue everywhere,
   PDF wears Adobe's red, which is what a PDF link already looks like to
   anybody. Filled, not outlined - a bar of colour is seen across the room,
   an outline has to be looked at.
   The red is picked, not guessed. It has to clear two bars at once: white
   text readable on it (4.67:1, above the 4.5 needed), and far enough from
   the Delete red #CF3636 not to be grabbed by mistake (deltaE 30.8, where
   anything under about 20 reads as the same colour). A deep #B30B00 failed
   the second bar at 17.9; Adobe's own #FA0F00 failed the first at 4.09.
   Same mistake as amber-versus-red on Deactivate, fixed once already. */
.btn--edit {
  background: #2563EB;
  border-color: #2563EB;
  color: #fff;
}
.btn--edit:hover { background: #1D4ED8; border-color: #1D4ED8; color: #fff; }

.btn--pdf {
  background: #EA0000;
  border-color: #EA0000;
  color: #fff;
}
.btn--pdf:hover { background: #C40000; border-color: #C40000; color: #fff; }

@media print { .btn--edit, .btn--pdf { display: none; } }

.btn--sm { min-height: 38px; padding: .4rem .8rem; font-size: .84rem; }
.btn--block { width: 100%; }
.btn--icon { width: 44px; padding: 0; flex: 0 0 44px; }

.btn-row {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
}
.btn-row .btn { flex: 1 1 auto; }

/* Sticky save bar on entry forms */
.form-actions {
  position: sticky;
  bottom: calc(var(--bottomnav-h) + var(--safe-b));
  z-index: 40;
  display: flex;
  gap: .6rem;
  margin: 1rem -0.9rem 0;
  padding: .75rem .9rem;
  background: #fff;   /* solid for the same reason as .bottomnav */
  border-top: 1px solid var(--line);
}
.form-actions .btn { flex: 1; }

/* ---------------------------------------------------------------------
   9. Alerts, empty states, toast
   --------------------------------------------------------------------- */
.alert {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .8rem .95rem;
  border-radius: var(--r-md);
  font-size: .88rem;
  font-weight: 500;
  margin-bottom: 1rem;
  border: 1px solid transparent;
}
.alert svg { width: 18px; height: 18px; flex: 0 0 18px; margin-top: 1px; }
.alert--success { background: var(--success-bg); color: var(--success); border-color: rgba(18,133,90,.2); }
.alert--danger  { background: var(--danger-bg);  color: var(--danger);  border-color: rgba(207,54,54,.2); }
.alert--warning { background: var(--warning-bg); color: var(--warning); border-color: rgba(201,122,12,.2); }
.alert--info    { background: var(--info-bg);    color: var(--info);    border-color: rgba(37,99,235,.2); }

.empty {
  padding: 2.5rem 1rem;
  text-align: center;
  color: var(--ink-400);
}
.empty svg { width: 46px; height: 46px; color: var(--ink-200); margin-bottom: .75rem; }
.empty h3 { color: var(--ink-600); font-size: 1rem; margin-bottom: .25rem; }
.empty p { font-size: .86rem; margin: 0; }

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--bottomnav-h) + var(--safe-b) + 82px);
  z-index: 95;
  transform: translate(-50%, 20px);
  max-width: min(92vw, 420px);
  padding: .75rem 1.1rem;
  border-radius: var(--r-pill);
  background: var(--ink-900);
  color: #fff;
  font-size: .88rem;
  font-weight: 500;
  box-shadow: var(--sh-3);
  opacity: 0;
  visibility: hidden;
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}
.toast.is-open { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.toast--danger  { background: var(--danger); }
.toast--success { background: var(--success); }

/* ---------------------------------------------------------------------
   10. Modal / confirm dialog
   --------------------------------------------------------------------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(16, 20, 28, .55);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--ease), visibility .2s;
}
.modal-backdrop.is-open { opacity: 1; visibility: visible; }

.modal {
  width: 100%;
  max-width: 400px;
  padding: 1.4rem 1.25rem 1.15rem;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-3);
  transform: translateY(14px) scale(.98);
  transition: transform .22s var(--ease);
}
.modal-backdrop.is-open .modal { transform: translateY(0) scale(1); }
.modal h3 { margin-bottom: .4rem; }
.modal p { font-size: .9rem; color: var(--ink-500); }
.modal__actions { display: flex; gap: .6rem; margin-top: 1.15rem; }
.modal__actions .btn { flex: 1; }
/* One full-width button per choice, stacked (sale form's store box). */
.modal__stack { display: grid; gap: .5rem; margin-top: .6rem; }
.modal__stack .btn { width: 100%; white-space: normal; }

/* ---------------------------------------------------------------------
   10b. Desktop lightbox - an entry form over the list it belongs to
   --------------------------------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 2.5vh 1rem;
  background: rgba(16, 20, 28, .55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--ease), visibility .2s;
}
.lightbox.is-open { opacity: 1; visibility: visible; }

.lightbox__panel {
  width: min(940px, 94vw);
  height: min(92vh, 940px);
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .35);
  overflow: hidden;
  transform: translateY(12px) scale(.99);
  transition: transform .22s var(--ease);
}
.lightbox.is-open .lightbox__panel { transform: translateY(0) scale(1); }

.lightbox__frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Phones never use the lightbox - a form deserves the whole screen there. */
@media (max-width: 1023px) {
  .lightbox { display: none !important; }
}

/* --- The page rendered inside the frame --- */
body.is-modal { background: var(--surface); }

.modalbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .85rem 1.15rem;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.modalbar__title {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--ink-900);
}
.modalbar__sub {
  display: block;
  font-family: var(--font-body);
  font-size: .76rem;
  font-weight: 500;
  color: var(--ink-500);
}
.modalbar__close {
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--ink-600);
  cursor: pointer;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.modalbar__close:hover { background: var(--line-soft); color: var(--ink-900); }

.page--modal {
  padding: 1.15rem 1.15rem 1.5rem;
  max-width: none;
}

/* The brief moment after a save, before the box closes itself. */
.modal-exit {
  display: grid;
  place-content: center;
  gap: .5rem;
  min-height: 60vh;
  padding: 2rem;
  text-align: center;
}
.modal-exit .alert { margin: 0; }

/* Inside the box the save bar is not sticky - the frame scrolls on its own. */
body.is-modal .form-actions {
  position: static;
  margin: 1.25rem 0 0;
  padding: 0;
  background: none;
  border: 0;
  backdrop-filter: none;
}
body.is-modal .form-actions .btn { flex: 0 0 auto; min-width: 150px; }

/* ---------------------------------------------------------------------
   11. Login screen
   --------------------------------------------------------------------- */
.auth {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 1.25rem;
  background:
    radial-gradient(1000px 520px at 12% -8%, rgba(232,135,30,.22), transparent 60%),
    radial-gradient(760px 460px at 105% 105%, rgba(232,135,30,.10), transparent 60%),
    var(--ink-900);
}
.auth__card {
  width: 100%;
  max-width: 400px;
  padding: 2rem 1.5rem 1.75rem;
  background: rgba(255, 255, 255, .96);
  border: 1px solid rgba(255, 255, 255, .5);
  border-radius: var(--r-xl);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
  animation: rise .45s var(--ease) both;
}
.auth__logo {
  width: 58px; height: 58px;
  margin: 0 auto .9rem;
  display: grid; place-items: center;
  border-radius: 16px;
  background: linear-gradient(140deg, var(--brand-500), var(--brand-700));
  box-shadow: var(--sh-fab);
  font-size: 1.7rem;
}
.auth__title {
  text-align: center;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  margin-bottom: .15rem;
}
.auth__sub {
  text-align: center;
  font-size: .85rem;
  color: var(--ink-500);
  margin-bottom: 1.5rem;
}
.auth__foot {
  margin-top: 1.4rem;
  text-align: center;
  font-size: .74rem;
  color: var(--ink-400);
}

/* Signature block at the foot of an invoice or voucher. */
.sign-row {
  display: flex;
  gap: 2rem;
  margin-top: 2.5rem;
}
.sign-col {
  flex: 1 1 0;
  text-align: center;
  padding-top: .5rem;
  border-top: 1px solid var(--ink-300);
  font-size: .82rem;
  color: var(--ink-600);
}

/* ---------------------------------------------------------------------
   12. Print - invoices and reports
   --------------------------------------------------------------------- */
@media print {
  .appbar, .bottomnav, .fab, .sidebar, .sheet, .sheet-backdrop,
  .form-actions, .no-print, .toast { display: none !important; }
  body { background: #fff; font-size: 12px; }
  .page { padding: 0; max-width: none; }
  .card { border: 0; box-shadow: none; }
  table.data { min-width: 0; font-size: 11px; }
  table.data th { background: #f0f0f0 !important; -webkit-print-color-adjust: exact; }
  a { color: #000; text-decoration: none; }
  .print-only { display: block !important; }

  /* A printed page is about 794px wide, which is BELOW the desktop
     breakpoint - so without this the phone cards would print and the
     table would not, on every list in the app. Paper wants the table. */
  .hide-desktop { display: none !important; }
  .hide-mobile  { display: block !important; }
}
.print-only { display: none; }

/* ---------------------------------------------------------------------
   13. Utilities
   --------------------------------------------------------------------- */
.mt-0 { margin-top: 0 !important; }
.mt-1 { margin-top: .5rem !important; }
.mt-2 { margin-top: 1rem !important; }
.mt-3 { margin-top: 1.5rem !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: .5rem !important; }
.mb-2 { margin-bottom: 1rem !important; }
.mb-3 { margin-bottom: 1.5rem !important; }
.flex { display: flex; }
.flex-between { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.flex-wrap { flex-wrap: wrap; }
.gap-1 { gap: .5rem; }
.gap-2 { gap: 1rem; }
.w-100 { width: 100%; }
.hide { display: none !important; }

/* Viewport-scoped visibility.
   A page can ship a card list for phones and a full table for desktop. */
.hide-desktop { display: block; }
.hide-mobile  { display: none; }
@media (min-width: 1024px) {
  .hide-desktop { display: none !important; }
  .hide-mobile  { display: block; }
}

/* Pagination bar - sits in a .card__foot or directly under a list. */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  flex-wrap: wrap;
  margin-top: .9rem;
  padding: .7rem .9rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.pager__info { font-size: .8rem; color: var(--ink-500); }
.pager__links { display: flex; gap: .35rem; flex-wrap: wrap; }
.pager__link {
  min-width: 38px;
  min-height: 38px;
  padding: 0 .6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: .84rem;
  font-weight: 600;
  color: var(--ink-600);
  transition: all .16s var(--ease);
}
.pager__link:hover { border-color: var(--brand-300); color: var(--brand-700); }
.pager__link.is-active {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: #fff;
}
.pager__link.is-disabled { opacity: .4; pointer-events: none; }

/* Key/value detail table - no 600px floor, so it stays compact on desktop. */
table.data--narrow { min-width: 0; }
table.data--narrow th {
  width: 45%;
  position: static;
  text-transform: none;
  letter-spacing: 0;
  font-size: .84rem;
  color: var(--ink-600);
  background: transparent;
  font-weight: 600;
}
table.data--narrow td { text-align: right; font-variant-numeric: tabular-nums; }

/* Generic column grids : stacked on phones, side by side on desktop. */
.cols-2, .cols-3 {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  align-items: start;
}
@media (min-width: 1024px) {
  .cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Share/progress bar for category breakdowns. */
.bar {
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--line-soft);
  overflow: hidden;
}
.bar__fill {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--brand-500), var(--brand-300));
}
.bar__fill--danger  { background: linear-gradient(90deg, var(--danger), #E88); }
.bar__fill--success { background: linear-gradient(90deg, var(--success), #6BC9A0); }

.divider {
  height: 1px;
  background: var(--line);
  margin: 1rem 0;
}

/* Skeleton loading */
.skeleton {
  background: linear-gradient(90deg, var(--line-soft) 25%, #F5F7FA 50%, var(--line-soft) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite;
  border-radius: var(--r-sm);
}
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* ---------------------------------------------------------------------
   14. Tablet  (>= 600px)
   --------------------------------------------------------------------- */
@media (min-width: 600px) {
  .page { padding-left: 1.35rem; padding-right: 1.35rem; }
  .stats { grid-template-columns: repeat(3, 1fr); }
  .stats--4 { grid-template-columns: repeat(4, 1fr); }
  .form-grid { grid-template-columns: repeat(2, 1fr); }
  .quick { grid-template-columns: repeat(6, 1fr); }
  .form-actions { margin-left: -1.35rem; margin-right: -1.35rem; padding-left: 1.35rem; padding-right: 1.35rem; }
}

/* ---------------------------------------------------------------------
   15. Desktop  (>= 1024px) - sidebar shell, no bottom nav
   --------------------------------------------------------------------- */
@media (min-width: 1024px) {
  .app { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

  .bottomnav, .fab, .sheet, .sheet-backdrop { display: none !important; }

  .sidebar {
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    padding: 1rem .75rem 1.5rem;
    background: var(--ink-900);
    color: #fff;
  }
  .sidebar__brand {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .5rem .5rem 1.25rem;
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
  }
  .sidebar__group {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--ink-400);
    padding: 1rem .75rem .4rem;
  }
  .sidebar__link {
    display: flex;
    align-items: center;
    gap: .7rem;
    padding: .62rem .75rem;
    margin-bottom: 2px;
    border-radius: var(--r-sm);
    font-size: .89rem;
    font-weight: 500;
    color: #C6CDD8;
    transition: background .16s var(--ease), color .16s var(--ease);
  }
  .sidebar__link svg { width: 18px; height: 18px; flex: 0 0 18px; }
  .sidebar__link:hover { background: rgba(255,255,255,.07); color: #fff; }
  .sidebar__link.is-active {
    background: linear-gradient(140deg, var(--brand-500), var(--brand-600));
    color: #fff;
    font-weight: 600;
    box-shadow: 0 3px 12px rgba(232,135,30,.32);
  }
  .sidebar__foot {
    margin-top: auto;
    padding: 1rem .75rem 0;
    border-top: 1px solid rgba(255,255,255,.1);
    font-size: .76rem;
    color: var(--ink-400);
  }

  .main { min-width: 0; }

  .appbar {
    background: var(--surface);
    color: var(--ink-900);
    border-bottom: 1px solid var(--line);
    box-shadow: none;
    height: 62px;
  }
  .appbar__title { color: var(--ink-900); font-size: 1.15rem; }
  .appbar__back, .appbar__action { background: var(--surface-2); color: var(--ink-700); }
  .appbar__back:hover, .appbar__action:hover { background: var(--line-soft); }
  .appbar__brand, .appbar__menu { display: none; }

  .page { padding: 1.5rem 1.75rem 3rem; }
  .stats { grid-template-columns: repeat(4, 1fr); }
  .stats--3 { grid-template-columns: repeat(3, 1fr); }
  .form-grid { grid-template-columns: repeat(3, 1fr); }
  .quick { grid-template-columns: repeat(8, 1fr); }

  .form-actions {
    position: static;
    margin: 1.25rem 0 0;
    padding: 0;
    background: none;
    border: 0;
    backdrop-filter: none;
  }
  .form-actions .btn { flex: 0 0 auto; min-width: 150px; }

  .toast { bottom: 24px; }
  table.data { min-width: 0; }
}

/* ---------------------------------------------------------------------
   16. Motion preferences
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* A search-only filter keeps its Apply and Reset on the bar itself. */
.filterbar__actions { flex: 0 0 auto; gap: .4rem; }
.filterbar__actions .btn { flex: 0 0 auto; }

/* =====================================================================
   17. Login screen v2 - "night shift" split
   Dark branded panel with the shop name as the hero, beside a bright
   high-contrast form panel. Scoped to .lg-* so nothing else is touched.
   ===================================================================== */
.lg-body {
  margin: 0;
  min-height: 100vh;
  background: var(--ink-900);
}

.lg {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* --- Brand panel --------------------------------------------------- */
.lg__brand {
  position: relative;
  overflow: hidden;
  padding: 2.1rem 1.35rem 2.3rem;
  padding-top: calc(2.1rem + env(safe-area-inset-top, 0px));
  color: #fff;
  background:
    radial-gradient(720px 380px at 8% -10%, rgba(232, 135, 30, .34), transparent 62%),
    radial-gradient(520px 320px at 108% 118%, rgba(232, 135, 30, .16), transparent 60%),
    linear-gradient(165deg, #141A25 0%, var(--ink-900) 58%, #0B0E14 100%);
}

/* Faint diagonal weave - the only decoration, pure CSS, no images. */
.lg__grain {
  position: absolute;
  inset: -20%;
  pointer-events: none;
  opacity: .35;
  background-image: repeating-linear-gradient(
    118deg,
    rgba(255, 255, 255, .045) 0 1px,
    transparent 1px 13px
  );
}

.lg__brandIn { position: relative; max-width: 460px; }

.lg__mark {
  width: 54px; height: 54px;
  display: grid; place-items: center;
  border-radius: 16px;
  color: #fff;
  background: linear-gradient(140deg, var(--brand-500), var(--brand-700));
  box-shadow: 0 10px 26px rgba(232, 135, 30, .38);
}

.lg__eyebrow {
  margin: 1.1rem 0 .35rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--brand-300);
}

.lg__name {
  font-family: var(--font-display);
  margin: 0;
  color: #fff;
  line-height: .92;
  letter-spacing: -.045em;
  text-transform: uppercase;
}
.lg__name-1,
.lg__name-2 { display: block; }
.lg__name-1 {
  font-size: clamp(2.5rem, 13vw, 3.6rem);
  font-weight: 800;
}
/* Second word is drawn as an outline so the two lines read as one lockup. */
.lg__name-2 {
  font-size: clamp(2.5rem, 13vw, 3.6rem);
  font-weight: 800;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--brand-300);
  text-shadow: 0 0 22px rgba(232, 135, 30, .22);
}
/* Browsers without text-stroke still get readable amber text. */
@supports not (-webkit-text-stroke: 1px #000) {
  .lg__name-2 { color: var(--brand-300); }
}

.lg__tag {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: .95rem 0 0;
  font-size: .84rem;
  letter-spacing: .04em;
  color: var(--ink-200);
}
.lg__rule {
  flex: 0 0 34px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brand-500), rgba(232, 135, 30, 0));
}

.lg__points {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: none;
}
.lg__points li {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .5rem 0;
  font-size: .88rem;
  color: var(--ink-200);
}
.lg__points svg {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  color: var(--brand-300);
}

/* --- Form panel ---------------------------------------------------- */
.lg__panel {
  flex: 1 1 auto;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 1.6rem 1.15rem calc(2rem + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  margin-top: -18px;
  position: relative;
  z-index: 1;
  box-shadow: 0 -14px 40px rgba(0, 0, 0, .35);
}
.lg__form { width: 100%; max-width: 400px; }

.lg__kicker {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .55rem;
  padding: .28rem .6rem;
  border-radius: var(--r-pill);
  background: var(--brand-50);
  color: var(--brand-700);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.lg__kicker svg { width: 14px; height: 14px; }

.lg__head {
  font-family: var(--font-display);
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -.025em;
  margin: 0 0 .2rem;
  color: var(--ink-900);
}
.lg__sub {
  margin: 0 0 1.15rem;
  font-size: .9rem;
  color: var(--ink-500);
}

.lg__fields { display: block; }
.lg__field { margin-bottom: .95rem; }
.lg__field label {
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-500);
}
.lg__field input {
  min-height: 52px;
  font-size: 16px;               /* stops iOS zooming on focus */
  background: var(--surface-2);
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease), background .18s var(--ease);
}
.lg__field input:hover { border-color: var(--ink-200); }
.lg__field input:focus,
.lg__field input:focus-visible {
  outline: none;
  background: var(--surface);
  border-color: var(--brand-500);
  box-shadow: 0 0 0 4px rgba(232, 135, 30, .18);
}

.lg__submit {
  min-height: 54px;
  margin-top: .35rem;
  font-size: 1rem;
  letter-spacing: .02em;
  box-shadow: 0 8px 22px rgba(232, 135, 30, .30);
}
.lg__submit:hover { box-shadow: 0 12px 28px rgba(232, 135, 30, .42); }

.lg__forgot { margin: .9rem 0 0; text-align: center; }
.lg__forgot a {
  display: inline-block;
  min-height: 48px;
  padding: .8rem .9rem;
  font-size: .88rem;
  font-weight: 600;
  color: var(--ink-500);
  border-radius: var(--r-sm);
}
.lg__forgot a:hover { color: var(--brand-700); }

.lg__foot {
  margin: 1.6rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--line-soft);
  text-align: center;
  font-size: .74rem;
  line-height: 1.6;
  color: var(--ink-400);
}

.lg .alert { margin-bottom: 1rem; }

/* --- Staggered reveal ---------------------------------------------- */
.lg__rv { animation: lgRise .5s var(--ease) both; }
.lg__brand .lg__rv:nth-child(1) { animation-delay: .04s; }
.lg__brand .lg__rv:nth-child(2) { animation-delay: .10s; }
.lg__brand .lg__rv:nth-child(3) { animation-delay: .16s; }
.lg__brand .lg__rv:nth-child(4) { animation-delay: .22s; }
.lg__brand .lg__rv:nth-child(5) { animation-delay: .28s; }
.lg__form  .lg__rv:nth-child(1) { animation-delay: .16s; }
.lg__form  .lg__rv:nth-child(2) { animation-delay: .22s; }
.lg__form  .lg__rv:nth-child(3) { animation-delay: .28s; }
.lg__form  .lg__rv:nth-child(4) { animation-delay: .34s; }
.lg__form  .lg__rv:nth-child(5) { animation-delay: .40s; }
.lg__form  .lg__rv:nth-child(6) { animation-delay: .46s; }

@keyframes lgRise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .lg__rv { animation: none; opacity: 1; transform: none; }
}

/* --- Tablet: give the brand panel room ----------------------------- */
@media (min-width: 600px) {
  .lg__brand { padding: 3rem 2.5rem 3.4rem; }
  .lg__points { display: block; }
  .lg__panel { padding: 2.2rem 2rem 3rem; }
}

/* --- Desktop: asymmetric split ------------------------------------- */
@media (min-width: 992px) {
  .lg { flex-direction: row; }

  .lg__brand {
    /* An even split, so the seam sits on the optical centre of the screen and
       the leftover space is the same on both outer edges. At 46% the right
       margin was almost twice the left and the page looked lopsided. */
    flex: 0 0 50%;
    display: flex;
    align-items: center;
    /* Pushed towards the seam. Left-aligned inside a 46% panel, the brand sat
       against the outer edge of the screen and left a dead black rectangle
       between it and the form - the two halves read as two unrelated pages
       rather than one. Against the seam they read as one composition, and the
       empty space becomes an outer margin instead of a hole in the middle. */
    justify-content: flex-end;
    padding: 3.5rem 3.4rem 3.5rem 2.5rem;
  }
  .lg__brandIn { max-width: 440px; }
  .lg__name-1,
  .lg__name-2 { font-size: clamp(3.2rem, 4.4vw, 4.6rem); }

  .lg__panel {
    flex: 1 1 auto;
    align-items: center;
    /* The form follows the seam too, for the same reason. */
    justify-content: flex-start;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 3rem 3rem 3rem 3.4rem;
    background: var(--surface);
  }
  /* A thin amber seam where the two halves meet. */
  .lg__panel::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--brand-500), rgba(232, 135, 30, .05));
  }
  .lg__form { max-width: 400px; }
}

/* The date in a list, read like a calendar: the day large, the month and year
   small underneath. On a list scanned by date the day is the only part the eye
   needs at full size, and stacking the rest keeps the column narrow - it used
   to wrap onto two ragged lines at full width. */
.datechip {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.05;
  text-decoration: none;
}
.datechip__day {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}
.datechip__rest {
  font-size: .72rem;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}
.datechip:hover .datechip__day { color: var(--brand); }

/* Bill, voucher and entry numbers.
   A document number is a reference, not a headline. Small and bold reads as a
   code, keeps its column narrow, and stops it competing with the money beside
   it. Kept outside every media query so it holds on the phone as well. */
.docno {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
}

/* The shop's own logo, wherever the drawn bird mark used to be.
   contain, never cover: a logo cropped to fill a square is a logo with its
   name cut off. The badge it sits in is already round and coloured, so the
   picture only has to fit inside it. Kept outside every media query so it
   holds on the phone as well. */
.brandmark {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: inherit;
}

/* At the head of a bill printed straight from the browser. Sized in
   millimetres because this one is only ever seen on paper. */
.printlogo {
  display: block;
  max-height: 18mm;
  max-width: 45mm;
  margin: 0 0 2mm;
}

/* The sign-in mark once the shop has uploaded its own logo.
   The orange badge is the frame the drawn bird needs - a real logo brings its
   own shape and colours, so the badge, its shadow and its rounding all come
   off and the picture stands on the dark panel by itself. 200px square, and
   the picture is fitted inside it rather than cropped to fill it. */
.lg__mark--img {
  width: 200px;
  height: 200px;
  max-width: 100%;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* The same, in the sidebar and the phone's top bar. The badge frames the
   drawn bird; a real logo frames itself, so the orange square, its rounding
   and its gradient all come off and only the picture is left. */
.appbar__logo--img {
  background: none;
  border-radius: 0;
}

/* A radio or checkbox row inside a bill head is a sentence, not a field
   caption. The caption rule above catches every direct label there, so a whole
   line of English came out shouted in small caps - "OPENING STOCK - WHAT WAS
   ALREADY IN THE SHOP WHEN THE SOFTWARE STARTED". These read as ordinary text
   again; only the caption above them keeps the small-caps treatment. */
.bill__party > label.check,
.bill__meta label.check {
  display: flex;
  font-size: .9rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink-900);
  margin-bottom: 0;
}

/* The Dr / Cr mark beside a line of the profit account. Small, quiet and the
   same width either way, so a column of them lines up and none of them
   competes with the words or the money they sit between. */
.drcr {
  display: inline-block;
  min-width: 1.55rem;
  padding: 0 .25rem;
  border-radius: 4px;
  font-size: .62rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: .04em;
  text-align: center;
  vertical-align: .1em;
  margin-left: .3rem;
}
.drcr--dr { background: #fdecec; color: #a92727; }
.drcr--cr { background: #e4f5ed; color: #0f6b48; }

/* ---------------------------------------------------------------------
   A figure must never break in the middle.

   On a 360px phone a full rupee amount does not fit a tile at the display
   size, and word-break split it across two lines - "Rs 2,34,690." on one and
   "00" on the next - which reads as a different number entirely. The figure
   steps down a size on a narrow screen instead, and is told to stay whole.
   --------------------------------------------------------------------- */
@media (max-width: 480px) {
  .stat__value {
    font-size: 1.2rem;
    word-break: normal;
    overflow-wrap: normal;
  }
}

/* ---------------------------------------------------------------------
   The three phone boxes in Settings.

   Each is a box with the dot beside it that says "this one goes on the
   bills". On a phone the dot drops under its box rather than squeezing
   the number into nothing.
   --------------------------------------------------------------------- */
.phone-line {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: .5rem;
}
.phone-line input[type="tel"] { flex: 1 1 auto; min-width: 0; }
.phone-line .check            { flex: 0 0 auto; margin: 0; white-space: nowrap; }
.phone-line .badge            { flex: 0 0 auto; }
@media (max-width: 640px) {
  /* Column, not a wrap: wrapping put the dot above its own box, so the row
     read as "this one on bills" followed by a number it did not belong to. */
  .phone-line { display: block; margin-bottom: .9rem; }
  .phone-line input[type="tel"] { width: 100%; }
  .phone-line .check { margin-top: .3rem; }
}

/* ---------------------------------------------------------------------
   Bill line labels for a phone
   Below 600px the header row above the lines is hidden, which on the sale
   screen left three unnamed number boxes: nothing said which was pieces,
   which was kilos and which was the rate. These carry the heading down
   into each box, and disappear again the moment the real header is back.
   --------------------------------------------------------------------- */
.bill__minilabel { display: none; }
@media (max-width: 599px) {
  .bill__minilabel {
    display: block;
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ink-400);
    margin-bottom: .2rem;
  }
}

/* A totals row can be switched off by the script - the "after cages" row
   stays away until an empty-cage weight is typed. `display: flex` on the
   class beats the browser's own [hidden] rule, so it is restated here. */
.bill__trow[hidden] { display: none; }

/* An icon-only button inside a row of buttons keeps its square. Without this
   `.btn-row .btn` wins on specificity and stretches it like a labelled one. */
.btn-row .btn--icon { flex: 0 0 44px; }

/* ---------------------------------------------------------------------
   Dashboard : sales & profit
   --------------------------------------------------------------------- */
.dash-unit { font-size: .8rem; font-weight: 600; color: var(--ink-400); letter-spacing: 0; }

.dash-chart { padding: 1rem; }

.dash-chart__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .6rem 1rem;
  margin-bottom: 1rem;
}
.dash-chart__dates {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .78rem;
  font-weight: 600;
  color: var(--ink-500);
}
.dash-chart__dates svg { width: 14px; height: 14px; }

/* --- The sum : a receipt on a phone, one line of tiles on a desktop --- */
.dash-eq {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.dash-eq__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .65rem .85rem;
  border-bottom: 1px solid var(--line-soft);
  background: var(--surface);
}
.dash-eq__op {
  flex: 0 0 1.45rem;
  height: 1.45rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: .9rem;
  font-weight: 700;
  line-height: 1;
  color: var(--ink-600);
}
.dash-eq__item:first-child { padding-left: calc(.85rem + 1.45rem + .7rem); }
.dash-eq__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.dash-eq__label { font-size: .84rem; font-weight: 600; color: var(--ink-800); }
.dash-eq__sub { font-size: .7rem; line-height: 1.35; color: var(--ink-400); }
.dash-eq__amt {
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink-900);
}
.dash-eq__item--sold  .dash-eq__amt { color: var(--success); }
.dash-eq__item--buy   .dash-eq__amt { color: var(--brand-600); }
.dash-eq__item--cost  .dash-eq__amt { color: var(--danger); }
.dash-eq__item--total {
  border-bottom: 0;
  background: var(--success-bg);
}
.dash-eq__item--total .dash-eq__label { font-size: .95rem; font-weight: 700; color: var(--ink-900); }
.dash-eq__item--total .dash-eq__amt { font-size: 1.35rem; color: var(--success); }
.dash-eq__item--total .dash-eq__op { background: var(--success); border-color: var(--success); color: #fff; }
.dash-eq__item--total.is-loss { background: var(--danger-bg); }
.dash-eq__item--total.is-loss .dash-eq__amt { color: var(--danger); }
.dash-eq__item--total.is-loss .dash-eq__op { background: var(--danger); border-color: var(--danger); }

@media (min-width: 1024px) {
  .dash-eq {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 1.3rem;
    border: 0;
    border-radius: 0;
    overflow: visible;
  }
  .dash-eq__item,
  .dash-eq__item:first-child {
    flex-direction: column;
    align-items: flex-start;
    gap: .15rem;
    padding: .7rem .85rem .75rem;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface-2);
  }
  .dash-eq__op {
    position: absolute;
    left: calc(-.65rem - .73rem);
    top: 50%;
    width: 1.45rem;
    transform: translateY(-50%);
    background: var(--surface);
    z-index: 1;
  }
  .dash-eq__text { order: 1; }
  .dash-eq__amt { order: 2; font-size: 1.12rem; margin-top: .2rem; }
  .dash-eq__label { font-size: .7rem; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-500); }
  .dash-eq__item--total { border-color: #BFE3D0; }
  .dash-eq__item--total.is-loss { border-color: #F1C4C4; }
  .dash-eq__item--total .dash-eq__label { font-size: .72rem; color: var(--ink-700); }
  .dash-eq__item--total .dash-eq__amt { font-size: 1.4rem; }
}

.dash-chart__note {
  margin: .65rem 0 0;
  font-size: .74rem;
  line-height: 1.5;
  color: var(--ink-500);
}
.dash-chart__note strong { color: var(--ink-700); font-weight: 600; }

/* --- The chart --- */
.dash-chart__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .4rem 1rem;
  margin-top: 1.1rem;
  padding-top: .9rem;
  border-top: 1px solid var(--line);
}
.dash-chart__title { font-family: var(--font-display); font-size: .95rem; font-weight: 700; color: var(--ink-900); }
.dash-chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .9rem;
  font-size: .74rem;
  font-weight: 500;
  color: var(--ink-600);
}
.dash-key {
  display: inline-block;
  width: 10px; height: 10px;
  margin-right: .35rem;
  border-radius: 3px;
  vertical-align: -1px;
}
.dash-key--sold, .dash-chart__bar--sold { background: var(--success); }
.dash-key--buy,  .dash-chart__bar--buy  { background: var(--brand-500); }
.dash-key--cost, .dash-chart__bar--cost { background: var(--danger); }

.dash-chart { --plot-h: 170px; --day-h: 2.05rem; --pl-h: 1.35rem; }
.dash-chart__canvas { display: flex; align-items: flex-start; margin-top: .6rem; }

/* The scale on the left, level with the guide lines. */
.dash-chart__axis {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: .5rem .45rem 0 0;
}
.dash-chart__ticks { position: relative; height: var(--plot-h); min-width: 2.2rem; }
.dash-chart__ticks span {
  position: absolute;
  right: 0;
  transform: translateY(50%);
  font-size: .62rem;
  font-weight: 500;
  color: var(--ink-400);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.dash-chart__axis-day { height: var(--day-h); }
.dash-chart__axis-pl {
  height: var(--pl-h);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  font-size: .64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-500);
}

.dash-chart__scroll { flex: 1; min-width: 0; overflow-x: auto; padding-bottom: .15rem; }
.dash-chart__plot { position: relative; display: flex; min-width: 100%; }
/* Guide lines at every quarter, drawn once across the whole plot. */
.dash-chart__plot::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: .5rem;
  height: var(--plot-h);
  box-sizing: border-box;
  background-image: linear-gradient(to bottom, var(--line) 1px, transparent 1px);
  background-size: 100% 25%;
  border-bottom: 1.5px solid var(--ink-200);
  pointer-events: none;
}
.dash-chart__group {
  position: relative;
  flex: 1 0 42px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .3rem;
  padding: .5rem .1rem .35rem;
  border-radius: var(--r-sm);
  color: inherit;
  transition: background .18s var(--ease);
}
.dash-chart__group:hover { color: inherit; background: rgba(16, 20, 28, .035); }
.dash-chart__bars {
  width: 100%;
  height: var(--plot-h);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
}
.dash-chart__bar {
  width: 9px;
  border-radius: 3px 3px 0 0;
  animation: dashGrow .55s var(--ease) both;
  transform-origin: bottom;
}
@keyframes dashGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.dash-chart__label {
  height: var(--day-h);
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
  color: var(--ink-700);
}
.dash-chart__label small { display: block; font-size: .6rem; font-weight: 500; color: var(--ink-400); }
.dash-chart__group.is-today .dash-chart__label { color: var(--brand-600); }

/* The profit or loss under each bar. */
.dash-pl {
  height: var(--pl-h);
  display: inline-flex;
  align-items: center;
  padding: 0 .38rem;
  border-radius: var(--r-pill);
  font-size: .62rem;
  font-weight: 700;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.dash-pl--profit { background: var(--success-bg); color: var(--success); }
.dash-pl--loss   { background: var(--danger-bg);  color: var(--danger); }
.dash-pl--none   { color: var(--ink-300); }

/* One wide group for today; thin ones per day for the month. */
.dash-chart__plot--today .dash-chart__group { flex-basis: 100%; }
.dash-chart__plot--today .dash-chart__bars  { gap: 12px; }
.dash-chart__plot--today .dash-chart__bar   { width: 46px; }
.dash-chart__plot--today .dash-pl           { font-size: .78rem; padding: 0 .6rem; }
.dash-chart__plot--month .dash-chart__group { flex-basis: 26px; padding-left: 0; padding-right: 0; }
.dash-chart__plot--month .dash-chart__bar   { width: 6px; }
.dash-chart__plot--month .dash-pl           { width: 9px; height: 9px; padding: 0; margin: calc((var(--pl-h) - 9px) / 2) 0; font-size: 0; overflow: hidden; }
.dash-chart__plot--month .dash-pl--profit   { background: var(--success); }
.dash-chart__plot--month .dash-pl--loss     { background: var(--danger); }
.dash-chart__plot--month .dash-pl--none     { background: var(--line); }
.dash-chart__plot--year .dash-chart__group  { flex-basis: 52px; }
.dash-chart__plot--7d .dash-chart__group    { flex-basis: 34px; padding-left: 0; padding-right: 0; }
.dash-chart__plot--7d .dash-chart__bar      { width: 7px; }
.dash-chart__plot--7d .dash-pl              { font-size: .56rem; padding: 0 .22rem; }
/* Month and year can be wider than a phone. Their bars are written newest
   first and laid right to left, so the chart opens on the latest days. */
.dash-chart__plot--month,
.dash-chart__plot--year { flex-direction: row-reverse; }

@media (min-width: 760px) {
  .dash-chart { padding: 1.2rem 1.35rem 1.25rem; --plot-h: 230px; }
  .dash-chart__ticks span { font-size: .68rem; }
  .dash-chart__label { font-size: .76rem; }
  .dash-pl { font-size: .7rem; padding: 0 .55rem; }
  .dash-chart__plot--7d .dash-chart__bar   { width: 20px; }
  .dash-chart__plot--year .dash-chart__bar { width: 16px; }
  .dash-chart__plot--month .dash-chart__bar { width: 7px; }
}

/* The one block on a purchase the owner must not miss: what really came
   through the door, against what the supplier billed. It is never folded
   away - a hidden box is a box nobody fills in. */
.optional-group--flag,
.bill__lines .optional-group--flag {
  border: 1px solid var(--brand-300);
  border-left: 4px solid var(--brand-500);
  border-radius: var(--r-md);
  background: var(--brand-50);
  margin: .7rem 0 .3rem;
}
.optional-group__title {
  display: flex;
  align-items: flex-start;
  gap: .45rem;
  padding: .7rem .85rem .4rem;
  font-size: .92rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--brand-700);
}
.optional-group__title svg { flex: 0 0 18px; width: 18px; height: 18px; margin-top: .1rem; }
.optional-group--flag .optional-group__body { padding: 0 .85rem .85rem; }
.optional-group--flag .field label { color: var(--ink-700); }
.optional-group--flag .field input { background: var(--surface); }
.optional-group--flag .field__hint { color: var(--ink-600); line-height: 1.5; }

/* A hint that has turned into a warning - used by the purchase screen when
   what "came in" reads as far less than the bill. */
.field__hint.is-warn { color: var(--danger); font-weight: 600; }

/* Two-way choice - money in or money out. One tap, coloured the way the book
   colours the columns, instead of two stacked radio sentences. */
.pick { display: flex; gap: .5rem; }
.pick__opt { flex: 1; min-width: 0; margin: 0; }
.pick__opt input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.pick__opt span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: .5rem .6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  font-size: .88rem;
  font-weight: 600;
  color: var(--ink-600);
  text-align: center;
  cursor: pointer;
  transition: background .15s var(--ease), border-color .15s var(--ease), color .15s var(--ease);
}
.pick__opt span:hover { border-color: var(--ink-300); }
.pick__opt--in input:checked + span {
  background: var(--success-bg);
  border-color: var(--success);
  color: var(--success);
}
.pick__opt--out input:checked + span {
  background: var(--danger-bg);
  border-color: var(--danger);
  color: var(--danger);
}
.pick__opt input:focus-visible + span { outline: 2px solid var(--brand-500); outline-offset: 2px; }

/* Buttons inside a table row.
   The card version lets them grow and wrap, which is right on a phone. In a
   table it was wrong: the last button stretched the whole width of the cell
   and dropped to its own line, so no two rows lined up. Here they stay on one
   line, each its own width, hard against the right of the column - and they
   are a size smaller, because a row is not a page header. */
.data .btn-row {
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: .4rem;
}
.data .btn-row .btn {
  flex: 0 0 auto;
  min-height: 38px;
  padding: .45rem .75rem;
  font-size: .85rem;
}
.data .btn-row .btn svg { width: 15px; height: 15px; }
