/* Tracker — design tokens and components.

   The palette is a warm neutral rather than the usual cold grey: it reads as
   paper, which suits a book of accounts and keeps the blues and greens doing
   real work. Chart colour follows the entity, never the mood — purchases and
   money out are blue, sales and money in are green — and the status colours
   (good / warning / critical) are reserved for state alone, so a red figure
   always means something is wrong rather than merely negative. */

:root {
  color-scheme: light;

  --page:          #f7f7f4;
  --surface:       #ffffff;
  --surface-2:     #f3f2ee;
  --surface-3:     #e9e8e2;
  --surface-sunk:  #efeeea;
  --ink:           #14140f;
  --ink-2:         #56554f;
  --ink-3:         #8b8981;
  --line:          #e4e3dc;
  --line-strong:   #cdccc2;
  --ring:          rgba(24, 79, 149, 0.28);

  --brand:         #184f95;
  --brand-hover:   #123d75;
  --brand-soft:    #e9f0fa;
  --brand-line:    #c3d6ef;
  --brand-ink:     #ffffff;

  --series-buy:    #2a78d6;   /* purchases, money out  */
  --series-sell:   #008300;   /* sales, money in       */
  --series-3:      #7a5af5;
  --series-4:      #d98324;
  --series-5:      #0f9b8e;
  --series-6:      #c2417c;

  --good:          #0ca30c;
  --warning:       #fab219;
  --serious:       #ec835a;
  --critical:      #d03b3b;
  --good-text:     #05690a;
  --warning-text:  #8a5a00;
  --serious-text:  #9a4a25;
  --critical-text: #b32b2b;
  --good-soft:     #e4f5e4;
  --warning-soft:  #fdf2d8;
  --serious-soft:  #fbe9e0;
  --critical-soft: #fae4e4;
  --neutral-soft:  #eceae4;
  --info-soft:     #e9f0fa;

  --grid:          #e8e7e0;
  --axis:          #cdccc2;
  --de-emphasis:   #c3c2b7;

  --label-blue:    #2a78d6;
  --label-green:   #008300;
  --label-amber:   #d98324;
  --label-red:     #d03b3b;
  --label-violet:  #7a5af5;
  --label-teal:    #0f9b8e;
  --label-slate:   #6b7280;
  --label-pink:    #c2417c;

  --radius-xs: 5px;
  --radius-s:  8px;
  --radius:    11px;
  --radius-lg: 16px;

  --shadow-xs: 0 1px 2px rgba(20, 20, 15, 0.05);
  --shadow:    0 1px 2px rgba(20, 20, 15, 0.04), 0 3px 10px rgba(20, 20, 15, 0.045);
  --shadow-md: 0 2px 4px rgba(20, 20, 15, 0.05), 0 8px 24px rgba(20, 20, 15, 0.08);
  --shadow-lg: 0 12px 48px rgba(20, 20, 15, 0.18);

  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  --sidebar-w: 236px;
  --topbar-h: 56px;
  --ease: cubic-bezier(0.2, 0, 0, 1);
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --page:          #0c0c0b;
  --surface:       #171716;
  --surface-2:     #212120;
  --surface-3:     #2b2b29;
  --surface-sunk:  #121211;
  --ink:           #f7f7f4;
  --ink-2:         #b6b4ac;
  --ink-3:         #86847d;
  --line:          #2a2a28;
  --line-strong:   #3a3a36;
  --ring:          rgba(87, 154, 232, 0.42);

  --brand:         #4b93e8;
  --brand-hover:   #6aa6ec;
  --brand-soft:    #14273e;
  --brand-line:    #24466e;
  --brand-ink:     #08111c;

  --series-buy:    #4b93e8;
  --series-sell:   #23a723;
  --series-3:      #9a80f8;
  --series-4:      #e29a48;
  --series-5:      #2ab5a7;
  --series-6:      #d96099;

  --good-text:     #37b737;
  --warning-text:  #e0a52a;
  --serious-text:  #ef9a76;
  --critical-text: #f08585;
  --good-soft:     #102910;
  --warning-soft:  #2f2609;
  --serious-soft:  #311e17;
  --critical-soft: #321818;
  --neutral-soft:  #2b2b29;
  --info-soft:     #14273e;

  --grid:          #262624;
  --axis:          #3a3a36;
  --de-emphasis:   #4a4a45;

  --label-slate:   #9ba1ac;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow:    0 1px 2px rgba(0, 0, 0, 0.5), 0 3px 10px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 12px 48px rgba(0, 0, 0, 0.6);
}

/* ------------------------------------------------------------------ accent

   The accent is chosen in Settings and stamped onto <html> as data-accent.
   Every option stays clear of the semantic hues — green means money in, amber
   means needs attention, red means overdue — so the brand can never be mistaken
   for a status. Each is a mid-dark tone in light mode and a bright one in dark,
   because the same ink cannot carry both backgrounds. */

:root[data-accent="indigo"] {
  --brand: #4338ca; --brand-hover: #3730a3;
  --brand-soft: #eef1ff; --brand-line: #c9cffa; --ring: rgba(67, 56, 202, 0.28);
}
:root[data-accent="violet"] {
  --brand: #6d28d9; --brand-hover: #5b21b6;
  --brand-soft: #f4efff; --brand-line: #d9c9f7; --ring: rgba(109, 40, 217, 0.28);
}
:root[data-accent="teal"] {
  --brand: #0f766e; --brand-hover: #115e59;
  --brand-soft: #e6f7f4; --brand-line: #a5ded4; --ring: rgba(15, 118, 110, 0.30);
}
:root[data-accent="ocean"] {
  --brand: #0e7490; --brand-hover: #155e75;
  --brand-soft: #e6f5fa; --brand-line: #a8dbeb; --ring: rgba(14, 116, 144, 0.30);
}
:root[data-accent="slate"] {
  --brand: #334155; --brand-hover: #1e293b;
  --brand-soft: #eef2f7; --brand-line: #cbd5e1; --ring: rgba(51, 65, 85, 0.30);
}

:root[data-theme="dark"][data-accent="indigo"] {
  --brand: #8b93f8; --brand-hover: #a5abfa;
  --brand-soft: #1d1f45; --brand-line: #363a72; --brand-ink: #0b0c1c;
  --ring: rgba(139, 147, 248, 0.42);
}
:root[data-theme="dark"][data-accent="violet"] {
  --brand: #a78bfa; --brand-hover: #bda5fc;
  --brand-soft: #241a40; --brand-line: #40306b; --brand-ink: #100a1e;
  --ring: rgba(167, 139, 250, 0.42);
}
:root[data-theme="dark"][data-accent="teal"] {
  --brand: #2dd4bf; --brand-hover: #5ce0d0;
  --brand-soft: #0e2f2c; --brand-line: #1b514a; --brand-ink: #041a17;
  --ring: rgba(45, 212, 191, 0.42);
}
:root[data-theme="dark"][data-accent="ocean"] {
  --brand: #38bdf8; --brand-hover: #66cffa;
  --brand-soft: #0d2c3d; --brand-line: #1a4d66; --brand-ink: #04161f;
  --ring: rgba(56, 189, 248, 0.42);
}
:root[data-theme="dark"][data-accent="slate"] {
  --brand: #94a3b8; --brand-hover: #b0bccd;
  --brand-soft: #232a33; --brand-line: #3b4654; --brand-ink: #0b0e12;
  --ring: rgba(148, 163, 184, 0.42);
}

/* ------------------------------------------------------- category colours

   A second palette, separate from the status one. These say what a thing *is* —
   a sale, a bill, a task — never how it is doing. Keeping the two apart is what
   lets red still mean overdue when everything else on screen is coloured too.
   Each hue is picked to stay legible on the page background at small sizes and
   to remain distinguishable from its neighbours for the common colour-vision
   deficiencies, which is why there is no red/green pair among them. */

:root {
  --tint-home:      #184f95;
  --tint-sales:     #067c06;
  --tint-purchases: #2a78d6;
  --tint-expenses:  #b3690f;
  --tint-money:     #0f766e;
  --tint-cheques:   #8a5cd6;
  --tint-inventory: #6d28d9;
  --tint-contacts:  #0e7490;
  --tint-reports:   #4338ca;
  --tint-todo:      #b03272;
  --tint-users:     #4b5563;
  --tint-settings:  #6b7280;

  --tint-home-soft:      #e9f0fa;
  --tint-sales-soft:     #e4f5e4;
  --tint-purchases-soft: #e7f0fc;
  --tint-expenses-soft:  #fbf0de;
  --tint-money-soft:     #e3f5f2;
  --tint-cheques-soft:   #f1eafc;
  --tint-inventory-soft: #f2ecfd;
  --tint-contacts-soft:  #e4f3f8;
  --tint-reports-soft:   #ebedfc;
  --tint-todo-soft:      #fbe9f2;
  --tint-users-soft:     #eef0f3;
  --tint-settings-soft:  #eef0f3;
}

:root[data-theme="dark"] {
  --tint-home:      #6ba6ee;
  --tint-sales:     #35bb35;
  --tint-purchases: #63a6ec;
  --tint-expenses:  #e0a94a;
  --tint-money:     #2dd4bf;
  --tint-cheques:   #b294f5;
  --tint-inventory: #a78bfa;
  --tint-contacts:  #38bdf8;
  --tint-reports:   #8b93f8;
  --tint-todo:      #e879b4;
  --tint-users:     #9aa5b4;
  --tint-settings:  #9aa5b4;

  --tint-home-soft:      #14273e;
  --tint-sales-soft:     #102910;
  --tint-purchases-soft: #14273e;
  --tint-expenses-soft:  #2f2609;
  --tint-money-soft:     #0e2f2c;
  --tint-cheques-soft:   #241a40;
  --tint-inventory-soft: #241a40;
  --tint-contacts-soft:  #0d2c3d;
  --tint-reports-soft:   #1d1f45;
  --tint-todo-soft:      #33172a;
  --tint-users-soft:     #232a33;
  --tint-settings-soft:  #232a33;
}

*, *::before, *::after { box-sizing: border-box; }

/* Any author rule that sets `display` outranks the browser's own [hidden]
   styling, which quietly breaks every element we hide by attribute. Settle it
   once, here, rather than remembering it at each call site. */
[hidden] { display: none !important; }

html, body { min-height: 100%; }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.25; letter-spacing: -0.011em; }
p { margin: 0; }
a { color: var(--brand); text-underline-offset: 2px; }
code { font-family: var(--mono); font-size: 0.92em; background: var(--surface-2);
       padding: 1px 5px; border-radius: var(--radius-xs); }

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

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

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

.app { display: flex; min-height: 100vh; align-items: flex-start; }
.app[hidden] { display: none; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 30;
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 14px 12px;
  min-height: var(--topbar-h);
}
.brand-mark {
  color: var(--brand); display: flex; flex: none;
}
.brand-text { display: flex; flex-direction: column; min-width: 0; }
.brand-text strong {
  font-size: 14px; font-weight: 620; letter-spacing: -0.015em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.brand-text small { color: var(--ink-3); font-size: 11px; letter-spacing: 0.01em; }
/* The menu button. It collapses the sidebar on a desktop and opens it on a
   phone — one control, whichever shape the sidebar is in. Declared with
   enough weight to beat .icon-btn, which is defined further down. */
.brand .nav-toggle { display: inline-flex; margin-left: auto; flex: none; }

/* overflow-y:auto alone makes overflow-x compute to auto too, so anything
   reaching past the rail earns a horizontal scrollbar. Say hidden. */
#nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 2px 9px 8px; }
#nav::-webkit-scrollbar { width: 8px; }
#nav::-webkit-scrollbar-thumb { background: var(--line); border-radius: 8px; }

.nav-group { margin-bottom: 12px; }
.nav-group-title {
  font-size: 10px; font-weight: 650; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-3); padding: 8px 8px 4px;
}
.nav-link {
  display: flex; align-items: center; gap: 9px;
  padding: 6.5px 9px; border-radius: var(--radius-s);
  color: var(--ink-2); text-decoration: none; font-weight: 500; font-size: 13.5px;
  transition: background 0.12s var(--ease), color 0.12s var(--ease);
  position: relative;
}
.nav-link svg { flex: 0 0 17px; opacity: 0.9; }
/* The icon carries the section's colour so the sidebar is scannable by hue
   before it is read as words — and it keeps that colour when active, which is
   what stops the active row becoming the only coloured thing on the page. */
.nav-link[data-tint] svg { color: var(--nav-tint); opacity: 1; }
.nav-link[data-tint="home"]      { --nav-tint: var(--tint-home); }
.nav-link[data-tint="dashboard"] { --nav-tint: var(--tint-home); }
.nav-link[data-tint="purchases"] { --nav-tint: var(--tint-purchases); }
.nav-link[data-tint="sales"]     { --nav-tint: var(--tint-sales); }
.nav-link[data-tint="expenses"]  { --nav-tint: var(--tint-expenses); }
.nav-link[data-tint="pay"]       { --nav-tint: var(--tint-purchases); }
.nav-link[data-tint="receive"]   { --nav-tint: var(--tint-sales); }
.nav-link[data-tint="cheques"]   { --nav-tint: var(--tint-cheques); }
.nav-link[data-tint="inventory"] { --nav-tint: var(--tint-inventory); }
.nav-link[data-tint="contacts"]  { --nav-tint: var(--tint-contacts); }
.nav-link[data-tint="reports"]   { --nav-tint: var(--tint-reports); }
.nav-link[data-tint="todo"]      { --nav-tint: var(--tint-todo); }
.nav-link[data-tint="users"]     { --nav-tint: var(--tint-users); }
.nav-link[data-tint="settings"]  { --nav-tint: var(--tint-settings); }

.nav-link:hover { background: var(--surface-2); color: var(--ink); }
.nav-link.active {
  background: var(--brand-soft); color: var(--brand); font-weight: 600;
}
:root[data-theme="dark"] .nav-link.active { color: var(--brand-hover); }
.nav-link.active svg { opacity: 1; }
.nav-link.active::before {
  content: ""; position: absolute; left: -9px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 17px; border-radius: 0 3px 3px 0; background: var(--brand);
}
.nav-badge {
  margin-left: auto; font-size: 10.5px; font-weight: 650;
  background: var(--critical-soft); color: var(--critical-text);
  border-radius: 20px; padding: 1px 6px; font-variant-numeric: tabular-nums;
  min-width: 19px; text-align: center;
}
.nav-badge.soft { background: var(--surface-3); color: var(--ink-2); }

.sidebar-foot { padding: 9px; border-top: 1px solid var(--line); display: grid; gap: 5px; }

/* ------------------------------------------------------- collapsed sidebar

   Icons only, so a wide table gets another 170px of page. The width lives in
   the same custom property the expanded sidebar uses, so nothing else in the
   layout has to know this mode exists. */

.app.nav-collapsed { --sidebar-w: 62px; }
.app.nav-collapsed .nav-label,
.app.nav-collapsed .brand-text,
.app.nav-collapsed .user-meta,
.app.nav-collapsed .nav-group-title { display: none; }

.app.nav-collapsed .brand { justify-content: center; padding: 14px 0 12px; }
.app.nav-collapsed #nav { padding: 4px 7px 8px; }
.app.nav-collapsed .nav-group { margin-bottom: 8px; }
/* A hairline stands in for the group heading, so the sections stay separable. */
.app.nav-collapsed .nav-group + .nav-group { border-top: 1px solid var(--line); padding-top: 8px; }
.app.nav-collapsed .nav-link {
  justify-content: center; padding: 9px 0; position: relative;
}
.app.nav-collapsed .nav-link.active::before { left: -7px; }
.app.nav-collapsed .brand-mark { display: none; }
.app.nav-collapsed .brand .nav-toggle { margin: 0; }
.app.nav-collapsed .user-chip { justify-content: center; padding: 7px 0; }
.app.nav-collapsed .user-chip > svg { display: none; }

/* The badge cannot sit beside the label any more, so it becomes a corner dot. */
.app.nav-collapsed .nav-badge {
  position: absolute; top: 2px; right: 4px; margin: 0;
  min-width: 15px; padding: 0 4px; font-size: 9.5px; line-height: 15px;
}

/* The collapsed rail names its icons with a tooltip placed by app.js. It has
   to live outside #nav: anything absolutely positioned inside a scroll
   container is clipped by it, and widens its scroll area into the bargain. */
.nav-tip {
  position: fixed; z-index: 70; pointer-events: none;
  background: var(--ink); color: var(--page);
  font-size: 12px; font-weight: 550; white-space: nowrap;
  padding: 5px 9px; border-radius: var(--radius-xs);
  box-shadow: var(--shadow-md);
  opacity: 0; transform: translateY(-50%) scale(0.96);
  transition: opacity 0.12s var(--ease), transform 0.12s var(--ease);
}
.nav-tip.show { opacity: 1; transform: translateY(-50%) scale(1); }

.user-chip {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 8px; border-radius: var(--radius-s);
  background: transparent; border: 1px solid transparent;
  color: var(--ink); font: inherit; cursor: pointer; text-align: left;
}
.user-chip:hover { background: var(--surface-2); }
.user-meta { min-width: 0; flex: 1; }
.user-meta strong {
  display: block; font-size: 12.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.user-meta small {
  display: block; color: var(--ink-3); font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.avatar {
  width: 28px; height: 28px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-soft); color: var(--brand);
  font-size: 11px; font-weight: 680; letter-spacing: 0.01em;
  border: 1px solid var(--brand-line);
}
/* Avatars take a colour derived from the name, so the same person is the same
   colour everywhere and a list of people is scannable without reading it. */
.avatar.c0 { background: var(--tint-purchases-soft); color: var(--tint-purchases); border-color: currentColor; }
.avatar.c1 { background: var(--tint-sales-soft);     color: var(--tint-sales);     border-color: currentColor; }
.avatar.c2 { background: var(--tint-inventory-soft); color: var(--tint-inventory); border-color: currentColor; }
.avatar.c3 { background: var(--tint-expenses-soft);  color: var(--tint-expenses);  border-color: currentColor; }
.avatar.c4 { background: var(--tint-money-soft);     color: var(--tint-money);     border-color: currentColor; }
.avatar.c5 { background: var(--tint-todo-soft);      color: var(--tint-todo);      border-color: currentColor; }
.avatar.c6 { background: var(--tint-contacts-soft);  color: var(--tint-contacts);  border-color: currentColor; }
.avatar.c7 { background: var(--tint-reports-soft);   color: var(--tint-reports);   border-color: currentColor; }
.avatar[class*="c"] { border-width: 1px; border-style: solid; }

/* Category chips — expense categories, task labels, roles — get the same
   name-derived treatment so a category is one colour across the whole portal. */
.chip.c0 { background: var(--tint-purchases-soft); color: var(--tint-purchases); }
.chip.c1 { background: var(--tint-sales-soft);     color: var(--tint-sales); }
.chip.c2 { background: var(--tint-inventory-soft); color: var(--tint-inventory); }
.chip.c3 { background: var(--tint-expenses-soft);  color: var(--tint-expenses); }
.chip.c4 { background: var(--tint-money-soft);     color: var(--tint-money); }
.chip.c5 { background: var(--tint-todo-soft);      color: var(--tint-todo); }
.chip.c6 { background: var(--tint-contacts-soft);  color: var(--tint-contacts); }
.chip.c7 { background: var(--tint-reports-soft);   color: var(--tint-reports); }
.avatar.sm { width: 22px; height: 22px; font-size: 9.5px; }
.avatar.lg { width: 40px; height: 40px; font-size: 14px; }

/* ------------------------------------------------------------------ topbar */

.workspace { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 25;
  display: flex; align-items: center; gap: 10px;
  min-height: var(--topbar-h);
  padding: 8px 26px;
  background: color-mix(in srgb, var(--page) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.topbar-spacer { flex: 1; }

.omni {
  display: flex; align-items: center; gap: 8px;
  min-width: 220px; max-width: 380px; flex: 1 1 260px;
  padding: 6px 10px; border-radius: var(--radius-s);
  background: var(--surface); border: 1px solid var(--line);
  color: var(--ink-3); font: inherit; font-size: 13px; cursor: pointer;
  text-align: left;
}
.omni:hover { border-color: var(--line-strong); color: var(--ink-2); }
.omni svg { flex: none; }
.omni .kbd-hint { margin-left: auto; }

.kbd {
  font-family: var(--sans); font-size: 10.5px; font-weight: 600;
  background: var(--surface-2); border: 1px solid var(--line);
  border-bottom-width: 2px; color: var(--ink-3);
  border-radius: var(--radius-xs); padding: 1px 5px; white-space: nowrap;
}

.bell { position: relative; }
.bell-dot {
  position: absolute; top: 4px; right: 4px;
  min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 8px; background: var(--critical); color: #fff;
  font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;
  border: 2px solid var(--page);
}

#main { flex: 1; min-width: 0; padding: 22px 26px 72px; outline: none; }

.loading-screen {
  display: flex; align-items: center; gap: 10px;
  color: var(--ink-3); padding: 60px 0; justify-content: center;
}
.spinner {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid var(--line-strong); border-top-color: var(--brand);
  animation: spin 0.7s linear infinite; display: inline-block; flex: none;
}
.spinner.lg { width: 26px; height: 26px; border-width: 2.5px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* -------------------------------------------------------------- page header */

.page-head {
  display: flex; align-items: flex-end; gap: 16px;
  flex-wrap: wrap; margin-bottom: 18px;
}
.page-head h1 { font-size: 23px; letter-spacing: -0.025em; }
/* Each page wears its section's colour, tying the heading back to the sidebar. */
.page-head .page-mark {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  margin-right: 12px;
}
.page-head .titles { display: flex; align-items: center; }
.tint-home      { background: var(--tint-home-soft);      color: var(--tint-home); }
.tint-sales     { background: var(--tint-sales-soft);     color: var(--tint-sales); }
.tint-purchases { background: var(--tint-purchases-soft); color: var(--tint-purchases); }
.tint-expenses  { background: var(--tint-expenses-soft);  color: var(--tint-expenses); }
.tint-money     { background: var(--tint-money-soft);     color: var(--tint-money); }
.tint-cheques   { background: var(--tint-cheques-soft);   color: var(--tint-cheques); }
.tint-inventory { background: var(--tint-inventory-soft); color: var(--tint-inventory); }
.tint-contacts  { background: var(--tint-contacts-soft);  color: var(--tint-contacts); }
.tint-reports   { background: var(--tint-reports-soft);   color: var(--tint-reports); }
.tint-todo      { background: var(--tint-todo-soft);      color: var(--tint-todo); }
.tint-users     { background: var(--tint-users-soft);     color: var(--tint-users); }
.tint-settings  { background: var(--tint-settings-soft);  color: var(--tint-settings); }
.page-head .sub { color: var(--ink-3); font-size: 13px; margin-top: 4px; }
.page-head-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

.crumbs {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--ink-3); margin-bottom: 6px;
}
.crumbs a { color: var(--ink-3); text-decoration: none; }
.crumbs a:hover { color: var(--ink-2); text-decoration: underline; }

.filter-bar {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 9px 10px; margin-bottom: 18px;
  box-shadow: var(--shadow-xs);
}
.filter-bar .grow { flex: 1 1 190px; min-width: 150px; }
.filter-bar .spacer { flex: 1 1 auto; }
.filter-count { color: var(--ink-3); font-size: 12.5px; white-space: nowrap; }

/* ------------------------------------------------------------------ controls */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: 13.5px; font-weight: 550; line-height: 1;
  padding: 8px 13px; border-radius: var(--radius-s);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  cursor: pointer; white-space: nowrap;
  box-shadow: var(--shadow-xs);
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease),
              color 0.12s var(--ease), transform 0.06s var(--ease);
}
.btn:hover { background: var(--surface-2); border-color: var(--line-strong); }
.btn:active { transform: translateY(0.5px); }
.btn-primary {
  background: var(--brand); color: var(--brand-ink); border-color: transparent;
}
.btn-primary:hover { background: var(--brand-hover); border-color: transparent; }
.btn-ghost { background: transparent; box-shadow: none; color: var(--ink-2); }
.btn-ghost:hover { background: var(--surface-2); color: var(--ink); }
.btn-quiet { background: transparent; border-color: transparent; box-shadow: none;
             color: var(--ink-2); }
.btn-quiet:hover { background: var(--surface-2); color: var(--ink); }
.btn-danger { background: transparent; border-color: var(--line); color: var(--critical-text); }
.btn-danger:hover { background: var(--critical-soft); border-color: var(--critical); }
.btn-sm { padding: 5px 9px; font-size: 12.5px; }
.btn-lg { padding: 10px 17px; font-size: 14px; }
.btn-block { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
.btn svg { flex: none; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--radius-s); flex: none;
  border: 1px solid transparent; background: transparent; color: var(--ink-2);
  cursor: pointer; padding: 0;
  transition: background 0.12s var(--ease), color 0.12s var(--ease);
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }
.icon-btn.danger:hover { background: var(--critical-soft); color: var(--critical-text); }

.input, select, textarea {
  font: inherit; font-size: 13.5px; color: var(--ink); background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--radius-s);
  padding: 7.5px 10px; width: 100%; min-width: 0;
  transition: border-color 0.12s var(--ease), box-shadow 0.12s var(--ease);
}
.input:hover, select:hover, textarea:hover { border-color: var(--ink-3); }
.input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--ring);
}
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b8981' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
  padding-right: 28px; cursor: pointer;
}
textarea { resize: vertical; min-height: 66px; line-height: 1.55; }
.input::placeholder, textarea::placeholder { color: var(--ink-3); }
.input[readonly] { background: var(--surface-2); color: var(--ink-2); }
.input.mono { font-family: var(--mono); letter-spacing: 0.04em; }

.search-wrap { position: relative; display: flex; align-items: center; }
.search-wrap svg { position: absolute; left: 10px; color: var(--ink-3); pointer-events: none; }
.search-wrap .input { padding-left: 31px; }

.field { display: grid; gap: 5px; }
.field > label, .field-label {
  font-size: 12px; font-weight: 600; color: var(--ink-2);
}
.field .hint { font-size: 11.5px; color: var(--ink-3); line-height: 1.45; }
.field .hint a { cursor: pointer; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.field-error { color: var(--critical-text); font-size: 11.5px; font-weight: 550; }

.seg {
  display: inline-flex; background: var(--surface-2); border-radius: var(--radius-s);
  padding: 2px; gap: 2px; border: 1px solid var(--line);
}
.seg-btn {
  font: inherit; font-size: 12.5px; font-weight: 550;
  border: none; background: transparent; color: var(--ink-2);
  padding: 5px 11px; border-radius: var(--radius-xs); cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s var(--ease), color 0.12s var(--ease);
}
.seg-btn:hover { color: var(--ink); }
.seg-btn[aria-pressed="true"] {
  background: var(--surface); color: var(--ink); box-shadow: var(--shadow-xs);
}

.tabs {
  display: flex; gap: 2px; border-bottom: 1px solid var(--line);
  margin-bottom: 18px; overflow-x: auto; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  font: inherit; font-size: 13.5px; font-weight: 550;
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--ink-3); padding: 9px 12px; cursor: pointer; white-space: nowrap;
  margin-bottom: -1px;
  transition: color 0.12s var(--ease), border-color 0.12s var(--ease);
}
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"] { color: var(--brand); border-bottom-color: var(--brand); }
.tab .tab-count {
  font-size: 11px; background: var(--surface-2); color: var(--ink-3);
  border-radius: 10px; padding: 1px 6px; margin-left: 5px;
}

.checkline { display: flex; align-items: flex-start; gap: 9px; font-size: 13px; cursor: pointer; }
.checkline input { width: 15px; height: 15px; accent-color: var(--brand); flex: none; margin-top: 2px; }
.checkline span.sub { display: block; color: var(--ink-3); font-size: 11.5px; }

.switch-row {
  display: flex; align-items: center; gap: 12px; justify-content: space-between;
  padding: 11px 0; border-bottom: 1px solid var(--line);
}
.switch-row:last-child { border-bottom: none; }
.switch-row .label strong { display: block; font-size: 13px; font-weight: 600; }
.switch-row .label small { color: var(--ink-3); font-size: 11.5px; }

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

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 0;
}
.card-head h2 { font-size: 14.5px; font-weight: 620; }
.card-head .sub { color: var(--ink-3); font-size: 12px; margin-top: 2px; }
.card-head-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.card-body { padding: 14px 16px 16px; }
.card-body.tight { padding: 8px 10px 10px; }
.card-foot {
  padding: 10px 16px; border-top: 1px solid var(--line);
  background: var(--surface-2); border-radius: 0 0 var(--radius) var(--radius);
  font-size: 12.5px; color: var(--ink-2);
  display: flex; align-items: center; gap: 8px;
}

.grid { display: grid; gap: 14px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.section-title {
  font-size: 11px; font-weight: 680; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3); margin: 26px 0 10px;
  display: flex; align-items: center; gap: 8px;
}
.section-title .rule { flex: 1; height: 1px; background: var(--line); }
.section-title:first-child { margin-top: 0; }

/* ---------------------------------------------------------------- stat tiles */

.hero-row { display: grid; grid-template-columns: minmax(240px, 320px) 1fr; gap: 14px; margin-bottom: 14px; }
.hero {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 20px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; justify-content: center;
}
.hero-label { font-size: 12px; font-weight: 600; color: var(--ink-2); }
.hero-value { font-size: 38px; font-weight: 660; letter-spacing: -0.035em; line-height: 1.1; margin: 6px 0 4px; font-variant-numeric: tabular-nums; }
.hero-note { font-size: 12.5px; color: var(--ink-3); }

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 172px), 1fr)); gap: 12px; }
.hero-row .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tiles-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tiles-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
/* Six across only on a genuinely wide screen. A business turning over millions
   writes ten-character figures, and six columns on a 1440 laptop leaves about
   109px for them — which wraps the number onto a second line. */
.tiles-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 700px)  { .tiles-kpi { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1150px) { .tiles-kpi { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1800px) { .tiles-kpi { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .hero-row .tiles, .tiles-2 { grid-template-columns: 1fr; } }

.tile {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 13px 14px; box-shadow: var(--shadow-xs);
  transition: border-color 0.12s var(--ease), box-shadow 0.12s var(--ease);
}
a.tile, button.tile { display: block; width: 100%; text-align: left; font: inherit;
                      color: inherit; text-decoration: none; cursor: pointer; }
a.tile:hover, button.tile:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.tile-label {
  font-size: 11.5px; font-weight: 600; color: var(--ink-2);
  display: flex; align-items: center; gap: 5px;
}

/* A tile with its own coloured mark. The colour carries the category, not the
   mood — money in is green wherever it appears, money out blue, overheads
   amber — so a glance down a row of tiles groups them without reading a word. */
.tile.has-mark { display: flex; gap: 11px; align-items: flex-start; min-width: 0; }
.tile.has-mark .tile-body { min-width: 0; flex: 1; }
.tile-mark {
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--ink-2);
}
.tile-mark.m-sell   { background: var(--good-soft);     color: var(--good-text); }
.tile-mark.m-buy    { background: var(--info-soft);     color: var(--series-buy); }
.tile-mark.m-cost   { background: var(--warning-soft);  color: var(--warning-text); }
.tile-mark.m-stock  { background: var(--brand-soft);    color: var(--brand); }
.tile-mark.m-alert  { background: var(--critical-soft); color: var(--critical-text); }
.tile-mark.m-cash   { background: var(--good-soft);     color: var(--good-text); }
.tile-mark.m-people { background: var(--brand-soft);    color: var(--brand); }
.tile-mark.m-task   { background: var(--surface-3);     color: var(--ink-2); }

.tile-spark { margin-top: 8px; }

/* Section headings carry the same mark, so a section and its tiles read as one
   block rather than a heading floating above unrelated boxes. */
.section-title .mark {
  width: 20px; height: 20px; border-radius: 6px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--ink-2);
}
.section-title .mark.m-sell  { background: var(--good-soft);    color: var(--good-text); }
.section-title .mark.m-buy   { background: var(--info-soft);    color: var(--series-buy); }
.section-title .mark.m-stock { background: var(--brand-soft);   color: var(--brand); }
.section-title .mark.m-cost  { background: var(--warning-soft); color: var(--warning-text); }
.section-title .mark.m-cash  { background: var(--good-soft);    color: var(--good-text); }
.section-title .mark.m-time  { background: var(--surface-3);    color: var(--ink-2); }

/* Card heads on the attention cards, tinted to match what they are about. */
.card-head .head-mark {
  width: 26px; height: 26px; border-radius: 8px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--ink-2); margin-right: 9px;
}
.card-head .head-mark.m-sell  { background: var(--good-soft);     color: var(--good-text); }
.card-head .head-mark.m-buy   { background: var(--info-soft);     color: var(--series-buy); }
.card-head .head-mark.m-alert { background: var(--critical-soft); color: var(--critical-text); }
.card-head .head-mark.m-cost  { background: var(--warning-soft);  color: var(--warning-text); }
.card-head .head-mark.m-task  { background: var(--brand-soft);    color: var(--brand); }

/* The hero gets a wash of the accent so the top of the page is not white. */
.hero.accented {
  background:
    linear-gradient(135deg, var(--brand-soft), transparent 62%),
    var(--surface);
  border-color: var(--brand-line);
}
.tile-value {
  font-size: 22px; font-weight: 640; letter-spacing: -0.025em; margin-top: 5px;
  font-variant-numeric: tabular-nums;
  /* A long money string has no natural break point, so without this it simply
     runs out past the edge of its card rather than wrapping. */
  overflow-wrap: anywhere;
  min-width: 0;
}
.tile-note { font-size: 11.5px; color: var(--ink-3); margin-top: 3px; }
.tile-value.is-good { color: var(--good-text); }
.tile-value.is-bad  { color: var(--critical-text); }
.tile-value.is-warn { color: var(--warning-text); }
.tile.accent-good { border-left: 3px solid var(--good); }
.tile.accent-bad  { border-left: 3px solid var(--critical); }
.tile.accent-warn { border-left: 3px solid var(--warning); }

.delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11.5px; font-weight: 620; border-radius: 20px; padding: 1px 6px;
}
.delta.up   { background: var(--good-soft); color: var(--good-text); }
.delta.down { background: var(--critical-soft); color: var(--critical-text); }
.delta.flat { background: var(--neutral-soft); color: var(--ink-3); }

/* --------------------------------------------------------------- quick acts */

.quick-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 175px), 1fr));
}
.quick {
  display: flex; flex-direction: column; align-items: flex-start; gap: 9px;
  padding: 16px 15px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow-xs); cursor: pointer; text-align: left;
  font: inherit; color: var(--ink); text-decoration: none;
  transition: border-color 0.14s var(--ease), box-shadow 0.14s var(--ease),
              transform 0.14s var(--ease);
}
.quick:hover {
  border-color: var(--brand-line); box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.quick:active { transform: translateY(0); }
.quick-icon {
  width: 34px; height: 34px; border-radius: var(--radius-s);
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-soft); color: var(--brand); flex: none;
}
.quick-icon.sell { background: var(--good-soft); color: var(--good-text); }
.quick-icon.buy  { background: var(--info-soft); color: var(--series-buy); }
.quick-icon.cost { background: var(--warning-soft); color: var(--warning-text); }
.quick strong { font-size: 13.5px; font-weight: 620; display: block; }
.quick small { font-size: 11.5px; color: var(--ink-3); display: block; margin-top: 1px; }

/* ------------------------------------------------------------------- tables */

/* A wrapper that scrolls sideways is its own scrollport, and a sticky heading
   inside one sticks to *it* — which, since the page is what actually scrolls,
   means it never sticks at all. So the wrapper only becomes scrollable when
   its table is genuinely too wide (UI.stampTables measures and sets .scrolls);
   the rest of the time the headings can pin themselves under the topbar. */
.table-wrap { overflow-x: clip; }

/* The bar under a capped list. Sits inside the card, below the table, so the
   totals row stays attached to the figures it adds up. */
.more-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; padding: 10px 14px;
  border-top: 1px solid var(--line); font-size: 12.5px;
}
.table-wrap.scrolls { overflow-x: auto; }
.table-wrap.sticky { max-height: 460px; overflow-y: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data th {
  text-align: left; font-weight: 620; font-size: 11.5px; letter-spacing: 0.015em;
  color: var(--ink-2); padding: 9px 10px; border-bottom: 1px solid var(--line-strong);
  white-space: nowrap; background: var(--surface); position: sticky;
  top: var(--topbar-h); z-index: 1;
}
/* Inside a scrollport of its own, the heading pins to the top of the box. */
.table-wrap.scrolls table.data th, .table-wrap.sticky table.data th { top: 0; }
table.data th.num, table.data td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data th.sortable { cursor: pointer; user-select: none; }
table.data th.sortable:hover { color: var(--ink); }
table.data th .sort-caret { opacity: 0.5; font-size: 9px; margin-left: 3px; }
table.data td {
  padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: middle;
}
table.data tbody tr { transition: background 0.1s var(--ease); }
table.data tbody tr:hover { background: var(--surface-2); }
table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr.is-overdue td:first-child { box-shadow: inset 3px 0 0 var(--critical); }
table.data tbody tr.is-paid td:first-child { box-shadow: inset 3px 0 0 var(--good); }
table.data tbody tr.is-nodate td:first-child { box-shadow: inset 3px 0 0 var(--warning); }
table.data tbody tr.clickable { cursor: pointer; }
table.data tfoot td {
  padding: 10px; font-weight: 650; border-top: 1px solid var(--line-strong);
  background: var(--surface-2); border-bottom: none;
}
table.data tfoot td.num { font-variant-numeric: tabular-nums; }
table.data .row-actions { display: flex; gap: 1px; justify-content: flex-end; opacity: 0.45; }
table.data tr:hover .row-actions { opacity: 1; }
table.data-roomy { min-width: 780px; }
table.data th.actions-col, table.data td.actions-col { width: 1%; white-space: nowrap; }
table.data td.truncate {
  max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.data td.truncate > div { overflow: hidden; text-overflow: ellipsis; }
.cell-strong { font-weight: 560; }
.cell-muted { color: var(--ink-3); }
.cell-sub {
  font-size: 11.5px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.nowrap { white-space: nowrap; }

.empty {
  padding: 44px 20px; text-align: center; color: var(--ink-3);
}
.empty .empty-art {
  width: 46px; height: 46px; margin: 0 auto 12px;
  border-radius: var(--radius); background: var(--surface-2);
  display: flex; align-items: center; justify-content: center; color: var(--ink-3);
}
.empty strong { display: block; color: var(--ink); font-size: 14.5px; margin-bottom: 4px; font-weight: 600; }
.empty p { max-width: 380px; margin: 0 auto; font-size: 13px; line-height: 1.5; }

/* --------------------------------------------------------------- skeletons */

.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
  border-radius: var(--radius-xs);
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.sk-line { height: 11px; margin: 8px 0; }
.sk-tile { height: 82px; border-radius: var(--radius); }
.sk-chart { height: 240px; border-radius: var(--radius); }
.sk-row { height: 38px; margin-bottom: 6px; border-radius: var(--radius-xs); }

/* -------------------------------------------------------------------- chips */

.chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: 20px;
  background: var(--neutral-soft); color: var(--ink-2); white-space: nowrap;
}
.chip svg { flex: none; }
.chip-paid     { background: var(--good-soft);     color: var(--good-text); }
.chip-partial  { background: var(--warning-soft);  color: var(--warning-text); }
.chip-unpaid   { background: var(--neutral-soft);  color: var(--ink-2); }
.chip-overdue  { background: var(--critical-soft); color: var(--critical-text); }
.chip-nodate   { background: var(--warning-soft);  color: var(--warning-text); }
.chip-postponed{ background: var(--brand-soft);    color: var(--brand); }
.chip-credit   { background: var(--brand-soft);    color: var(--brand); }
.chip-role     { background: var(--surface-2);     color: var(--ink-2); }
.chip-admin    { background: var(--brand-soft);    color: var(--brand); }
.chip-btn { border: none; font: inherit; cursor: pointer; }

.dot {
  width: 7px; height: 7px; border-radius: 50%; flex: none; display: inline-block;
}
.dot.on { background: var(--good); }
.dot.off { background: var(--de-emphasis); }

/* ------------------------------------------------------------------- charts */

.chart-card { position: relative; }
.chart-legend { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--ink-2); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.legend-line { width: 14px; height: 2px; border-radius: 2px; flex: none; }

.chart-holder { position: relative; margin-top: 12px; }
.chart-holder svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart-tip {
  position: absolute; pointer-events: none; z-index: 5;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-s); box-shadow: var(--shadow-lg);
  padding: 8px 10px; font-size: 12px; min-width: 132px;
  opacity: 0; transform: translate(-50%, -100%); transition: opacity 0.1s;
}
.chart-tip.show { opacity: 1; }
.chart-tip .tip-title { font-weight: 650; margin-bottom: 5px; }
.chart-tip .tip-row { display: flex; align-items: center; gap: 7px; justify-content: space-between; }
.chart-tip .tip-key { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); }
.chart-tip .tip-val { font-variant-numeric: tabular-nums; font-weight: 600; }
.chart-empty { padding: 46px 0; text-align: center; color: var(--ink-3); font-size: 13px; }

.status-bar-row { display: grid; gap: 8px; margin-bottom: 14px; }
.status-bar-row:last-child { margin-bottom: 0; }
.status-bar-head { display: flex; justify-content: space-between; font-size: 12px; color: var(--ink-2); gap: 10px; }
.status-bar-head b { font-variant-numeric: tabular-nums; color: var(--ink); }

/* Horizontal ranked bars — used all over the reports. */
.rank-row { display: grid; gap: 5px; margin-bottom: 11px; }
.rank-row:last-child { margin-bottom: 0; }
.rank-head { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; }
.rank-head .name { color: var(--ink); font-weight: 520; overflow: hidden;
                   text-overflow: ellipsis; white-space: nowrap; }
.rank-head .val { font-variant-numeric: tabular-nums; font-weight: 620; flex: none; }
.rank-track { height: 8px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.rank-fill { height: 100%; border-radius: 4px; transition: width 0.4s var(--ease); }

.sparkline { display: block; width: 100%; height: 34px; }

/* ------------------------------------------------------------------- modals */

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(20, 20, 15, 0.42);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 40px 16px; overflow-y: auto; z-index: 60;
  animation: fade 0.12s ease-out;
  backdrop-filter: blur(2px);
}
@keyframes fade { from { opacity: 0; } }
.modal {
  background: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  width: 100%; max-width: 560px; border: 1px solid var(--line);
  animation: pop 0.15s var(--ease);
}
.modal.wide { max-width: 900px; }
.modal.narrow { max-width: 440px; }
@keyframes pop { from { transform: translateY(10px) scale(0.99); opacity: 0; } }
.modal-head {
  display: flex; align-items: center; gap: 10px;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
}
.modal-head h2 { font-size: 16px; }
.modal-head .sub { font-size: 12.5px; color: var(--ink-3); margin-top: 2px; }
.modal-head .icon-btn { margin-left: auto; }
.modal-body { padding: 18px; display: grid; gap: 14px; }
.modal-body.flush { padding: 0; gap: 0; }
.modal-foot {
  display: flex; gap: 8px; justify-content: flex-end; align-items: center;
  padding: 13px 18px; border-top: 1px solid var(--line); flex-wrap: wrap;
  background: var(--surface-2); border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.modal-foot .left { margin-right: auto; }
.form-error {
  background: var(--critical-soft); color: var(--critical-text);
  border-radius: var(--radius-s); padding: 9px 11px; font-size: 12.5px; font-weight: 550;
}
.form-ok {
  background: var(--good-soft); color: var(--good-text);
  border-radius: var(--radius-s); padding: 9px 11px; font-size: 12.5px; font-weight: 550;
}

/* ------------------------------------------------------------ command menu */

.palette-backdrop {
  position: fixed; inset: 0; background: rgba(20, 20, 15, 0.36);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 12vh 16px 16px; z-index: 80; animation: fade 0.1s ease-out;
  backdrop-filter: blur(2px);
}
.palette {
  width: 100%; max-width: 560px; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); overflow: hidden; animation: pop 0.14s var(--ease);
}
.palette-input {
  display: flex; align-items: center; gap: 10px; padding: 13px 15px;
  border-bottom: 1px solid var(--line);
}
.palette-input svg { color: var(--ink-3); flex: none; }
.palette-input input {
  border: none; background: none; font: inherit; font-size: 15px;
  color: var(--ink); width: 100%; outline: none; padding: 0;
}
.palette-list { max-height: 46vh; overflow-y: auto; padding: 6px; }
.palette-group {
  font-size: 10px; font-weight: 680; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3); padding: 9px 9px 4px;
}
.palette-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 9px; border-radius: var(--radius-s); border: none;
  background: transparent; color: var(--ink); font: inherit; font-size: 13.5px;
  cursor: pointer; text-align: left;
}
.palette-item svg { color: var(--ink-3); flex: none; }
.palette-item .meta { margin-left: auto; font-size: 11.5px; color: var(--ink-3); }
.palette-item[aria-selected="true"] { background: var(--brand-soft); color: var(--brand); }
.palette-item[aria-selected="true"] svg { color: var(--brand); }
.palette-foot {
  display: flex; gap: 12px; padding: 8px 14px; border-top: 1px solid var(--line);
  background: var(--surface-2); font-size: 11.5px; color: var(--ink-3);
}

/* ---------------------------------------------------------------- popovers */

.pop {
  position: fixed; z-index: 70; min-width: 240px; max-width: 360px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  animation: pop 0.12s var(--ease); overflow: hidden;
}
.pop-head {
  padding: 11px 13px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
}
.pop-head h3 { font-size: 13px; }
.pop-head .icon-btn { margin-left: auto; }
.pop-body { max-height: 340px; overflow-y: auto; }
.pop-item {
  display: flex; gap: 9px; width: 100%; text-align: left;
  padding: 10px 13px; border: none; background: none; font: inherit;
  color: var(--ink); cursor: pointer; border-bottom: 1px solid var(--line);
}
.pop-item:last-child { border-bottom: none; }
.pop-item:hover { background: var(--surface-2); }
.pop-item.unread { background: var(--brand-soft); }
.pop-item strong { font-size: 12.5px; font-weight: 600; display: block; }
.pop-item small { font-size: 11.5px; color: var(--ink-3); display: block; }
.pop-menu { padding: 5px; }
.pop-menu .pop-item {
  border-bottom: none; border-radius: var(--radius-s); padding: 7px 9px;
  align-items: center; font-size: 13.5px;
}
.pop-menu .divider { margin: 4px 2px; }

/* ------------------------------------------------------------- line editor */

.lines-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.lines-table th {
  text-align: left; font-size: 11.5px; font-weight: 600; color: var(--ink-2);
  padding: 0 6px 5px; white-space: nowrap;
}
.lines-table th.num { text-align: right; }
.lines-table td { padding: 3px 6px 3px 0; vertical-align: middle; }
.lines-table td:first-child { padding-left: 0; }
.lines-table .input, .lines-table select { padding: 6px 8px; }
.lines-table .amount-cell {
  text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap;
}
.lines-total {
  display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px solid var(--line-strong); margin-top: 10px; padding-top: 10px;
}
.lines-total .label { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.lines-total .value { font-size: 20px; font-weight: 650; font-variant-numeric: tabular-nums; }
.unit-tag { font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }

/* -------------------------------------------------------------------- toast */

#toast-root {
  position: fixed; bottom: 20px; right: 20px;
  display: grid; gap: 8px; z-index: 90; width: max-content; max-width: min(92vw, 400px);
}
.toast {
  display: flex; align-items: flex-start; gap: 9px;
  background: var(--ink); color: var(--page);
  padding: 11px 14px; border-radius: var(--radius); font-size: 13px; font-weight: 500;
  box-shadow: var(--shadow-lg); animation: slide-in 0.18s var(--ease);
}
.toast svg { flex: none; margin-top: 1px; }
.toast.err { background: var(--critical); color: #fff; }
.toast.ok  { background: var(--good-text); color: #fff; }
.toast .toast-action {
  margin-left: 6px; background: none; border: none; font: inherit; font-weight: 650;
  color: inherit; text-decoration: underline; cursor: pointer; padding: 0;
}
@keyframes slide-in { from { transform: translateX(14px); opacity: 0; } }

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

.auth-shell {
  min-height: 100vh; display: grid; place-items: center; padding: 24px 16px;
  background:
    radial-gradient(1100px 460px at 12% -8%, var(--brand-soft), transparent 62%),
    radial-gradient(900px 420px at 108% 8%, var(--good-soft), transparent 58%),
    var(--page);
}
.auth-card {
  width: 100%; max-width: 420px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md); padding: 30px 30px 26px;
  animation: pop 0.2s var(--ease);
}
.auth-card.wide { max-width: 520px; }
.auth-brand {
  display: flex; align-items: center; gap: 10px; margin-bottom: 20px;
}
.auth-brand .brand-mark svg { width: 32px; height: 32px; }
.auth-card h1 { font-size: 20px; letter-spacing: -0.02em; }
.auth-card .lede { color: var(--ink-3); font-size: 13.5px; margin-top: 6px; line-height: 1.5; }
.auth-form { display: grid; gap: 14px; margin-top: 22px; }
.auth-foot {
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
  font-size: 12.5px; color: var(--ink-3); display: flex; gap: 10px;
  align-items: center; flex-wrap: wrap;
}
.auth-foot button {
  background: none; border: none; font: inherit; font-size: 12.5px;
  color: var(--brand); cursor: pointer; padding: 0; text-decoration: underline;
}
.pw-meter { display: flex; gap: 4px; margin-top: 6px; }
.pw-meter i {
  height: 3px; flex: 1; border-radius: 2px; background: var(--surface-3);
  transition: background 0.2s var(--ease);
}
.pw-meter.s1 i:nth-child(1) { background: var(--critical); }
.pw-meter.s2 i:nth-child(-n+2) { background: var(--warning); }
.pw-meter.s3 i:nth-child(-n+3) { background: var(--series-buy); }
.pw-meter.s4 i { background: var(--good); }

/* ------------------------------------------------------------------- kanban */

.board-scroll {
  display: flex; gap: 12px; align-items: flex-start;
  overflow-x: auto; padding-bottom: 14px; scroll-snap-type: x proximity;
}
.board-col {
  flex: 0 0 300px; width: 300px; scroll-snap-align: start;
  background: var(--surface-sunk); border: 1px solid var(--line);
  border-radius: var(--radius); display: flex; flex-direction: column;
  max-height: calc(100vh - 210px);
  transition: background 0.14s var(--ease), border-color 0.14s var(--ease);
}
.board-col.drop-target {
  background: var(--brand-soft); border-color: var(--brand);
  border-style: dashed;
}
.board-col-head {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 12px 9px; border-bottom: 1px solid var(--line);
  border-top: 2px solid var(--col-tint, var(--line-strong));
  border-radius: var(--radius) var(--radius) 0 0;
}
/* The columns warm up left to right, so the board reads as a progression
   rather than five identical grey boxes. */
.board-col[data-status="backlog"] { --col-tint: var(--de-emphasis); }
.board-col[data-status="todo"]    { --col-tint: var(--tint-purchases); }
.board-col[data-status="doing"]   { --col-tint: var(--tint-expenses); }
.board-col[data-status="review"]  { --col-tint: var(--tint-inventory); }
.board-col[data-status="done"]    { --col-tint: var(--tint-sales); }
.board-col-head h3 { color: var(--col-tint, var(--ink)); }
.board-col-head h3 { font-size: 12.5px; font-weight: 650; letter-spacing: 0.01em; }
.board-col-head .count {
  font-size: 11px; font-weight: 650; color: var(--ink-3);
  background: var(--surface-3); border-radius: 20px; padding: 1px 7px;
  font-variant-numeric: tabular-nums;
}
.board-col-head .icon-btn { margin-left: auto; width: 26px; height: 26px; }
.board-col-body {
  padding: 9px; display: grid; gap: 9px; align-content: start;
  overflow-y: auto; flex: 1; min-height: 70px;
}
.board-col-empty {
  border: 1px dashed var(--line-strong); border-radius: var(--radius-s);
  padding: 18px 10px; text-align: center; color: var(--ink-3); font-size: 12px;
}

.tcard {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-s); padding: 11px 12px; cursor: grab;
  box-shadow: var(--shadow-xs); display: grid; gap: 8px;
  transition: box-shadow 0.13s var(--ease), border-color 0.13s var(--ease),
              transform 0.13s var(--ease);
}
.tcard:hover { box-shadow: var(--shadow); border-color: var(--line-strong); }
.tcard:active { cursor: grabbing; }
.tcard.dragging { opacity: 0.4; transform: rotate(1.2deg) scale(0.99); }
.tcard.is-overdue { border-left: 3px solid var(--critical); }
.tcard.is-soon { border-left: 3px solid var(--warning); }
.tcard-title { font-size: 13.5px; font-weight: 560; line-height: 1.4; }
.tcard-labels { display: flex; flex-wrap: wrap; gap: 4px; }
.tlabel {
  font-size: 10.5px; font-weight: 650; padding: 1.5px 7px; border-radius: 20px;
  color: #fff; white-space: nowrap;
}
.tcard-meta {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 11.5px; color: var(--ink-3);
}
.tcard-meta .m { display: inline-flex; align-items: center; gap: 4px; }
.tcard-meta .m.bad { color: var(--critical-text); font-weight: 600; }
.tcard-meta .m.warn { color: var(--warning-text); font-weight: 600; }
.tcard-meta .spacer { flex: 1; }
.pri {
  width: 6px; height: 6px; border-radius: 50%; display: inline-block; flex: none;
}
.pri-urgent { background: var(--critical); }
.pri-high   { background: var(--serious); }
.pri-medium { background: var(--warning); }
.pri-low    { background: var(--de-emphasis); }

.progress {
  height: 4px; border-radius: 3px; background: var(--surface-3); overflow: hidden;
}
.progress > i {
  display: block; height: 100%; border-radius: 3px; background: var(--good);
  transition: width 0.3s var(--ease);
}
.progress.brand > i { background: var(--brand); }

.drop-line {
  height: 2px; background: var(--brand); border-radius: 2px; margin: -4px 0;
}

.checklist { display: grid; gap: 2px; }
.check-item {
  display: flex; align-items: flex-start; gap: 9px; padding: 5px 6px;
  border-radius: var(--radius-xs); font-size: 13px;
}
.check-item:hover { background: var(--surface-2); }
.check-item input { margin-top: 3px; accent-color: var(--good); width: 15px; height: 15px; flex: none; }
.check-item.done label { color: var(--ink-3); text-decoration: line-through; }
.check-item label { flex: 1; cursor: pointer; }

.comment {
  display: flex; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--line);
}
.comment:last-child { border-bottom: none; }
.comment-body { flex: 1; min-width: 0; }
.comment-head { display: flex; align-items: baseline; gap: 8px; }
.comment-head strong { font-size: 12.5px; font-weight: 620; }
.comment-head time { font-size: 11px; color: var(--ink-3); }
.comment-text { font-size: 13px; margin-top: 2px; white-space: pre-wrap; word-break: break-word; }

.attach {
  display: flex; align-items: center; gap: 9px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: var(--radius-s);
  background: var(--surface-2); font-size: 12.5px;
}
.attach .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attach .size { color: var(--ink-3); font-size: 11.5px; flex: none; }

.dropzone {
  border: 1.5px dashed var(--line-strong); border-radius: var(--radius-s);
  padding: 16px; text-align: center; color: var(--ink-3); font-size: 12.5px;
  cursor: pointer; transition: border-color 0.13s var(--ease), background 0.13s var(--ease);
}
.dropzone:hover, .dropzone.over { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); }

/* ------------------------------------------------------------------ reports */

.report-nav {
  display: grid; gap: 4px; position: sticky; top: calc(var(--topbar-h) + 14px);
  align-self: start;
}
.report-layout { display: grid; grid-template-columns: 208px 1fr; gap: 18px; align-items: start; }
@media (max-width: 1000px) { .report-layout { grid-template-columns: 1fr; }
                             .report-nav { position: static; grid-auto-flow: column;
                                           overflow-x: auto; } }
.report-nav a {
  display: block; padding: 7px 10px; border-radius: var(--radius-s);
  font-size: 13px; color: var(--ink-2); text-decoration: none; white-space: nowrap;
  border: 1px solid transparent;
}
.report-nav a:hover { background: var(--surface-2); color: var(--ink); }
.report-nav a.active { background: var(--brand-soft); color: var(--brand); font-weight: 600; }

.report-section { scroll-margin-top: calc(var(--topbar-h) + 16px); }

/* ---------------------------------------------------------------- settings */

.settings-layout { display: grid; grid-template-columns: 220px 1fr; gap: 20px; align-items: start; }
@media (max-width: 940px) { .settings-layout { grid-template-columns: 1fr; } }
.settings-nav { display: grid; gap: 3px; position: sticky; top: calc(var(--topbar-h) + 14px); }
@media (max-width: 940px) {
  .settings-nav { position: static; grid-auto-flow: column; overflow-x: auto;
                  padding-bottom: 6px; }
}
.settings-nav a {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: var(--radius-s);
  font-size: 13.5px; color: var(--ink-2); text-decoration: none; white-space: nowrap;
}
.settings-nav a svg { opacity: 0.7; flex: none; }
.settings-nav a:hover { background: var(--surface-2); color: var(--ink); }
.settings-nav a.active { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.settings-nav a.active svg { opacity: 1; }

/* ------------------------------------------------------------------ helpers */

.text-good { color: var(--good-text); }
.text-bad  { color: var(--critical-text); }
.text-warn { color: var(--warning-text); }
.text-muted { color: var(--ink-3); }
.text-sm { font-size: 12.5px; }
.money { font-variant-numeric: tabular-nums; }
.stack { display: grid; gap: 14px; }
.stack-sm { display: grid; gap: 8px; }
.row { display: flex; align-items: center; gap: 8px; }
.row.wrap { flex-wrap: wrap; }
.row .spacer { flex: 1; }
.inline-list { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.divider { height: 1px; background: var(--line); margin: 4px 0; }
.mt-0 { margin-top: 0; }
.hidden { display: none !important; }

.callout {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--info-soft); border-radius: var(--radius);
  padding: 12px 14px; font-size: 13px; color: var(--ink-2); line-height: 1.5;
  border: 1px solid var(--brand-line);
}
.callout svg { flex: none; color: var(--brand); margin-top: 1px; }
.callout.warn { background: var(--warning-soft); color: var(--warning-text);
                border-color: var(--warning); }
.callout.warn svg { color: var(--warning-text); }
.callout.danger { background: var(--critical-soft); color: var(--critical-text);
                  border-color: var(--critical); }
.callout.danger svg { color: var(--critical-text); }
.callout.good { background: var(--good-soft); color: var(--good-text); border-color: var(--good); }
.callout.good svg { color: var(--good-text); }
.callout strong { display: block; margin-bottom: 2px; color: inherit; }

.sticky-actions {
  position: sticky; bottom: 0; z-index: 20;
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding: 11px 14px; margin: 18px -26px -72px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  border-top: 1px solid var(--line);
}
.sticky-actions .spacer { flex: 1; }

.fab {
  position: fixed; right: 20px; bottom: 20px; z-index: 40;
  width: 50px; height: 50px; border-radius: 50%;
  display: none; align-items: center; justify-content: center;
  background: var(--brand); color: var(--brand-ink); border: none;
  box-shadow: var(--shadow-md); cursor: pointer;
}

/* --------------------------------------------------------------- responsive */

@media (max-width: 900px) {
  .app { flex-direction: column; }
  .sidebar {
    width: 100%; flex: none; height: auto; position: sticky; top: 0; z-index: 40;
    border-right: none; border-bottom: 1px solid var(--line);
  }
  .brand { padding: 10px 14px; }
  /* The sidebar is a top bar here, so collapsing has nothing to collapse. */
  .app.nav-collapsed { --sidebar-w: 100%; }
  .app.nav-collapsed .nav-label,
  .app.nav-collapsed .brand-text,
  .app.nav-collapsed .user-meta,
  .app.nav-collapsed .nav-group-title { display: revert; }
  .app.nav-collapsed .nav-link { justify-content: flex-start; padding: 6.5px 9px; }
  .app.nav-collapsed .brand { justify-content: flex-start; padding: 10px 14px; }
  .app.nav-collapsed .nav-badge { position: static; margin-left: auto; }
  .app.nav-collapsed .brand-mark { display: flex; }
  #nav, .sidebar-foot { display: none; }
  .sidebar.open #nav { display: block; padding-bottom: 10px; max-height: 62vh; }
  .sidebar.open .sidebar-foot { display: grid; }
  .topbar { padding: 8px 14px; top: 0; position: relative; }
  #main { padding: 16px 14px 84px; }
  .hero-row { grid-template-columns: 1fr; }
  .page-head h1 { font-size: 20px; }
  .page-head-actions { width: 100%; }
  .modal-backdrop { padding: 0; align-items: flex-end; }
  .modal { max-width: 100%; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .modal-foot { border-radius: 0; }
  .board-col { flex: 0 0 84vw; width: 84vw; max-height: none; }
  .sticky-actions { margin: 18px -14px -84px; }
  .fab { display: flex; }
  .omni { min-width: 0; }
  .omni .label, .omni .kbd-hint { display: none; }
}

@media (max-width: 560px) {
  .quick-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiles-kpi, .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-value { font-size: 30px; }

  /* Two tiles across a phone leaves roughly 100px for the figure once the
     icon has taken its share. Stacking the icon gives that back, and the
     smaller type buys the headroom for a seven-figure sum. */
  .tile.has-mark { flex-direction: column; gap: 8px; }
  .tile { padding: 12px 12px; }
  .tile-value { font-size: 18.5px; letter-spacing: -0.03em; }
  .tile-label { font-size: 11px; }
  .tile-note { font-size: 11px; }
  .quick { padding: 13px 12px; }
  .page-head h1 { font-size: 19px; }
  .card-head h2 { font-size: 13.5px; }
}

/* ------------------------------------------------- tables without sideways

   A wide table on a phone is a wall you have to drag. Below this width every
   data table turns into one card per row: the column headings move into each
   cell as a label, so nothing is lost and nothing scrolls off the side.
   The labels are stamped onto the cells by UI.stampTables, which reads them
   from the table's own <thead> — so a table gets this for free. */

@media (max-width: 720px) {
  table.data,
  table.data thead,
  table.data tbody,
  table.data tfoot,
  table.data tr,
  table.data td { display: block; width: 100%; }

  table.data { border-collapse: separate; border-spacing: 0; min-width: 0; }
  table.data-roomy { min-width: 0; }
  .table-wrap, .table-wrap.scrolls, .table-wrap.sticky {
    overflow-x: visible; max-height: none;
  }

  /* The header row is redundant once every cell is labelled. */
  table.data thead { display: none; }

  table.data tbody tr {
    border: 1px solid var(--line); border-radius: var(--radius-s);
    padding: 4px 12px; margin-bottom: 9px; background: var(--surface);
  }
  table.data tbody tr:hover { background: var(--surface); }
  table.data tbody tr.is-overdue { border-left: 3px solid var(--critical); }
  table.data tbody tr.is-paid    { border-left: 3px solid var(--good); }
  table.data tbody tr.is-nodate  { border-left: 3px solid var(--warning); }
  table.data tbody tr td:first-child { box-shadow: none !important; }

  table.data td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 14px; text-align: right; padding: 6px 0;
    border-bottom: 1px solid var(--line);
  }
  table.data tr td:last-child { border-bottom: none; }
  table.data td::before {
    content: attr(data-label);
    flex: 0 0 auto; text-align: left; white-space: nowrap;
    font-size: 11.5px; font-weight: 620; color: var(--ink-3);
  }
  /* A cell with no heading and no content is just noise on a card. */
  table.data td:empty { display: none; }
  table.data td:not([data-label])::before { content: ""; }

  /* The first cell is the card's title, so it gets the whole line. */
  table.data td:first-child {
    display: block; text-align: left; font-size: 14px;
    padding-top: 10px; padding-bottom: 8px;
  }
  table.data td:first-child::before { display: none; }
  table.data td.truncate { max-width: none; white-space: normal; }
  table.data td.truncate > div { white-space: normal; }
  table.data .cell-sub { white-space: normal; }

  table.data td.actions-col { width: auto; }
  table.data .row-actions { opacity: 1; justify-content: flex-end; }

  table.data tfoot tr {
    border: 1px solid var(--line-strong); border-radius: var(--radius-s);
    background: var(--surface-2); padding: 4px 12px;
  }
  table.data tfoot td { border-bottom: 1px solid var(--line); background: none; }
  table.data tfoot td:last-child { border-bottom: none; }

  /* The board stacks rather than scrolling sideways. */
  .board-scroll { flex-direction: column; overflow-x: visible; }
  .board-col { flex: 1 1 auto; width: 100%; }

  /* Anything else that scrolled horizontally now wraps. */
  .tabs { flex-wrap: wrap; overflow-x: visible; }
  .report-nav, .settings-nav {
    grid-auto-flow: row; overflow-x: visible;
  }
  .chart-holder { overflow-x: visible; }
  .lines-table, .lines-table tbody, .lines-table tr { display: block; width: 100%; }
  .lines-table thead { display: none; }
  .lines-table tr { border: 1px solid var(--line); border-radius: var(--radius-s);
                    padding: 8px 10px; margin-bottom: 8px; }
  .lines-table td { display: block; width: 100% !important; padding: 4px 0; }
  .lines-table .amount-cell { text-align: right; }
}

/* ---------------------------------------------------------------- fancy mode

   Chosen in Settings → Appearance. Normal mode spends colour only where it
   carries meaning; fancy mode spends it on category as well — tinted cards,
   filled icons, coloured table headings, striped rows.

   What does NOT change: green still means money in, amber still means needs
   attention, red still means overdue. The tints are drawn from the category
   palette, never from the status one, so a red figure is still the only red
   thing on a row and still means the same thing. Tints stay under about 10%
   so text contrast is untouched.

   The tile tints key off the icon inside via :has(), which keeps this entirely
   in the stylesheet — no page had to be told this mode exists. */

:root[data-display="fancy"] .tile:has(.m-sell),
:root[data-display="fancy"] .tile:has(.m-cash) {
  background: linear-gradient(140deg, var(--good-soft), var(--surface) 58%);
  border-color: color-mix(in srgb, var(--good) 26%, var(--line));
}
:root[data-display="fancy"] .tile:has(.m-buy) {
  background: linear-gradient(140deg, var(--info-soft), var(--surface) 58%);
  border-color: color-mix(in srgb, var(--series-buy) 26%, var(--line));
}
:root[data-display="fancy"] .tile:has(.m-cost) {
  background: linear-gradient(140deg, var(--warning-soft), var(--surface) 58%);
  border-color: color-mix(in srgb, var(--warning) 30%, var(--line));
}
:root[data-display="fancy"] .tile:has(.m-alert) {
  background: linear-gradient(140deg, var(--critical-soft), var(--surface) 58%);
  border-color: color-mix(in srgb, var(--critical) 26%, var(--line));
}
:root[data-display="fancy"] .tile:has(.m-stock),
:root[data-display="fancy"] .tile:has(.m-people),
:root[data-display="fancy"] .tile:has(.m-task) {
  background: linear-gradient(140deg, var(--brand-soft), var(--surface) 58%);
  border-color: var(--brand-line);
}

/* Filled icon marks rather than tinted ones — the second level of the hue. */
:root[data-display="fancy"] .tile-mark,
:root[data-display="fancy"] .card-head .head-mark,
:root[data-display="fancy"] .section-title .mark {
  color: #fff;
}
:root[data-display="fancy"] .tile-mark.m-sell,
:root[data-display="fancy"] .tile-mark.m-cash,
:root[data-display="fancy"] .card-head .head-mark.m-sell,
:root[data-display="fancy"] .section-title .mark.m-sell,
:root[data-display="fancy"] .section-title .mark.m-cash { background: var(--good-text); }
:root[data-display="fancy"] .tile-mark.m-buy,
:root[data-display="fancy"] .card-head .head-mark.m-buy,
:root[data-display="fancy"] .section-title .mark.m-buy { background: var(--series-buy); }
:root[data-display="fancy"] .tile-mark.m-cost,
:root[data-display="fancy"] .card-head .head-mark.m-cost,
:root[data-display="fancy"] .section-title .mark.m-cost { background: var(--warning-text); }
:root[data-display="fancy"] .tile-mark.m-alert,
:root[data-display="fancy"] .card-head .head-mark.m-alert { background: var(--critical); }
:root[data-display="fancy"] .tile-mark.m-stock,
:root[data-display="fancy"] .tile-mark.m-people,
:root[data-display="fancy"] .tile-mark.m-task,
:root[data-display="fancy"] .card-head .head-mark.m-task,
:root[data-display="fancy"] .section-title .mark.m-stock,
:root[data-display="fancy"] .section-title .mark.m-time { background: var(--brand); }

/* Page marks fill in too, matching their section's colour. */
:root[data-display="fancy"] .page-head .page-mark { color: #fff; }
:root[data-display="fancy"] .page-mark.tint-home      { background: var(--tint-home); }
:root[data-display="fancy"] .page-mark.tint-sales     { background: var(--tint-sales); }
:root[data-display="fancy"] .page-mark.tint-purchases { background: var(--tint-purchases); }
:root[data-display="fancy"] .page-mark.tint-expenses  { background: var(--tint-expenses); }
:root[data-display="fancy"] .page-mark.tint-money     { background: var(--tint-money); }
:root[data-display="fancy"] .page-mark.tint-cheques   { background: var(--tint-cheques); }
:root[data-display="fancy"] .page-mark.tint-inventory { background: var(--tint-inventory); }
:root[data-display="fancy"] .page-mark.tint-contacts  { background: var(--tint-contacts); }
:root[data-display="fancy"] .page-mark.tint-reports   { background: var(--tint-reports); }
:root[data-display="fancy"] .page-mark.tint-todo      { background: var(--tint-todo); }
:root[data-display="fancy"] .page-mark.tint-users     { background: var(--tint-users); }
:root[data-display="fancy"] .page-mark.tint-settings  { background: var(--tint-settings); }

/* Tables: a coloured heading and quiet stripes. The heading keeps a solid
   background because it is sticky and has to hide the rows passing beneath. */
:root[data-display="fancy"] table.data th {
  background: var(--brand-soft); color: var(--brand);
  border-bottom-color: var(--brand-line);
}
:root[data-display="fancy"] table.data tbody tr:nth-child(even) {
  background: color-mix(in srgb, var(--brand-soft) 45%, transparent);
}
:root[data-display="fancy"] table.data tbody tr:hover {
  background: color-mix(in srgb, var(--brand-soft) 85%, transparent);
}
:root[data-display="fancy"] table.data tfoot td {
  background: var(--brand-soft); color: var(--ink);
  border-top-color: var(--brand-line);
}

/* Cards and the rest of the furniture. */
:root[data-display="fancy"] .card { border-color: color-mix(in srgb, var(--brand) 16%, var(--line)); }
:root[data-display="fancy"] .hero {
  background: linear-gradient(135deg, var(--brand-soft), transparent 66%), var(--surface);
  border-color: var(--brand-line);
}
:root[data-display="fancy"] .filter-bar {
  background: linear-gradient(135deg, var(--brand-soft), var(--surface) 55%);
  border-color: var(--brand-line);
}
:root[data-display="fancy"] .quick:hover { box-shadow: var(--shadow-lg); }
:root[data-display="fancy"] .quick .quick-icon { color: #fff; }
:root[data-display="fancy"] .quick .quick-icon.sell { background: var(--good-text); }
:root[data-display="fancy"] .quick .quick-icon.buy  { background: var(--series-buy); }
:root[data-display="fancy"] .quick .quick-icon.cost { background: var(--warning-text); }
:root[data-display="fancy"] .quick .quick-icon:not(.sell):not(.buy):not(.cost) {
  background: var(--brand);
}

/* The board's columns wear their stage colour rather than just a top rule. */
:root[data-display="fancy"] .board-col-head {
  background: color-mix(in srgb, var(--col-tint) 12%, transparent);
}
:root[data-display="fancy"] .section-title { color: var(--ink-2); }

/* Anyone who has asked for less motion has also asked for less of this. */
@media (prefers-reduced-motion: reduce) {
  :root[data-display="fancy"] .quick:hover { box-shadow: var(--shadow-md); }
}

/* Nothing should ever push the page itself sideways. If something does, this
   is a symptom to fix rather than to hide — but it should not break the layout
   for the person using it in the meantime.

   `clip`, not `hidden`: an ancestor with overflow:hidden becomes the scroll
   container for everything inside it, which silently kills `position: sticky`
   on the sidebar. `clip` trims the overflow without creating a scrollport, so
   the sidebar keeps sticking. */
html, body { max-width: 100%; overflow-x: clip; }

/* -------------------------------------------------------------------- print */

@media print {
  :root { --page: #fff; --surface: #fff; }
  .sidebar, .topbar, .filter-bar, .page-head-actions, .row-actions,
  .fab, .sticky-actions, .report-nav, .seg, .tabs, #toast-root { display: none !important; }
  .app { display: block; }
  #main { padding: 0; }
  .card { box-shadow: none; break-inside: avoid; border-color: #ccc; }
  .report-layout { grid-template-columns: 1fr; }
  .table-wrap, .table-wrap.scrolls, .table-wrap.sticky {
    overflow: visible; max-height: none;
  }
  table.data { font-size: 10.5px; }
  table.data th {
    background: #eee !important; color: #000; position: static;
  }
  .report-section { break-inside: auto; page-break-inside: auto; }
  h1, h2, h3 { break-after: avoid; }
  a { color: inherit; text-decoration: none; }
  .print-only { display: block !important; }
}
.print-only { display: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
