:root {
  --green: #2f8f5b;
  --green-dark: #1f6b42;
  --green-light: #e8f5ee;
  --ink: #1d2b24;
  --muted: #6b7d74;
  --line: #e2e8e4;
  --bg: #f4f7f5;
  /* The workspace canvas alone sits darker than the rest of the app: its white windows float ON it,
     so a softer backdrop stops a screen full of white panels from glaring. */
  --ws-bg: #b5bdb7;
  --card: #ffffff;
  /* Form controls. These were hardcoded white in every rule that styled them, so in dark mode the
     themed text colour landed on a white box and whatever you typed went invisible. Anything you
     type INTO belongs on --field-bg; a menu or panel you only read from belongs on --card. */
  --field-bg: #ffffff;
  --field-fg: #1d2b24;
  --field-ph: #94a69c;       /* placeholder text */
  /* Label colour for anything sitting ON a green fill. Dark mode lifts the green so it reads against
     a dark page, and that same lift leaves a white label on a green button at 2.4:1, under the 3:1
     floor. A light fill wants a dark label, so this flips while the fill stays bright. Hue-proof:
     the accent picker rotates hue only, so the fill keeps its lightness whatever colour is picked. */
  --on-green: #ffffff;
  /* Label for anything on a --green FILL. Distinct from --on-green, which is solved against
     --green-dark (the band): the fill is lighter, so the two do not always agree. */
  --on-accent: #08130d;
  --tint-amber: #fdf3d7;   /* pale fills behind status pills */
  --tint-red: #fdeaea;
  --tint-gray: #eef1ef;
  --danger: #c0392b;
  --amber: #b8860b;
  --radius: 10px;
  --shadow: 0 1px 3px rgba(0,0,0,.06), 0 4px 16px rgba(0,0,0,.04);
  --title-bar: #dfe9e2;      /* workspace window title bar */
  --th-bg: #f7faf8;          /* table headers and list headers */
  --green-line: #bfe3ce;     /* the hairline on green-tinted pills */
  --toast-bg: #1d2b24;
  --toast-fg: #ffffff;
  color-scheme: light;
}

/* Dark theme. Same variables, different values, so everything already written as var(--x)
   follows without being touched. The green is lifted from #2f8f5b to #4bbd7f: the brand green
   is tuned for white behind it and goes muddy on a dark surface, failing contrast on exactly
   the things that matter most (buttons, active nav, totals).
   Set on <html> by the inline script in index.html so it applies before first paint. */
:root[data-theme="dark"] {
  --green: #4bbd7f;
  --green-dark: #3aa06a;
  --green-light: #16281f;
  --ink: #e6efea;
  --muted: #93a89e;
  --line: #2a3a33;
  --bg: #121815;
  --ws-bg: #0d1210;
  --card: #1a221e;
  /* A touch under --card so a field still reads as a well you type into, but lifted off pure black
     (was #0f1613, which read as harsh black boxes on the darker forms). */
  --field-bg: #232e28;
  --field-fg: #e6efea;
  --field-ph: #7d9188;
  --on-green: #08130d;
  --on-accent: #08130d;
  --tint-amber: #3a2f14;
  --tint-red: #3d1f1c;
  --tint-gray: #232c27;
  --danger: #ef8479;
  --amber: #e8c37a;
  --shadow: 0 1px 3px rgba(0,0,0,.5), 0 4px 16px rgba(0,0,0,.35);
  --title-bar: #202b26;
  --th-bg: #161d1a;
  --green-line: #2c4c3a;
  --toast-bg: #2c3b34;
  --toast-fg: #e6efea;
  color-scheme: dark;
}
* { box-sizing: border-box; }
/* The browser's own [hidden] rule is display:none at the LOWEST specificity, so any of the 200+
   class rules in here that set display (".rs-drop { display: flex }", ".settings-item { display:
   flex }" ...) silently beats it, and an element given the hidden attribute stays on screen.
   That has now produced two separate bugs - a dead settings card, and a file chooser shown on a
   screen that had already fetched the file. One rule ends the class of bug; !important is
   deliberate, because outranking every class rule is exactly the point. */
[hidden] { display: none !important; }
html, body { margin: 0; height: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--ink); background: var(--bg); font-size: 14px;
}
.hidden { display: none !important; }
button { font-family: inherit; cursor: pointer; }

/* Every text control gets a themed background by default, so a control that is added later, or that
   never had a rule of its own, cannot go invisible in dark mode. Plain element selectors on purpose:
   any class rule outranks these, so the specific styling below still wins.
   Checkbox, radio, range and colour are left alone - the browser paints those itself and a
   background flattens them into grey squares. */
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),
textarea, select {
  background: var(--field-bg); color: var(--field-fg);
}
input::placeholder, textarea::placeholder { color: var(--field-ph); }

/* ---------- Login ---------- */
.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--green) 0%, var(--green-dark) 100%);
}
.login-card {
  background: var(--card); padding: 36px 34px; border-radius: 16px; width: 340px;
  box-shadow: 0 20px 60px rgba(0,0,0,.25); display: flex; flex-direction: column;
}
.login-card .brand { text-align: center; margin-bottom: 18px; }
.login-card .leaf { font-size: 40px; }
.login-card h1 { font-size: 20px; margin: 8px 0 2px; }
.login-card .brand p { margin: 0; color: var(--muted); font-size: 13px; }
.login-card label { font-size: 12px; color: var(--muted); margin: 12px 0 4px; font-weight: 600; }
.login-card input {
  padding: 11px 12px; border: 1px solid var(--line); border-radius: 8px; font-size: 14px;
}
.login-card input:focus { outline: 2px solid var(--green); border-color: var(--green); }
.login-card button {
  margin-top: 20px; background: var(--green); color: var(--on-green); border: 0; padding: 12px;
  border-radius: 8px; font-size: 15px; font-weight: 600;
}
.login-card button:hover { background: var(--green-dark); }
/* text-style links inside the login card (Forgot password / Back to sign in) */
.login-card button.link-btn {
  margin-top: 10px; background: none; color: var(--green); padding: 4px;
  font-size: 13px; font-weight: 600; text-decoration: underline; width: auto;
}
.login-card button.link-btn:hover { background: none; color: var(--green-dark); }
.error { color: var(--danger); font-size: 13px; margin-top: 12px; text-align: center; min-height: 16px; }

/* ---------- Shell ---------- */
#app { display: flex; min-height: 100vh; }
.sidebar {
  width: 230px; background: color-mix(in srgb, var(--green) 18%, #0d1210); color: #cfe0d6;
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.side-brand {
  display: flex; align-items: center; gap: 10px; padding: 20px 18px; font-weight: 700;
  font-size: 16px; line-height: 1.1; border-bottom: 1px solid rgba(255,255,255,.08);
}
.side-brand small { color: #8fb7a0; font-weight: 500; }
.side-brand .leaf { font-size: 24px; }
/* The company you are working in, under the wordmark. Settings, books and WhatsApp credentials
   are all per company, so having it permanently on screen stops you editing the wrong one. */
.side-brand-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.side-brand-name { font-size: 16px; font-weight: 700; line-height: 1.15; }
.side-co {
  font-size: 11.5px; font-weight: 600; color: #8fb7a0; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* min-height:0 lets this flex child actually shrink and scroll instead of pushing
   the Subscription link + footer off the bottom when the menu (e.g. many email
   accounts) grows taller than the screen. */
#nav { flex: 1; min-height: 0; overflow-y: auto; padding: 10px 0; }
/* slim, unobtrusive scrollbar on the dark sidebar */
#nav::-webkit-scrollbar { width: 7px; }
#nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,.14); border-radius: 4px; }
#nav::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.24); }
#nav a {
  display: flex; align-items: center; gap: 11px; padding: 11px 20px; color: #b9cdc1;
  text-decoration: none; font-size: 14px; font-weight: 500; border-left: 3px solid transparent;
}
#nav a:hover { background: rgba(255,255,255,.05); color: #fff; }
#nav a.active { background: color-mix(in srgb, var(--green) 22%, transparent); color: #fff; border-left-color: var(--green); }
#nav a .ic { width: 20px; text-align: center; font-size: 16px; }
/* Follows the accent rather than WhatsApp's own green: the badge counts messages from any
   messenger, and a fixed #25D366 on a violet or indigo sidebar looked like a stray. --on-green is
   the label colour measured against the accent, so the count stays readable on every one. */
.nav-badge {
  margin-left: auto; margin-right: 2px; background: var(--green); color: var(--on-accent);
  border-radius: 12px; min-width: 24px; height: 22px; padding: 0 9px;
  font-size: 11.5px; font-weight: 700; display: inline-flex;
  align-items: center; justify-content: center;
  animation: navBadgePulse 1.7s ease-out infinite;
}
.nav-badge.upd { background: var(--amber, #b8860b); }
/* The Messenger "New Message" badge is text (not a number) - smaller + more compact. */
#wa-nav-badge { font-size: 9px; height: 18px; padding: 0 7px; letter-spacing: .2px; }
/* Wave only, no scale. A count that grows and shrinks is harder to read at a glance than one
   that holds still, and the ring on its own already carries the "something arrived" signal. */
@keyframes navBadgePulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 55%, transparent); }
  70%  { box-shadow: 0 0 0 9px color-mix(in srgb, var(--green) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 0%, transparent); }
}
/* respect users who prefer no motion */
@media (prefers-reduced-motion: reduce) { .nav-badge { animation: none; } }
.wa-upd {
  padding: 14px 16px; border-radius: 12px;
  background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow);
  font-size: 13px; color: var(--muted);
}
.wa-upd-title {
  font-size: 12.5px; letter-spacing: .01em;
  color: var(--muted); font-weight: 700; margin-bottom: 8px;
}
.wa-upd-row { display: flex; justify-content: space-between; gap: 8px; margin: 3px 0; }
.wa-upd-row span { color: var(--muted); }
.wa-upd-row b { color: var(--ink); font-weight: 650; text-align: right; }
.wa-upd-flag { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); font-weight: 600; }
.wa-upd-flag.ok { color: var(--green); }
.wa-upd-flag.has { color: var(--amber); }
.wa-upd-flag small { display: block; font-weight: 400; color: var(--muted); margin-top: 2px; }
/* clickable variant (an update is available) */
button.wa-upd-flag {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-top: 1px solid var(--line); border-radius: 0; cursor: pointer;
  font: inherit; font-size: 13px; line-height: 1.35; padding: 10px 0 0; color: var(--amber);
}
button.wa-upd-flag.has:hover { color: var(--green-dark); }
button.wa-upd-flag.has:hover small { color: var(--muted); }
.wa-upd-check {
  display: block; width: 100%; margin-top: 10px; background: none; border: 0;
  color: var(--green); cursor: pointer; font: inherit; font-size: 12px;
  text-decoration: underline; text-align: left; padding: 0;
}
.wa-upd-check:hover { color: var(--green-dark); }
/* Settings two-column layout: cards on the left, update panel on the right. */
.settings-layout { display: flex; gap: 26px; align-items: flex-start; flex-wrap: wrap; }
.settings-side { width: 420px; flex-shrink: 0; display: flex; flex-direction: column; gap: 14px; }
/* Raised from 1180: the wider side needs more room beside the 560px list before it has to wrap
   under it, or the two columns get cramped at mid widths. */
@media (max-width: 1260px){ .settings-side { width: 100%; max-width: 560px; } }
/* busy dialog */
.wa-upd-modal { text-align: center; padding: 6px 4px 2px; }
.wa-upd-spin {
  width: 34px; height: 34px; margin: 4px auto 14px; border-radius: 50%;
  border: 3px solid #e3ece7; border-top-color: var(--green);
  animation: waUpdSpin .9s linear infinite;
}
@keyframes waUpdSpin { to { transform: rotate(360deg); } }
.wa-upd-modal #wa-upd-msg { font-weight: 600; margin: 0 0 8px; }
.wa-upd-modal #wa-upd-msg.err { color: var(--danger); }
.wa-upd-modal .wa-upd-note { font-size: 12.5px; color: #6b7a72; margin: 0; }
@media (prefers-reduced-motion: reduce) { .wa-upd-spin { animation: none; } }
/* Drag handle on the sidebar's right edge - grab and drag left/right to resize.
   The sidebar is position:sticky (a positioning context), so this pins to its edge. */
.side-resize {
  position: absolute; top: 0; right: -3px; width: 6px; height: 100%;
  cursor: col-resize; z-index: 30; touch-action: none;
}
.side-resize::after {                 /* thin line that lights up on hover/drag */
  content: ""; position: absolute; top: 0; right: 3px; width: 2px; height: 100%;
  background: transparent; transition: background .15s;
}
.side-resize:hover::after, .side-resize.dragging::after { background: var(--green); }
.sidebar.collapsed .side-resize { display: none; }   /* no resizing while collapsed to icons */

.side-foot { padding: 16px 20px; border-top: 1px solid rgba(255,255,255,.08); font-size: 13px; }
/* "Administrator" and the build number share a line; the row owns the spacing now. */
.side-foot-who { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.side-foot #whoami { color: #8fb7a0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.link-btn { background: none; border: 0; color: #cfe0d6; padding: 0; text-decoration: underline; font-size: 13px; }
/* The sidebar is dark in BOTH themes, so this row keeps its own light-on-dark colours. */
.side-foot-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.accent-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; }
.accent-sw { height: 58px; border-radius: 10px; border: 2px solid transparent; cursor: pointer;
  display: flex; align-items: flex-end; justify-content: center; padding: 6px; position: relative;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08); }
.accent-sw span { font-size: 11.5px; font-weight: 700; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.4); }
.accent-sw.on { border-color: var(--ink); }
.accent-sw.on:after { content: "\2713"; position: absolute; top: 6px; right: 8px; color: #fff;
  font-size: 14px; font-weight: 700; text-shadow: 0 1px 2px rgba(0,0,0,.4); }
.theme-toggle { flex: none; width: 46px; height: 26px; border-radius: 999px; cursor: pointer;
  background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.18); position: relative;
  padding: 0; transition: background .16s; }
.theme-toggle:hover { background: rgba(255,255,255,.22); }
.theme-toggle:before { content: "\2600"; position: absolute; top: 1px; left: 1px; width: 22px; height: 22px;
  border-radius: 50%; background: var(--card); color: #b8860b; font-size: 13px; line-height: 22px;
  text-align: center; transition: transform .16s; }
:root[data-theme="dark"] .theme-toggle { background: rgba(75,189,127,.28); border-color: rgba(75,189,127,.4); }
:root[data-theme="dark"] .theme-toggle:before { content: "\1F319"; transform: translateX(20px);
  background: #0d1210; color: #e8c37a; }

main { flex: 1; min-width: 0; padding: 26px 32px; }  /* full window width; zoom out (Ctrl+-) to fit more */

/* ---------- Finance home (QuickBooks-style workflow canvas) ---------- */
/* Wrap rather than crush. These are three fixed-ish columns inside a window the user resizes, so
   the viewport media queries below cannot see it getting narrow - a 968px window inside a 1440px
   screen still counts as "desktop". Without a floor on the tile column, widening the balances
   column squeezed it to 239px and the paired tiles (Quotations / Sales Orders) silently stacked. */
.fin-wrap { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.fin-main { flex: 1; display: flex; flex-direction: column; gap: 22px; min-width: 300px; }
.fin-side { width: 300px; display: flex; flex-direction: column; gap: 22px; }
.fin-sec { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 22px 20px 14px; position: relative; }
.fin-chip { position: absolute; top: -10px; left: 16px; background: var(--green-light); color: var(--green-dark);
  font-size: 10.5px; font-weight: 800; letter-spacing: 1px; padding: 3px 12px; border-radius: 10px; border: 1px solid var(--line); }
.fin-row { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin: 6px 0; }
.fin-col { display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
.fin-col .fin-item { flex-direction: row; justify-content: flex-start; min-width: 0; padding: 10px 12px; }
.fin-item { display: flex; flex-direction: column; align-items: center; gap: 8px; background: none;
  border: 1px solid transparent; border-radius: 10px; padding: 12px 14px; min-width: 104px;
  cursor: pointer; font-size: 12.5px; font-weight: 600; color: var(--ink); position: relative; }
.fin-item:hover { background: var(--bg); border-color: var(--line); }
.fin-ic { display: inline-flex; }
.fin-ic svg { width: 38px; height: 38px; }
.fin-col .fin-ic svg { width: 28px; height: 28px; }
.fin-soon { position: absolute; top: 5px; right: 6px; font-size: 8.5px; font-weight: 800; letter-spacing: .5px;
  color: #b8860b; background: #fdf6e3; border: 1px solid #ecd9a0; padding: 1px 5px; border-radius: 8px; }
.fin-col .fin-soon { position: static; order: 2; margin-left: auto; }
/* Count pill on a workspace tile (open bills waiting to be paid). Amber: something is waiting,
   nothing is wrong. Hidden at zero rather than showing a 0. */
/* Dark ink, not white: --amber is a deep gold in light mode but a pale one in dark, and white
   text vanishes on the pale version. Dark ink reads on both. */
/* Waves like the other counts. The drop shadow has to be repeated in every keyframe: box-shadow is
   one property, so animating the ring would otherwise drop the shadow the pill sits on. */
.fin-count { position: absolute; top: 5px; right: 6px; min-width: 19px; height: 19px; padding: 0 6px;
  border-radius: 10px; background: var(--amber); color: #2b1f04; font-size: 10.5px; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  box-shadow: 0 1px 3px rgba(0,0,0,.22);
  animation: finCountWave 1.9s ease-out infinite; }
@keyframes finCountWave {
  0%   { box-shadow: 0 1px 3px rgba(0,0,0,.22), 0 0 0 0 color-mix(in srgb, var(--amber) 62%, transparent); }
  70%  { box-shadow: 0 1px 3px rgba(0,0,0,.22), 0 0 0 10px color-mix(in srgb, var(--amber) 0%, transparent); }
  100% { box-shadow: 0 1px 3px rgba(0,0,0,.22), 0 0 0 0 color-mix(in srgb, var(--amber) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .fin-count { animation: none; } }
.fin-count[hidden] { display: none; }
.fin-col .fin-count { position: static; order: 2; margin-left: auto; }
.fin-arrow { color: #b9c6bd; flex: 0 0 auto; }
/* The converging connector under Quotations / Sales Orders. Its left stem is 9px in from the SVG
   edge and a .fin-item is 104px wide with 14px of side padding, so 43px of offset puts that stem
   on the first tile's centre line - and on Create Invoice, which sits in the same column below. */
.fin-row-down { margin: -8px 0 -6px; }
.fin-converge { margin-left: 43px; }
/* Same column as Create Invoice above it: 52px to the tile's centre, less the stem's own 9px. */
.fin-down { margin-left: 43px; }
/* The picker that narrows the list to one customer. */
.inv-cust { max-width: 220px; font: inherit; font-size: 12.5px; padding: 5px 8px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--field-bg); color: var(--field-fg); cursor: pointer; }
/* Account balances on the home screen, the way QuickBooks shows them: the money accounts
   at a glance, each row opening the register behind it. */
/* Wide enough that a long account name and a seven-figure balance are not fighting each other
   for the same line, and that a group heading like OTHER CURRENT LIABILITY fits on one. */
.fin-mid { width: 340px; display: flex; flex-direction: column; gap: 22px; }
.fin-bal { padding-bottom: 8px; }
.fin-bal-list { display: flex; flex-direction: column; max-height: 460px; overflow-y: auto; margin: 2px -6px 0; }
.fin-bal-wait { color: var(--muted); font-size: 12.5px; padding: 8px 6px; }
/* Same colour as the ACCOUNT BALANCES chip above them: these are headings of the same kind,
   one level down, so they should read as the same voice rather than as greyed-out noise. */
.fin-bal-grp { font-size: 10px; font-weight: 800; letter-spacing: .9px; color: var(--green-dark);
  text-transform: uppercase; padding: 10px 6px 3px; }
.fin-bal-row { display: flex; align-items: baseline; gap: 10px; width: 100%; background: none;
  border: 1px solid transparent; border-radius: 8px; padding: 6px 6px; cursor: pointer; text-align: left; }
.fin-bal-row:hover { background: var(--bg); border-color: var(--line); }
.fin-bal-nm { flex: 1; font-size: 12.5px; font-weight: 600; color: var(--ink); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.fin-bal-amt { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); }
.fin-bal-amt.neg { color: var(--danger); }
@media (max-width: 1180px) { .fin-mid { width: 290px; } }
@media (max-width: 900px) { .fin-wrap { flex-direction: column; } .fin-side { width: 100%; }
  .fin-mid { width: 100%; } .fin-bal-list { max-height: none; } }

/* ---------- Finance workspace: desktop with draggable child windows ---------- */
.ws { position: relative; margin: -26px -32px; height: 100vh; overflow: hidden; background: var(--ws-bg); }
.ws-win { position: absolute; display: flex; flex-direction: column; background: var(--card);
  border: 1px solid var(--line); border-radius: 0; overflow: hidden;
  box-shadow: 0 14px 44px rgba(0,0,0,.20); min-width: 340px; min-height: 220px; }
.ws-title { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 8px 8px 14px; background: var(--title-bar); border-bottom: 1px solid var(--line);
  cursor: move; user-select: none; font-weight: 700; font-size: 13.5px; color: var(--ink); }
/* Window controls: the glyph itself carries the colour - minimise yellow, maximise green, close
   red - and hovering lays a soft tint of that same colour behind it. */
.ws-ctl { display: flex; gap: 3px; align-items: center; }
.ws-ctl button { background: none; border: 0; cursor: pointer; line-height: 1; flex: none;
  width: 34px; height: 28px; border-radius: 7px; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .13s ease; }
.ws-ctl button svg { display: block; width: 18px; height: 18px; }
.ws-ctl button[data-w="min"] { color: #f0a72a; }
.ws-ctl button[data-w="max"] { color: #23b74a; }
.ws-ctl button[data-w="close"], .ws-ctl .x { color: #f0574f; }
.ws-ctl button[data-w="min"]:hover  { background: color-mix(in srgb, #f0a72a 22%, transparent); }
.ws-ctl button[data-w="max"]:hover  { background: color-mix(in srgb, #23b74a 22%, transparent); }
.ws-ctl button[data-w="close"]:hover, .ws-ctl .x:hover { background: color-mix(in srgb, #f0574f 24%, transparent); }
.ws-ctl button:active { background: color-mix(in srgb, var(--ink) 16%, transparent); }
.ws-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
.ws-grip { position: absolute; right: 1px; bottom: 1px; width: 18px; height: 18px; z-index: 6;
  cursor: nwse-resize; opacity: .5; border-bottom-right-radius: 9px;
  background: linear-gradient(135deg, transparent 0 55%, #93a79b 55% 61%, transparent 61% 70%,
    #93a79b 70% 76%, transparent 76% 85%, #93a79b 85% 91%, transparent 91%); }
.ws-grip:hover { opacity: 1; }
/* Drag any of the four sides to resize a window. The side strips stop short of the title bar so
   dragging the header still MOVES the window; the top strip is the thin band above it. */
.ws-edge { position: absolute; z-index: 6; }
.ws-edge-l, .ws-edge-r { top: 42px; bottom: 30px; width: 7px; cursor: ew-resize; }
.ws-edge-l { left: 0; } .ws-edge-r { right: 0; }
.ws-edge-t, .ws-edge-b { left: 9px; right: 9px; height: 7px; cursor: ns-resize; }
.ws-edge-t { top: 0; } .ws-edge-b { bottom: 0; }
/* invoice sheets: the SIDE strips also stay clear of the green band (top) and the footer buttons */
.ws-win:has(.qb-sheet) > .ws-edge-l, .ws-win:has(.qb-sheet) > .ws-edge-r,
.qb-sheet.qb-float > .ws-edge-l, .qb-sheet.qb-float > .ws-edge-r { top: 118px; bottom: 68px; }
.ws-edge:hover { background: color-mix(in srgb, var(--green) 16%, transparent); }
.ws-home { padding: 18px; }
/* Email-invoice dialog: a movable/resizable window with the form + a live invoice
   preview side by side (QuickBooks-style). Sized by makeDialogWindow (inline px). */
.email-inv-dlg .modal-body { overflow: hidden; }        /* the panes scroll, not the whole body */
.email-inv-cols { display: flex; gap: 20px; align-items: stretch; height: 100%; }
.email-inv-form { flex: 0 0 44%; min-width: 0; overflow: auto; display: flex; flex-direction: column; }
/* the Message field grows to fill the tall left pane so there's plenty of room to type */
.email-inv-msg { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.email-inv-dlg .email-inv-msg textarea { flex: 1; min-height: 220px; resize: vertical; }
.em-ccbcc-toggle { font-size: 11.5px; font-weight: 600; margin-left: 8px; color: var(--green-dark); }
.em-ccbcc-toggle.on { text-decoration: underline; }
.email-inv-preview { flex: 1; min-width: 0; display: flex; flex-direction: column;
  background: #eef1ef; border: 1px solid var(--line); border-radius: 10px; padding: 12px; }
.email-inv-preview-label { font-size: 10.5px; font-weight: 800; letter-spacing: .8px; color: var(--muted); margin-bottom: 10px; }
.email-inv-preview-page { flex: 1; overflow: auto; min-height: 0; }
/* Render the real invoice sheet, scaled to fit the pane (transform doesn't shrink the
   layout box, so the wrapper is widened by 1/scale to compensate). */
.email-inv-preview-page .inv-sheet { transform: scale(.72); transform-origin: top left; width: 138.9%;
  flex: none; min-height: 0; box-shadow: 0 2px 10px rgba(0,0,0,.12); padding: 30px 34px; margin-bottom: -28%; }
.email-inv-preview-page .table-wrap { overflow: visible; }   /* show every column in the preview */
@media (max-width: 780px) {
  .email-inv-cols { flex-direction: column; height: auto; }
  .email-inv-form { flex: none; }
  .email-inv-preview-page .inv-sheet { transform: scale(.9); width: 111%; margin-bottom: -10%; }
}

/* Dynamic pricing - FIFO batches (inside the item edit window) */
.med-dyn { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.med-dyn-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.med-dyn-head b { font-size: 13px; }
.dyn-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.dyn-table th { text-align: left; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: .5px; padding: 4px 8px; border-bottom: 1px solid var(--line); }
.dyn-table td { padding: 5px 8px; border-bottom: 1px solid var(--line); }
.dyn-table .right { text-align: right; }
.dyn-table tr.dyn-active { background: var(--green-light); }
.dyn-table .btn.sm { padding: 2px 8px; }

/* Reports (QuickBooks-style Report Center) */
.rep-center { padding: 18px; display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; align-items: start; }
.rep-cat { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow); }
.rep-card { display: block; width: 100%; text-align: left; background: none; border: 0; border-top: 1px solid var(--line); padding: 10px 6px; cursor: pointer; }
.rep-cat .rep-card:first-of-type { border-top: 0; }
.rep-card b { display: block; font-size: 13.5px; color: var(--ink); }
.rep-card span { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.rep-card:hover b { color: var(--green-dark); }
.rep-body { padding: 0 0 12px; }
.rep-select, .rep-date { padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px; font-size: 13px; background: var(--field-bg); }
tr.rep-total td { font-weight: 700; border-top: 2px solid var(--ink); background: var(--card); }
tr.rep-grand td { font-size: 15px; }
tr.rep-sec td { font-weight: 700; background: var(--th-bg); }
.rep-ind td:first-child { padding-left: 34px; }
.rep-neg { color: #b3261e; }

/* Chart of Accounts */
.coa-sec td { background: var(--th-bg); color: var(--muted); font-size: 10.5px; font-weight: 800; letter-spacing: .9px; padding: 6px 16px; border-bottom: 1px solid var(--line); }
.coa-actions .btn.sm { padding: 3px 10px; font-size: 12px; }
.coa-indent { color: var(--muted); }
.coa-caret { background: none; border: 0; cursor: pointer; font-size: 17px; line-height: 1; font-weight: 700;
  color: var(--green-dark); padding: 0; margin-right: 7px; width: 18px; display: inline-block; text-align: center; vertical-align: -2px; }
.coa-caret:hover { color: var(--green); transform: scale(1.15); }
.coa-caret-sp { display: inline-block; width: 18px; margin-right: 7px; }
.coa-kidcount { display: inline-block; font-size: 10.5px; font-weight: 700; color: var(--green-dark);
  background: var(--green-light); border-radius: 9px; padding: 0 7px; margin-left: 8px; }
/* Tint parent (main) rows and their sub-accounts so the grouping reads at a glance. */
tr.coa-main > td { background: color-mix(in srgb, var(--green) 16%, var(--card)); }
tr.coa-main > td:first-child { box-shadow: inset 3px 0 0 var(--green); }
tr.coa-sub > td { background: color-mix(in srgb, var(--green) 5%, var(--card)); }
tr.coa-sub.coa-d2 > td { background: color-mix(in srgb, var(--green) 9%, var(--card)); }
tr.coa-sub.coa-d3 > td { background: color-mix(in srgb, var(--green) 12%, var(--card)); }
tr.coa-sub > td:first-child { box-shadow: inset 3px 0 0 #cfe0d6; }
/* Scan box on the invoice / quotation / sales order sheets. The dot IS the state: green
   when it has focus and is ready, grey when a stray scan would land somewhere else. */
.iv-scan { display: inline-flex; align-items: center; gap: 9px; margin-top: 10px; margin-right: 10px;
  padding: 5px 12px 5px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--field-bg); }
.iv-scan-dot { width: 9px; height: 9px; border-radius: 50%; background: #c8d2cc; flex: none; transition: background .15s; }
.iv-scan:focus-within .iv-scan-dot { background: var(--green); box-shadow: 0 0 0 3px rgba(45,122,74,.16); }
.iv-scan-in { border: 0; outline: 0; font-size: 13px; padding: 3px 0; width: 190px; background: transparent; }
.iv-scan:focus-within { border-color: var(--green); }
.iv-scan::after { content: "Click here to scan"; font-size: 11px; color: var(--muted); }
.iv-scan:focus-within::after { content: "Ready to scan"; color: var(--green-dark); font-weight: 600; }
/* A failed scan stays red until the next one - the toast is gone in 2.6 seconds. */
.iv-scan.err { border-color: var(--danger); background: var(--tint-red); }
.iv-scan.err .iv-scan-dot { background: #c0392b; }
.iv-scan.err::after { content: "Not found - scan again"; color: var(--danger); font-weight: 600; }
/* Insert-items mode: the bar stays visible so the till looks the same either way, but it is
   plainly out of use and says which button turns it back on. The input itself is disabled, so
   this is only the appearance of the state, not the state. */
.iv-scan.off { opacity: .5; cursor: not-allowed; }
.iv-scan.off .iv-scan-in { cursor: not-allowed; }
.iv-scan.off::after { content: "Switch to Scan bar code to use this"; }
.iv-scan.off:focus-within::after { content: "Switch to Scan bar code to use this"; color: var(--muted); font-weight: 400; }
@keyframes iv-flash { from { background: #d8efe0; } to { background: transparent; } }
tr.iv-flash > td { animation: iv-flash .6s ease-out; }
/* the invoice page rendered inside a workspace window */
.ws-body.iv-in-win { padding: 14px 18px 18px; background: var(--bg); display: block; }
.ws-body.iv-in-win .page-head { margin-bottom: 12px; flex-wrap: wrap; gap: 8px; }
.ws-body.iv-in-win .page-head h2 { font-size: 18px; }
/* Invoice detail: green "hat" header, matching every other finance window */
.ws-body.iv-in-win > .page-head { background: var(--green-dark); color: var(--on-green); margin: -14px -18px 16px; padding: 13px 18px; align-items: center; }
.ws-body.iv-in-win > .page-head > div:first-child { min-width: 0; }
.ws-body.iv-in-win > .page-head h2 { color: #fff; }
.ws-body.iv-in-win > .page-head h2 .muted { color: color-mix(in srgb, var(--on-green) 72%, transparent) !important; }
/* Invoice detail header: keep the ‹ › browse arrows pinned at the far left so they don't
   shift under the cursor when an invoice's action buttons (Mark paid / Refund / Edit …) change
   width. Arrows live in a left group; the action buttons stay right-anchored and free to reflow. */
.iv-head-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
.iv-nav { display: inline-flex; align-items: center; flex: none; }
.iv-acts { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.ws-body.iv-in-win .inv-sheet { padding: 30px 34px; }
.ws-bar { position: absolute; left: 0; right: 0; bottom: 0; z-index: 99990; display: flex; gap: 8px;
  align-items: center; padding: 7px 14px; background: rgba(24, 39, 31, .94); }
.ws-chip { background: #2e4237; color: #cfe0d6; border: 0; border-radius: 7px; padding: 6px 14px;
  font-size: 12.5px; font-weight: 600; cursor: pointer; max-width: 220px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; touch-action: none; }
.ws-chip:hover { background: #3a5546; color: #fff; }
/* The chip for the window you are in sends a wave out, rather than breathing. The earlier version
   scaled 1.8% against a 4px ring at 30%, which is under the threshold you actually notice in the
   corner of your eye - it read as nothing happening. The chip now holds still and the ring alone
   travels, further (12px) and from a stronger start, so the movement is the signal. */
.ws-chip.active { background: var(--green); color: var(--on-green);
  animation: wsChipWave 1.9s ease-out infinite; }
@keyframes wsChipWave {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 62%, transparent); }
  70%  { box-shadow: 0 0 0 12px color-mix(in srgb, var(--green) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .ws-chip.active { animation: none; } }
.ws-chip-drag { opacity: .9; box-shadow: 0 5px 16px rgba(0,0,0,.4); transform: translateY(-2px) scale(1.03);
  cursor: grabbing; z-index: 2; position: relative; }
/* pages rendered inside a window: neutralize the full-page pinned-header bleed */
.ws-win .page-pin { position: sticky; top: 0; margin: 0; padding: 14px 16px 10px; }
.ws-win .page-head { margin-bottom: 12px; }
.ws-win .page-head h2 { font-size: 17px; }
.ws-win .table-wrap { margin: 0 16px 16px; }
.ws-win .pager { margin: 0 16px 14px; }
/* Green "hat" header for list-style workspace windows (matches the invoice band) */
.win-band { display: flex; align-items: center; gap: 12px; background: var(--green-dark); padding: 14px 18px; flex-wrap: wrap; row-gap: 8px; }
.ws-win .win-band { position: sticky; top: 0; z-index: 20; }
.win-btn:disabled { opacity: .5; cursor: default; }
.win-band .rep-select, .win-band .rep-date { background: var(--field-bg); border: 0; border-radius: 7px;
  padding: 7px 10px; font-size: 13px; color: var(--ink); cursor: pointer; }
.win-band-head { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: none; }
.win-band-head h2 { margin: 0; font-size: 17px; color: var(--on-green); line-height: 1.2; white-space: nowrap; }
/* --on-green is now measured against the chosen accent (see onInkFor in app.js), so this follows
   the band instead of assuming it is green. Raised from 72% to 82%: at 12px the fainter mix was
   the weakest text on the band on several accents. */
.win-band-head .sub { font-size: 12px; color: color-mix(in srgb, var(--on-green) 82%, transparent); margin-top: 1px; white-space: nowrap; }
/* Workspace company switcher (multi-company) - sits at the right of the green home band. */
.ws-company-btn { margin-left: auto; display: inline-flex; align-items: center; gap: 7px; flex: none;
  background: rgba(255,255,255,.14); color: #fff; border: 1px solid rgba(255,255,255,.30);
  border-radius: 9px; padding: 7px 12px; font-size: 13px; font-weight: 600; cursor: pointer; max-width: 320px; }
.ws-company-btn:hover { background: rgba(255,255,255,.24); }
/* How many companies are on this account, on the switcher itself. Same wave as the sidebar
   unread badge, but the pill does not scale with it: a number that jiggles is hard to read, and
   the ring alone is what carries the "there is more behind this" signal. White rather than the
   badge's green, because the band underneath is already green. */
/* The pill is white in BOTH themes, so its text cannot follow --green-dark: dark mode lifts that
   green to sit on a dark page, and the lifted version on white measured 3.27:1. Mixing it back
   toward near-black keeps the accent's hue while staying readable on white whatever the theme. */
.ws-co-count { flex: none; display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 19px; padding: 0 6px; border-radius: 10px; background: #fff;
  color: color-mix(in srgb, var(--green-dark) 55%, #0b1a12); font-size: 11px; font-weight: 800;
  line-height: 1; animation: coCountWave 1.7s ease-out infinite; }
@keyframes coCountWave {
  0%   { box-shadow: 0 0 0 0 rgba(255,255,255,.6); }
  70%  { box-shadow: 0 0 0 10px rgba(255,255,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); }
}
@media (prefers-reduced-motion: reduce) { .ws-co-count { animation: none; } }
.ws-company-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-company-caret { opacity: .85; font-size: 11px; }
.ws-co-menu { background: var(--card); border: 1px solid var(--line, #dbe3ea); border-radius: 11px; min-width: 234px;
  box-shadow: 0 14px 38px rgba(0,0,0,.20); padding: 6px; }
.ws-co-menu-head { font-size: 10.5px; font-weight: 800; letter-spacing: .8px; color: var(--muted, #7a8a83); padding: 7px 10px 5px; }
.ws-co-item { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; background: none; border: 0;
  padding: 9px 10px; border-radius: 8px; cursor: pointer; font-size: 13.5px; color: var(--ink, #1f2a30); }
.ws-co-item:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.ws-co-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-co-dot { width: 8px; height: 8px; border-radius: 50%; background: #cdd8d2; flex: none; }
/* The company you are in waves, like every other "this one is live" marker in the app. The dot
   holds still and only the ring travels, same as the counts. */
.ws-co-item.on .ws-co-dot { background: var(--green); animation: coDotWave 1.9s ease-out infinite; }
@keyframes coDotWave {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 62%, transparent); }
  70%  { box-shadow: 0 0 0 9px color-mix(in srgb, var(--green) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .ws-co-item.on .ws-co-dot { animation: none; } }
.ws-co-item.on { font-weight: 700; }
.ws-co-new { color: var(--green, #2f8f5b); font-weight: 700; border-top: 1px solid var(--line, #eef1ef); margin-top: 4px; }
.win-band-search { flex: 0 1 300px; min-width: 120px; background: var(--field-bg); border: 0; border-radius: 7px;
  padding: 8px 11px; font-size: 14px; margin-left: 6px; color: var(--ink); }
.win-band-search::placeholder { color: #9aa8a0; }
.modal-inline-action { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.cd-cur.locked input { background: var(--surface); color: var(--muted); cursor: not-allowed; }
.cd-lock { font-size: 15px; opacity: .85; padding: 0 6px; }

/* ---------- Customer Center (QuickBooks-style master-detail) ---------- */
.cc-wrap { display: flex; min-height: 0; height: calc(100vh - 176px); background: var(--card);
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.ws-win .cc-wrap { flex: 1; height: auto; border: 0; border-radius: 0; }
.cc-list-pane { width: 340px; flex: none; display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); }
.cc-list-top { padding: 10px 12px; border-bottom: 1px solid var(--line); }
.cc-filter { width: 100%; padding: 7px 10px; border: 1px solid var(--line); border-radius: 7px; font-size: 13px; background: var(--card); color: var(--ink); cursor: pointer; }
.cc-list-head { display: flex; align-items: center; gap: 8px; padding: 6px 14px; font-size: 10.5px;
  font-weight: 800; letter-spacing: .5px; color: var(--muted); background: var(--th-bg); border-bottom: 1px solid var(--line); }
.cc-list { flex: 1; overflow: auto; min-height: 0; }
.cc-row { display: flex; align-items: center; gap: 8px; padding: 9px 14px; cursor: pointer;
  border-bottom: 1px solid #eef2ef; font-size: 13.5px; }
.cc-row:hover { background: var(--green-light); }
/* The tick box builds a mailing list. It keeps its own column so the name, balance and
   credit stay aligned with the header above them. */
.cc-pick, .cc-pick-sp { flex: none; width: 15px; height: 15px; margin: 0; }
.cc-pick { cursor: pointer; accent-color: var(--green); }
.cc-row.sel .cc-pick { accent-color: #fff; }
.cc-row.sel { background: var(--green); color: var(--on-green); }
.cc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-bal { flex: none; width: 60px; text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
.cc-bal.owed { color: #b26a00; font-weight: 700; }
.cc-cr { flex: none; width: 84px; text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
.cc-cr.has { color: var(--green-dark); font-weight: 700; }
.cc-row.sel .cc-bal, .cc-row.sel .cc-bal.owed, .cc-row.sel .cc-cr, .cc-row.sel .cc-cr.has { color: #fff; }
.cc-pager { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 12px; border-top: 1px solid var(--line); font-size: 12px; }
.cc-pager .btn.sm { padding: 3px 12px; }
.cc-vsplit { flex: none; width: 7px; cursor: col-resize; position: relative; align-self: stretch; touch-action: none; }
.cc-vsplit::after { content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; background: var(--line); }
.cc-vsplit:hover::after, .cc-vsplit.drag::after { background: var(--green); width: 2px; left: 2.5px; }
.cc-hsplit { flex: none; height: 7px; cursor: row-resize; position: relative; touch-action: none; }
.cc-hsplit::after { content: ""; position: absolute; left: 0; right: 0; top: 3px; height: 1px; background: var(--line); }
.cc-hsplit:hover::after, .cc-hsplit.drag::after { background: var(--green); height: 2px; top: 2.5px; }
.cc-detail { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow: auto; }
.cc-info { flex: none; overflow: auto; }
.cc-blank { padding: 44px 24px; color: var(--muted); text-align: center; }
.cc-blank.sm { padding: 22px; text-align: left; }
.cc-info { padding: 16px 22px; }
.cc-info-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.cc-info-head h2 { margin: 0; font-size: 20px; }
.cc-info-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 30px; }
.cc-fld { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cc-lbl { font-size: 10.5px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--muted); }
.cc-val { font-size: 14px; overflow: hidden; text-overflow: ellipsis; }
.cc-val.strong { font-weight: 700; font-size: 15px; }
.cc-tabs { display: flex; align-items: center; gap: 2px; padding: 8px 14px 0; border-bottom: 1px solid var(--line); flex: none; }
.cc-tab { background: none; border: 0; border-bottom: 2px solid transparent; padding: 8px 14px; margin-bottom: -1px;
  font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer; }
.cc-tab:hover { color: var(--ink); }
.cc-tab.active { color: var(--green-dark); border-bottom-color: var(--green); }
.cc-tab-spacer { flex: 1; }
.cc-tab-body { flex: 1; overflow: auto; min-height: 0; }
.cc-table { width: 100%; border-collapse: collapse; }
.cc-table th { text-align: left; font-size: 10.5px; font-weight: 800; letter-spacing: .5px; color: var(--muted);
  padding: 8px 12px; border-bottom: 1px solid var(--line); background: #f8faf9; position: sticky; top: 0; z-index: 1; }
.cc-table td { padding: 8px 12px; border-bottom: 1px solid #eef2ef; font-size: 13px; white-space: nowrap; }
.cc-table th.right, .cc-table td.right { text-align: right; }
.cc-table tr.clickable:hover { background: var(--green-light); cursor: pointer; }
.cc-table td.owed { color: #b26a00; font-weight: 700; }
.cc-aging { color: #b3261e; font-weight: 700; }
@media (max-width: 820px) { .cc-info-grid { grid-template-columns: 1fr; } .cc-list-pane { width: 250px; } }

/* ---------- Enter Bills (accounts payable) ---------- */
.bill-wrap { display: flex; flex: 1; min-height: 0; }
.bill-main { flex: 1; min-width: 0; overflow: auto; padding: 16px 18px; }
.bill-side { width: 280px; flex: none; border-left: 1px solid var(--line); background: var(--th-bg); overflow: auto; padding: 14px 16px; }
.bill-sheet { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 14px 18px 16px; }
.bill-word { font-size: 30px; font-weight: 800; color: color-mix(in srgb, var(--ink) 72%, var(--card)); letter-spacing: .5px; margin-bottom: 8px; line-height: 1; }
.bill-grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: 10px 24px; align-items: start; }
.bill-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.bill-field.span2 { grid-column: 1 / -1; }
.bill-field.grid-tall { grid-row: span 2; }
.bill-field label { font-size: 10px; font-weight: 800; letter-spacing: .8px; color: var(--muted); }
.bill-field input, .bill-field textarea { border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; font-size: 13.5px; background: var(--field-bg); color: var(--field-fg); width: 100%; }
.bill-field input[readonly] { background: var(--surface); color: var(--muted); font-weight: 700; }
.bill-field textarea { resize: vertical; min-height: 44px; }
.bill-lines-head { display: flex; align-items: baseline; gap: 12px; margin: 16px 0 6px; font-size: 14px; }
.bill-lines-wrap { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.bill-lines-tbl { width: 100%; border-collapse: collapse; }
.bill-lines-tbl th { text-align: left; font-size: 10px; font-weight: 800; letter-spacing: .5px; color: var(--muted); background: var(--th-bg); padding: 7px 10px; border-bottom: 1px solid var(--line); }
.bill-lines-tbl th.right { text-align: right; }
.bill-lines-tbl td { padding: 4px 8px; border-bottom: 1px solid var(--line); }
.bill-lines-tbl td.right { text-align: right; }
.bill-lines-tbl select, .bill-lines-tbl input { border: 1px solid transparent; border-radius: 6px; padding: 6px 7px; font-size: 13px; width: 100%; background: var(--field-bg); color: var(--field-fg); }
.bill-lines-tbl select:focus, .bill-lines-tbl input:focus { border-color: var(--green); outline: none; }
.bill-lines-tbl .bl-amt { text-align: right; }
.bl-x { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 13px; }
.bl-x:hover { color: var(--danger); }
/* The line-remove ✕ in the invoice/quote editor: red, since it deletes the row. Overrides the
   ghost button it borrows its shape from - text and border go red, filling red on hover. */
.qb-rm.btn.ghost { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--line)); font-weight: 700; }
.qb-rm.btn.ghost:hover { background: var(--danger); border-color: var(--danger); color: #fff; }
.bill-foot { display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-top: 1px solid var(--line); background: var(--card); flex: none; }
.bill-total-big { font-size: 14px; color: var(--muted); }
.bill-total-big b { font-size: 20px; color: var(--ink); margin-left: 8px; }
.bill-toggle { color: #fff; font-size: 13px; font-weight: 600; display: inline-flex; align-items: center; gap: 5px; margin-left: 8px; cursor: pointer; }
.bill-toggle input { accent-color: #fff; }
.bill-side-h { font-size: 15px; font-weight: 700; margin-bottom: 8px; }
.bill-side-name { font-weight: 700; font-size: 15px; margin-bottom: 4px; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.bill-side-edit { background: none; border: 1px solid var(--line); border-radius: 6px; width: 27px; height: 25px; cursor: pointer; color: var(--muted); flex: none; }
.bill-side-edit:hover { background: var(--green-light); color: var(--green-dark); border-color: var(--green); }
.bill-side-row b.bill-ell { max-width: 165px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; }
.bill-side-sec { font-size: 10px; font-weight: 800; letter-spacing: .8px; color: var(--muted); margin: 14px 0 6px; }
.bill-side-row { display: flex; justify-content: space-between; gap: 8px; padding: 5px 2px; font-size: 13px; border-bottom: 1px solid var(--line); }
.bill-side-row.clickable { cursor: pointer; }
.bill-side-row.clickable:hover { background: var(--green-light); }
.bill-side-row b.owed { color: var(--amber); }

/* ---------- Account register (ledger) ---------- */
.reg-wrap { flex: 1; min-height: 0; overflow: auto; }
.reg-tbl { width: 100%; border-collapse: collapse; }
/* --th-bg, not a literal: every other table header in the app already uses it, and the hardcoded
   light grey here is what left the Pay Bills and register headers as a white bar across a dark
   window. Same for the row rule, which was a light literal on a dark background. */
.reg-tbl th { position: sticky; top: 0; z-index: 1; text-align: left; font-size: 10px; font-weight: 800; letter-spacing: .5px;
  color: var(--muted); background: var(--th-bg); padding: 7px 10px; border-bottom: 1px solid var(--line); }
.reg-tbl th.right { text-align: right; }
.reg-tbl td { padding: 3px 8px; border-bottom: 1px solid var(--line); font-size: 13px; vertical-align: middle; }
.reg-tbl td.right { text-align: right; }
.reg-row.ro td { background: var(--th-bg); color: var(--muted); }
.reg-row.ro td b { color: var(--ink); }
/* A row someone typed in, rather than one a document produced. Same amber as the "Hand-entered"
   figure in the bar above, so the two read as the same idea, with a stripe down the near edge.
   Deliberately weaker than the hover and selection rules below, which still take over. */
tr.reg-manual > td { background: color-mix(in srgb, var(--amber) 15%, var(--card)); }
tr.reg-manual > td:first-child { box-shadow: inset 3px 0 0 var(--amber); }
.reg-row.reg-open { cursor: pointer; }
.reg-row.reg-open:hover > td { background: color-mix(in srgb, var(--green) 9%, transparent); }
.reg-tbl tr.reg-row.sel > td { background: color-mix(in srgb, var(--green) 22%, var(--card)); color: var(--ink); }
.reg-row.sel:focus { outline: none; }
.reg-entry td { background: color-mix(in srgb, var(--amber) 12%, var(--card)); }
.reg-tbl .re-c { width: 100%; border: 1px solid transparent; border-radius: 5px; padding: 5px 6px; font-size: 13px; background: transparent; color: var(--ink); }
.reg-tbl .re-c:hover { border-color: var(--line); background: var(--field-bg); }
.reg-tbl .re-c:focus { border-color: var(--green); background: var(--field-bg); outline: none; }
.reg-tbl .re-c.right { text-align: right; }
/* Same red remove button as an invoice line (.qb-rm): red on a red-tinted outline, filling solid
   on hover, so "this deletes something" reads the same wherever you meet it. */
.reg-del, .reg-rmrow { background: var(--card); color: var(--danger); cursor: pointer;
  font-size: 12.5px; font-weight: 700; line-height: 1; padding: 4px 9px; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--danger) 40%, var(--line));
  transition: background .13s ease, border-color .13s ease, color .13s ease; }
.reg-del:hover, .reg-rmrow:hover { background: var(--danger); border-color: var(--danger); color: #fff; }
/* Banner shown when a register is too long to draw in one go (a 13-year A/R is 73,131
   lines). It has to state what is on screen, or a partial ledger reads as the whole one. */
.reg-more-band { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 16px; font-size: 12px; color: var(--muted);
  background: var(--card); border-bottom: 1px solid var(--line); flex: none; }
.reg-more-band b { color: var(--text); }
.reg-more-band .win-btn { margin-left: 4px; }

/* Does the balance agree with the documents behind it? Green when the whole balance came from
   invoices and credit notes, amber when something was typed in by hand and needs a human to
   say whether it belongs (a payment to the tax office does; a stray line does not). */
.reg-recon { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 9px 16px; font-size: 12.5px; color: var(--muted);
  border-bottom: 1px solid var(--line); flex: none; }
.reg-recon b { color: var(--ink); font-variant-numeric: tabular-nums; }
.reg-recon.ties { background: color-mix(in srgb, var(--green) 10%, var(--card)); }
.reg-recon.has-manual { background: color-mix(in srgb, var(--amber) 14%, var(--card)); }
.reg-recon-dot { opacity: .45; }
.reg-recon-ok { margin-left: auto; color: var(--green-dark); font-weight: 700; }
.reg-recon-btn { margin-left: auto; cursor: pointer; font-size: 12px; font-weight: 700;
  color: var(--amber); background: none; border: 1px solid color-mix(in srgb, var(--amber) 45%, var(--line));
  border-radius: 8px; padding: 4px 11px; transition: background .13s ease, color .13s ease; }
.reg-recon-btn:hover { background: var(--amber); color: #2b1f04; }
/* the filter itself */
.reg-only-manual #reg-rows tr.reg-row:not(.reg-manual) { display: none; }
.reg-band-hint { margin-left: auto; font-style: italic; opacity: .75; }
/* Shown when a report is too long to draw in full. It has to be impossible to miss:
   a truncated total that looks complete is the worst thing an accounting screen can do. */
/* Shown when an invoice will close a customer's appointment. Visible on purpose: closing
   someone's visit is a real consequence, so it should never happen silently. */
.iv-appt { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 14px; font-size: 12.5px; color: var(--green-dark, #1e5c37);
  background: var(--green-light); border-bottom: 1px solid var(--green-line); }
.iv-appt select { border: 1px solid var(--green-line); border-radius: 7px; background: var(--field-bg); padding: 3px 6px;
  font-size: 12.5px; font-weight: 600; color: var(--green-dark, #1e5c37); cursor: pointer; max-width: 340px; }
.rep-cap-band { margin: 0 0 10px; padding: 9px 13px; font-size: 12.5px; border-radius: 8px;
  color: var(--text); background: var(--warn-bg, #fff6e5); border: 1px solid var(--warn-line, #f0d9a8); }
.reg-foot { display: flex; align-items: center; gap: 12px; padding: 10px 16px; border-top: 1px solid var(--line); background: var(--card); flex: none; }
.reg-ending { font-size: 13px; color: var(--muted); }
.reg-ending b { font-size: 19px; color: var(--ink); margin-left: 8px; }
.reg-ro-hint { display: inline-flex; align-items: center; gap: 6px; }
.reg-ro-tag { font-size: 10px; font-weight: 800; letter-spacing: .4px; text-transform: uppercase;
  background: rgba(255,255,255,.18); color: #eaf3ee; border-radius: 6px; padding: 2px 7px; margin-left: 8px; vertical-align: 1px; }

/* ---------- Pay Bills ---------- */
.pb-tbl td.pb-chk, .pb-tbl th.pb-chk { text-align: center; padding-left: 6px; padding-right: 6px; }
.pb-tbl .pb-check, .pb-tbl #pb-all { width: 15px; height: 15px; cursor: pointer; accent-color: var(--green); }
.pb-row { cursor: default; }
.pb-row:hover > td { background: color-mix(in srgb, var(--green) 9%, transparent); }
.pb-tbl tr.pb-row.pb-sel > td { background: color-mix(in srgb, var(--green) 20%, var(--card)); }
.pb-overdue { color: var(--danger); font-weight: 600; }
.pb-tbl .pb-amt { width: 100%; border: 1px solid var(--line); border-radius: 5px; padding: 5px 6px; font-size: 13px;
  background: #fffef4; color: var(--ink); text-align: right; }
.pb-tbl .pb-amt:focus { border-color: var(--green); background: var(--field-bg); outline: none; }
.pb-open { cursor: pointer; }
.pb-filter { display: inline-flex; align-items: center; gap: 6px; color: #eaf3ee; font-size: 12.5px; font-weight: 600; }
.pb-filter input[type="checkbox"] { accent-color: #fff; }
.pb-date { width: 110px; border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px; font-size: 13px; }
.win-band .pb-filter .pb-date { border-color: rgba(255,255,255,.4); background: rgba(255,255,255,.14); color: #fff; }
.win-band .pb-filter .pb-date::placeholder { color: color-mix(in srgb, var(--on-green) 72%, transparent); }
.pb-foot { display: flex; align-items: center; gap: 16px; padding: 10px 16px; border-top: 1px solid var(--line); background: var(--card); flex: none; flex-wrap: wrap; }
.pb-pay { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.pb-pay label { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted); font-weight: 600; }
.pb-pay select { border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px; font-size: 13px; background: var(--field-bg); color: var(--field-fg); }
.pb-total { font-size: 13px; color: var(--muted); }
.pb-total b { font-size: 19px; color: var(--ink); margin-left: 8px; }
.pb-foot .btn:disabled { opacity: .5; cursor: not-allowed; }
.win-band-jump { display: inline-flex; align-items: center; gap: 8px; margin-left: 18px;
  background: rgba(255,255,255,.14); border-radius: 8px; padding: 5px 6px 5px 12px; flex: none; }
.win-band-jump > span { font-size: 10px; font-weight: 800; letter-spacing: 1px; color: color-mix(in srgb, var(--on-green) 72%, transparent); }
.win-jump-input { background: var(--field-bg); border: 0; border-radius: 6px; padding: 6px 10px; font-size: 13px;
  color: var(--ink); width: 124px; }
.win-jump-input::placeholder { color: #9aa8a0; }
.win-jump-input.bad { box-shadow: 0 0 0 2px #e5533c; }
.win-band-actions { margin-left: auto; display: flex; gap: 8px; flex: none; }
.win-btn { background: rgba(255,255,255,.15); color: #fff; border: 0; border-radius: 7px;
  padding: 8px 14px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.win-btn:hover { background: rgba(255,255,255,.28); }
.win-btn.primary { background: var(--card); color: var(--green-dark); font-weight: 700; }
.win-btn.primary:hover { background: color-mix(in srgb, var(--on-green) 12%, var(--green)); }
/* Calendar inside a workspace window: fit the day-view to the window and scroll
   internally, instead of the full-page calc(100vh) height that overflows the window. */
.ws-win .cal-layout { padding: 16px; flex: 1; min-height: 0; align-items: stretch; }
.ws-win .cal-side { align-self: flex-start; }
.ws-win .day-col { display: flex; flex-direction: column; }
.ws-win .day-scroll { height: auto; flex: 1; min-height: 0; }

/* the invoice sheet, when it lives inside a window instead of the overlay */
.qb-sheet.qb-in-win { flex: 1; display: flex; flex-direction: column; min-height: 0; width: auto;
  box-shadow: none; border-radius: 0; max-width: none; max-height: none; margin: 0; }

/* ---------- QuickBooks-style invoice sheet ---------- */
.qb-back { align-items: flex-start; padding: 2.5vh 2vw; }
/* floating-dialog variant (opened outside the workspace): movable/resizable/maximizable */
.qb-sheet.qb-float { max-width: none; max-height: none; margin: 0; box-shadow: 0 18px 60px rgba(0,0,0,.35); }
.qb-float .qb-top { cursor: move; user-select: none; }
/* The editor's close button inherits the shared .ws-ctl treatment above. */
.qb-float .ws-grip { border-bottom-right-radius: 12px; }
.qb-sheet { background: var(--card); border-radius: 12px; width: 100%; max-width: 1240px; margin: 0 auto;
  max-height: 95vh; display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 70px rgba(0,0,0,.30); }
.qb-top { display: flex; align-items: center; justify-content: space-between; padding: 10px 18px;
  border-bottom: 1px solid #cfdbd3; background: #dfe9e2; }
.qb-top h3 { margin: 0; font-size: 15px; }
.qb-top .x { background: none; border: 0; font-size: 22px; line-height: 1; cursor: pointer; color: var(--muted); }
.qb-band { display: flex; align-items: flex-end; gap: 18px; background: var(--green-dark); padding: 12px 20px; }
.qb-band label { display: block; font-size: 10px; font-weight: 800; letter-spacing: 1px; color: color-mix(in srgb, var(--on-green) 72%, transparent); margin-bottom: 4px; }
.qb-band-cust input { width: 320px; max-width: 60vw; background: var(--field-bg); border: 0; border-radius: 7px; padding: 8px 11px; font-size: 14px; }
.qb-nav { display: flex; gap: 4px; padding-bottom: 1px; }
/* Nav arrows + Find: translucent, they sit quietly on the band. */
.qb-nav button, #qb-find { background: rgba(255,255,255,.16); color: #fff;
  border: 1px solid rgba(255,255,255,.34); border-radius: 9px; cursor: pointer;
  transition: background .15s ease, box-shadow .15s ease, border-color .15s ease, transform .08s ease; }
.qb-nav button { width: 36px; height: 36px; font-size: 15px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; }
#qb-find { padding: 0 15px; height: 36px; font-size: 13px; font-weight: 600; margin-bottom: 1px; }
.qb-nav button:hover, #qb-find:hover { background: rgba(255,255,255,.30); border-color: rgba(255,255,255,.55);
  box-shadow: 0 2px 9px rgba(0,0,0,.16); }
/* Print / email / open: solid white chips with the accent-coloured icon, so the real actions
   pop off the band and read as buttons instead of muddy translucent squares. */
#qb-print, #qb-email, #qb-open { width: 38px; height: 36px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: #fff; color: var(--green-dark); border: 0; border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0,0,0,.22);
  transition: background .15s ease, box-shadow .15s ease, transform .09s ease; }
#qb-print svg, #qb-email svg, #qb-open svg { width: 18px; height: 18px; }
#qb-print:hover, #qb-email:hover, #qb-open:hover { transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,.26); }
#qb-print:active, #qb-email:active, #qb-open:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(0,0,0,.22); }
.qb-nav button:active, #qb-find:active { transform: translateY(1px); box-shadow: none; }
.qb-nav button:focus-visible, #qb-find:focus-visible, #qb-print:focus-visible, #qb-email:focus-visible, #qb-open:focus-visible {
  outline: 2px solid rgba(255,255,255,.85); outline-offset: 1px; }
.qb-viewonly { align-self: center; background: #fdf6e3; color: #b8860b; border: 1px solid #ecd9a0;
  font-size: 11px; font-weight: 800; letter-spacing: .6px; padding: 4px 12px; border-radius: 9px; white-space: nowrap; }
.row-inactive td { opacity: .45; }
.row-inactive td:last-child { opacity: 1; }
.ev-flash { animation: evflash 1.4s ease-out 2; }
@keyframes evflash { 0% { box-shadow: 0 0 0 4px var(--green); } 100% { box-shadow: 0 0 0 0 rgba(47,143,91,0); } }
/* The appointment you jumped to keeps a gentle "breathing" glow so you can spot it in a
   busy day - until you click it. Lifts above (and un-dims) the other blocks. */
.ev.ev-breathe { animation: evbreathe 1.7s ease-in-out infinite; z-index: 9; opacity: 1; }
/* Highlighting an appointment must not repaint it - the colour is its status. Just bring a faded
   one (no-show, cancelled) up to full strength so it is clearly the one being pointed at. */
.ev.ev-breathe.out-done, .ev.ev-breathe.out-noshow, .ev.ev-breathe.out-cancelled { opacity: 1; }
@keyframes evbreathe {
  0%, 100% { box-shadow: 0 0 0 2px var(--green), 0 1px 3px rgba(0,0,0,.10); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--green) 40%, transparent), 0 3px 12px color-mix(in srgb, var(--green) 35%, transparent); }
}
.qb-find-list { max-height: 260px; overflow-y: auto; margin-top: 12px; border-top: 1px solid var(--line); padding-top: 6px; }
/* dialog-as-window (makeDialogWindow): Find Invoices, New email, … */
.dlg-win { display: flex; flex-direction: column; max-width: none; }
.dlg-win .modal-body { flex: 1; overflow-y: auto; min-height: 0; }
.dlg-win .modal-head { cursor: move; user-select: none; }
.dlg-win .ws-grip { border-bottom-right-radius: 12px; }
.qb-find-dlg .qb-find-list { max-height: none; overflow: visible; }
.qb-tmpl { margin-left: auto; font-size: 12px; color: color-mix(in srgb, var(--on-green) 72%, transparent); padding-bottom: 8px; }
.qb-tmpl b { color: var(--on-green); }
.qb-cols { display: flex; flex: 1; min-height: 0; }
.qb-mainpane { flex: 1; min-width: 0; padding: 20px 24px; overflow-y: auto; position: relative; }
.qb-pastdue { position: absolute; top: 74px; right: 36px; z-index: 5; font-size: 42px; font-weight: 800;
  letter-spacing: 3px; color: rgba(179,38,30,.28); border: 5px solid rgba(179,38,30,.28); border-radius: 10px;
  padding: 4px 18px; transform: rotate(-14deg); pointer-events: none; }
.qb-sidepane { width: 264px; flex: 0 0 auto; background: var(--th-bg); padding: 16px 18px; overflow-y: auto; }
.qb-split { flex: 0 0 7px; cursor: col-resize; border-left: 1px solid var(--line); background: transparent; }
.qb-split:hover, .qb-split:active { background: var(--green-light); border-left-color: var(--green); }
.qb-headrow { display: flex; gap: 22px; align-items: flex-start; margin-bottom: 16px; flex-wrap: wrap; }
.qb-invword { font-size: 34px; font-weight: 300; letter-spacing: .5px; color: color-mix(in srgb, var(--ink) 78%, var(--card)); }
.qb-meta { display: flex; gap: 16px; margin-left: auto; }
.qb-field label, .qb-billto label { display: block; font-size: 10px; font-weight: 800; letter-spacing: 1px;
  color: var(--muted); margin-bottom: 4px; }
.qb-field input[type="date"] { padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; font-size: 13.5px; }
.qb-due-row { position: relative; display: flex; gap: 4px; align-items: stretch; }
.qb-term-num { display: inline-flex; align-items: center; justify-content: center; min-width: 34px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--th-bg); font-weight: 700; font-size: 13px; color: var(--ink); }
.qb-due-btn { width: 30px; align-self: stretch; border: 1px solid var(--line); background: var(--field-bg);
  border-radius: 8px; cursor: pointer; color: var(--muted); font-size: 12px; }
.qb-due-btn:hover { background: var(--green-light); color: var(--green-dark); border-color: var(--green); }
.qb-due-btn:disabled { opacity: .4; cursor: default; }
.qb-due-menu { position: absolute; top: calc(100% + 4px); right: 0; z-index: 60; background: var(--card);
  border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 10px 28px rgba(0,0,0,.16);
  padding: 4px; display: flex; flex-direction: column; min-width: 110px; }
.qb-due-menu[hidden] { display: none; }
.qb-due-menu button { text-align: left; background: none; border: 0; padding: 7px 12px; border-radius: 6px;
  font-size: 13px; cursor: pointer; }
.qb-due-menu button:hover { background: var(--green-light); color: var(--green-dark); }
.qb-ro { padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; font-size: 13.5px;
  background: var(--bg); color: var(--muted); min-width: 64px; text-align: center; }
.qb-billto { min-width: 210px; max-width: 280px; }
.qb-billto > div { background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 12px; font-size: 13px; min-height: 40px; line-height: 1.45; }
.qb-table { width: 100%; border-collapse: collapse; margin-top: 6px; }
.qb-table th { text-align: left; font-size: 10.5px; letter-spacing: .8px; color: var(--muted);
  border-bottom: 2px solid var(--line); padding: 7px 8px; }
.qb-table th.right { text-align: right; }
.qb-table td { padding: 5px 6px; border-bottom: 1px solid var(--line); font-size: 13.5px; }
/* Every line row carries the same faint tint, so each white field reads as its own boxed cell -
   uniform, instead of only the alternating rows looking framed. */
.qb-table tbody tr td { background: color-mix(in srgb, var(--ink) 4%, transparent); }
.qb-table input { width: 100%; border: 1px solid transparent; background: var(--field-bg); border-radius: 6px;
  padding: 7px 8px; font-size: 13.5px; }
.qb-table input:focus { background: var(--field-bg); border-color: var(--green); outline: none; }
.qb-amt { font-weight: 600; white-space: nowrap; }
.qb-totals { margin-left: auto; width: 300px; margin-top: 18px; display: flex; flex-direction: column; gap: 7px; font-size: 13px; }
.qb-totals > div { display: flex; justify-content: space-between; align-items: baseline; }
.qb-totals > div[hidden] { display: none; }
.qb-totals span { color: var(--muted); font-size: 11px; font-weight: 700; letter-spacing: .8px; }
.qb-grand { border-top: 2px solid var(--ink); padding-top: 8px; }
.qb-grand b { font-size: 17px; }
/* discount input inside the totals stack (PERCENT off BEFORE tax) */
.qb-totals .qb-disc-line { align-items: center; }
.qb-totals .qb-disc-wrap { display: flex; align-items: center; gap: 10px; }
.qb-totals .qb-disc-line input { width: 58px; text-align: right; padding: 4px 8px; font-size: 13.5px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--field-bg); }
.qb-totals .qb-disc-line input:focus { border-color: var(--green); outline: none; }
.qb-foot { display: flex; gap: 10px; align-items: center; padding: 13px 24px; border-top: 1px solid var(--line); background: var(--th-bg); }
.qb-side-name { font-weight: 700; font-size: 15px; margin-bottom: 4px; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.qb-side-edit { background: none; border: 1px solid var(--line); border-radius: 6px; width: 27px; height: 25px;
  cursor: pointer; color: var(--muted); font-size: 13px; line-height: 1; flex: 0 0 auto; }
.qb-side-edit:hover { background: var(--green-light); color: var(--green-dark); border-color: var(--green); }
.qb-side-h { font-size: 10px; font-weight: 800; letter-spacing: 1px; color: var(--muted); margin: 16px 0 6px;
  border-bottom: 1px solid var(--line); padding-bottom: 4px; }
.qb-kv { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; padding: 4px 0; }
.qb-kv span { color: var(--muted); }
.qb-kv b { font-weight: 600; text-align: right; }
.qb-kv b { min-width: 0; }
.qb-ell { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qb-red { color: var(--danger); }
.qb-link { cursor: pointer; border-radius: 6px; }
.qb-link:hover { background: var(--green-light); }
.qb-side-empty { color: var(--muted); font-size: 12.5px; margin-top: 10px; line-height: 1.5; }
@media (max-width: 900px) { .qb-sidepane, .qb-split { display: none; } }

/* ---------- Page bits ---------- */
/* Pinned page header (Customers / Inventory / Invoices): the title row + search bar stay
   fixed at the top of the window while only the table scrolls beneath them. Bleeds over
   main's 26/32px padding so table rows never peek out around the pinned block's edges. */
.page-pin { position: sticky; top: 0; z-index: 20; background: var(--bg);
  margin: -26px -32px 16px; padding: 26px 32px 10px; }
.page-pin .toolbar { margin-bottom: 0; }
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 20px; }
/* space out the action buttons in a page header so they don't touch */
.page-head button + button { margin-left: 10px; }
.page-head h2 { margin: 0; font-size: 22px; }
.page-head .sub { color: var(--muted); font-size: 13px; margin-top: 2px; }

.btn {
  background: var(--green); color: var(--on-green); border: 0; padding: 9px 16px; border-radius: 8px;
  font-size: 14px; font-weight: 600;
}
.btn:hover { background: var(--green-dark); }
.btn.ghost { background: var(--card); color: var(--ink); border: 1px solid var(--line); }
.btn.ghost:hover { background: var(--bg); }
.btn.danger { background: var(--danger); }
/* Amber "think before you click" button, for actions that overwrite data but are not deletions.
   Dark text on amber, because white on yellow is unreadable. */
.btn.warn { background: #f2b202; color: #3d2c00; border: 1px solid #d99e00; }
.btn.warn:hover { background: #dea201; }
.btn.sm { padding: 5px 10px; font-size: 12.5px; }
/* Restore dialog: a proper drop target instead of the browser's raw file input, which looks
   unfinished next to the rest of the app. The native input stays in the DOM but hidden, so
   clicking the label still opens the file chooser and keyboard users keep the same path. */
.rs-drop {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 26px 18px; border: 2px dashed var(--line); border-radius: 12px;
  background: var(--bg); cursor: pointer; text-align: center;
  transition: border-color .15s, background .15s;
}
.rs-drop:hover, .rs-drop.over { border-color: var(--green); background: var(--green-light); }
.rs-drop.chosen { border-style: solid; border-color: var(--green); background: var(--green-light); }
.rs-drop-ic { font-size: 30px; line-height: 1; }
.rs-drop-main { font-weight: 700; font-size: 14.5px; color: var(--ink); }
.rs-drop-sub { font-size: 12.5px; color: var(--muted); }
.rs-group { margin: 16px 0 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
            text-transform: uppercase; color: var(--muted); }
.rs-count { font-size: 12.5px; color: var(--muted); }

.toolbar { display: flex; gap: 10px; margin-bottom: 16px; align-items: center; flex-wrap: wrap; }
.search { flex: 1; min-width: 200px; }
input.search, .field input, .field select, .field textarea {
  padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px; font-size: 14px; width: 100%;
  background: var(--field-bg); font-family: inherit;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--green); border-color: var(--green); }

/* phone/mobile with a fixed, non-editable country-code chip */
.ph-input { display: flex; }
.ph-input input { flex: 1; min-width: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; }
.ph-cc { display: inline-flex; align-items: center; padding: 0 9px; background: #eef1ef; border: 1px solid var(--line);
  border-right: 0; border-radius: 8px 0 0 8px; color: #333; font-size: 14px; font-weight: 600; white-space: nowrap; user-select: none; }
.ph-cc:empty { display: none; }                 /* no country selected -> plain input */
.ph-cc:empty + input { border-radius: 8px; }

/* country picker dropdown (all countries shown; matches float to the top) */
.cc-field { position: relative; }
.cc-dd { position: absolute; left: 0; right: 0; top: 100%; margin-top: 3px; background: var(--card); border: 1px solid var(--line);
  border-radius: 8px; box-shadow: 0 12px 30px rgba(0,0,0,.18); max-height: 220px; overflow-y: auto; z-index: 50; }
.cc-opt { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 9px 12px; cursor: pointer; font-size: 14px; }
.cc-opt:hover, .cc-opt.active { background: var(--green-light); }
.cc-opt .cc-pfx { color: var(--muted); font-size: 12.5px; }

/* Cards / stats */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; margin-bottom: 24px; }
.stat { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow); }
.stat .n { font-size: 26px; font-weight: 700; color: var(--green-dark); }
.stat .l { color: var(--muted); font-size: 12.5px; margin-top: 3px; text-transform: uppercase; letter-spacing: .03em; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.card h3 { margin: 0; padding: 14px 18px; border-bottom: 1px solid var(--line); font-size: 15px; }
.card-head-flex { display: flex; align-items: center; justify-content: space-between; padding: 10px 18px; border-bottom: 1px solid var(--line); }
.card-head-flex h3 { padding: 0; border: 0; }
.card .card-body { padding: 14px 18px; }

/* Tables */
/* Only the page scrolls vertically (the sidebar is sticky and stays put). The table keeps
   horizontal scroll for wide columns, but no vertical scroll of its own - otherwise Windows
   shows TWO vertical scrollbars (page + table) and you'd scroll inside both. */
.table-wrap { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow-x: auto; box-shadow: var(--shadow); }
/* always-visible green horizontal scrollbar so you can scroll right to reach clipped columns */
.table-wrap::-webkit-scrollbar { height: 13px; width: 13px; }
.table-wrap::-webkit-scrollbar-track { background: #eef1ef; border-radius: 0 0 var(--radius) var(--radius); }
.table-wrap::-webkit-scrollbar-thumb { background: var(--green); border-radius: 7px; border: 3px solid #eef1ef; }
.table-wrap::-webkit-scrollbar-thumb:hover { background: var(--green-dark); }
.table-wrap { scrollbar-color: var(--green) #eef1ef; }   /* Firefox */

/* Checkbox column (multi-select for bulk email) */
.chk-col { width: 34px; text-align: center; overflow: visible !important; }
.chk-col input[type="checkbox"] { width: 15px; height: 15px; cursor: pointer; accent-color: var(--green); vertical-align: middle; }

/* WhatsApp chat page */
.wa-hint { background: #eef7f0; border: 1px solid #cfe8d6; color: #2c6b40; border-radius: 8px;
  padding: 10px 14px; font-size: 13px; margin-bottom: 14px; }
.wa-hint a { color: #1c7c3c; font-weight: 600; }
.btn.wa-btn { background: #25d366; border-color: #25d366; color: #fff; }
.btn.wa-btn:hover { background: #1eb658; border-color: #1eb658; }

/* ---- Embedded WhatsApp inbox ---- */
.wa-me-head { display: flex; align-items: center; gap: 14px; }
.wa-me-av { width: 46px; height: 46px; min-width: 46px; font-size: 18px; cursor: pointer; position: relative; }
.wa-me-av:hover { filter: brightness(.9); }
/* "Change photo" badge - a crisp drawn camera, not the 📷 emoji (which rendered as
   an unreadable white dot at this size). */
.wa-me-av::after {
  content: "";
  position: absolute; right: -3px; bottom: -3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--field-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%232f8f5b' d='M9 5h6l1.3 2H20a2.2 2.2 0 0 1 2.2 2.2V18A2.2 2.2 0 0 1 20 20.2H4A2.2 2.2 0 0 1 1.8 18V9.2A2.2 2.2 0 0 1 4 7h3.7z'/%3E%3Ccircle cx='12' cy='13.4' r='3.7' fill='%23ffffff'/%3E%3Ccircle cx='12' cy='13.4' r='1.9' fill='%232f8f5b'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
  border: 1px solid #e6ece8;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
/* Non-admins can't change the business profile, so don't dangle a camera badge at them. */
.wa-me-av.no-edit { cursor: default; }
.wa-me-av.no-edit:hover { filter: none; }
.wa-me-av.no-edit::after { display: none; }
.wa-tabs { display: flex; align-items: center; gap: 8px; }
/* View actions (Unread / Archived / New) sit in the page header rather than the list column.
   margin-left:auto groups them with the connector chips on the right; the margin reset stops
   .page-head's "button + button" rule from stacking on top of the flex gap. */
.wa-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.wa-actions button + button { margin-left: 0; }

/* your profile panel (modal) */
.wa-pf { text-align: center; }
.wa-pf-pic { width: 96px; height: 96px; border-radius: 50%; margin: 4px auto 10px; background: #25d366; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 36px; font-weight: 700; background-size: cover; background-position: center; }
.wa-pf-pic.has-pic { color: transparent; font-size: 0; }
.wa-pf-name { font-weight: 700; font-size: 16px; margin-top: 10px; }
.wa-pf-num { font-size: 13px; }
.wa-tab { display: inline-flex; align-items: center; gap: 7px; padding: 7px 14px; border-radius: 8px;
  border: 1px solid var(--border, #dde3dd); background: var(--card); cursor: pointer; font-size: 13px; font-weight: 600; color: #333; }
.wa-tab.active { background: #e7f6ec; border-color: #9fd9b4; color: #1c7c3c; }
/* colour-coded actions, matching the soft-tint style of the active tab */
#wa-restart { background: #fdf3d3; border-color: #e6c757; color: #8a6a12; }
#wa-restart:hover:not(:disabled) { background: #fbecba; border-color: #dcb941; }
#wa-unlink { background: var(--tint-red); border-color: #e3a1a1; color: #b3261e; }
#wa-unlink:hover:not(:disabled) { background: var(--tint-red); border-color: #d98a8a; }
.wa-dot { width: 9px; height: 9px; border-radius: 50%; background: #c2c8c2; }
.wa-dot.on { background: #25d366; } .wa-dot.wait { background: #f0ad3c; } .wa-dot.off { background: #c2c8c2; }

.wa-body { height: calc(100vh - 150px); min-height: 420px; }
.wa-center { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; color: var(--muted); }

.spinner { width: 34px; height: 34px; border: 3px solid #d9e4dc; border-top-color: #25d366; border-radius: 50%; animation: waspin .8s linear infinite; }
@keyframes waspin { to { transform: rotate(360deg); } }

/* connect / QR screens */
.wa-connect { max-width: 460px; margin: 4vh auto 0; text-align: center; background: var(--card); border: 1px solid var(--border, #dde3dd); border-radius: 12px; padding: 30px 28px; }
.wa-connect h3 { margin: 6px 0 14px; }
.wa-big { font-size: 44px; }
.wa-qr { width: 300px; height: 300px; margin: 0 auto 14px; display: flex; align-items: center; justify-content: center; background: var(--card); border: 1px solid #eee; border-radius: 10px; }
.wa-qr img { border-radius: 6px; }
.wa-steps { text-align: left; max-width: 320px; margin: 0 auto 12px; color: #444; font-size: 13.5px; line-height: 1.7; }
.wa-warn { background: #fff4e5; border: 1px solid #f3d19e; color: #9a5b00; border-radius: 8px; padding: 8px 12px; font-size: 12px; margin-top: 8px; }
.wa-err { color: var(--danger); font-size: 12.5px; word-break: break-word; }
/* Telegram two-step-verification password entry */
.tg-pw { display: flex; gap: 8px; max-width: 340px; margin: 6px auto 12px; }
.tg-pw-input { flex: 1; padding: 10px 12px; border: 1px solid var(--border, #cfd8cf); border-radius: 8px; font-size: 14px; background: var(--field-bg); color: var(--field-fg); }
.tg-pw-input:focus { outline: none; border-color: #25d366; box-shadow: 0 0 0 2px rgba(37,211,102,.15); }
.tg-pw .btn { white-space: nowrap; }

/* two-pane inbox */
/* Thin top bar in the chat list while a freshly-linked account syncs its history. */
.wa-syncing { background: #fff7e6; color: #8a6d1f; border-bottom: 1px solid #f0e2bf;
  padding: 7px 12px; font-size: 12px; font-weight: 600; text-align: center; flex: none; }
.wa-inbox { display: flex; height: 100%; border: 1px solid var(--border, #dde3dd); border-radius: 12px; overflow: hidden; background: var(--card); }
.wa-list { width: 320px; min-width: 320px; border-right: 1px solid var(--border, #dde3dd); display: flex; flex-direction: column; }
.wa-list-head { display: flex; gap: 8px; padding: 10px; border-bottom: 1px solid var(--border, #eee); }
.wa-list-head .search.sm { flex: 1; min-width: 0; padding: 7px 10px; font-size: 13px; }
.wa-filter { border: 1px solid var(--border, #dde3dd); background: var(--card); border-radius: 15px; padding: 6px 11px; font-size: 12px; cursor: pointer; white-space: nowrap; color: #444; flex: 0 0 auto; }
.wa-filter:hover { background: #f4f6f4; }
.wa-filter.active { background: #e7f6ec; border-color: #9fd9b4; color: #1c7c3c; font-weight: 700; }
.wa-chats { flex: 1; overflow-y: auto; }
.wa-chat { display: flex; gap: 10px; padding: 10px 12px; cursor: pointer; border-bottom: 1px solid #f2f4f2; position: relative; }
.wa-chat:hover { background: #f6f9f6; }
.wa-chat.active { background: #e7f6ec; }
/* Archive control: hidden until the row is hovered, so it never competes with the message preview.
   Kept keyboard-reachable - :focus-visible reveals it for anyone tabbing rather than mousing. */
.wa-chat-arch { position: absolute; right: 10px; bottom: 8px; opacity: 0; transition: opacity .12s;
  border: 1px solid var(--line); background: var(--card); color: var(--muted); border-radius: 6px;
  padding: 2px 8px; font-size: 11px; font-family: inherit; cursor: pointer; }
.wa-chat:hover .wa-chat-arch, .wa-chat-arch:focus-visible { opacity: 1; }
.wa-chat-arch:hover { background: var(--green-light); border-color: var(--green); color: var(--green-dark); }
.wa-av { width: 40px; height: 40px; min-width: 40px; border-radius: 50%; background: #25d366; color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; }
.wa-chat-main { flex: 1; min-width: 0; }
.wa-chat-top { display: flex; justify-content: space-between; gap: 6px; }
.wa-chat-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wa-chat-time { font-size: 11px; color: var(--muted); white-space: nowrap; }
.wa-chat-bot { display: flex; justify-content: space-between; align-items: center; gap: 6px; margin-top: 2px; }
.wa-snip { font-size: 12.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wa-unread { background: #25d366; color: #fff; font-size: 11px; font-weight: 700; border-radius: 11px; min-width: 20px; height: 20px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center; }

.wa-thread { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #efe7de; }
.wa-thread-head { display: flex; align-items: center; gap: 10px; padding: 8px 14px; background: var(--card); border-bottom: 1px solid var(--border, #eee); }
.wa-th-id { min-width: 0; }
.wa-th-name { font-weight: 700; line-height: 1.2; }
.wa-add-cust { margin-left: auto; flex-shrink: 0; }
.wa-th-sub { font-size: 12px; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wa-biz { display: inline-block; background: #e7f6ec; color: #1c7c3c; border: 1px solid #bfe6cd; border-radius: 4px; padding: 0 5px; font-size: 10.5px; font-weight: 700; vertical-align: middle; }
/* Live presence pill next to the Business badge - same shape, filled green for "online". */
.wa-presence { display: inline-block; background: #2fae5a; color: #fff; border: 1px solid #2fae5a; border-radius: 4px; padding: 0 6px; font-size: 10.5px; font-weight: 700; vertical-align: middle; }
.wa-presence.typing { background: #eaf6ee; color: #1c7c3c; border-color: #bfe6cd; font-style: italic; }
.wa-presence.offline { background: #eef1f4; color: #6b7783; border-color: #d7dee4; }
.wa-lastseen { font-size: 11px; vertical-align: middle; }
.wa-media { font-style: italic; opacity: .92; }
.wa-msg.call { justify-content: center; }
.wa-msg.call .wa-bubble { background: #eef1ee; color: #555; font-size: 12.5px; text-align: center; box-shadow: none; }
.wa-msgs { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 6px; }
.wa-loadmore { align-self: center; margin: 2px 0 8px; padding: 4px 12px; border-radius: 12px; background: rgba(0,0,0,.05); color: var(--muted); font-size: 12px; }
.wa-msg { display: flex; }
.wa-msg.me { justify-content: flex-end; }
.wa-bubble { max-width: 72%; padding: 7px 10px 5px; border-radius: 8px; font-size: 13.5px; line-height: 1.4; position: relative; word-wrap: break-word; white-space: pre-wrap; box-shadow: 0 1px 0 rgba(0,0,0,.08); }
.wa-msg.them .wa-bubble { background: var(--card); }
.wa-msg.me .wa-bubble { background: #d9fdd3; }
.wa-link-a { color: #1c74c4; text-decoration: underline; word-break: break-all; }
.wa-link-a:hover { color: #12579b; }
.wa-mtime { display: block; text-align: right; font-size: 10px; color: #667; margin-top: 2px; }
/* Delivery ticks on sent messages: grey = sent/delivered, blue = read (like WhatsApp) */
.wa-tick { display: inline-flex; align-items: center; margin-left: 4px; color: #92a3ae; vertical-align: -1px; }
.wa-tick.read { color: #53bdeb; }
.wa-tick.err { color: var(--danger); font-weight: 700; font-size: 11px; }
.wa-composer { display: flex; gap: 10px; padding: 10px 12px; background: var(--card); border-top: 1px solid var(--border, #eee); align-items: flex-end; }
.wa-composer textarea { flex: 1; resize: none; max-height: 120px; padding: 9px 12px; border: 1px solid var(--border, #dde3dd); border-radius: 20px; font: inherit; font-size: 14px; }
.wa-clip { font-size: 19px; line-height: 1; padding: 6px 11px; }

/* staged attachment preview(s) above the composer */
.wa-attach-preview { padding: 10px 12px; background: var(--card); border-top: 1px solid var(--border, #eee); }
.wa-ap-items { display: flex; gap: 12px; overflow-x: auto; padding: 4px 4px 6px; }
.wa-ap-item { position: relative; width: 64px; flex: 0 0 auto; }
.wa-ap-thumb { width: 64px; height: 64px; border-radius: 8px; overflow: hidden; background: #eef1ee; display: flex; align-items: center; justify-content: center; }
.wa-ap-thumb img { width: 100%; height: 100%; object-fit: cover; }
.wa-ap-ic { font-size: 28px; }
.wa-ap-x { position: absolute; top: -6px; right: -6px; width: 20px; height: 20px; border-radius: 50%; border: 2px solid #fff; background: #444; color: #fff; font-size: 10px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; }
.wa-ap-x:hover { background: #c0392b; }
.wa-ap-name { font-size: 10px; color: var(--muted); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }
.wa-ap-hint { font-size: 12px; color: var(--muted); margin-top: 4px; }

/* profile pictures on the avatar circles */
.wa-av { background-size: cover; background-position: center; overflow: hidden; }
.wa-av.group { background-color: #6b8fa3; font-size: 18px; } /* background-COLOR only - the `background` shorthand would reset background-size:cover and break group photos */
.wa-av.has-pic { color: transparent; font-size: 0; }   /* must come AFTER .group so a group WITH a photo hides its icon */

/* inline media: photos, stickers, voice/video/document */
.wa-photo { max-width: 260px; max-height: 320px; border-radius: 6px; display: block; }
.wa-photo.sticker { max-width: 120px; max-height: 120px; }
.wa-photo-wrap { position: relative; display: inline-block; line-height: 0; }
.wa-dl { position: absolute; top: 6px; right: 6px; width: 30px; height: 30px; border-radius: 50%; border: none;
  background: rgba(0,0,0,.55); color: #fff; font-size: 15px; cursor: pointer; display: flex; align-items: center;
  justify-content: center; opacity: 0; transition: opacity .12s; }
.wa-photo-wrap:hover .wa-dl { opacity: 1; }
.wa-dl:hover { background: rgba(0,0,0,.8); }
.wa-mediabox { min-width: 70px; }
.wa-mbtn { background: #f0f4f0; border: 1px solid #cfe0d4; color: #1c6b3a; border-radius: 16px; padding: 6px 13px; font-size: 13px; cursor: pointer; font-weight: 600; }
.wa-mbtn:hover { background: #e4efe7; }
.wa-mbtn:disabled { opacity: .7; cursor: default; }
.wa-video { max-width: 280px; max-height: 320px; border-radius: 6px; display: block; }

/* compact inline voice-note player (stays a pill, plays in place) */
.wa-voice { display: flex; align-items: center; gap: 9px; min-width: 210px; }
.wa-vplay { width: 30px; height: 30px; min-width: 30px; border-radius: 50%; border: none; background: #25d366; color: #fff; font-size: 12px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; }
.wa-vplay:hover { background: #1eb658; }
.wa-vbar { flex: 1; height: 5px; background: #ccd7ce; border-radius: 3px; position: relative; cursor: pointer; min-width: 90px; }
.wa-vfill { position: absolute; left: 0; top: 0; height: 100%; width: 0; background: #25d366; border-radius: 3px; }
.wa-vtime { font-size: 11px; color: #5a6b5e; min-width: 30px; text-align: right; }
/* appointment "resolved / done" chip toggle */
.done-toggle { display: inline-flex; align-items: center; gap: 9px; margin-top: 6px; padding: 9px 14px;
  border: 1px solid var(--line); border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px;
  color: var(--muted); user-select: none; transition: background .12s, border-color .12s, color .12s; }
.done-toggle:hover { border-color: #b7c9bf; }
.done-toggle input { width: 18px; height: 18px; accent-color: var(--green); cursor: pointer; margin: 0; flex: none; }
.done-toggle.on { background: var(--green-light); border-color: #9fd9b4; color: var(--green-dark); }
/* appointment participant rows (multiple clients in one slot) */
.ap-client-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.ap-client-row .ac-wrap, .ap-client-row > input { flex: 1; min-width: 0; }
.ap-client-x { flex: none; width: 34px; height: 34px; border: 1px solid var(--line); background: var(--card); border-radius: 8px; cursor: pointer; color: var(--danger); font-size: 13px; }
.ap-client-x:hover { border-color: var(--danger); background: var(--tint-red); }
/* permission chips (same chip style as the done toggle) */
.perm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 6px; }
.perm-chip { display: flex; align-items: center; gap: 9px; padding: 9px 14px; border: 1px solid var(--line);
  border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; color: var(--muted); user-select: none;
  transition: background .12s, border-color .12s, color .12s; }
.perm-chip:hover { border-color: #b7c9bf; }
.perm-chip input { width: 18px; height: 18px; accent-color: var(--green); cursor: pointer; margin: 0; flex: none; }
.perm-chip.on { background: var(--green-light); border-color: #9fd9b4; color: var(--green-dark); }
.perm-chip.wide { grid-column: 1 / -1; }
.perm-chip.locked { cursor: not-allowed; opacity: .65; }
.perm-chip.locked input { cursor: not-allowed; }
.scope-pick { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.scope-opt { display: flex; align-items: flex-start; gap: 10px; padding: 10px 13px; border: 1px solid var(--line);
  border-radius: 9px; cursor: pointer; font-size: 13px; line-height: 1.4; transition: border-color .12s, background .12s; }
.scope-opt:hover { border-color: #b7c9bf; }
.scope-opt input { width: 17px; height: 17px; accent-color: var(--green); cursor: pointer; margin: 1px 0 0; flex: none; }
.scope-opt:has(input:checked) { background: var(--green-light); border-color: #9fd9b4; }
.scope-opt b { color: var(--green-dark); }
.smtp-note { font-size: 12px; margin-top: 10px; padding: 9px 11px; background: #fff8e6; border: 1px solid #f0e0b0; border-radius: 8px; line-height: 1.45; }
.smtp-note:empty { display: none; }

/* Email Connection Setup - list of connected accounts */
.ea-list { display: flex; flex-direction: column; gap: 8px; }
.ea-row {
  display: flex; align-items: center; gap: 12px; padding: 11px 13px;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px; cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}
.ea-row:hover, .ea-row:focus { border-color: var(--green); box-shadow: 0 2px 8px color-mix(in srgb, var(--green) 12%, transparent); outline: none; }
.ea-av {
  width: 38px; height: 38px; min-width: 38px; border-radius: 50%;
  background: var(--green); color: var(--on-green); font-weight: 700; font-size: 16px;
  display: flex; align-items: center; justify-content: center;
}
.ea-main { flex: 1; min-width: 0; }
.ea-addr { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 8px; }
.ea-sub { font-size: 12.5px; margin-top: 1px; }
.ea-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--green-dark); background: #e8f5ee; border: 1px solid #bfe3ce;
  padding: 1px 7px; border-radius: 999px;
}
.ea-go { color: var(--muted); font-size: 22px; line-height: 1; }

.mail-head-actions { display: flex; align-items: center; gap: 8px; }

/* Compact Email header: the connected mailbox IS the title, with an unread pill
   beside it - one line instead of two, so the inbox list below gets more height. */
.mail-head { margin-bottom: 14px; }
.mail-head-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mail-head-title h2 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60vw; }
.mail-unread-pill {
  flex: none; background: var(--green); color: var(--on-green); border: 0;
  border-radius: 999px; padding: 3px 11px; font-size: 12px; font-weight: 700; white-space: nowrap;
}

/* Email nav: caret + collapsible mailbox switcher under the Email item */
.nav-caret {
  margin-left: auto; margin-right: -4px; background: none; border: none; cursor: pointer;
  color: #8fb7a0; font-size: 17px; font-weight: 700; line-height: 1; padding: 5px 6px; border-radius: 6px;
  transition: transform .18s, color .15s;
}
.nav-caret:hover { color: #fff; background: rgba(255,255,255,.08); }
.nav-caret.open { transform: rotate(180deg); }
/* the badge already claims margin-left:auto; when it's visible the caret sits after it */
.nav-badge + .nav-caret { margin-left: 6px; }

.nav-sub { max-height: 0; overflow: hidden; transition: max-height .22s ease; }
.nav-sub.open { max-height: 340px; overflow-y: auto; }
.nav-sub-row {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: none; border: none; cursor: pointer;
  padding: 8px 20px 8px 24px; color: #9fbcac; font-size: 12.5px; font-weight: 500;
  border-left: 3px solid transparent;
}
.nav-sub-row:hover { background: rgba(255,255,255,.05); color: #fff; }
/* --acct-color is set per-row (each mailbox its own colour) - accent bar + dot use it */
.nav-sub-row.active { color: #fff; border-left-color: var(--acct-color, var(--green)); }
.nav-sub-check { width: 14px; flex: none; color: var(--acct-color, var(--green)); font-weight: 700; font-size: 13px; line-height: 1; }
.nav-sub-row:not(.active) .nav-sub-check { font-size: 15px; }   /* the • dot reads a touch bigger */
.nav-sub-addr { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* "＋ Add messenger" row - a muted call-to-action under the connected list */
.nav-sub-add { color: rgba(255,255,255,.55); }
.nav-sub-add .nav-sub-check { color: rgba(255,255,255,.55); font-size: 15px; }
.nav-sub-add:hover { color: #fff; }
/* per-messenger unread count pill, anchored to the right of its row */
.msgr-unread { margin-left: auto; flex: none; background: #25D366; color: #fff; border-radius: 10px;
  min-width: 18px; height: 18px; padding: 0 6px; font-size: 10.5px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; }
/* Add-messenger picker (modal) */
.msgr-add-grid { display: flex; flex-direction: column; gap: 10px; }
.msgr-add-btn { display: flex; align-items: center; gap: 12px; width: 100%; padding: 13px 15px; border: 1px solid var(--line, #dbe3ea);
  border-radius: 10px; background: var(--card); cursor: pointer; font-size: 15px; font-weight: 600; color: #1c2b3a; text-align: left; transition: border-color .12s, background .12s; }
.msgr-add-btn:hover { border-color: var(--green, #2f8f5b); background: #f6faf7; }
.msgr-add-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; }
.msgr-add-name { flex: 1; }
.msgr-add-arrow { color: #9aa7b2; font-size: 20px; }
/* collapsed icon-only sidebar: hide the switcher entirely */
.sidebar.collapsed .nav-caret, .sidebar.collapsed .nav-sub { display: none !important; }
.wa-cap { margin-top: 5px; }
/* link preview card + inline player */
.wa-linkprev { margin-top: 8px; }
.wa-linkprev.card { display: block; width: min(300px, 100%); border: 1px solid rgba(0,0,0,.1); border-radius: 12px; overflow: hidden; background: rgba(0,0,0,.03); }
.wa-lp-media { position: relative; width: 100%; background: #0000000f; display: block; line-height: 0; }
.wa-lp-media img { width: 100%; display: block; object-fit: cover; }
.wa-linkprev.card:not(.portrait) .wa-lp-media img { aspect-ratio: 16 / 9; }
.wa-linkprev.card.portrait .wa-lp-media img { height: 300px; }
.wa-lp-play { position: absolute; inset: 0; margin: auto; width: 52px; height: 52px; border-radius: 50%; background: rgba(0,0,0,.55); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 20px; padding-left: 3px; box-shadow: 0 2px 10px rgba(0,0,0,.4); }
.wa-lp-meta { padding: 8px 10px; }
.wa-lp-title { font-weight: 600; font-size: 13px; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.wa-lp-site { font-size: 11.5px; color: var(--muted); margin-top: 3px; text-transform: capitalize; }
.wa-linkprev.embed .wa-lp-frame { position: relative; width: min(300px, 100%); border-radius: 12px; overflow: hidden; background: #000; }
.wa-linkprev.embed:not(.portrait) .wa-lp-frame { aspect-ratio: 16 / 9; }
.wa-linkprev.embed.portrait .wa-lp-frame { width: min(260px, 100%); aspect-ratio: 9 / 16; }
.wa-lp-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.wa-lightbox { position: fixed; inset: 0; background: rgba(0,0,0,.85); display: flex; align-items: center; justify-content: center; z-index: 3000; cursor: zoom-out; }
.wa-lb-inner { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.wa-lightbox img { max-width: 92vw; max-height: 84vh; border-radius: 6px; box-shadow: 0 8px 40px rgba(0,0,0,.5); cursor: default; }
.wa-lb-dl { background: #25d366; color: #fff; border: none; padding: 9px 18px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; }
.wa-lb-dl:hover { background: #1eb658; }
/* Prev/next arrows pinned to the screen edges, so they never crowd the picture. */
.wa-lb-nav { position: fixed; top: 50%; transform: translateY(-50%); width: 46px; height: 76px; display: flex; align-items: center; justify-content: center; background: rgba(255,255,255,.12); color: #fff; border: none; border-radius: 8px; font-size: 34px; line-height: 1; cursor: pointer; user-select: none; }
.wa-lb-nav:hover { background: rgba(255,255,255,.26); }
.wa-lb-nav.prev { left: 16px; }
.wa-lb-nav.next { right: 16px; }
.wa-lb-count { color: rgba(255,255,255,.72); font-size: 13px; letter-spacing: .04em; cursor: default; }
.wa-lightbox img.loading { opacity: .45; transition: opacity .12s; }

/* WhatsApp account dialog */
.wa-status { padding: 8px 12px; border-radius: 6px; font-size: 13px; margin-bottom: 12px; }
/* Cash exchange on the invoice sheet, under the paid note. Prints with the invoice: the customer
   gets a record of what they handed over and what came back. */
.inv-cash { margin-top: 6px; padding-top: 6px; border-top: 1px dotted #cfdad4; }
.inv-cash div { display: flex; justify-content: space-between; font-size: 12.5px; color: #55655c; }
.inv-cash div:last-child { font-weight: 700; color: var(--ink); }
/* Till helper on the "mark as paid" dialog: type what the customer handed over, read the change.
   Shown for Cash only. The invoice is still settled for its full amount either way. */
/* Cash tendered can arrive in another currency; the picker sits against the amount so it
   reads as one control, and the conversion line shows the sum being done rather than just
   its result - a till figure nobody can check is a till figure nobody trusts. */
.cash-in-row { display: flex; gap: 8px; align-items: stretch; }
.cash-in-row select { flex: none; width: 84px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--field-bg); font-size: 15px; font-weight: 700; padding: 0 6px; cursor: pointer; }
.cash-in-row #cash-in { flex: 1; }
.cash-conv span { color: var(--muted); font-size: 12.5px; }
/* The change line carries its own currency picker: a customer who paid with a $20 note
   usually wants dollars back, not guilders. */
.cash-change select { flex: none; margin-left: auto; margin-right: 8px; border: 1px solid var(--line);
  border-radius: 7px; background: var(--field-bg); font-size: 12.5px; font-weight: 700; padding: 2px 4px; cursor: pointer; }
.cash-change { display: flex; align-items: center; gap: 6px; }
/* On the invoice: the foreign figure reads first because that is what changed hands, with
   the local value beside it so the books can always be tied back. Prints as it shows. */
.inv-fx { color: var(--muted); font-weight: 400; font-size: .88em; margin-left: 5px; }
.cash-conv b { font-weight: 600; }
.cash-box { margin-top: 12px; padding: 12px 14px; border: 1px solid var(--line);
            border-radius: 10px; background: var(--bg); }
.cash-lbl { display: block; font-size: 12.5px; font-weight: 600; color: var(--muted); margin-bottom: 5px; }
.cash-box input {
  width: 100%; padding: 10px 12px; font-size: 20px; font-weight: 700; text-align: right;
  border: 1px solid var(--line); border-radius: 8px; background: var(--field-bg); color: var(--ink);
}
.cash-box input:focus { outline: none; border-color: var(--green); }
.cash-line { display: flex; justify-content: space-between; align-items: baseline;
             margin-top: 8px; font-size: 13px; color: var(--muted); }
.cash-line b { color: var(--ink); font-size: 14px; }
.cash-change { padding-top: 8px; border-top: 1px dashed var(--line); }
.cash-change b { font-size: 19px; }
.cash-change b.cash-ok { color: var(--green); }
.cash-change b.cash-short { color: var(--danger); }
/* Save was pressed while the counter is still short: draw the eye back to the box. */
.cash-box.cash-nudge { border-color: var(--danger); animation: cashNudge .28s ease; }
@keyframes cashNudge {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-4px); }
  75%      { transform: translateX(4px); }
}
.wa-status.ok { background: #e7f6ec; color: #1c7c3c; border: 1px solid #bfe6cd; }
/* Neutral variant, used to name the company a settings dialog is editing. */
.wa-status:not(.ok):not(.err) { background: var(--bg); border: 1px solid var(--line); color: var(--ink); }
.wa-test-row { display: flex; align-items: center; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
.wa-test-out { font-size: 13px; }
.wa-test-out.ok { color: #1c7c3c; }
.wa-test-out.err { color: var(--danger); }

/* BCC recipient preview inside the bulk-email dialog */
.bcc-box { max-height: 90px; overflow: auto; background: #f4f6f4; border: 1px solid var(--border, #dde3dd);
  border-radius: 6px; padding: 8px 10px; font-size: 12.5px; color: var(--muted); word-break: break-word; line-height: 1.5; }

/* Bulk-email drip progress bar */
.bulk-bar { height: 12px; background: #e6ece8; border-radius: 999px; overflow: hidden; margin-top: 14px; }
.bulk-bar-fill { height: 100%; width: 0; background: var(--green); border-radius: 999px; transition: width .4s ease; }
.queued-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px;
  background: rgba(58,143,99,.12); color: var(--green); font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: default; }

/* Resizable columns: drag the right edge of a header to widen/narrow it. */
table.resizable.locked { table-layout: fixed; }
table.resizable.locked th, table.resizable.locked td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* sticky headers: column labels + green resize grips stay visible while scrolling rows */
.table-wrap thead th { position: sticky; top: 0; z-index: 2; }
.col-resizer { position: absolute; top: 0; right: 0; width: 10px; height: 100%; cursor: col-resize; z-index: 3; }
/* always-visible green grip so it's obvious where to drag */
.col-resizer::after {
  content: ""; position: absolute; right: 3px; top: 22%; height: 56%; width: 3px;
  border-radius: 2px; background: var(--green);
}
.col-resizer:hover::after { top: 0; height: 100%; width: 4px; background: var(--green-dark); }
body.col-resizing-active, body.col-resizing-active * { cursor: col-resize !important; user-select: none !important; }
/* arrow marking the currently-sorted column (set via the Sort dialog) */
.sort-arrow { color: var(--green); font-size: 11px; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 11px 16px; font-size: 13.5px; }
th { background: var(--th-bg); color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; border-bottom: 1px solid var(--line); }
tbody tr { border-top: 1px solid var(--line); }
tbody tr:hover { background: var(--green-light); }
td.right, th.right { text-align: right; }
/* Inline-editable inventory cells: click to edit, Enter/blur to save. */
.edit-cell { cursor: text; }
.edit-cell:hover { box-shadow: inset 0 0 0 1px var(--green, #2f8f5b); background: var(--green-light); }
.cell-edit { width: 100%; box-sizing: border-box; font: inherit; padding: 4px 6px; margin: -3px 0; border: 1px solid var(--green, #2f8f5b); border-radius: 4px; background: var(--field-bg); color: var(--ink, #1d2b24); }
td.right .cell-edit { text-align: right; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.clickable { cursor: pointer; }
/* Approve Invoice: the status filter and what you can do with the result. */
.inv-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 14px; border-bottom: 1px solid var(--line); background: var(--th-bg); flex: none; }
.inv-filters { display: inline-flex; background: var(--card); border: 1px solid var(--line);
  border-radius: 9px; padding: 2px; gap: 2px; }
.inv-filter { border: 0; background: none; padding: 6px 14px; border-radius: 7px; cursor: pointer;
  font-size: 13px; font-weight: 600; color: var(--muted); transition: background .12s, color .12s; }
.inv-filter:hover { color: var(--ink); background: color-mix(in srgb, var(--green) 10%, transparent); }
.inv-filter.on { background: var(--green); color: var(--on-green); }
.inv-sel-note { font-size: 12.5px; font-weight: 700; color: var(--green-dark); }
.inv-chk-th, .inv-chk-td { width: 34px; text-align: center; }
.inv-chk-td { cursor: default; }
/* Dashboard rows that link somewhere get a gentle hover so they read as clickable. */
.card tr.clickable { transition: background .12s ease; }
.card tr.clickable:hover td { background: color-mix(in srgb, var(--green) 10%, transparent); }

.badge { display: inline-block; padding: 2px 9px; border-radius: 20px; font-size: 12px; font-weight: 600; }
.badge.green { background: var(--green-light); color: var(--green-dark); }
.badge.amber { background: var(--tint-amber); color: var(--amber); }
.badge.red { background: var(--tint-red); color: var(--danger); }
.badge.gray { background: var(--tint-gray); color: var(--muted); }

.pager { display: flex; gap: 10px; align-items: center; justify-content: flex-end; margin-top: 14px; color: var(--muted); font-size: 13px; }
.empty { padding: 40px; text-align: center; color: var(--muted); }
.muted { color: var(--muted); }

/* Modal */
/* Dialogs sit ABOVE the whole Finance workspace: windows raise their z-index on
   every click (unbounded), and the taskbar is at 99990 - so the modal layer must
   beat both, or an "Edit customer" opened from a busy window sinks behind it. */
.modal-back { position: fixed; inset: 0; background: rgba(20,30,25,.45); display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px; z-index: 99995; overflow: auto; }
.modal { background: var(--card); color: var(--ink); border-radius: 12px; width: 540px; max-width: 100%; box-shadow: 0 24px 70px rgba(0,0,0,.3); }
.modal.wide { width: 760px; }
.modal-head { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--line); }
.modal-head h3 { margin: 0; font-size: 17px; }
.acct-modal .modal-head { background: var(--green-dark); border-bottom: 0; border-radius: 12px 12px 0 0; }
.acct-modal .modal-head h3 { color: #fff; }
.acct-modal .modal-head .x { color: #cfe0d6; }
.acct-modal .modal-head .x:hover { color: #fff; }
.modal-head .x { background: none; border: 0; font-size: 22px; color: var(--muted); line-height: 1; }
.modal-body { padding: 20px; }
.modal-foot { padding: 14px 20px; border-top: 1px solid var(--line); display: flex; justify-content: flex-end; gap: 10px; }
.modal.confirm-modal { width: 460px; }
.confirm-msg { font-size: 14.5px; line-height: 1.55; color: var(--ink); }
/* refund choice (store credit vs cash) */
.refund-opts { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.refund-opt { display: flex; align-items: flex-start; gap: 11px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 8px; cursor: pointer; }
.refund-opt:hover { border-color: #9fd9b4; background: var(--green-light); }
.refund-opt:has(input:checked) { border-color: var(--green); background: var(--green-light); }
.refund-opt input { margin-top: 2px; width: 17px; height: 17px; accent-color: var(--green); flex: none; }
.refund-opt-txt { display: flex; flex-direction: column; gap: 2px; }
.refund-opt-txt b { font-size: 14px; }
.refund-opt-txt .muted { font-size: 12.5px; }
.inv-refund-note { margin-top: 8px; color: var(--amber); font-size: 13px; font-weight: 600; }
.inv-paid-note { margin-top: 8px; color: var(--green-dark); font-size: 13px; font-weight: 600; }
.inv-usd { color: var(--green-dark); font-size: 13px; font-weight: 600; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field { display: flex; flex-direction: column; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: 12px; color: var(--muted); font-weight: 600; margin-bottom: 5px; }
/* a field whose input sits next to a small action button (e.g. Group + add) */
.field-with-btn { display: flex; gap: 8px; align-items: stretch; }
.field-with-btn > select, .field-with-btn > input { flex: 1; min-width: 0; }
.add-inline { flex: none; padding: 0 13px; font-size: 17px; line-height: 1; font-weight: 700; }
.field textarea { min-height: 70px; resize: vertical; }
/* inline autocomplete dropdown */
.ac-wrap { position: relative; }
.ac-menu { position: fixed; display: none; z-index: 200; background: var(--card); border: 1px solid var(--line);
  border-radius: 8px; box-shadow: 0 10px 28px rgba(0,0,0,.18); max-height: 240px; overflow-y: auto; min-width: 280px; }
.ac-item { display: flex; justify-content: space-between; gap: 12px; padding: 8px 12px; cursor: pointer; font-size: 13.5px; }
.ac-item:hover, .ac-item.active { background: var(--green-light); }
.ac-item .ac-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac-item .ac-sub { color: var(--muted); font-size: 12px; white-space: nowrap; }
.ac-item .ac-rm { border: 0; background: none; color: var(--muted); font-size: 15px; line-height: 1;
  padding: 0 3px; cursor: pointer; border-radius: 4px; flex: none; }
.ac-item .ac-rm:hover { color: #b3261e; background: rgba(179,38,30,.1); }
.ac-item.ac-create { color: var(--green-dark); font-weight: 600; border-bottom: 1px solid var(--line); background: var(--green-light); }
.ac-item.ac-create:hover, .ac-item.ac-create.active { background: #d3ecdd; }
.perm-cb { display: flex; gap: 8px; align-items: center; font-weight: 500; }
.perm-cb.locked { opacity: .5; cursor: not-allowed; }
.perm-cb.locked input { cursor: not-allowed; }

/* Toast */
.tip-pop { position: fixed; z-index: 100000; background: #18271f; color: #e8f5ee; font-size: 12px;
  font-weight: 600; padding: 6px 11px; border-radius: 8px; box-shadow: 0 10px 28px rgba(0,0,0,.28);
  pointer-events: none; max-width: 280px; line-height: 1.4; animation: tipin .12s ease-out; }
.tip-pop[hidden] { display: none; }
@keyframes tipin { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); background: var(--toast-bg); color: var(--toast-fg); padding: 11px 20px; border-radius: 8px; font-size: 14px; z-index: 99999; box-shadow: 0 8px 30px rgba(0,0,0,.3); }
/* Send/Receive: the circular arrows spin while inboxes are being checked */
.sr-ico { display: inline-block; line-height: 0; vertical-align: -2px; }
.sr-ico.spinning { animation: sr-spin .9s linear infinite; }
@keyframes sr-spin { to { transform: rotate(360deg); } }
.toast.err { background: var(--danger); }

/* Persistent, dismissable update nudge (stays until the user closes it). */
.update-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px;
  background: var(--ink); color: #fff; padding: 10px 10px 10px 18px;
  border-radius: 10px; font-size: 14px; z-index: 200;
  box-shadow: 0 8px 30px rgba(0,0,0,.35); max-width: min(92vw, 560px);
  animation: updateToastIn .18s ease-out;
}
@keyframes updateToastIn { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.update-toast-msg {
  background: none; border: 0; color: inherit; font: inherit; text-align: left;
  cursor: pointer; padding: 2px 0; flex: 1 1 auto;
}
.update-toast-msg:hover { text-decoration: underline; }
.update-toast-x {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 6px;
  background: rgba(255,255,255,.14); border: 0; color: #fff; cursor: pointer;
  font-size: 13px; line-height: 1; display: flex; align-items: center; justify-content: center;
}
.update-toast-x:hover { background: rgba(255,255,255,.3); }
/* Brief highlight of the update card when arriving from the toast. */
.sw-upd-flash { animation: swUpdFlash .9s ease-in-out 0s 2; border-radius: var(--radius); }
@keyframes swUpdFlash { 0%, 100% { box-shadow: 0 0 0 0 rgba(224,164,59,0); } 50% { box-shadow: 0 0 0 3px rgba(224,164,59,.9); } }

/* Settings list buttons */
.settings-list { display: flex; flex-direction: column; gap: 12px; max-width: 560px; }
.settings-item {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow); font-size: 14px; color: var(--ink);
}
.settings-item:hover { border-color: var(--green); background: var(--green-light); }
.settings-item .si-icon { font-size: 24px; line-height: 1; }
.settings-item .si-text { display: flex; flex-direction: column; flex: 1; gap: 2px; }
.settings-item .si-text .muted { font-size: 12.5px; }
.settings-item .si-arrow { font-size: 24px; color: var(--muted); }
/* inventory groups manager */
.grp-list { max-height: 50vh; overflow-y: auto; }
.grp-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 2px; border-bottom: 1px solid var(--line); }
.grp-row:last-child { border-bottom: 0; }
.grp-name { font-size: 14px; }

/* Invoice sheet */
/* the invoice view: let the sheet grow to fill the screen so there's no grey gap.
   Class-based (not :has) + min-height:100vh flex column = works in Safari too. */
/* White background on the whole invoice view so no grey ever shows through,
   even if a browser (Brave/Safari) doesn't paint the flex-grown sheet area. */
main.invoice-view { display: flex; flex-direction: column; min-height: 100vh; background: #fff; }
.inv-sheet { background: #fff; padding: 44px 48px; border: 1px solid var(--line); border-radius: var(--radius);
  flex: 1 0 auto; box-shadow: var(--shadow); display: flex; flex-direction: column; }
/* zebra rows on the invoice document - soft grey-green, so the hover/active green stays its own thing */
.inv-sheet tbody tr:nth-child(even) td { background: #f4f7f5; }
.inv-footer { margin-top: auto; padding-top: 40px; color: var(--muted); font-size: 13px; line-height: 1.6; }
.inv-head { display: flex; justify-content: space-between; margin-bottom: 34px; }
.inv-head h1 { margin: 0 0 14px; font-size: 24px; color: var(--green-dark); }
.inv-head .company-lines { line-height: 1.6; }
.inv-total-row { display: flex; justify-content: flex-end; margin-top: 28px; }
.inv-totals { width: 340px; }
.inv-totals div { display: flex; justify-content: space-between; gap: 18px; padding: 4px 0; }
.inv-totals .inv-usd span:first-child, .inv-totals .inv-paid-note { white-space: nowrap; }
.inv-totals .grand { font-weight: 700; font-size: 17px; border-top: 2px solid var(--ink); margin-top: 6px; padding-top: 8px; }

@media print {
  .sidebar, .page-head .btn, .no-print { display: none !important; }
  /* Force a white page everywhere so the app's grey background never prints as a
     grey block below the invoice on the last page. */
  html, body { background: #fff !important; }
  main, main.invoice-view { padding: 0; display: block; min-height: 0; background: #fff !important; }
  /* Keep the browser's default page margins so the logo isn't clipped.
     min-height:100vh makes the sheet fill at least one page, so on a SHORT
     invoice the footer still sits at the bottom of the page. For a 2-page bill
     a small script (see _invoicePrintFooter) grows the sheet to ~2 pages so the
     footer drops to the bottom of page 2 as well. */
  /* A comfortable margin inside the paper, so the content never prints flush to the page edge
     even when the browser's own page margin is set to None. box-sizing:border-box (set globally)
     keeps this within the 100vh sheet, so it does not spill onto a second page. */
  .inv-sheet { border: 0; min-height: 100vh; box-shadow: none; padding: 8mm 14mm; flex: none; background: #fff !important; }
  /* print every line in solid black; keep ONLY the logo green */
  .inv-sheet, .inv-sheet * { color: #000 !important; }
  .inv-sheet h1 { color: #1f6b42 !important; }
  /* Clean pagination for long invoices: repeat the ITEM/PRICE/QTY/AMOUNT header
     on each page, never split a single row, and keep the totals + footer whole. */
  .inv-sheet table { page-break-inside: auto; }
  .inv-sheet thead { display: table-header-group; }
  .inv-sheet tr { page-break-inside: avoid; }
  /* The document always prints on white paper, whatever theme is on screen. The table wrap and
     header carry a themed background that would print dark in dark mode, so pin them light here.
     This is the belt to the braces of the light-palette override on .inv-sheet. */
  .inv-sheet .table-wrap { background: #fff !important; box-shadow: none !important; border-color: #e2e8e4 !important; }
  .inv-sheet thead th, .inv-sheet th { background: #f7faf8 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .inv-sheet tbody tr:nth-child(odd) td { background: #fff !important; }
  /* keep the zebra rows on paper too (browsers skip backgrounds otherwise) */
  .inv-sheet tbody tr:nth-child(even) td { background: #f4f7f5 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .inv-total-row { page-break-inside: avoid; break-inside: avoid; }
  /* The bank/CRIB footer now flows at the END of the document (bottom of the
     LAST page) rather than being fixed on every page, so it never lands on top
     of the items. margin-top:auto keeps it pinned to the bottom on a 1-page bill. */
  .inv-footer { position: static; margin-top: auto; padding: 28px 0 0; break-inside: avoid; page-break-inside: avoid; }
}

/* ---- Printable customer list ---- */
#print-root { display: none; }
@page cust-list { size: A4 landscape; margin: 14mm; }
@media print {
  /* when printing the list, hide the whole app and show only the print sheet */
  body.printing-list #app,
  body.printing-list #login,
  body.printing-list #modal-root,
  body.printing-list #toast { display: none !important; }
  /* A little inner padding so the sheet never prints flush to the paper even when the browser's
     own page margin is set to None. */
  body.printing-list #print-root { display: block !important; page: cust-list; color: #000; padding: 3mm 4mm; }

  #print-root .print-head h1 { font-size: 17pt; margin: 0 0 3px; color: #1f6b42; font-weight: 800; letter-spacing: .2px; }
  #print-root .print-meta { font-size: 8.5pt; color: #6b7d74; margin: 0 0 15px; padding-bottom: 11px;
    border-bottom: 1px solid #d8e2db; }
  /* list-only table styling (scoped so it never restyles an invoice sheet in print-root) */
  /* table-layout:fixed + colgroup %s + width:100% => columns can never run off the page */
  body.printing-list #print-root table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 9pt; }
  /* Appointment day sheet. Each day starts a new page so a doctor is handed one sheet for
     their day rather than a roll of everyone's, and no row is split across a page break. */
  body.printing-list #print-root .appt-print-day + .appt-print-day { break-before: page; page-break-before: always; }
  body.printing-list #print-root .appt-print-day { margin-bottom: 16px; }
  body.printing-list #print-root .appt-print-day h2 { font-size: 13pt; margin: 0 0 9px; padding-bottom: 6px;
    border-bottom: 2px solid #1f6b42; color: #1f6b42; display: flex; align-items: baseline; font-weight: 800; }
  body.printing-list #print-root .appt-print-count { font-size: 8.5pt; font-weight: 500; color: #6b7d74;
    margin-left: auto; letter-spacing: .3px; }
  body.printing-list #print-root .appt-print-day tbody tr { break-inside: avoid; page-break-inside: avoid; }
  /* Cleaner report look for the day sheet: no boxed grid, just a header rule and light row
     separators with zebra shading and roomier cells. Scoped to .appt-print-day, so the customer
     list keeps its own grid from the base rule below. */
  body.printing-list #print-root .appt-print-day th,
  body.printing-list #print-root .appt-print-day td { border: 0; border-bottom: 1px solid #dbe4dd; padding: 7px 10px; }
  body.printing-list #print-root .appt-print-day thead th { background: #e8f5ee !important; color: #1f5b3a;
    font-size: 8pt; font-weight: 800; text-transform: uppercase; letter-spacing: .6px; border-bottom: 1.5px solid #bcd8c7; }
  body.printing-list #print-root .appt-print-day tbody tr:nth-child(even) td { background: #f4f8f5;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* Short values only. "30 min" or "01:30" split over two lines doubles every row's height. */
  body.printing-list #print-root .appt-print-day .nw { white-space: nowrap; }
  body.printing-list #print-root th, body.printing-list #print-root td {
    border: 1px solid #999; padding: 4px 6px; text-align: left; vertical-align: top;
    overflow-wrap: anywhere; word-break: break-word;
  }
  body.printing-list #print-root th { background: #e8f5ee !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  body.printing-list #print-root thead { display: table-header-group; }   /* repeat header on every page */
  body.printing-list #print-root tr { page-break-inside: avoid; }

  /* printing ONE invoice from the browsing sheet: hide the app, show only the
     shared .inv-sheet rendered into #print-root - the same template the invoice
     page prints (its @media print rules above apply to it unchanged). */
  body.printing-inv #app,
  body.printing-inv #login,
  body.printing-inv #modal-root,
  body.printing-inv #toast { display: none !important; }
  body.printing-inv #print-root { display: block !important; color: #000; }
}
@media (max-width: 800px) {
  .grid2 { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .sidebar { width: 64px; }
  .side-brand span:not(.leaf), #nav a span:not(.ic), .side-foot, .wa-upd { display: none !important; }
}

/* ===== Appointments: month calendar + day timeline ===== */
/* The padding used to come from `.ws-win .cal-layout`, which only applied while the calendar
   was a window inside the Workspace. It is its own page now and never in a window, so that rule
   is dead and the month grid sat hard against the green band. */
.cal-layout { display: flex; gap: 20px; align-items: flex-start; padding: 18px; }
.cal-side { position: relative; width: 300px; flex: none; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.cal-head b { font-size: 15px; }
.cal-title-btn { display: inline-flex; align-items: center; gap: 5px; background: none; border: 0; padding: 4px 6px; margin: -4px -6px; border-radius: 6px; font-size: 15px; font-weight: 700; color: var(--ink); cursor: pointer; }
.cal-title-btn:hover { background: var(--green-light); color: var(--green-dark); }
.cal-caret { font-size: 10px; color: var(--muted); }
/* month / year jump picker */
.cal-picker { position: absolute; left: 14px; right: 14px; top: 48px; bottom: 14px; background: var(--card); z-index: 6; flex-direction: column; }
.cal-picker[hidden] { display: none; }
.cal-picker:not([hidden]) { display: flex; }
.cal-pick-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.cal-pick-year { background: none; border: 0; font-size: 15px; font-weight: 700; color: var(--ink); cursor: pointer; padding: 4px 10px; border-radius: 6px; }
.cal-pick-year:hover { background: var(--green-light); color: var(--green-dark); }
.cal-pick-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; flex: 1; align-content: center; }
.cal-pick-cell { border: 1px solid var(--line); background: var(--card); border-radius: 8px; padding: 12px 0; cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.cal-pick-cell:hover { border-color: var(--green); background: var(--green-light); color: var(--green-dark); }
.cal-pick-cell.sel { background: var(--green); border-color: var(--green); color: var(--on-green); }
.cal-navs { display: flex; gap: 4px; }
.cal-nav { width: 28px; height: 28px; border: 0; background: none; border-radius: 6px; cursor: pointer; font-size: 17px; color: var(--muted); }
.cal-nav:hover { background: var(--green-light); color: var(--green-dark); }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-dow { text-align: center; font-size: 11px; color: var(--muted); font-weight: 600; padding: 4px 0; }
.cal-day { position: relative; aspect-ratio: 1; border: 0; background: none; cursor: pointer; border-radius: 8px; font-size: 13px; color: var(--ink); display: flex; align-items: center; justify-content: center; }
.cal-day:hover { background: var(--green-light); }
.cal-day.other { color: #b7c2bb; }
.cal-day.today .cal-num { color: var(--green-dark); font-weight: 700; }
.cal-day.sel { background: var(--green); }
.cal-day.sel .cal-num { color: var(--on-green); font-weight: 700; }
.cal-day.sel:hover { background: var(--green-dark); }
.cal-dot { position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%); width: 5px; height: 5px; border-radius: 50%; background: #9fb3a8; }
.cal-dot.pend { background: var(--amber); }
.cal-day.sel .cal-dot { background: rgba(255,255,255,.9); }
.cal-legend { margin-top: 12px; font-size: 11px; color: var(--muted); display: flex; align-items: center; }
.cal-legend .cal-dot { position: static; transform: none; display: inline-block; margin: 0 4px; }

/* Per-user seat billing: the explanation and the per-person list on the Subscription page.
   The computed total lives on its own .sub-status-row, never inside .sub-price, which is
   26px/800/nowrap and would overflow the plan row on a phone. */
.sub-note { margin: 12px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--muted); }
.sub-seats { margin-top: 12px; border-top: 1px solid var(--line); }
.sub-seat-row { display: flex; align-items: baseline; gap: 10px; padding: 7px 0;
  border-bottom: 1px solid var(--line); font-size: 13px; }
.sub-seat-row > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sub-seat-row > span i { color: var(--muted); font-style: normal; font-size: 12px; }
.sub-seat-row > b { white-space: nowrap; }
.sub-seat-row > em { flex: 0 0 auto; color: var(--muted); font-style: normal; font-size: 12px;
  white-space: nowrap; }
@media (max-width: 520px) {
  .sub-seat-row { flex-wrap: wrap; }
  .sub-seat-row > em { flex-basis: 100%; }
}

/* "Hours to show" presets, and the print column chooser. */
.hours-presets { display: flex; flex-wrap: wrap; gap: 8px; }
.hours-preset { padding: 7px 12px; font-size: 13px; }
.hours-preset.on { background: var(--green); border-color: var(--green); color: var(--on-green); }
.print-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 14px; }
.print-cols label { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 500;
  padding: 5px 7px; border-radius: 7px; cursor: pointer; }
.print-cols label:hover { background: var(--bg); }
.print-cols input { width: 15px; height: 15px; accent-color: var(--green); }

.day-col { flex: 1; min-width: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.day-head { display: flex; align-items: center; gap: 13px; padding: 13px 16px; border-bottom: 1px solid var(--line); background: linear-gradient(180deg, var(--card), rgba(0,0,0,.012)); }
.dh-badge { display: flex; flex-direction: column; align-items: center; justify-content: center; min-width: 50px; padding: 5px 9px 6px; background: var(--green-light); border-radius: 12px; line-height: 1; flex: none; }
.dh-badge-dow { font-size: 10px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--green-dark); opacity: .85; }
.dh-badge-num { font-size: 22px; font-weight: 800; color: var(--green-dark); margin-top: 3px; }
.dh-badge.today { background: var(--green); box-shadow: 0 2px 8px rgba(46,125,90,.28); }
.dh-badge.today .dh-badge-dow { color: var(--on-green); opacity: .92; }
.dh-badge.today .dh-badge-num { color: var(--on-green); }
.dh-titles { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dh-weekday { font-size: 16px; font-weight: 700; color: var(--ink); line-height: 1.2; }
.dh-full { color: var(--muted); font-size: 13px; }
.dh-today-pill { margin-left: auto; align-self: center; font-size: 11px; font-weight: 700; color: var(--green-dark); background: var(--green-light); border: 1px solid var(--green); padding: 3px 11px; border-radius: 999px; text-transform: uppercase; letter-spacing: .04em; }
.day-scroll { position: relative; display: flex; height: calc(100vh - 230px); min-height: 460px; overflow-y: auto; }
.time-gutter { position: relative; width: 56px; flex: none; }
.hour-lbl { position: absolute; right: 8px; font-size: 11px; color: var(--muted); }
.events-track { position: relative; flex: 1; border-left: 1px solid var(--line); cursor: copy; }
.hour-line { position: absolute; left: 0; right: 0; border-top: 1px solid var(--line); }
.now-line { position: absolute; left: 0; right: 0; height: 0; border-top: 2px solid var(--danger); z-index: 5; }
.now-line::before { content: ""; position: absolute; left: -5px; top: -5px; width: 9px; height: 9px; border-radius: 50%; background: var(--danger); }
.ev { position: absolute; display: flex; gap: 10px; align-items: flex-start; background: var(--green-light); border-left: 3px solid var(--green); border-radius: 5px; padding: 3px 7px; cursor: pointer; box-shadow: 0 1px 2px rgba(0,0,0,.08); z-index: 1; }
.ev:hover { box-shadow: 0 2px 8px rgba(0,0,0,.16); z-index: 6; }
.ev-main { flex: 0 1 auto; min-width: 0; max-width: 55%; }
.ev-t { font-size: 10.5px; color: var(--green-dark); font-weight: 600; white-space: nowrap; }
.ev-n { font-size: 12.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the note sits to the RIGHT of the time/name, filling the free horizontal space */
.ev-note { flex: 1 1 0; min-width: 0; align-self: center; font-size: 11px; color: var(--muted); white-space: pre-wrap; overflow-wrap: anywhere; }
/* Outcome colours for calendar blocks. One meaning per colour, matching the status badges in the
   lists: still to happen is amber, seen is green, did not turn up fades grey, called off is red.
   Mixed against --card so they hold up in both themes. */
.ev.out-pending { background: color-mix(in srgb, var(--amber) 22%, var(--card)); border-left-color: var(--amber); }
.ev.out-pending .ev-t { color: var(--amber); }
/* Booked but not finished yet: nothing is owed and nobody is waiting, so it stays plain. It turns
   amber on its own once the end time passes. Kept as a clean card rather than a grey fill, so it
   never reads as the faded grey of a no-show. */
.ev.out-pending.ev-upcoming { background: var(--card); border-left-color: color-mix(in srgb, var(--ink) 32%, transparent); }
.ev.out-pending.ev-upcoming .ev-t { color: var(--muted); }
.ev.out-done { background: var(--green-light); border-left-color: var(--green); }
.ev.out-done .ev-t { color: var(--green-dark); }
.ev.out-noshow { background: color-mix(in srgb, var(--muted) 20%, var(--card)); border-left-color: var(--muted); opacity: .88; }
.ev.out-noshow .ev-t { color: var(--muted); }
.ev.out-cancelled { background: var(--tint-red); border-left-color: var(--danger); opacity: .9; }
.ev.out-cancelled .ev-n { text-decoration: line-through; color: var(--danger); }
.ev.out-cancelled .ev-t { color: var(--danger); }
/* bill / invoice button on the right of each appointment block */
.ev-bill { flex: none; margin-left: auto; align-self: center; width: 26px; height: 26px; border: 1px solid var(--line); background: var(--card); border-radius: 6px; cursor: pointer; font-size: 13px; line-height: 1; display: flex; align-items: center; justify-content: center; padding: 0; }
.ev-bill:hover { border-color: var(--green); background: var(--green-light); }
.ev-bill.billed { border-color: var(--green); }
.badge.sm { padding: 1px 7px; font-size: 10.5px; vertical-align: middle; }
/* PAID watermark on a paid invoice sheet */
.inv-sheet.pastdue-stamp { position: relative; }
.inv-sheet.pastdue-stamp::after { content: "PAST DUE"; position: absolute; top: 120px; right: 48px; z-index: 5;
  font-size: 54px; font-weight: 800; letter-spacing: 4px; color: rgba(179,38,30,.22);
  border: 6px solid rgba(179,38,30,.22); border-radius: 12px; padding: 6px 22px; transform: rotate(-14deg); pointer-events: none; }
.inv-sheet.paid-stamp { position: relative; }
.inv-sheet.paid-stamp::after { content: "PAID"; position: absolute; top: 120px; right: 48px; z-index: 5; font-size: 60px; font-weight: 800; letter-spacing: 4px; color: rgba(47,143,91,.22); border: 6px solid rgba(47,143,91,.22); border-radius: 12px; padding: 6px 22px; transform: rotate(-14deg); pointer-events: none; }
/* keep the stamp above the items table in every engine (table cells can create
   their own stacking); the sticky header sits below it */
.inv-sheet.paid-stamp .table-wrap { z-index: 0; }
/* Stamp toggle (the button on the invoice toolbar): suppress the PAID/UNPAID/PAST DUE/REFUNDED
   stamp on screen and in print. Wins over each stamp's own ::after via !important. */
.inv-sheet.stamp-off::after { display: none !important; content: none !important; }
/* UNPAID stamp (amber) on an open invoice that isn't overdue yet */
.inv-sheet.unpaid-stamp { position: relative; }
.inv-sheet.unpaid-stamp::after { content: "UNPAID"; position: absolute; top: 120px; right: 40px; z-index: 5;
  font-size: 54px; font-weight: 800; letter-spacing: 4px; color: rgba(184,134,11,.22);
  border: 6px solid rgba(184,134,11,.22); border-radius: 12px; padding: 6px 22px; transform: rotate(-14deg); pointer-events: none; }
/* REFUNDED stamp (amber) */
.inv-sheet.refunded-stamp { position: relative; }
.inv-sheet.refunded-stamp::after { content: "REFUNDED"; position: absolute; top: 120px; right: 30px; z-index: 5; font-size: 44px; font-weight: 800; letter-spacing: 3px; color: rgba(184,134,11,.22); border: 6px solid rgba(184,134,11,.22); border-radius: 12px; padding: 6px 20px; transform: rotate(-14deg); pointer-events: none; }
/* store-credit row inside the invoice form */
.iv-credit { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 2px; padding: 10px 12px; background: var(--green-light); border: 1px solid #9fd9b4; border-radius: 8px; font-size: 13.5px; }
.iv-credit[hidden] { display: none; }
.iv-credit-avail { color: var(--green-dark); }
.iv-credit-apply { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-weight: 600; }
.iv-credit-apply input { width: 90px; }
@media (max-width: 720px) { .cal-layout { flex-direction: column; } .cal-side { width: 100%; } }

/* ---------- Email / webmail client ---------- */
.mail-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.mail-tabs-group { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mail-filter { border: 1px solid var(--line); background: var(--card); padding: 8px 16px; border-radius: 8px; font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer; }
.mail-filter:hover { border-color: var(--green); color: var(--green-dark); }
.mail-filter.active { background: var(--green); border-color: var(--green); color: var(--on-green); }
.mail-empty { border: 1px solid #e5b3b3; background: var(--tint-red); color: var(--danger); padding: 8px 16px; border-radius: 8px; font-size: 13.5px; font-weight: 600; cursor: pointer; }
.mail-empty:hover { background: #c0392b; border-color: var(--danger); color: #fff; }
.mail-empty:disabled { opacity: .5; cursor: default; }
.mail-tabs { display: inline-flex; background: var(--th-bg); border: 1px solid var(--line);
  border-radius: 9px; padding: 3px; }
.mail-tab { border: 0; background: none; padding: 7px 18px; border-radius: 6px; font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer; }
.mail-tab { transition: background .12s, color .12s; }
.mail-tab:hover { color: var(--ink); background: color-mix(in srgb, var(--green) 10%, transparent); }
.mail-tab.active { background: var(--green); color: var(--on-green); box-shadow: none; }
.mail-tab.active:hover { background: var(--green); }
.mail-search-wrap { display: flex; gap: 8px; align-items: center; flex: 1; justify-content: flex-end; }
.mail-search { flex: 1; min-width: 160px; max-width: 320px; padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px; font-size: 13.5px; }
.mail-filter-btn { flex: none; border: 1px solid var(--line); background: var(--card); padding: 9px 14px; border-radius: 8px; font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer; white-space: nowrap; }
.mail-filter-btn:hover { border-color: var(--green, #2f8f5b); color: var(--green, #2f8f5b); }
.mail-filter-btn.on { background: var(--green); border-color: var(--green); color: var(--on-green); }   /* a filter is active */
.mail-chk { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 500; cursor: pointer; padding-top: 4px; }
.mail-chk input { width: 16px; height: 16px; }
.mail-search:focus { outline: 2px solid var(--green); border-color: var(--green); }
.mail-split { display: flex; gap: 10px; align-items: flex-start; }
.mail-list { width: 340px; flex-shrink: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; max-height: calc(100vh - 176px); overflow-y: auto; }

/* Drag handle between the message list and the reading pane - a faint grip line
   that's always a little visible so you can find it, and turns green on hover/drag. */
.mail-resize {
  flex: 0 0 8px; align-self: stretch; min-height: calc(100vh - 176px);
  cursor: col-resize; position: relative; background: transparent;
}
.mail-resize::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 4px; border-radius: 4px; background: #cbd5cf; transition: background .15s;
}
.mail-resize:hover::before, .mail-resize.dragging::before { background: var(--green); }
/* Preview pane OFF: hide the reading pane + divider, let the list fill the width */
.mail-split.no-preview .mail-read, .mail-split.no-preview .mail-resize { display: none; }
.mail-split.no-preview .mail-list { width: 100% !important; }
#mail-preview-toggle.active { background: var(--green-light); border-color: var(--green); color: var(--green-dark); }
.mail-item { position: relative; padding: 11px 14px; border-bottom: 1px solid var(--line); cursor: pointer; user-select: none; }
.mail-item.checked { background: color-mix(in srgb, #3b82f6 15%, var(--card)); box-shadow: inset 3px 0 0 #3b82f6; }
.mail-item.checked.sel { background: color-mix(in srgb, #3b82f6 24%, var(--card)); }
.mail-del { position: absolute; top: 8px; right: 8px; display: none; border: 0; background: transparent; cursor: pointer; font-size: 14px; line-height: 1; padding: 4px 7px; border-radius: 6px; color: var(--muted); }
.mail-item:hover .mail-del { display: inline-flex; }
.mail-item:hover .mi-date { visibility: hidden; }   /* trash takes the date's spot on hover */
.mail-del:hover { background: var(--tint-red); color: var(--danger); }
.mail-del:disabled { opacity: .5; cursor: default; }
.mail-item:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.mail-item.sel { background: color-mix(in srgb, var(--green) 15%, var(--card)); }
.mail-item.unread .mi-from, .mail-item.unread .mi-subj { font-weight: 700; color: var(--ink); }
.mail-item.unread { border-left: 3px solid var(--green); padding-left: 11px; }
.mi-row { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.mi-from { font-size: 13.5px; color: color-mix(in srgb, var(--ink) 82%, var(--muted)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mi-date { font-size: 11.5px; color: var(--muted); flex-shrink: 0; }
.mi-subj { font-size: 12.5px; color: var(--muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mail-more-wrap { padding: 12px; text-align: center; }
.mail-read { flex: 1; min-width: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 20px; min-height: 300px; max-height: calc(100vh - 176px); overflow-y: auto; }
.mail-read-empty { padding: 60px 20px; text-align: center; }
.mr-head { border-bottom: 1px solid var(--line); padding-bottom: 12px; margin-bottom: 14px; }
.mr-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.mr-actions { display: flex; gap: 6px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
.mr-subj { margin: 0 0 8px; font-size: 19px; }
.mr-meta { font-size: 13px; margin-top: 2px; }
.mr-when { margin-left: 8px; }
.mr-atts { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; }

/* Double-click pop-out email window (Outlook-style) */
.modal.mail-window { width: 940px; max-width: 96vw; }
.modal.mail-window .modal-body { max-height: 78vh; overflow-y: auto; }
.mw-toolbar { display: flex; gap: 8px; flex-wrap: wrap; padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--line); }
.mw-meta { font-size: 13px; margin: 3px 0; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.mw-when { margin-left: auto; }
.mw-body { margin-top: 14px; }
.mw-body .mail-frame { width: 100%; border: 0; min-height: 200px; }
.mw-body .mail-text { white-space: pre-wrap; word-wrap: break-word; font-size: 14px; line-height: 1.5; }
.mail-att { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 5px 6px 5px 10px; background: #f4f6f4; border: 1px solid var(--line); border-radius: 6px; }
.mail-att:hover { background: var(--green-light); }
.mail-att a { text-decoration: none; color: var(--green-dark); }
.mail-att-open:hover { text-decoration: underline; }
.mail-att-dl { border-left: 1px solid var(--line); padding: 0 6px 0 8px; font-size: 14px; line-height: 1; }
.mail-att-dl:hover { color: #111; }
.mc-sig-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.sig-prev { margin-top: 6px; padding: 10px; border: 1px dashed var(--line); border-radius: 8px; background: #fafcfb; display: flex; align-items: center; justify-content: center; min-height: 60px; }
.sig-prev img { max-width: 100%; max-height: 160px; height: auto; border-radius: 4px; }
.mail-frame { width: 100%; border: 0; min-height: 200px; }
.mail-text { white-space: pre-wrap; word-wrap: break-word; font-size: 14px; line-height: 1.5; }
.mail-text a { color: var(--green-dark); }
@media (max-width: 820px) { .mail-split { flex-direction: column; } .mail-list { width: 100%; max-height: 320px; } }

/* ---------- Company Details: repeatable bank / currency rows ---------- */
.cd-sec-label { display: block; font-size: 11.5px; font-weight: 700; color: var(--muted); margin: 18px 0 6px; text-transform: uppercase; letter-spacing: .3px; }
.cd-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.cd-row input { flex: 1; padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px; font-size: 14px; }
.cd-row input:focus { outline: 2px solid var(--green); border-color: var(--green); }
.cd-x { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 15px; padding: 4px 9px; border-radius: 6px; flex-shrink: 0; }
.cd-x:hover { background: var(--tint-red); color: var(--danger); }

/* ---- Licensing: lock screen + reminder banner ---- */
#lock-screen { position: fixed; inset: 0; z-index: 5000; display: flex; align-items: center;
  justify-content: center; background: #1c2a22; padding: 20px; }
.lock-card { background: var(--card); border-radius: 16px; padding: 36px 40px; max-width: 480px; width: 100%;
  text-align: center; box-shadow: 0 20px 60px rgba(0,0,0,.4); }
.lock-card .lock-icon { font-size: 40px; margin-bottom: 6px; }
.lock-card h2 { margin: 0 0 10px; }
.lock-card textarea { width: 100%; margin-top: 14px; padding: 10px; border: 1px solid var(--line);
  border-radius: 8px; font-family: ui-monospace, Menlo, monospace; font-size: 12px; resize: vertical; }
.lock-card .btn { width: 100%; margin-top: 12px; }
.lock-error { color: var(--danger); font-size: 13px; min-height: 18px; margin-top: 6px; }
.lock-links { margin-top: 14px; font-size: 13px; display: flex; flex-direction: column; gap: 8px; }
.lock-links a { color: var(--green-dark); }
#license-banner { position: fixed; bottom: 18px; right: 18px; z-index: 900; display: flex;
  align-items: center; gap: 10px; background: #fff8e6; border: 1px solid #e8d9a8; color: #6b5b1e;
  border-radius: 10px; padding: 9px 12px; font-size: 13px; box-shadow: 0 6px 24px rgba(0,0,0,.12); }
#license-banner button { border: 0; background: var(--green-dark); color: var(--on-green); border-radius: 7px;
  padding: 5px 10px; font-size: 12.5px; cursor: pointer; }
#license-banner i { cursor: pointer; font-style: normal; color: #9a8a4a; padding: 0 2px; }
.lic-row { display: flex; justify-content: space-between; gap: 16px; padding: 7px 0;
  border-bottom: 1px solid var(--line); font-size: 14px; }
.lic-row span { color: var(--muted); }

/* Subscribe buttons (lock screen + trial banner) */
.lock-card .lock-subscribe { width: 100%; margin-bottom: 6px; background: var(--green); }
#license-banner .lb-subscribe { background: var(--green-dark); color: var(--on-green); }

/* Sidebar Subscription link - matches the regular nav items (#nav a) */
.side-sub {
  display: flex; align-items: center; gap: 10px; padding: 11px 12px 11px 20px; color: #b9cdc1;
  text-decoration: none; font-size: 14px; font-weight: 500; border-left: 3px solid transparent;
}
.side-sub:hover { background: rgba(255,255,255,.05); color: #fff; }
.side-sub.active { background: color-mix(in srgb, var(--green) 22%, transparent); color: #fff; border-left-color: var(--green); }
.side-sub .ic { width: 20px; text-align: center; font-size: 16px; }
.side-sub-days { margin-left: auto; font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 10px; white-space: nowrap; }
.side-sub-days:empty { display: none; }
.side-sub-days.trial { background: rgba(184,134,11,.28); color: #e8c274; }
.side-sub-days.grace { background: rgba(192,57,43,.24); color: #e79684; }
.side-sub-days.soon  { background: color-mix(in srgb, var(--green) 30%, transparent); color: var(--green); }
.side-sub-days.ok    { background: color-mix(in srgb, var(--green) 26%, transparent); color: var(--green); }
/* Only the LABEL span flexes (grows to fill, truncates with … when tight) so a wide
   badge never spills past the sidebar edge. Exclude the badge spans - otherwise they'd
   get flex:1 too and stretch across the row instead of hugging their text. */
.side-sub > span:not(.ic):not(.side-sub-days),
#nav a > span:not(.ic):not(.nav-badge) {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-sub-days, .nav-badge { flex: 0 0 auto; }   /* natural width, anchored right, never stretch */

/* In-app Control Panel - the same dark console as the desktop Sealuno Control app.
   Palette lifted from control_panel.html so the two never drift apart. */
.ctrl-dark {
  --c-panel: #151f1a;
  --c-panel-2: #111a15;
  --c-ink: #eaf3ee;
  --c-ink-soft: #adbdb4;
  --c-ink-faint: #7c8d84;
  --c-line: #243029;
  --c-brand: #2fce6d;
  --c-good: #37d977;
  --c-good-glow: rgba(55,217,119,.5);
  --c-off: #5f6f66;
  background:
    radial-gradient(1200px 700px at 15% -10%, #0e1713, transparent 60%),
    radial-gradient(1000px 600px at 100% 0%, #0a110d, transparent 55%),
    #0c1310;
  color: var(--c-ink);
  /* Fill the whole content area edge-to-edge (eat main's 26x32 padding) instead of
     floating as a rounded card. */
  margin: -26px -32px;
  min-height: 100vh;
  padding: 40px 32px 48px;
}
/* Centre a narrower column of controls inside the full-width dark background. */
.ctrl-inner { max-width: 960px; margin: 0 auto; }
.ctrl-head { display: flex; align-items: center; gap: 14px; margin-bottom: 22px; }
.ctrl-head h2 { margin: 0; font-size: 22px; color: var(--c-ink); }
.ctrl-head-sub { font-size: 13px; color: var(--c-ink-faint); font-weight: 500; }
.ctrl-mark {
  width: 44px; height: 44px; border-radius: 13px; flex: 0 0 auto;
  background: linear-gradient(160deg, #2fce6d, #27b862);
  display: grid; place-items: center;
  box-shadow: 0 6px 16px rgba(55,217,119,.32);
}
.ctrl-wait { padding: 30px 0; text-align: center; color: var(--c-ink-faint); font-size: 14px; }

.ctrl-cards { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.ctrl-card {
  flex: 1; min-width: 190px; background: var(--c-panel-2); border: 1px solid var(--c-line);
  border-radius: 14px; padding: 16px 18px; position: relative;
}
.ctrl-card.ok { border-color: rgba(55,217,119,.32); }
.ctrl-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--c-off); margin-bottom: 10px; }
.ctrl-card.ok .ctrl-dot {
  background: var(--c-good);
  animation: ctrl-pulse 2.4s ease-in-out infinite;
}
@keyframes ctrl-pulse {
  0%, 100% { box-shadow: 0 0 10px 0 var(--c-good-glow); }
  50%      { box-shadow: 0 0 16px 3px var(--c-good-glow); }
}
.ctrl-lab { font-size: 11px; font-weight: 700; letter-spacing: .06em; color: var(--c-ink-faint); }
.ctrl-big { font-size: 19px; font-weight: 700; margin: 3px 0 2px; color: var(--c-ink); }
.ctrl-card.ok .ctrl-big { color: var(--c-good); }
.ctrl-sub { font-size: 12.5px; color: var(--c-ink-soft); }

.ctrl-urls { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.ctrl-url {
  flex: 1; min-width: 240px; background: var(--c-panel-2); border: 1px solid var(--c-line);
  border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 2px;
}
.ctrl-url .muted { font-size: 12px; }
.ctrl-url b { font-size: 14px; color: var(--c-ink); }
.ctrl-url .btn { align-self: flex-start; margin-top: 8px; padding: 5px 12px; font-size: 12.5px; }

.ctrl-acts { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.ctrl-acts .btn { flex: 1; min-width: 180px; }

.ctrl-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  background: var(--c-panel-2); border: 1px solid var(--c-line); border-radius: 12px;
  padding: 14px 16px; margin-bottom: 12px; flex-wrap: wrap;
}
.ctrl-row b { color: var(--c-ink); }
.ctrl-active-box { background: var(--c-panel-2); border: 1px solid var(--c-line); border-radius: 12px; padding: 14px 16px; margin-bottom: 12px; }
.ctrl-active-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.ctrl-active-head b { color: var(--c-ink); }
.ctrl-active-count { font-size: 12px; color: var(--c-ink-faint); }
.ctrl-active { display: flex; flex-direction: column; }
.ctrl-user { display: flex; align-items: center; gap: 10px; padding: 6px 2px; font-size: 13.5px; color: var(--c-ink); border-top: 1px solid var(--c-line); }
.ctrl-user:first-child { border-top: 0; }
.ctrl-user b { color: var(--c-ink); font-weight: 600; }
.ctrl-user-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--c-ink-faint); flex: none; }
.ctrl-user-dot.on { background: var(--c-good); box-shadow: 0 0 0 3px rgba(55,217,119,.18); }
.ctrl-user-dot.idle { background: #e0a83a; }
.ctrl-user-dot.away { background: var(--c-ink-faint); }
.ctrl-user-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctrl-user-status { margin-left: auto; font-size: 12.5px; color: var(--c-ink-faint); }
.ctrl-user-acts { display: flex; gap: 6px; align-items: center; flex: none; }
.ctrl-user-btn { background: transparent; border: 1px solid var(--c-line); color: var(--c-ink-faint);
  font-size: 11.5px; padding: 3px 9px; border-radius: 7px; cursor: pointer; white-space: nowrap; }
.ctrl-user-btn:hover { color: var(--c-ink); border-color: var(--c-ink-faint); }
.ctrl-user-btn.danger:hover { color: #ff8a8a; border-color: #ff8a8a; }
.row-suspended td { opacity: .55; }
.row-suspended td.row-actions { opacity: 1; }
.grp-row.row-suspended .grp-name { opacity: .55; }
.ctrl-dark .muted { color: var(--c-ink-faint); }
.ctrl-dark a { color: var(--c-brand); }

/* The app's light-grey buttons disappear on this surface, so re-theme them here. */
.ctrl-dark .btn.ghost {
  background: var(--c-panel); border-color: var(--c-line); color: var(--c-ink);
}
.ctrl-dark .btn.ghost:hover { border-color: var(--c-brand); color: var(--c-brand); }
.ctrl-dark .btn:not(.ghost) {
  background: linear-gradient(180deg, #2fce6d, #27b862);
  border-color: transparent; color: #07130c; font-weight: 700;
}
.ctrl-dark .btn:not(.ghost):hover { filter: brightness(1.08); }

/* Sidebar collapse toggle - frees up screen width for the content */
.side-toggle {
  margin-left: auto; flex: none; background: none; border: 0; color: #8fb7a0;
  cursor: pointer; font-size: 21px; font-weight: 700; line-height: 1; padding: 4px 7px; border-radius: 6px;
}
.side-toggle:hover { background: rgba(255,255,255,.10); color: #fff; }

.sidebar.collapsed { width: 64px; }
.sidebar.collapsed .side-brand { padding: 18px 4px; justify-content: center; gap: 2px; }
.sidebar.collapsed .side-brand span:not(.leaf) { display: none; }   /* wordmark only; keep the shield */
.sidebar.collapsed .side-brand .leaf { font-size: 20px; }
.sidebar.collapsed .side-toggle { margin-left: 0; font-size: 19px; padding: 4px; }
.sidebar.collapsed #nav a,
.sidebar.collapsed .side-sub {
  justify-content: center; padding-left: 0; padding-right: 0; border-left-color: transparent;
}
.sidebar.collapsed #nav a span:not(.ic),
.sidebar.collapsed .side-sub span:not(.ic),
.sidebar.collapsed .side-sub-days,
.sidebar.collapsed .nav-badge,
.sidebar.collapsed .wa-upd { display: none !important; }
.sidebar.collapsed .side-foot { padding: 14px 0; text-align: center; }
.sidebar.collapsed .side-foot > div { display: none; }              /* the "Administrator" line */

/* Subscription page */
.sub-wrap { max-width: 640px; margin: 0 auto; }
.sub-card {
  background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  padding: 26px; box-shadow: 0 1px 2px rgba(16,24,40,.05);
}
.sub-plan-row {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; padding-bottom: 18px; border-bottom: 1px solid var(--line);
}
.sub-plan { font-size: 18px; font-weight: 700; }
.sub-desc { color: var(--muted); font-size: 13px; margin-top: 3px; }
.sub-price { font-size: 26px; font-weight: 800; white-space: nowrap; }
.sub-price span { font-size: 14px; font-weight: 600; color: var(--muted); }
.sub-status-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 11px 0; border-bottom: 1px solid var(--line); font-size: 14px;
}
.sub-status-row > span:first-child { color: var(--muted); }
.sub-badge { font-weight: 600; font-size: 13px; }
.sub-badge.ok { color: #12805c; }
.sub-badge.trial { color: var(--amber); }
.sub-badge.exp { color: var(--danger); }
.sub-go { width: 100%; margin-top: 20px; font-size: 15px; padding: 13px; background: var(--green); }
.sub-secure { text-align: center; color: var(--muted); font-size: 12px; margin: 10px 0 0; }
.sub-embed { margin-top: 18px; }
.sub-embed-load {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 34px; text-align: center; color: var(--muted); font-size: 14px;
}
#sub-embed-mount {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 8px; min-height: 60px;
}

/* Account Charts import preview: colour-code what each row will do. */
.ai-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.ai-table th { text-align: left; padding: 7px 9px; background: var(--bg); border-bottom: 1px solid var(--line);
               position: sticky; top: 0; font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.ai-table td { padding: 7px 9px; border-bottom: 1px solid var(--line); vertical-align: top; }
.ai-table tr.ai-add td { background: #f2faf5; }
.ai-table tr.ai-skip td { color: var(--muted); }
.ai-table tr.ai-conflict td { background: var(--tint-red); }

/* Till mode: type item names, or scan them. Sits in the dark header beside the customer
   box, so it reads as a setting for this sheet rather than another field to fill in. */
.iv-mode { display: inline-flex; align-items: stretch; user-select: none; margin-left: 10px;
  padding: 3px; border-radius: 9px; background: rgba(0,0,0,.18);
  border: 1px solid rgba(255,255,255,.22); white-space: nowrap; }
.iv-mode-b { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; border: 0;
  padding: 6px 12px; border-radius: 7px; background: transparent; color: rgba(255,255,255,.72);
  font-size: 12.5px; font-weight: 600; letter-spacing: .2px; font-family: inherit;
  transition: background .13s, color .13s; }
.iv-mode-b:hover { color: #fff; background: rgba(255,255,255,.12); }
/* The active mode is a filled chip: which one you are in has to be readable at a glance
   from across a counter, not inferred from a tick. */
.iv-mode-b.on { background: var(--field-bg); color: var(--green-dark, #1e5c37); box-shadow: 0 1px 2px rgba(0,0,0,.18); }
.iv-mode-b.on:hover { background: var(--field-bg); }
.iv-mode-i { font-size: 11px; opacity: .8; }
.iv-mode-b.on .iv-mode-i { opacity: 1; }

/* ---- Dangerous zone + workspace archive (handover feature) ---- */
/* The only red block in Settings. It sits below the ordinary rows with a rule above it, so a
   destructive action never lines up flush with a harmless one. */
.dz { margin-top: 26px; border-top: 1px solid var(--line); padding-top: 16px; }
.dz-head { margin: 0 0 8px; font-size: 11px; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--danger); }
.settings-item.danger:hover { border-color: var(--danger); background: var(--tint-red); }
.settings-item.danger .si-arrow { color: var(--danger); }

/* Passphrase panel: shown once, so it has to read as important without looking like an error. */
.ho-pass-wrap { margin-top: 14px; border: 1px solid #e5b3b3; background: var(--tint-red); border-radius: 10px; padding: 14px; }
.ho-pass-label { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--danger); margin-bottom: 8px; }
.ho-pass { font-family: var(--font-mono, monospace); font-size: 22px; font-weight: 700; letter-spacing: 3px;
  text-align: center; color: #1f2d25; user-select: all; }

/* Export/import status chips inside the dialogs. */
.aw-chip { border-radius: 8px; padding: 8px 12px; font-size: 13px; }
.aw-chip.ok { background: var(--green-light); border: 1px solid var(--green-line); color: var(--green-dark); }
.aw-chip.warn { background: #fff7ed; border: 1px solid #f0d3a8; color: #9a6412; }

/* The archive list. Neutral .card styling on purpose - it is where data is rescued, not destroyed,
   so nothing here is red. */
.ar-wrap { display: flex; flex-direction: column; gap: 10px; max-width: 720px; }
.ar-row { display: flex; align-items: center; gap: 16px; padding: 14px 16px; }
.ar-main { flex: 1; min-width: 0; }
.ar-name { font-weight: 700; font-size: 15px; }
.ar-meta { font-size: 12.5px; color: var(--muted); margin-top: 3px; }
.ar-acts { display: flex; gap: 8px; flex-shrink: 0; }

/* The invoice / quote / sales-order document is a picture of the printed page, so it stays a white
   sheet in dark mode - on screen (read-only view AND the email preview) and on paper. Re-declaring
   the LIGHT palette on the sheet turns every var()-driven colour inside it back to its light value:
   the table wrap (var(--card)) and the header (var(--th-bg)) were going dark and showing through the
   transparent odd rows, so the rows read as black-on-black. This fixes them at the source. */
:root[data-theme="dark"] main.invoice-view,
:root[data-theme="dark"] .inv-sheet {
  --bg: #f4f7f5; --card: #ffffff; --surface: #f0f5f2; --th-bg: #f7faf8;
  --ink: #1d2b24; --muted: #6b7d74; --line: #e2e8e4; --green-line: #bfe3ce;
  --field-bg: #ffffff; --field-fg: #1d2b24; --field-ph: #94a69c;
  --green: #2f8f5b; --green-dark: #1f6b42; --green-light: #e8f5ee; --on-green: #ffffff;
  --tint-amber: #fdf3d7; --tint-red: #fdeaea; --tint-gray: #eef1ef;
  color: #1d2b24; background: #ffffff;
}

/* An account box that has text in it matching nothing: say so quietly rather than saving a blank. */
.bl-acct-bad { border-color: var(--danger) !important; background: var(--tint-red); }

/* Icons inside a button: sit on the text baseline and keep a consistent gap, so a labelled icon
   button lines up the same wherever it appears. */
.btn-ico { display: inline-block; vertical-align: -3px; margin-right: 5px; flex: none; }

/* ---- Email payment reminders ---- */
.rem-sum { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border-radius: 10px; background: var(--th-bg); border: 1px solid var(--line);
  font-size: 13.5px; }
.rem-sum-amt { font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ink); }
.rem-list { margin-top: 10px; max-height: 210px; overflow-y: auto; border: 1px solid var(--line);
  border-radius: 10px; background: var(--card); }
.rem-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  border-bottom: 1px solid var(--line); font-size: 13px; }
.rem-row:last-child { border-bottom: 0; }
.rem-no { flex: none; min-width: 42px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
.rem-who { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.35; }
.rem-mail { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rem-amt { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }
.rem-skip { margin-top: 10px; padding: 9px 12px; border-radius: 9px; font-size: 12.5px;
  background: var(--tint-amber); color: var(--ink); border: 1px solid color-mix(in srgb, var(--amber) 45%, var(--line)); }
.rem-lbl { display: block; margin: 14px 0 5px; font-size: 12.5px; font-weight: 700; }
#rem-msg { width: 100%; box-sizing: border-box; font: inherit; font-size: 13px; line-height: 1.5;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--field-bg); color: var(--field-fg); resize: vertical; }
.rem-foot-note { margin-top: 8px; font-size: 12px; color: var(--muted); }

/* ---- Subscription hover panel ---- */
/* Sizes to its widest line rather than a fixed width, so a long plan name and the price breakdown
   each sit on one line, while short trial states stay compact. Capped so it never runs off a
   narrow screen. */
.sub-tip { position: fixed; z-index: 9000; width: max-content; min-width: 250px; max-width: min(430px, 92vw);
  padding: 12px 14px; border-radius: 12px;
  background: var(--card); color: var(--ink); border: 1px solid var(--line);
  box-shadow: 0 12px 34px rgba(0,0,0,.28); font-size: 12.5px; pointer-events: none;
  animation: subTipIn .13s ease-out; }
/* Rises from its bottom-left corner, matching where it is anchored. */
@keyframes subTipIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .sub-tip { animation: none; } }
.sub-tip-name { white-space: nowrap; }        /* the full plan name on one line */
.sub-tip-head { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 13px;
  padding-bottom: 8px; margin-bottom: 4px; border-bottom: 1px solid var(--line); }
/* --green-dark, not --green: at 10px the lighter green measured 3.6:1 on the light chip, which is
   under the 4.5 needed for text this size. Same reason the amber below is mixed toward ink. */
.sub-tip-chip { margin-left: auto; font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 10px;
  background: var(--green-light); color: var(--green-dark); }
.sub-tip-chip.trial { background: var(--tint-amber); color: var(--ink); }
.sub-tip-chip.grace { background: var(--tint-red); color: var(--danger); }
.sub-tip-tbl { width: 100%; border-collapse: collapse; }
.sub-tip-tbl td { padding: 5px 0; vertical-align: top; }
.sub-tip-tbl td:first-child { color: var(--muted); white-space: nowrap; padding-right: 10px; }
.sub-tip-tbl td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.sub-tip-warn { color: color-mix(in srgb, var(--amber) 72%, var(--ink)); }
.sub-tip-calc { display: block; font-size: 10.5px; color: var(--muted); font-weight: 400; margin-top: 1px; white-space: nowrap; }
.sub-tip-foot { margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--line);
  font-size: 11px; color: var(--muted); }

/* Build this workspace is running, in the Settings header. Quiet by default: it is reference,
   not a call to action - it only takes the amber treatment when an update is waiting. */
/* --muted straight on --th-bg measured 4.15 at this size, under the 4.5 AA floor; mixed toward
   --ink it clears in both themes while still reading as secondary. */
.ver-chip { flex: none; font-size: 11.5px; font-weight: 700; letter-spacing: .2px;
  padding: 4px 10px; border-radius: 10px; background: var(--th-bg);
  color: color-mix(in srgb, var(--muted) 50%, var(--ink));
  border: 1px solid var(--line); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ver-chip.upd { background: var(--tint-amber); color: var(--ink);
  border-color: color-mix(in srgb, var(--amber) 45%, var(--line)); }
.ver-chip[hidden] { display: none; }

/* Version chip on the sidebar. The sidebar keeps its own dark palette whatever the theme, so
   this cannot inherit .ver-chip's --th-bg / --line - in light mode that painted a white chip
   on a near-black panel. */
.side-ver { background: rgba(255,255,255,.10); color: #cfe3d7; border-color: rgba(255,255,255,.18); }
.side-ver.upd { background: rgba(240,167,42,.22); color: #f6dca6; border-color: rgba(240,167,42,.45); }
.sidebar.collapsed .side-ver { display: none; }

/* ---- Messenger (Telegram / WhatsApp) in dark mode ----
   The messenger skin is a deliberate WhatsApp look - cream chat pane, green "me" bubbles - and
   every colour in it was written for light mode only. In dark it stayed cream and glared. This
   remaps just those hardcoded values to a proper dark chat look; light mode is untouched. Also
   fixes the borders: they used var(--border, ...) and --border is defined nowhere, so the light
   fallback showed through in dark. */
:root[data-theme="dark"] {
  --border: #2a3a33;                 /* now the messenger borders follow the theme */
}
:root[data-theme="dark"] .wa-thread { background: #0e1512; }          /* the chat backdrop */
:root[data-theme="dark"] .wa-msgs .wa-loadmore { background: rgba(255,255,255,.06); }
:root[data-theme="dark"] .wa-msg.them .wa-bubble { background: #1e2823; color: var(--ink); }
:root[data-theme="dark"] .wa-msg.me .wa-bubble { background: #124d3a; color: #eaf6ee; }
:root[data-theme="dark"] .wa-bubble { box-shadow: 0 1px 0 rgba(0,0,0,.25); }
:root[data-theme="dark"] .wa-mtime { color: #9db3a8; }
:root[data-theme="dark"] .wa-msg.call .wa-bubble { background: #202b26; color: var(--muted); }
:root[data-theme="dark"] .wa-link-a { color: #6fb2f0; }
:root[data-theme="dark"] .wa-link-a:hover { color: #96c8f5; }
/* chat list */
:root[data-theme="dark"] .wa-chat { border-bottom-color: var(--line); }
:root[data-theme="dark"] .wa-chat:hover { background: rgba(255,255,255,.04); }
:root[data-theme="dark"] .wa-chat.active { background: color-mix(in srgb, var(--green) 20%, var(--card)); }
:root[data-theme="dark"] .wa-filter { color: var(--muted); }
:root[data-theme="dark"] .wa-filter:hover { background: rgba(255,255,255,.05); }
:root[data-theme="dark"] .wa-filter.active,
:root[data-theme="dark"] .wa-tab.active { background: color-mix(in srgb, var(--green) 24%, var(--card));
  border-color: color-mix(in srgb, var(--green) 45%, var(--line)); color: var(--green-dark); }
/* small chips + thumbs */
:root[data-theme="dark"] .wa-biz { background: color-mix(in srgb, var(--green) 22%, var(--card));
  color: var(--green-dark); border-color: color-mix(in srgb, var(--green) 40%, var(--line)); }
:root[data-theme="dark"] .wa-presence.typing { background: color-mix(in srgb, var(--green) 20%, var(--card));
  color: var(--green-dark); border-color: color-mix(in srgb, var(--green) 40%, var(--line)); }
:root[data-theme="dark"] .wa-presence.offline { background: #202b26; color: var(--muted); border-color: var(--line); }
:root[data-theme="dark"] .wa-ap-thumb,
:root[data-theme="dark"] .wa-msg.call .wa-bubble { background: #202b26; }

/* ---- Automatic cloud backup dialog ---- */
.ab-toggle { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; cursor: pointer; margin: 0 0 12px; }
.ab-toggle input { width: 18px; height: 18px; accent-color: var(--green); flex: none; }
.ab-when { transition: opacity .15s; }
.ab-row { display: flex; align-items: center; gap: 8px; font-size: 13.5px; flex-wrap: wrap; }
.ab-row select { font: inherit; font-size: 13.5px; padding: 6px 8px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--field-bg); color: var(--field-fg); cursor: pointer; }
.ab-status { margin-top: 14px; padding: 10px 12px; border-radius: 9px; background: var(--th-bg);
  border: 1px solid var(--line); font-size: 12.5px; color: var(--ink); }

/* ---- Cloud backups list inside the Automatic Cloud Backup dialog ---- */
.ab-restore { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.ab-restore-head { font-size: 12.5px; font-weight: 800; margin-bottom: 8px; }
.ab-bk { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 9px;
  border: 1px solid var(--line); background: var(--card); margin-bottom: 6px; font-size: 12.5px; }
.ab-bk-when { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.ab-bk-when .muted { font-size: 11px; }
.ab-bk-size { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; }
.ab-bk-go { flex: none; }

/* ---- Cloud Backup add-on upsell ---- */
.ab-price { display: flex; align-items: baseline; gap: 8px; margin: 10px 0 14px; }
.ab-price b { font-size: 30px; line-height: 1; }
.ab-price span { color: var(--muted); font-size: 13px; }
.ab-sell { margin: 0 0 16px; padding-left: 20px; font-size: 13.5px; line-height: 1.85; }
.ab-sell li { margin: 0; }

/* ---- Automatic Cloud Backup: inline Settings panel ---- */
.ab-panel { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 18px 18px 20px; margin-bottom: 18px; }
.ab-p-head { display: flex; align-items: center; gap: 9px; font-size: 15px; }
.ab-p-head b { font-size: 15px; }
.ab-p-ic { font-size: 18px; }
.ab-p-state { margin-left: auto; font-size: 11px; font-weight: 800; letter-spacing: .3px;
  padding: 2px 9px; border-radius: 10px; }
.ab-p-state.on { background: var(--green-light); color: var(--green-dark); }
.ab-p-state.off { background: var(--th-bg); color: var(--muted); border: 1px solid var(--line); }
.ab-p-lead { font-size: 13px; color: var(--muted); margin: 10px 0 4px; }
.ab-panel .ab-toggle { margin-top: 14px; }
.ab-p-status { margin-top: 12px; padding: 9px 11px; border-radius: 9px; background: var(--th-bg);
  border: 1px solid var(--line); font-size: 12px; color: var(--ink); }
.ab-panel .btn.sm { padding: 8px 12px; font-size: 13px; }

/* Cap the cloud-backups list at ~5 rows (row stride 57px) and scroll inside, so the panel does
   not grow without bound as backups accumulate. padding-right keeps the scrollbar off the
   Restore buttons. */
#ab-p-list, #ab-list { max-height: 300px; overflow-y: auto; padding-right: 3px; }
