/* =====================================================================
   LOGICPULSE INVENTORY — "The Ink Ledger" identity layer
   Over Tabler (Bootstrap 5). Tokens first; components second.
   Palette: cool ledger paper, Process Cyan (in), Rubber Stamp (out).
   ===================================================================== */

:root {
  /* -- ink ---------------------------------------------------------- */
  --ink-0: #101418;      /* press black — display type, sidebar */
  --ink-1: #2A343C;      /* slate ink — body text */
  --ink-2: #5C6975;      /* diluted ink — secondary text */

  /* -- paper -------------------------------------------------------- */
  --paper: #F2F4F3;      /* ledger paper — page background */
  --sheet: #FFFFFF;      /* fresh sheet — cards */
  --rule: #D9DFDD;       /* hairline rules */
  --rule-soft: #E8ECEA;

  /* -- process colors (the plates of the ink trade) ------------------ */
  --cyan: #0E7C86;       /* process cyan — brand, links, stock in */
  --cyan-deep: #0A5A62;
  --cyan-wash: #E4F1F2;
  --stamp: #C2402A;      /* rubber stamp — stock out, rejected */
  --stamp-wash: #F8E9E6;
  --amber: #B98A2F;      /* batch amber — pending, warnings */
  --amber-wash: #F7F0DF;
  --ok: #2E7D5B;         /* ledger green — approved, paid */
  --ok-wash: #E5F1EB;

  /* -- type ---------------------------------------------------------- */
  --font-display: "Bricolage Grotesque", "IBM Plex Sans", sans-serif;
  --font-body: "IBM Plex Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* -- Tabler bridge -------------------------------------------------- */
  --tblr-primary: #0E7C86;
  --tblr-primary-rgb: 14, 124, 134;
  --tblr-body-bg: #F2F4F3;
  --tblr-font-sans-serif: "IBM Plex Sans", system-ui, sans-serif;
  --tblr-border-color: #D9DFDD;
  --tblr-border-radius: 6px;
}

/* -- base ------------------------------------------------------------ */
html {
  scroll-behavior: smooth; /* anchor clicks glide instead of jumping */
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font-body);
  color: var(--ink-1);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .h1, .h2, .h3 {
  font-family: var(--font-display);
  color: var(--ink-0);
  text-wrap: balance; /* no orphaned word on the last line */
}
p, li, td {
  text-wrap: pretty; /* softer paragraph rag */
}

::selection { background: var(--cyan-wash); color: var(--cyan-deep); }

a { color: var(--cyan); }
a:hover { color: var(--cyan-deep); }

/* Keyboard focus is never invisible. */
:focus-visible {
  outline: 2px solid var(--cyan) !important;
  outline-offset: 2px;
  border-radius: 2px;
}

/* Skip link: invisible until keyboard-focused, then front and centre (WCAG 2.4.1). */
.visually-hidden-focusable:not(:focus):not(:focus-within) {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}
.visually-hidden-focusable:focus {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2000;
  padding: 0.5rem 0.875rem;
  background: var(--ink-0);
  color: #F5F7F6;
  border-radius: 6px;
  text-decoration: none;
}

/* On the dark footer bar the cyan hover is 2.2:1 — a pale ink stays legible (1.4.3). */
.lp-auth-footer a:hover,
.lp-auth-footer a:focus-visible {
  color: #7FD4DC;
}

/* -- keyboard-hint overlay (bottom-right corner) ------------------------
   Decorative only (pointer-events: none) but it must never sit on top of
   form action buttons, sticky footers, modals or the mobile keyboard. */
.lp-kb-hint {
  z-index: 900; /* below Tabler modals (z 1055), dropdowns (1000) and sticky headers (1030-ish) */
  max-width: 60vw;
  text-align: right;
}

/* Small screens & touch devices: the on-screen keyboard covers the bottom
   half when typing, and space is tight — the hint would only collide with
   form buttons, so simply don't show it. Desktops keep the hint. */
@media (max-width: 991.98px) {
  .lp-kb-hint { display: none !important; }
}
@media (hover: none) and (pointer: coarse) {
  .lp-kb-hint { display: none !important; }
}

/* Respect iOS home-indicator safe area so it never overlaps it. */
@supports (bottom: env(safe-area-inset-bottom)) {
  .lp-kb-hint { bottom: calc(0.5rem + env(safe-area-inset-bottom)); }
}

/* When the on-screen keyboard opens (viewport shrinks), fold the hint away
   so it can never overlap the visible action buttons. */
@keyframes kb-hint-out {
  to { opacity: 0; visibility: hidden; }
}
.lp-kb-hint.kb-hidden {
  animation: kb-hint-out .15s ease forwards;
}

/* -- mono voice: labels, refs, quantities, metadata -------------------- */
.lp-label,
.subheader,
.badge,
.navbar-vertical .nav-link,
.page-title-sub,
.lp-mono {
  font-family: var(--font-mono);
}

.lp-label {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* =====================================================================
   SIDEBAR — the ink rail
   ===================================================================== */
.navbar-vertical {
  background: var(--ink-0) !important;
  border-right: 1px solid var(--ink-0);
}

.navbar-vertical .navbar-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: #F5F7F6 !important;
  letter-spacing: 0.01em;
  padding-top: 1.25rem;
}

.lp-mark {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--cyan);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  border-radius: 4px;
  position: relative;
}

/* registration mark corner ticks on the brand plate */
.lp-mark::before,
.lp-mark::after {
  content: "";
  position: absolute;
  width: 5px;
  height: 5px;
  border: 1px solid rgba(255, 255, 255, 0.55);
}
.lp-mark::before { top: -4px; left: -4px; border-right: 0; border-bottom: 0; }
.lp-mark::after { bottom: -4px; right: -4px; border-left: 0; border-top: 0; }

.lp-brand-sub {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245, 247, 246, 0.45);
  margin-top: 2px;
}

/* section labels in the rail */
.navbar-vertical .lp-nav-section {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245, 247, 246, 0.38);
  padding: 1.1rem 1.25rem 0.4rem;
}

.navbar-vertical .nav-link {
  color: rgba(245, 247, 246, 0.78) !important;
  font-size: 0.8125rem;
  font-weight: 400;
  letter-spacing: 0.01em;
  border-radius: 4px;
  margin: 1px 10px;
  padding: 0.5rem 0.75rem !important;
}

.navbar-vertical .nav-link:hover {
  color: #fff !important;
  background: rgba(255, 255, 255, 0.06);
}

.navbar-vertical .nav-link.active,
.navbar-vertical .dropdown-toggle.active,
.navbar-vertical .nav-link[aria-expanded="true"] {
  color: #fff !important;
  background: rgba(14, 124, 134, 0.28);
  box-shadow: inset 2px 0 0 var(--cyan);
}

/* -- mobile navigation drawer (offcanvas) ------------------------------ */
/* Overlay drawer opened by the mobile hamburger; slides over the page. */
.lp-mobile-nav {
  --lp-nav-w: min(84vw, 300px);
  --tblr-offcanvas-width: var(--lp-nav-w); /* feed Tabler's own width rule our value */
  width: var(--lp-nav-w);
  max-width: var(--lp-nav-w);
  background: var(--ink-0);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
}
.lp-mobile-nav .offcanvas-header {
  background: var(--ink-0);
  padding: 1rem 1rem 0.75rem;
}
.lp-mobile-nav .offcanvas-header .navbar-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: #F5F7F6 !important;
}
.lp-mobile-nav .offcanvas-body {
  overflow-y: auto;
  padding-bottom: 2rem;
}
/* Reuse the desktop rail's link styling inside the drawer. */
.lp-mobile-nav .nav-link {
  color: rgba(245, 247, 246, 0.78) !important;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  border-radius: 4px;
  margin: 1px 10px;
  padding: 0.55rem 0.75rem !important;
}
.lp-mobile-nav .nav-link:hover {
  color: #fff !important;
  background: rgba(255, 255, 255, 0.06);
}
.lp-mobile-nav .nav-link.active {
  color: #fff !important;
}
.lp-mobile-nav .lp-nav-section {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245, 247, 246, 0.38);
  padding: 1.1rem 1.25rem 0.4rem;
}
/* Offcanvas backdrops render behind the drawer (z-index 1045); raise ours. */
.lp-mobile-nav.navbar-vertical {
  background: var(--ink-0);
}

/* Hamburger on the white mobile header — default grey icon is invisible-ish. */
header.navbar-light .navbar-toggler {
  color: var(--ink-0);
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 4px;
  padding: 0.25rem 0.5rem;
}
header.navbar-light .navbar-toggler .navbar-toggler-icon {
  filter: invert(1);
  width: 1.4em;
  height: 1.4em;
}

.navbar-vertical .dropdown-menu {
  background: #1A2129;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 6px;
  padding: 0.35rem;
}

.navbar-vertical .dropdown-item {
  color: rgba(245, 247, 246, 0.82);
  font-size: 0.8125rem;
  border-radius: 4px;
  padding: 0.45rem 0.75rem;
}

.navbar-vertical .dropdown-item:hover,
.navbar-vertical .dropdown-item.active {
  color: #fff;
  background: rgba(14, 124, 134, 0.35);
}

/* thin ink scrollbar in the rail */
.navbar-vertical .navbar-collapse { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.18) transparent; }

/* =====================================================================
   DESKTOP SIDEBAR TOGGLE — html.lp-side-collapsed hides the ink rail and
   releases Tabler's margin offsets, so content takes the full width.
   Below lg the rail is already hidden (d-none d-lg-flex) — no-op there.
   Selectors carry html+context so they outrank
   `.navbar-expand-lg.navbar-vertical~.page-wrapper { margin-left:15rem }`.
   ===================================================================== */
@media (min-width: 992px) {
  /* !important required: Tabler's d-lg-flex utility is display:flex !important. */
  html.lp-side-collapsed aside.navbar-vertical { display: none !important; }
  html.lp-side-collapsed .page > header.navbar,
  html.lp-side-collapsed .page > .page-wrapper { margin-left: 0; transition: margin-left .25s ease; }
  .page > header.navbar,
  .page > .page-wrapper { transition: margin-left .25s ease; }
}

/* The toggle button in the desktop header. */
.lp-side-toggle { color: var(--ink-1); border: 1px solid transparent; }
.lp-side-toggle:hover { color: var(--ink-0); background: rgba(16, 20, 24, 0.05); }
.lp-side-toggle:focus-visible { box-shadow: 0 0 0 2px var(--cyan-wash); }

/* =====================================================================
   HEADER
   ===================================================================== */
header.navbar {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  min-height: 3.25rem;
}

header.navbar .form-control {
  background: var(--sheet);
  border-color: var(--rule);
  font-size: 0.875rem;
}

header.navbar .form-control:focus {
  border-color: var(--cyan);
  box-shadow: 0 0 0 2px var(--cyan-wash);
}

.lp-bell { position: relative; font-size: 1.05rem; text-decoration: none; }
.lp-bell .badge {
  position: absolute;
  top: -4px;
  right: -8px;
  background: var(--stamp);
  font-size: 0.625rem;
  padding: 0.15em 0.4em;
}

.lp-userchip { gap: 0.6rem; }
/* The name must survive a narrow header: it truncates rather than pushing
   the search box and the bell around, and the full text is in the title. */
.lp-userchip-text { min-width: 0; }
.lp-userchip-name { max-width: 11rem; }
.lp-userchip .avatar {
  background: var(--cyan-wash) !important;
  color: var(--cyan-deep) !important;
  font-family: var(--font-display);
  font-weight: 700;
}

/* =====================================================================
   PAGE TITLE — display voice with a cyan baseline tick
   ===================================================================== */
.page-title {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -0.022em;
  line-height: 1.15;
}

.lp-titleblock { position: relative; padding-left: 0.9rem; }
.lp-titleblock::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.2rem;
  bottom: 0.2rem;
  width: 3px;
  background: var(--cyan);
}

.page-title-sub {
  font-size: 0.75rem;
  color: var(--ink-2);
  letter-spacing: 0.02em;
  margin-top: 0.15rem;
}

/* The signed-in person's name inside the title line — ledger green, so the
   eye lands on WHO this screen belongs to before the date. */
.lp-who {
  color: var(--ok);
  font-weight: 600;
}

/* =====================================================================
   THE LEDGER STRIP — signature KPI band
   One continuous ruled strip; cells separated by hairline verticals.
   ===================================================================== */
.lp-ledger {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 1.5rem;
}

.lp-ledger-cell {
  position: relative;
  padding: 0.9rem 1.1rem 0.8rem;
  border-left: 1px solid var(--rule-soft);
  min-width: 0;
}
.lp-ledger-cell:nth-child(4n + 1) { border-left: 0; }
.lp-ledger-cell:nth-child(n + 5) { border-top: 1px solid var(--rule-soft); }

.lp-ledger-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lp-ledger-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.65rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink-0);
  margin-top: 0.25rem;
  font-variant-numeric: tabular-nums;
}

.lp-ledger-num.is-money { font-size: 1.3rem; padding-top: 0.2rem; }

/* Three across instead of four: the salesman's own nine figures (money, then
   the stock he was issued). Same ruled strip, one column fewer, and the
   hairline rules are redrawn for the 3-wide grid. */
.lp-ledger.is-trio { grid-template-columns: repeat(3, 1fr); }
.lp-ledger.is-trio .lp-ledger-cell:nth-child(4n + 1) { border-left: 1px solid var(--rule-soft); }
.lp-ledger.is-trio .lp-ledger-cell:nth-child(3n + 1) { border-left: 0; }
.lp-ledger.is-trio .lp-ledger-cell:nth-child(n + 4) { border-top: 1px solid var(--rule-soft); }

/* The strip's own sheet: a titled block ("Sale page short cut" + the period
   it is showing) sitting directly on top of the ruled cells, so the header
   and the nine figures read as one ledger table rather than a button with a
   strip underneath. The block owns the border; the strip drops its own. */
.lp-ledger-block {
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 1rem;
}
.lp-ledger-block > .lp-ledger {
  border: 0;
  border-radius: 0;
  margin-bottom: 0;
}

.lp-ledger-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem 1rem;
  padding: 0.6rem 1.1rem;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}

.lp-ledger-shortcut {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cyan);
  text-decoration: none;
}
.lp-ledger-shortcut:hover,
.lp-ledger-shortcut:focus-visible {
  color: var(--cyan-deep);
  text-decoration: underline;
}

.lp-ledger-when {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.lp-ledger-when strong { color: var(--ink-1); font-weight: 600; }

/* The definitions behind the strip, folded away so the figures lead. */
.lp-defs > summary {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.lp-defs > summary:hover { color: var(--ink-1); }
.lp-defs[open] > summary { margin-bottom: 0.4rem; }

/* the delta tick: a small plate-colored square beside the number */
.lp-tick {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 7px;
  border-radius: 1px;
  background: var(--ink-2);
  vertical-align: 0.35em;
}
.lp-tick.is-in { background: var(--cyan); }
.lp-tick.is-out { background: var(--stamp); }
.lp-tick.is-hold { background: var(--amber); }
.lp-tick.is-return { background: var(--amber); } /* goods coming back = batch amber */
.lp-tick.is-ok { background: var(--ok); }

@media (max-width: 767.98px) {
  .lp-ledger { grid-template-columns: repeat(2, 1fr); }
  .lp-ledger-cell { padding: 0.75rem 0.9rem 0.65rem; }
  .lp-ledger-cell:nth-child(4n + 1) { border-left: 1px solid var(--rule-soft); }
  .lp-ledger-cell:nth-child(2n + 1) { border-left: 0; }
  .lp-ledger-cell:nth-child(n + 3) { border-top: 1px solid var(--rule-soft); }
  .lp-ledger-cell:nth-child(n + 5) { border-top: 1px solid var(--rule-soft); }
  .lp-ledger-num { font-size: 1.35rem; }
  /* The trio strip goes two across on phones too — rules redrawn for it. */
  .lp-ledger.is-trio { grid-template-columns: repeat(2, 1fr); }
  .lp-ledger.is-trio .lp-ledger-cell:nth-child(3n + 1) { border-left: 1px solid var(--rule-soft); }
  .lp-ledger.is-trio .lp-ledger-cell:nth-child(4n + 1) { border-left: 1px solid var(--rule-soft); }
  .lp-ledger.is-trio .lp-ledger-cell:nth-child(2n + 1) { border-left: 0; }
  /* An odd number of figures (headcount, active, payroll) leaves one cell
     alone on the last line: it takes the whole line instead of sitting in
     half a strip with an empty neighbour. */
  .lp-ledger > .lp-ledger-cell:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    border-left: 0;
    border-top: 1px solid var(--rule-soft);
  }
}

/* =====================================================================
   CARDS — quiet sheets with a mono-caps header
   ===================================================================== */
.card {
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 1px 2px rgba(16, 20, 24, 0.03);
}

.card-header {
  border-bottom: 1px solid var(--rule-soft);
  padding: 0.7rem 1rem;
}

.card-title {
  font-family: var(--font-mono) !important;
  font-size: 0.75rem !important;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-1) !important;
}

/* =====================================================================
   BUTTONS — press-solid primary, stamp-outline danger
   ===================================================================== */
.btn {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  border-radius: 4px;
}

.btn-primary {
  background: var(--cyan);
  border-color: var(--cyan);
  color: #fff;
}
.btn-primary:hover, .btn-primary:focus {
  background: var(--cyan-deep);
  border-color: var(--cyan-deep);
  color: #fff;
}
.btn-outline-primary {
  color: var(--cyan);
  border-color: var(--cyan);
}
.btn-outline-primary:hover {
  background: var(--cyan-wash);
  color: var(--cyan-deep);
  border-color: var(--cyan);
}
.btn-outline-danger { color: var(--stamp); border-color: var(--stamp); }
.btn-outline-danger:hover { background: var(--stamp-wash); color: var(--stamp); border-color: var(--stamp); }
.btn-danger { background: var(--stamp); border-color: var(--stamp); }

/* =====================================================================
   BADGES — plate washes; the approval stamp is the loud one
   ===================================================================== */
.badge {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 3px;
  padding: 0.3em 0.55em;
}
.badge.bg-success-lt { background: var(--ok-wash) !important; color: var(--ok) !important; }
.badge.bg-warning-lt { background: var(--amber-wash) !important; color: #8A6516 !important; }
.badge.bg-danger-lt { background: var(--stamp-wash) !important; color: var(--stamp) !important; }
.badge.bg-secondary-lt { background: var(--rule-soft) !important; color: var(--ink-2) !important; }
.badge.bg-info-lt { background: var(--cyan-wash) !important; color: var(--cyan-deep) !important; }
.badge.bg-dark-lt { background: var(--rule-soft) !important; color: var(--ink-1) !important; }

/* the rubber stamp: only for pending_approval documents */
.lp-stamp {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amber);
  border: 1.5px solid var(--amber);
  border-radius: 3px;
  padding: 0.25em 0.5em;
  transform: rotate(-4deg);
  background: var(--amber-wash);
}

/* =====================================================================
   TABLES — ledger lines
   ===================================================================== */
.table { --tblr-table-border-color: var(--rule-soft); }
.table thead th {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  border-bottom: 1px solid var(--rule) !important;
}
.table td { font-size: 0.875rem; }
.table td strong a { font-family: var(--font-mono); font-weight: 600; }
.table td.text-end, .table th.text-end { font-variant-numeric: tabular-nums; }
.text-success { color: var(--ok) !important; }
.text-danger { color: var(--stamp) !important; }
.card-table td:first-child, .card-table th:first-child { padding-left: 1rem; }
.card-table td:last-child, .card-table th:last-child { padding-right: 1rem; }

/* =====================================================================
   LONG DOCUMENT LISTS — the column headings ride along
   =====================================================================
   A list runs past a screenful, and by the last row its column names are a
   screen above it: the figures then sit under headings nobody can see. The
   heading row is pinned to the top of the WINDOW instead (beneath the phone
   layout's own bar, whose height app.js measures into --lp-pin-top).

   NOTHING HERE IS A SCROLL BOX. A <th> inside an overflow container sticks
   to THAT container's top, which is exactly what slides off screen when the
   page scrolls; only a plain page can pin a heading to the window. So the
   card clips its sheet (overflow: clip — clipping does not create a
   scrollport, unlike auto or hidden) and the table itself is slid sideways
   by a transform that the slim bar above the footer drives. The Sales
   Summary documents page works the same way. */
/* A browser without `overflow: clip` cannot have both a pinned heading and a
   readable sheet (its only alternatives are visible, which spills the table
   out of the card, or auto, which kills the pin), so it keeps the plain
   scrollable table it always had: the script bails out for the same reason. */
@supports (overflow: clip) {
  .lp-pin-card { overflow: clip; }
  .lp-pin-card .lp-pin-wrap { overflow: visible !important; }
  .lp-pin-card .lp-pin-table thead th {
    position: sticky;
    top: var(--lp-pin-top, 0px);
    z-index: 3;
    background: var(--sheet) !important;
    /* A collapsed border belongs to the table, not the cell, so the rule under
       a pinned heading would stay behind with the rows: it is drawn on the
       cell itself instead. */
    box-shadow: inset 0 -1px 0 var(--rule);
  }
  .lp-pin-card .lp-pin-hscroll {
    position: sticky;
    bottom: 0;
    z-index: 2;
    height: 0.9rem;
    overflow-x: auto;
    overflow-y: hidden;
    background: var(--sheet);
    border-top: 1px solid var(--rule);
  }
  .lp-pin-card .lp-pin-hscroll > div { height: 1px; }
}
@media print {
  /* Paper has no window to pin against: every row and column prints from the
     sheet's left edge, with the table's own heading row repeated per page. */
  .lp-pin-card { overflow: visible !important; }
  .lp-pin-card .lp-pin-wrap { overflow: visible !important; transform: none !important; }
  .lp-pin-card .lp-pin-table thead th { position: static; box-shadow: none; }
  .lp-pin-card .lp-pin-hscroll { display: none !important; }
}

/* =====================================================================
   FORMS
   ===================================================================== */
.form-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: 0.35rem;
}
.form-control, .form-select {
  border-color: var(--rule);
  border-radius: 4px;
  font-size: 0.9rem;
  color: var(--ink-1);
}
.form-control:focus, .form-select:focus {
  border-color: var(--cyan);
  box-shadow: 0 0 0 2px var(--cyan-wash);
}

/* =====================================================================
   READING THE SCREEN — fit, legibility, contrast
   =====================================================================
   Three rules keep every page readable, phone included:

   1. LAYOUT CHILDREN MAY SHRINK. A number input is ~150px wide by default,
      so four of them in a narrow row used to overrun their columns and paint
      on top of each other (the labour fields on the invoice screen).
   2. GAPS NEVER EXCEED THE PADDING THAT HOLDS THEM. A .g-4 row's negative
      margins are half a 32px gutter against 10px of container padding, which
      pushed the row 6px past the window on every page that used one.
   3. SMALL TYPE AND PALE TINTS STAY ABOVE AA on their own wash: 11px is the
      floor, and a status badge is ink on a tint, never a tint on a tint. */

/* 1 — nothing keeps its intrinsic width */
.row > [class*="col"],
.d-flex > *,
.input-group > *,
.btn-list > * { min-width: 0; }

.form-control, .form-select, input, select, textarea {
  min-width: 0;
  max-width: 100%;
}
.form-control, .form-select { width: 100%; }

img, svg, video, canvas { max-width: 100%; }
.table-responsive { min-width: 0; }

/* 2 — gutters follow the page's own padding, so a row can never overhang */
main .row.g-0, main .row.g-1, main .row.g-2,
main .row.g-3, main .row.g-4, main .row.g-5 { --tblr-gutter-x: 1.25rem; }

/* A button label wraps instead of being clipped when its column is narrow:
   a two-line "Find sales" is readable, a cut-off "Find sal…" is not. */
.btn { white-space: normal; }

@media (max-width: 575.98px) {
  .page-title { font-size: 1.4rem; line-height: 1.2; }
  .card-title { font-size: 0.72rem !important; }
  /* A table cell that held its actions on one line used to push the last
     button through the column edge; let them stack instead. */
  .table td.text-nowrap, .table th.text-nowrap { white-space: normal !important; }
  .lp-ledger-label {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    letter-spacing: 0.08em;
  }
}

/* 3 — legibility */
.table thead th { font-size: 0.7rem; }
.footer { font-size: 0.6875rem; }
.navbar-vertical .lp-nav-section,
.lp-mobile-nav .lp-nav-section { font-size: 0.6875rem; color: rgba(245, 247, 246, 0.62); }

/* Status badges: dark ink on the wash, never a pale ink on a pale tint. */
.badge.bg-success-lt, .badge.bg-green-lt { background: var(--ok-wash) !important; color: #1F5C42 !important; }
.badge.bg-danger-lt, .badge.bg-red-lt { background: var(--stamp-wash) !important; color: #93331F !important; }
.badge.bg-warning-lt, .badge.bg-orange-lt, .badge.bg-yellow-lt { background: var(--amber-wash) !important; color: #7A5410 !important; }
.badge.bg-info-lt, .badge.bg-azure-lt, .badge.bg-cyan-lt { background: var(--cyan-wash) !important; color: var(--cyan-deep) !important; }
.badge.bg-secondary-lt, .badge.bg-dark-lt { background: var(--rule-soft) !important; color: var(--ink-1) !important; }

/* Quiet action links carried the loud tint instead of readable ink. */
.btn-ghost-success { color: #1F6045 !important; }
.btn-ghost-warning { color: #7A5410 !important; }
.btn-ghost-danger { color: #A33220 !important; }
.btn-ghost-primary { color: var(--cyan-deep) !important; }
.btn-outline-primary { color: var(--cyan-deep); border-color: var(--cyan); }
.text-warning { color: #7A5410 !important; }

/* =====================================================================
   ALERTS — plain-spoken notices, ink on wash
   ===================================================================== */
.alert {
  border-radius: 6px;
  border: 1px solid transparent;
  font-size: 0.875rem;
}
.alert-success { background: var(--ok-wash); border-color: #CBDEd4; color: #1F5C42; }
.alert-danger { background: var(--stamp-wash); border-color: #EBCBC5; color: #93331F; }
.alert-warning { background: var(--amber-wash); border-color: #E5D6B0; color: #7A5A15; }
.alert-info { background: var(--cyan-wash); border-color: #C4DDE0; color: #0A5A62; }

/* =====================================================================
   LOGIN — two dresses. Default: the ink counter (dark panel + paper
   column). With a background image (Settings → Login Screen): the photo
   fills the frame and the counter sits on its empty side.
   ===================================================================== */
.lp-auth {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  background: var(--paper);
}
.lp-auth-panel {
  background: var(--ink-0);
  color: #F5F7F6;
  padding: 3rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
}

/* ---------- image mode ---------- */
/* The URL is handed in by the view as --lp-art, so it still travels through
   asset()'s / url() cache-busting. */
.lp-auth--art {
  position: relative;
  background-color: #EDE7DD;
  background-image: var(--lp-art, none);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
@supports (min-height: 100svh) {
  .lp-auth--art { min-height: 100svh; }
}

/* a breath of veil, light at the top where the type sits and a little heavier
   at the foot under the spec lines — the middle of the frame, the goods
   themselves, is left as it was shot */
.lp-auth--art::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(252, 250, 246, 0.46) 0%,
    rgba(252, 250, 246, 0.14) 38%,
    rgba(252, 250, 246, 0.18) 68%,
    rgba(252, 250, 246, 0.6) 100%);
}
/* the type sits straight on the picture, so it carries its own halo */
.lp-auth--art .lp-auth-panel {
  background: none;
  color: var(--ink-1);
  text-shadow: 0 0 22px rgba(252, 250, 246, 0.95), 0 0 44px rgba(252, 250, 246, 0.7);
}
.lp-auth--art .lp-auth-side { z-index: 1; }
.lp-auth-panel h1 {
  color: #F5F7F6;
  font-size: clamp(1.7rem, 2.6vw, 2.4rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  max-width: 18ch;
}
.lp-auth-panel .lp-accent { color: var(--cyan); }
.lp-auth--art .lp-auth-panel h1 { color: var(--ink-0); }
.lp-auth--art .lp-auth-panel .lp-accent { color: var(--cyan-deep); }
.lp-auth-copy {
  color: rgba(245, 247, 246, 0.66);
  font-size: 0.925rem;
  max-width: 44ch;
  margin-top: 1rem;
}
.lp-auth--art .lp-auth-copy { color: rgba(16, 20, 24, 0.78); }
.lp-auth-spec {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(245, 247, 246, 0.45);
}
.lp-auth-spec div { margin-top: 0.5rem; }
.lp-auth--art .lp-auth-spec { color: rgba(16, 20, 24, 0.64); }
.lp-auth-side { display: flex; align-items: center; justify-content: center; padding: 2rem; position: relative; }
.lp-auth-card { width: 100%; max-width: 400px; }
.lp-auth-card .card { border-radius: 8px; }
.lp-auth--art .lp-auth-card .card {
  border-color: rgba(16, 20, 24, 0.08);
  box-shadow: 0 26px 60px -34px rgba(16, 20, 24, 0.65);
}
.lp-auth-card .card-body { padding: 2rem; }

/* the builder's mark — one quiet ink bar pinned to the bottom of the frame,
   so it reads on the dark panel, on the paper column and over any photo */
.lp-auth-footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35em;
  padding: 0.55rem 1rem;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(245, 247, 246, 0.66);
  background: rgba(16, 20, 24, 0.82);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.lp-auth-footer a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.lp-auth-footer a:hover { color: var(--cyan); }

/* the same builder's mark inside the app (light paper instead of dark bar) */
.lp-brand-footer {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.lp-brand-footer a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.lp-brand-footer a:hover { color: var(--cyan); }

.lp-auth-tagline {
  text-align: center;
  margin: 0.875rem 0 0;
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.lp-auth--art .lp-auth-tagline {
  color: rgba(16, 20, 24, 0.68);
  text-shadow: 0 0 18px rgba(252, 250, 246, 0.95);
}

/* registration crosshairs, quiet, corners of the panel */
.lp-reg {
  position: absolute;
  width: 14px;
  height: 14px;
  border: 1px solid rgba(245, 247, 246, 0.22);
  border-radius: 50%;
}
.lp-reg::before, .lp-reg::after {
  content: "";
  position: absolute;
  background: rgba(245, 247, 246, 0.22);
}
/* over the picture the hairlines go to ink */
.lp-auth--art .lp-reg { border-color: rgba(16, 20, 24, 0.16); }
.lp-auth--art .lp-reg::before, .lp-auth--art .lp-reg::after { background: rgba(16, 20, 24, 0.16); }
.lp-reg::before { left: 50%; top: -5px; bottom: -5px; width: 1px; transform: translateX(-0.5px); }
.lp-reg::after { top: 50%; left: -5px; right: -5px; height: 1px; transform: translateY(-0.5px); }
.lp-reg.tl { top: 18px; left: 18px; }
.lp-reg.tr { top: 18px; right: 18px; }
.lp-reg.bl { bottom: 18px; left: 18px; }
.lp-reg.br { bottom: 18px; right: 18px; }

/* Phones and small tablets: one column, the card below the copy. */
@media (max-width: 991.98px) {
  .lp-auth { grid-template-columns: 1fr; }
  .lp-auth-panel { padding: 2rem; min-height: 0; }
  .lp-auth-panel h1 { font-size: 1.5rem; max-width: none; }
  .lp-auth-copy { display: none; }
  .lp-auth-spec { display: none; }
  .lp-auth-side { padding: 1.5rem; }
  .lp-reg { display: none; }

  /* image mode: a phone-sized frame is too narrow to hold both the goods and
     the empty wall, so the crop keeps the goods visible behind the card (the
     copy sits on the wall above them) and the card row takes the rest of the
     screen. */
  .lp-auth--art {
    grid-template-rows: auto 1fr;
    background-position: 32% center;
  }
  .lp-auth--art::before {
    background: linear-gradient(180deg,
      rgba(252, 250, 246, 0.34) 0%,
      rgba(252, 250, 246, 0.16) 45%,
      rgba(252, 250, 246, 0.36) 100%);
  }
  .lp-auth--art .lp-auth-panel { padding: 1.75rem 1.5rem 0; }
  .lp-auth--art .lp-auth-side { padding: 1.5rem 1.5rem 2rem; }
  .lp-auth-card .card-body { padding: 1.5rem; }

  /* the footer still has to clear the card on a short phone screen */
  .lp-auth,
  .lp-auth--art { padding-bottom: 2.4rem; }
  .lp-auth-footer { font-size: 0.5625rem; padding: 0.45rem 0.75rem; }
}

/* =====================================================================
   ORCHESTRATED LOAD — rules draw, ink settles. Once, quietly.
   Stagger via --i (child index); fluid cubic-bezier per motion baseline.
   ===================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .lp-ledger { animation: lp-ink-in 0.35s ease-out both; }
  .lp-titleblock { animation: lp-ink-in 0.3s ease-out both; }
  .page-body .card {
    animation: lp-sheet-in 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
    animation-delay: calc(var(--i, 0) * 60ms);
  }
  .page-body .lp-rcard {
    animation: lp-sheet-in 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
    animation-delay: calc(var(--i, 0) * 45ms);
  }
  .lp-ledger-cell {
    animation: lp-ink-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
    animation-delay: calc(var(--i, 0) * 40ms);
  }
  @keyframes lp-ink-in {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: none; }
  }
  @keyframes lp-sheet-in {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
  }
}

/* Fluid transitions everywhere (motion baseline: fluid, spring-like decay). */
.btn, .lp-rcard, .dropdown-item, .form-control, .form-select, .nav-link {
  transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Tactile feedback: buttons physically push in. */
.btn:active { transform: translateY(1px) scale(0.98); }
.lp-rcard:active { transform: translateY(0) scale(0.99); }

/* Hover lift on interactive sheets — one consistent light source above. */
.lp-rcard:hover,
.card-hover:hover {
  box-shadow: 0 10px 24px -14px rgba(14, 124, 134, 0.35); /* cyan-tinted, not black */
  transform: translateY(-1px);
}

/* =====================================================================
   SKELETONS — matching layout shapes, shimmer in ink tones
   ===================================================================== */
.lp-skel {
  position: relative;
  overflow: hidden;
  background: var(--rule-soft);
  border-radius: 4px;
  color: transparent !important;
  pointer-events: none;
  user-select: none;
}
.lp-skel::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.65), transparent);
  animation: lp-shimmer 1.4s infinite;
}
@keyframes lp-shimmer {
  to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .lp-skel::after { animation: none; }
}

/* =====================================================================
   EMPTY STATES — an invitation, not a shrug
   ===================================================================== */
.lp-empty {
  text-align: center;
  padding: 2.5rem 1.5rem;
}
.lp-empty-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--rule);
  border-radius: 50%;
  color: var(--ink-2);
}
.lp-empty-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--ink-1);
}
.lp-empty-text {
  font-size: 0.8125rem;
  color: var(--ink-2);
  max-width: 42ch;
  margin: 0.25rem auto 0;
}

/* =====================================================================
   NOTIFICATIONS
   ===================================================================== */
.lp-notif-menu { width: 340px; max-width: 90vw; border-radius: 8px; overflow: hidden; }
.lp-notif-list { max-height: 320px; overflow-y: auto; }
.lp-notif-item {
  display: flex;
  gap: 0.65rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--rule-soft);
  text-decoration: none;
  transition: background 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.lp-notif-item:last-child { border-bottom: 0; }
.lp-notif-item:hover { background: var(--paper); text-decoration: none; }
.lp-notif-item.is-unread { background: var(--cyan-wash); }
.lp-notif-item.is-unread:hover { background: #D8E9EB; }
.lp-notif-dot {
  flex: 0 0 8px;
  width: 8px;
  height: 8px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--rule);
}
.lp-notif-item.is-unread .lp-notif-dot { background: var(--cyan); }
.lp-notif-title { font-size: 0.8125rem; font-weight: 600; color: var(--ink-0); }
.lp-notif-body { font-size: 0.75rem; color: var(--ink-2); margin-top: 1px; }
.lp-notif-time {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-top: 3px;
}

/* =====================================================================
   MISC + PRINT
   ===================================================================== */

/* =====================================================================
   REPORTS HUB — grouped index with ruled section headers
   ===================================================================== */
.lp-rsection { margin-bottom: 2rem; }

.lp-rsection-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.9rem;
}

.lp-rsection-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-0);
}

.lp-rsection-rule {
  flex: 1;
  height: 1px;
  background: var(--rule);
  position: relative;
  top: -0.2rem;
}

.lp-rsection-note {
  font-size: 0.75rem;
  color: var(--ink-2);
  white-space: nowrap;
}

.lp-rcard {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 0.95rem 1rem;
  height: 100%;
  text-decoration: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.lp-rcard:hover {
  border-color: var(--cyan);
  box-shadow: 0 2px 10px rgba(14, 124, 134, 0.1);
  transform: translateY(-1px);
  text-decoration: none;
}

.lp-rcard:hover .lp-rarrow { color: var(--cyan); transform: translateX(2px); }

.lp-rcard:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

.lp-ricon {
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--cyan-wash);
  color: var(--cyan-deep);
  border-radius: 5px;
}

.lp-rbody { min-width: 0; display: block; }

.lp-rtitle {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--ink-0);
  line-height: 1.25;
}

.lp-rdesc {
  display: block;
  font-size: 0.75rem;
  color: var(--ink-2);
  margin-top: 0.15rem;
  line-height: 1.35;
}

.lp-rarrow {
  margin-left: auto;
  flex: 0 0 auto;
  color: var(--rule);
  transition: color 0.15s ease, transform 0.15s ease;
}

.lp-rfootnote {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--ink-2);
  border-top: 1px dashed var(--rule);
  padding-top: 0.9rem;
}

@media (max-width: 575.98px) {
  .lp-rsection-note { display: none; }
}

/* =====================================================================
   MISC + PRINT
   ===================================================================== */
.list-group-item { border-color: var(--rule-soft); }
.footer { background: transparent; color: var(--ink-2); font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.08em; }
.dropdown-menu { border-color: var(--rule); border-radius: 6px; }
.dropdown-item:active { background: var(--cyan); }
.pagination .page-link { font-family: var(--font-mono); font-size: 0.8125rem; }
.empty { color: var(--ink-2); }

@media print {
  .navbar-vertical, header.navbar, .btn-list, .btn, footer.footer,
  .alert, form.card-body .row, .d-print-none { display: none !important; }
  .page { padding: 0; }
  .card { border: none; box-shadow: none; }
  .inv-builder-col, .inv-preview-col { display: block !important; width: 100% !important; max-width: 100% !important; flex: 0 0 100% !important; }
  .inv-builder-col { display: none !important; }
  /* The live preview prints the A4 sheet at its real size: no scroll box, no
     fitted scale, no card chrome around the paper. */
  .inv-preview-wrap { position: static; overflow: visible !important; max-height: none !important; padding: 0; border: 0; background: none; }
  .inv-paper-fit { position: static; width: auto !important; height: auto !important; }
  .inv-paper-fit > .inv-sheet { position: static; }
  .inv-preview-wrap .inv-sheet { transform: none !important; margin-bottom: 0 !important; box-shadow: none; }
  main, .container-xl { max-width: 100% !important; padding: 0 !important; }
  body { background: #fff !important; }
  .lp-ledger { border-color: #000; }
  /* A grid row's negative margins have no padding to sit inside on paper:
     they pushed printed pages 8px wider than the sheet on both sides. Every
     row prints flush, inside the @page margin below. */
  .row { margin-left: 0 !important; margin-right: 0 !important; }
  .row > [class*="col"] { padding-left: 0 !important; padding-right: 0 !important; }
  .nav-tabs, .card-header-tabs, .pagination, .page-title-sub { display: none !important; }
  /* Nothing may be cut off on paper: a sheet prints whole. */
  .table-responsive { overflow: visible !important; }
  .table { width: 100% !important; max-width: 100% !important; }
  a { color: inherit !important; text-decoration: none !important; }
  .text-secondary { color: #444 !important; }
}

/* Paper has a margin of its own; the views that print a bespoke sheet declare
   their own @page and override this one. */
@page { margin: 10mm; }

/* =====================================================================
   SALES SUMMARY PAPER — .lp-summary-print
   The summary sheet is read like the office's own ledger: fourteen money
   columns on one landscape page. Its rules live here (not in the view) because
   two pages print this table — the report itself and the print pack that adds
   the document list behind it — and a figure must not be laid out two ways.
   Each page still declares its own @page, because the pack reserves a margin
   band for its footer and this one does not. */
@media print {
  .lp-summary-print .table-responsive { overflow: visible !important; }
  .lp-summary-print .table-responsive::-webkit-scrollbar { display: none !important; }
  .lp-summary-print .table {
    width: 100% !important; max-width: 100% !important;
    table-layout: fixed; font-size: 6.8pt; margin: 0 !important;
  }
  .lp-summary-print th, .lp-summary-print td {
    padding: 2px 3px !important;
    font-size: 6.8pt;
    border: 1px solid #8a8a8a !important;
    /* Wrap inside the column rather than widen the sheet past the page. */
    white-space: normal !important;
    overflow-wrap: break-word;
    vertical-align: top !important;
  }
  .lp-summary-print thead th { font-size: 6pt; line-height: 1.1; }
  .lp-summary-print thead th:first-child { width: 12%; }
  .lp-summary-print thead { display: table-header-group; }
  .lp-summary-print tfoot { display: table-row-group; }
  .lp-summary-print tr { break-inside: avoid; page-break-inside: avoid; }
  .lp-summary-print a { color: inherit !important; text-decoration: none !important; }
  .lp-summary-print .card-body { padding: 0 !important; }
}

/* =====================================================================
   REPORT PRINT SHEET — .lp-print-sheet
   A summary report whose table lives inside a .table-responsive box prints
   only the columns that happened to fit the window (the rest, and the
   sideways scrollbar, are simply not on the sheet), and with auto layout a
   run of no-wrap number columns pushes the table past the paper edge. Any
   report card that carries this class gets the same paper treatment: the
   scroll box is opened, the table is laid out to the page width with fixed
   columns, and type/padding shrink so a month of rows still reads on a
   couple of landscape sheets instead of one row per page.

   Each view keeps its own @page rule (invoice print needs portrait A4) and
   only the column widths its own headings need; everything shared is here.
   Two narrower variants exist for the sheets that carry the most figures:
   .lp-print-tight (the salesman summary) and .lp-print-tiny, which a view
   asks for once its own column count would squeeze a crore figure into a
   column too narrow to hold it whole. */
@media print {
  .lp-print-sheet .table-responsive { overflow: visible !important; }
  .lp-print-sheet .table-responsive::-webkit-scrollbar { display: none !important; }
  .lp-print-sheet .table {
    width: 100% !important;
    max-width: 100% !important;
    table-layout: fixed;
    font-size: 6.8pt;
    margin: 0 !important;
  }
  .lp-print-sheet .table th,
  .lp-print-sheet .table td {
    padding: 1px 2px !important;
    font-size: 6.8pt;
    line-height: 1.18;
    border: 1px solid #8a8a8a !important;
    /* Wrapping (with a break-word fallback) keeps a long party or document
       name inside its own column instead of widening the sheet. */
    white-space: normal !important;
    overflow-wrap: break-word;
    /* TOP, not middle: a two-line name would otherwise float the row's
       figures halfway down, so a printed row no longer reads as one record.
       !important because Tabler's table-vcenter pins every cell to middle. */
    vertical-align: top !important;
  }
  .lp-print-sheet .table thead th { font-size: 6pt; line-height: 1.1; letter-spacing: 0; }
  /* The heading row repeats on every sheet, the totals row closes the table. */
  .lp-print-sheet .table thead { display: table-header-group; }
  .lp-print-sheet .table tfoot { display: table-row-group; }
  .lp-print-sheet .table tr { break-inside: avoid; page-break-inside: avoid; }
  .lp-print-sheet .table a { color: inherit !important; text-decoration: none !important; }
  .lp-print-sheet .table .badge {
    border: 1px solid #666; color: #000 !important; background: none !important;
    font-size: 4.8pt; padding: 0 1px; line-height: 1.15;
  }
  /* Figures keep the right edge they have on screen. */
  .lp-print-sheet .table .text-end { text-align: right !important; }
  .lp-print-sheet .table .small,
  .lp-print-sheet .table td div.small { font-size: 5.6pt; line-height: 1.15; }
  /* The second line under a party's name (his code, company, phone) becomes a
     suffix on that same line on paper: a two-line cell doubles the height of
     every row, and on a sixty-row statement that is a whole extra sheet. */
  .lp-print-sheet .table td > div.small { display: inline; }
  .lp-print-sheet .table td > div.small::before { content: ' · '; }
  .lp-print-sheet .card-body { padding: 0 !important; }
  .lp-print-sheet.lp-print-tight .table,
  .lp-print-sheet.lp-print-tight .table th,
  .lp-print-sheet.lp-print-tight .table td { font-size: 5.4pt; }
  .lp-print-sheet.lp-print-tight .table thead th { font-size: 5pt; }
  .lp-print-sheet.lp-print-tight .table td div.small { font-size: 4.6pt; }
  /* Past ~18 columns even the tight step cannot hold a crore figure in one
     column, and a figure broken mid-number is not readable at all: the
     views that can grow that wide (the salesman summary, one column per
     expense box) ask for this last step by counting their own columns. */
  .lp-print-sheet.lp-print-tiny .table,
  .lp-print-sheet.lp-print-tiny .table th,
  .lp-print-sheet.lp-print-tiny .table td { font-size: 4.6pt; }
  .lp-print-sheet.lp-print-tiny .table thead th { font-size: 4.4pt; }
  .lp-print-sheet.lp-print-tiny .table td div.small { font-size: 4pt; }
}

/* =====================================================================
   INVOICE BUILDER — live A4 preview ("Smart Invoice Studio" UX,
   restyled in the Ink Ledger identity)
   ===================================================================== */
.inv-preview-wrap {
  background: repeating-linear-gradient(45deg, var(--paper), var(--paper) 10px, #ECF0EF 10px, #ECF0EF 20px);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 1.25rem;
  display: flex;
  justify-content: center;
  overflow: auto;
  /* Reserve the scrollbar's width whether or not it is showing: the fitted
     scale is computed from clientWidth, and a gutter that appeared and
     vanished as the sheet was resized would make that measurement jump. */
  scrollbar-gutter: stable;
  max-height: calc(100vh - 160px);
  position: sticky;
  top: 1rem;
}
.inv-sheet {
  width: 210mm;
  min-height: 297mm;
  background: #fff;
  color: var(--ink-1);
  box-shadow: 0 20px 25px -5px rgba(16, 20, 24, .08), 0 8px 10px -6px rgba(16, 20, 24, .05);
  padding: 14mm;
  font-family: var(--font-body);
  font-size: 12.5px;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  transform-origin: top center;
}
.inv-sheet .inv-sheet-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  border-bottom: 3px solid var(--cyan);
  padding-bottom: 12px;
}
.inv-sheet .inv-sheet-brand h2 { font-family: var(--font-display); font-size: 26px; margin: 0; color: var(--ink-0); letter-spacing: -0.02em; }
.inv-sheet .inv-sheet-brand .inv-sub { font-family: var(--font-mono); font-size: 10px; letter-spacing: .08em; color: var(--cyan); text-transform: uppercase; }
.inv-sheet .inv-sheet-meta { text-align: right; }
.inv-sheet .inv-sheet-meta .inv-doc-label { font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--ink-0); letter-spacing: .04em; }
.inv-sheet .inv-sheet-meta .inv-doc-number { font-family: var(--font-mono); color: var(--cyan-deep); font-size: 13px; }
.inv-sheet .inv-sheet-meta .inv-doc-line { font-size: 11px; color: var(--ink-2); }
.inv-sheet .inv-parties { display: flex; justify-content: space-between; gap: 24px; margin: 18px 0; }
.inv-sheet .inv-party h4 { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2); margin: 0 0 4px; }
.inv-sheet .inv-party .inv-name { font-weight: 600; color: var(--ink-0); font-size: 14px; }
.inv-sheet .inv-party .inv-line { font-size: 11.5px; color: var(--ink-2); }
.inv-sheet table.inv-items { width: 100%; border-collapse: collapse; margin-top: 4px; }
.inv-sheet table.inv-items th {
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-2); text-align: left; padding: 7px 8px; border-bottom: 2px solid var(--ink-0);
  background: var(--rule-soft);
}
.inv-sheet table.inv-items td { padding: 7px 8px; border-bottom: 1px solid var(--rule-soft); font-size: 12px; }
.inv-sheet table.inv-items .num { text-align: right; font-family: var(--font-mono); font-size: 11.5px; }
.inv-sheet .inv-totals { margin-left: auto; width: 300px; margin-top: 14px; }
.inv-sheet .inv-totals table { width: 100%; border-collapse: collapse; }
.inv-sheet .inv-totals td { padding: 4px 8px; font-size: 12px; }
.inv-sheet .inv-totals td.num { text-align: right; font-family: var(--font-mono); }
.inv-sheet .inv-totals tr.inv-grand td {
  border-top: 2px solid var(--ink-0); font-weight: 700; font-size: 15px;
  font-family: var(--font-display); color: var(--ink-0); padding-top: 8px;
}
.inv-sheet .inv-totals .inv-profit-chip {
  display: inline-block; margin-top: 6px; padding: 2px 10px;
  font-family: var(--font-mono); font-size: 10px; border-radius: 999px;
}
.inv-sheet .inv-sheet-foot {
  margin-top: auto; padding-top: 14px; border-top: 1px dashed var(--rule);
  font-size: 10.5px; color: var(--ink-2); display: flex; justify-content: space-between; gap: 16px;
}
.inv-sheet .inv-stamp {
  /* Status stamp as a BIG background watermark: diagonal across the sheet,
     heavily faded (multiply blend keeps content under it readable). */
  position: absolute; top: 48%; left: 50%; z-index: 0;
  transform: translate(-50%,-50%) rotate(-22deg);
  font-family: var(--font-display); font-weight: 800; font-size: 68px;
  letter-spacing: .14em; text-transform: uppercase; line-height: 1.05;
  width: 92%; text-align: center; white-space: normal;
  opacity: .12; mix-blend-mode: multiply; pointer-events: none;
}
/* Scale the sheet to FIT its column at any width — no clipping, no
   horizontal scrollbar (the old fixed .82/.72 breakpoints still overflowed
   on hosting layouts). fitSheet() in the builder AND in the edit page writes
   --js-sheet-scale from the column's real width; the values below are only
   the no-JS fallback.

   The column must be allowed to shrink (min-width: 0) or a grid child keeps
   the 210mm sheet's width and the whole page overflows sideways instead of
   the paper shrinking — that is what a browser zoom looked like before.

   A transform does not change the element's layout box, so the sheet sits
   absolutely inside .inv-paper-fit and JavaScript gives THAT box the scaled
   width and height. Without it the wrap still holds a 210mm-wide layout box
   and shows a sideways scrollbar even though the paper looks small. */
.inv-preview-col { min-width: 0; }
.inv-preview-wrap { --sheet-scale: 1; max-width: 100%; align-items: flex-start; }
.inv-preview-wrap .inv-sheet {
  transform: scale(var(--js-sheet-scale, var(--sheet-scale)));
  margin-bottom: calc((var(--js-sheet-scale, var(--sheet-scale)) - 1) * 297mm);
}
/* Papers that fit themselves (create page): the sheet sits in a box of the
   SCALED size, so no layout width is left over to scroll or overflow. */
.inv-paper-fit { position: relative; flex: 0 0 auto; }
.inv-paper-fit > .inv-sheet {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  margin-bottom: 0;
}
@media (max-width: 991.98px) {
  .inv-preview-wrap { --sheet-scale: .62; }
}
@media (max-width: 575.98px) {
  .inv-preview-wrap { --sheet-scale: .45; }
}

/* =====================================================================
   MOBILE DATA-ENTRY — item lines become labelled cards
   On phones the classic ledger table is too cramped: the Qty box shrinks
   to a sliver (the screenshot complaint: "can't see what he entered") and
   the on-screen keyboard covers the row being typed. Below 768px each
   line renders as a stacked card with a mono label above every field,
   inputs use a 16px font so iOS Safari never auto-zooms on focus, and
   the ✕ button floats in the card corner instead of eating a column.
   Desktop (>767px) is untouched — data-label attributes are inert there.
   ===================================================================== */
@media (max-width: 767.98px) {
  /* 16px stops iOS Safari from zooming the page into inputs on focus. */
  .form-control, .form-select { font-size: 16px; }

  .lp-items-table { border: 0; }
  .lp-items-table thead { display: none; }
  .lp-items-table,
  .lp-items-table tbody { display: block; width: 100%; }
  .lp-items-table tr {
    display: block;
    position: relative;
    padding: 0.55rem 2.4rem 0.75rem 0.75rem;
    margin: 0 0 0.75rem;
    border: 1px solid var(--rule);
    border-radius: 6px;
    background: var(--sheet);
  }
  .lp-items-table tr:last-child { margin-bottom: 0; }
  .lp-items-table td {
    display: block;
    width: 100%;
    padding: 0.3rem 0;
    border: 0;
    text-align: left !important;
  }
  .lp-items-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-family: var(--font-mono);
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-2);
    margin-bottom: 0.25rem;
  }
  /* Plain text cells (available stock, line totals…) read as values, not captions. */
  .lp-items-table td.avail,
  .lp-items-table td.line-total,
  .lp-items-table td.holding {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ink-1);
  }
  /* The ✕ remove button floats in the card corner instead of its own full row. */
  .lp-items-table td:last-child {
    position: absolute;
    top: 0.3rem;
    right: 0.35rem;
    width: auto;
  }

  /* A header that carries eight action buttons used to squeeze its own title
     into a one-letter column ("I T E M S" stacked on the invoice page). The
     title keeps the whole row; the buttons wrap onto their own lines. */
  .card-header { flex-wrap: wrap; gap: 0.5rem; }
  .card-header .card-title { flex: 1 1 100%; }
  .card-header .btn-list {
    width: 100%;
    margin-left: 0 !important;
    flex-wrap: wrap;
    gap: 0.4rem;
  }
  .card-header .btn-list .btn { flex: 1 1 auto; }
  /* Action bars wrap instead of overlapping the Total (seen on the sale form). */
  .card-footer.d-flex { flex-wrap: wrap; gap: 0.5rem; }
  .card-footer .btn-list { width: 100%; flex-wrap: wrap; gap: 0.5rem; }
  .card-footer .btn-list .btn { flex: 1 1 40%; }
}

/* =====================================================================
   INLINE PRICE EDITING — products list. Editable cells read like data,
   not buttons: a pencil appears on hover, the cell gets a dashed underline.
   ===================================================================== */
.lp-edit-hint { font-size: 0.6875rem; opacity: 0.45; cursor: help; }

.lp-price-cell {
  cursor: text;
  font-variant-numeric: tabular-nums;
  position: relative;
}
.lp-price-cell:hover {
  background: var(--cyan-wash, rgba(14, 124, 134, 0.06));
  box-shadow: inset 0 0 0 1px var(--cyan, #0E7C86);
}
.lp-price-cell::after {
  content: "✎";
  position: absolute;
  left: 0.35rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.6875rem;
  opacity: 0;
  transition: opacity 0.12s ease;
  pointer-events: none;
  color: var(--cyan, #0E7C86);
}
.lp-price-cell:hover::after { opacity: 0.7; }

.lp-price-input {
  max-width: 130px;
  font-family: var(--font-mono);
}

.lp-price-saving { opacity: 0.55; pointer-events: none; }

@keyframes lp-price-flash {
  0% { background: rgba(47, 133, 90, 0.28); }
  100% { background: transparent; }
}
.lp-price-flash { animation: lp-price-flash 1.1s ease forwards; }

/* Generic inline editing (lists): the same click-to-edit feel for text,
   number, date and select cells across every list page. */
/* A cell that *looks* editable elsewhere but is frozen here (e.g. a stock-in
   quantity whose stock has already been issued). */
.lp-locked-mark { font-size: 0.75rem; opacity: 0.5; cursor: help; }
.lp-inline {
  cursor: text;
  display: inline-block;
  max-width: 100%;
  border-radius: 3px;
}
.lp-inline:hover {
  background: var(--cyan-wash, rgba(14, 124, 134, 0.06));
  box-shadow: inset 0 0 0 1px var(--cyan, #0E7C86);
}
.lp-inline-block { display: block; }
.lp-inline-num { font-variant-numeric: tabular-nums; }
.lp-inline-input { max-width: 190px; }
.lp-inline-saving { opacity: 0.55; pointer-events: none; }

/* Customer list: the name is a link to the customer's page, so the rename
   editor sits on a small pencil beside it instead of on the name itself
   (clicking the name must navigate, not open an editor). */
.lp-name-edit {
  font-size: 0.6875rem;
  line-height: 1;
  margin-left: 0.3rem;
  opacity: 0.35;
  vertical-align: 1px;
  cursor: text;
}
.lp-name-edit:hover { opacity: 0.9; }

@keyframes lp-inline-error {
  0%, 100% { background: transparent; }
  30% { background: rgba(214, 57, 57, 0.22); }
}
.lp-inline-error { animation: lp-inline-error 0.5s ease 2; }

@keyframes lp-price-error {
  0% { background: rgba(214, 57, 57, 0.25); }
  100% { background: transparent; }
}
.lp-price-error { animation: lp-price-error 1.4s ease forwards; }

/* Stock Out list row states. Red (sale+invoice deleted) wins over the
   light-blue "invoice pending" wash; both stay readable on hover. */
tr.lp-row-invpending > td {
  background: rgba(14, 124, 134, 0.07); /* light blue wash */
}
tr.lp-row-invpending > td .lp-inline:hover,
tr.lp-row-invpending > td a.lp-inline {
  background: transparent;
}
/* A REVERSED document — a deleted/reversed sale (lp-row-saledel) or a
   reversed stock receipt (lp-row-reversed). It is kept for the audit trail but
   is no longer real stock movement, so a light red wash says so at a glance. */
tr.lp-row-saledel > td,
tr.lp-row-reversed > td {
  background: rgba(214, 57, 57, 0.10); /* light red wash */
  text-decoration-color: rgba(214, 57, 57, 0.4);
}

/* =====================================================================
   PRODUCT PICKER — searchable combobox for item lines
   A native <select> is unusable once the catalogue grows: hundreds of rows
   to scroll, no way to type a name or SKU, and no hint of what is in stock.
   The line's picker filters as you type and shows live stock beside every
   product; the chosen id still posts through the hidden input.
   ===================================================================== */
.lp-picker { position: relative; }
.lp-picker-input { cursor: text; }
.lp-picker-menu {
  position: fixed;               /* escapes the responsive table's overflow */
  z-index: 1080;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 8px;
  box-shadow: 0 14px 34px rgba(16, 20, 24, 0.18);
  padding: 4px;
}
.lp-picker-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.5rem;
  border-radius: 6px;
  cursor: pointer;
}
.lp-picker-item.is-active,
.lp-picker-item:hover { background: var(--cyan-wash); }
.lp-picker-item.is-selected .lp-picker-name { font-weight: 600; }
.lp-picker-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lp-picker-sku {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--ink-2);
}
.lp-picker-stock {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--ok);
  white-space: nowrap;
}
.lp-picker-stock.is-out { color: var(--stamp); }
.lp-picker-empty,
.lp-picker-more {
  padding: 0.4rem 0.5rem;
  font-size: 0.75rem;
  color: var(--ink-2);
}

/* ---------------------------------------------------------------------------
   "Viewing as" bar (Admin → Users → Sign in as).
   Shown on every page while the shop is being looked at through another
   user's account. It is deliberately loud: the one mistake worth preventing
   is forgetting whose account you are in and acting in someone else's name.
   --------------------------------------------------------------------------- */
.lp-viewas-bar {
  background: var(--stamp, #b4231f);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 1040;
}
.lp-viewas-bar .text-secondary { color: rgba(255, 255, 255, 0.75) !important; }
.lp-viewas-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.25);
  flex: 0 0 auto;
}
@media print { .lp-viewas-bar { display: none; } }

/* =====================================================================
   READABILITY & FIT — the second pass over the whole app
   =====================================================================
   The ledger identity stays; what changes is that every word has to be
   READ, at 320px as much as at 1440px. Four rules drive this block:

   1. SECONDARY INK IS DARK ENOUGH. 11px grey on a pale wash was the
      smallest thing on the page and the first thing to disappear. Labels
      and hints move up a size and a shade.
   2. A LABEL AND ITS BOX ARE ONE UNIT. Field rows used to align on their
      label's TOP, so a label that wrapped to two lines dropped its input
      half a line below its neighbours (the labour row on the invoice
      screen). Fields now align on the INPUT, whatever the label does.
   3. A FIELD NEVER SHRINKS BELOW ITS CONTENT. Dates and placeholders were
      being clipped ("08-Sep-2", "Invoice # / c"); on a phone a date field
      takes the whole row instead.
   4. TOUCH TARGETS ARE 38px. Anything you tap on a phone is at least that
      tall, so a mistyped figure stops being a thumbnail problem.
   ===================================================================== */

:root {
  /* Deeper secondary ink + a slightly cooler sheet: same palette, more
     contrast where the eye needs it (hints, captions, table headings). */
  --ink-2: #46525C;
  --paper: #EFF2F1;
  --rule: #D2D9D7;
  --rule-soft: #E6EBE9;
  --tblr-border-color: #D2D9D7;
}

/* -- 1. text that has to be read -------------------------------------- */
.form-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.045em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--ink-1);
  margin-bottom: 0.3rem;
  overflow-wrap: break-word;
}
.form-label .text-secondary { color: var(--ink-2) !important; }

.form-hint,
.form-text {
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--ink-2);
}

/* Tabler paints secondary text through a token; the token itself is the
   cleanest place to raise the contrast everywhere at once. */
.text-secondary,
.text-muted {
  color: var(--ink-2) !important;
}

/* -- 2. inputs --------------------------------------------------------- */
.form-control,
.form-select {
  min-height: 2.4rem;
  padding: 0.42rem 0.6rem;
  font-size: 0.9375rem;
  color: var(--ink-0);
  border-color: var(--rule);
  background-color: var(--sheet);
}
.form-control::placeholder { color: #707C86; opacity: 1; }
.form-control:disabled,
.form-select:disabled {
  background-color: var(--paper);
  color: var(--ink-1);
  opacity: 1;
}
.form-control[readonly] { background-color: var(--paper); }
.form-select { padding-right: 2rem; }

/* A field is a column that ends with its input: when one label wraps and its
   neighbour does not, both inputs still sit on the same line. */
.lp-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: 0.9rem 1rem;
  align-items: stretch;
}
.lp-fields > * {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-width: 0;
}
.lp-fields > .lp-field-full { grid-column: 1 / -1; }
.lp-fields .form-hint { margin-top: 0.3rem; }

/* A card's heading with one sentence of orientation under it, stacked (a
   heading with a paragraph pinned to its right was being pushed into two
   lines and read as two headings). */
.lp-card-lead { margin-bottom: 0.75rem; }
.lp-card-note {
  margin: 0.25rem 0 0;
  max-width: 62ch;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--ink-2);
}

/* Two fields and their button on one line: the button is only as wide as it
   needs to be, so "Find sales" stays on one line instead of breaking in two. */
.lp-fields-inline { grid-template-columns: repeat(2, minmax(0, 1fr)) auto; }
@media (max-width: 575.98px) {
  .lp-fields-inline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lp-fields-inline > :last-child { grid-column: 1 / -1; }
  .lp-fields-inline > :last-child .form-label { display: none; }
}

/* A figure the form works out for you (labour total). It is not a box you
   can type in, so it does not look like one: no fill, a dotted rule, the
   word AUTO beside it. */
.lp-calc {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 2.4rem;
  padding: 0.42rem 0.6rem;
  border: 1px dashed #BFCFCC;
  border-radius: 4px;
  background: var(--paper);
}
.lp-calc-tag {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.lp-calc-figure {
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink-0);
  font-variant-numeric: tabular-nums;
}

/* -- 3. nothing is clipped -------------------------------------------- */
/* A date box carries 11 characters plus a picker glyph; in half a phone it
   was cut to "08-Sep-2". It takes the row. */
@media (max-width: 575.98px) {
  main .row > [class*="col-6"]:has(> input[type="date"]),
  main .row > [class*="col-6"]:has(> input[type="time"]),
  main .row > [class*="col-6"]:has(> input[type="datetime-local"]),
  main .row > [class*="col-6"]:has(> .form-label + input[type="date"]),
  main .row > [class*="col-6"]:has(> .form-label + input[type="time"]) {
    width: 100%;
    max-width: 100%;
    flex: 0 0 100%;
  }
  .lp-filters .row > [class*="col-"]:has(input[type="date"]) {
    width: 100%;
    max-width: 100%;
    flex: 0 0 100%;
  }
  /* A two-up filter bar: the search box and the buttons keep half a row. */
  .lp-filters .row > [class*="col-"] > .btn,
  .lp-filters .row > [class*="col-"] > .form-control[type="submit"] { width: 100%; }
}
@media (max-width: 359.98px) {
  .lp-fields { grid-template-columns: minmax(0, 1fr); }
}

/* Very small phones: a two-up field row leaves ~130px per box, which clips
   "All categories" to "All categ" and a date to "08-Sep-2". Below 400px a
   field takes the whole row and reads in full. */
/* Tablets: six filter fields on one 768px line gives each of them 120px,
   which is where "Any status" became "Any stat" and a date lost its year.
   Three per line is the same row height and twice the room. */
@media (min-width: 576px) and (max-width: 991.98px) {
  main .row:not(.row-cards) > [class*="col-md-2"],
  main .row:not(.row-cards) > [class*="col-md-3"] {
    flex: 0 0 33.3333%;
    max-width: 33.3333%;
  }
}

@media (max-width: 400px) {
  /* .row-cards holds the little figure tiles (customers owe us, money in…).
     Those are two short words and a number: they stay two-up and cost no
     height. Every other half-row is a field, and it takes the full width. */
  main .row:not(.row-cards) > [class*="col-6"]:not(:has(> .card)) {
    width: 100%;
    max-width: 100%;
    flex: 0 0 100%;
  }
  main .row-cards > [class*="col-6"] { width: 50%; max-width: 50%; flex: 0 0 50%; }
}

/* -- 4. the phone's own scale ----------------------------------------- */
@media (max-width: 575.98px) {
  .card-body { padding: 0.9rem; }
  .card-header { padding: 0.65rem 0.9rem; }
  .card-footer { padding: 0.7rem 0.9rem; }
  .page-title { font-size: 1.35rem; }
  .lp-ledger-cell { padding: 0.7rem 0.8rem 0.6rem; }
  .lp-ledger-num { font-size: 1.3rem; }
  /* A figure never breaks after its currency symbol: "Rs." alone on a line
     above the number reads as a missing value. It shrinks to stay whole. */
  .lp-ledger-num,
  .lp-ledger-num.is-money { white-space: nowrap; }
  .lp-ledger-num.is-money { font-size: 0.98rem; padding-top: 0.35rem; }
  .card-sm .h2 { font-size: 1.1rem; white-space: nowrap; }
  .card-sm .subheader { font-size: 0.6875rem; letter-spacing: 0.04em; }
  .lp-ledger-label { letter-spacing: 0.08em; font-size: 0.6875rem; }
  /* A badge or a date broken over three lines is not a table cell anymore. */
  .lp-pin-table td:first-child,
  .lp-pin-table th:first-child,
  .lp-pin-table .badge { white-space: nowrap; }
  /* A document number is one word: "INV-2026-" / "000171" on two lines is
     not a reference anyone can read out. The sheet scrolls sideways instead. */
  .lp-pin-table td.text-nowrap { white-space: nowrap !important; }
  .lp-pin-table td { vertical-align: middle; }
  /* Names break between words, never inside one. */
  .card-table:not(.lp-pin-table) td:first-child { min-width: 8.5rem; }
  .card-table td:first-child strong { overflow-wrap: break-word; }
}

/* The sideways control of a wide list: a visible track with a real thumb, so
   "there is more to the right" is a shape on the screen, not a guess. */
.lp-pin-card .lp-pin-hscroll::-webkit-scrollbar { height: 9px; }
.lp-pin-card .lp-pin-hscroll::-webkit-scrollbar-track { background: var(--paper); }
.lp-pin-card .lp-pin-hscroll::-webkit-scrollbar-thumb {
  background: #B6C4C1;
  border-radius: 99px;
}

/* Chips (Money In / Money Out / Pending): the count used to touch the label. */
.nav-pills { gap: 0.35rem; }
.nav-pills .nav-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.7rem;
  font-size: 0.8125rem;
  font-weight: 600;
  border-radius: 999px;
}
.nav-pills .nav-link.active { background: var(--cyan); color: #fff; }
@media (max-width: 575.98px) {
  .nav-pills { flex-wrap: wrap; }
  .nav-pills .nav-link { font-size: 0.78rem; padding: 0.28rem 0.6rem; }
}

/* Section tabs on a document page (Transactions / Returns / Payments) read as
   a row of links once the underline is gone. A heavier active tab and a real
   gap between them makes the current section obvious at a glance. */
.nav-tabs {
  gap: 0.25rem 1.15rem;
  border-bottom-color: var(--rule);
}
.nav-tabs .nav-link {
  padding: 0.45rem 0;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-2);
  border: 0;
  border-bottom: 2px solid transparent;
}
.nav-tabs .nav-link:hover { color: var(--ink-0); }
.nav-tabs .nav-link.active {
  color: var(--ink-0);
  background: none;
  border-bottom-color: var(--cyan);
}
@media (max-width: 575.98px) {
  .nav-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .nav-tabs::-webkit-scrollbar { display: none; }
  .nav-tabs .nav-link { white-space: nowrap; font-size: 0.78rem; }
}

/* A totals row names itself on one line: "Grand Total" broken over four
   lines in a 90px column was unreadable. The sheet scrolls sideways anyway. */
.table tfoot th,
.table tfoot td { white-space: nowrap; }
.lp-total-label .text-secondary { font-size: 0.72rem; }

/* Numbers line up in every column of figures. */
.table td.text-end,
.table th.text-end,
.lp-ledger-num,
.lp-calc-figure { font-variant-numeric: tabular-nums; }

/* Paper: the darker ink above is a screen decision. Paper keeps its own
   contrast, with the micro-labels a touch larger so a photocopy still reads. */
@media print {
  .text-secondary, .text-muted { color: #3D3D3D !important; }
  .form-label { color: #1F1F1F !important; letter-spacing: 0.03em; }
  .lp-calc { border-color: #8A8A8A; background: none; }
  .lp-fields { display: block; }
  /* The shortcut bar is a screen aid: it was printing on the bottom right of
     every report. */
  .lp-kb-hint, .lp-viewas-bar { display: none !important; }
  /* Paper never scrolls: a rule that only existed to show "more to the right"
     must not print, and a table heading must repeat rather than float. */
  .lp-pin-hscroll { display: none !important; }
  main table thead { display: table-header-group; }
  main table tr { break-inside: avoid; page-break-inside: avoid; }
  /* Screen tints are not inks: amber and green money printed pale enough to
     vanish on a cheap laser printer. Paper gets its own, darker plates. */
  :root {
    --ink-2: #333333;
    --amber: #6B4E10;
    --ok: #14512F;
    --cyan: #0A4A50;
    --cyan-deep: #0A4A50;
    --stamp: #8A2C1C;
  }
}
