/* App styles. Light only; colours are tokens so they can be changed in one place. */

:root {
  color-scheme: light;
  --bg: #f5f6f8;
  --surface: #ffffff;
  --surface-2: #f0f2f5;
  --border: #e1e4e9;
  --border-strong: #c9ced6;
  --text: #1c2330;
  --text-muted: #5e6878;
  --accent: #1f5f8b;
  --accent-hover: #184d72;
  --accent-soft: #e6eff6;
  --accent-text: #ffffff;
  --danger: #b42318;
  --danger-soft: #fdecea;
  --success: #1e7a46;
  --success-soft: #e7f5ec;
  --warning: #b54708;
  --warning-soft: #fff6e0;
  --shadow: 0 1px 2px rgb(16 24 40 / 0.06), 0 1px 3px rgb(16 24 40 / 0.08);
  --radius: 8px;
  --radius-sm: 6px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.5;
}


* { box-sizing: border-box; }

/* the scrollbar is always there (greyed out on short pages), so the header and
   nav don't move sideways between short pages and long ones. Scrollbars that
   float over the page (Linux, macOS) take no room either way */
html { overflow-y: scroll; scrollbar-gutter: stable; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
}

h1, h2, h3 { line-height: 1.25; margin: 0; }
h1 { font-size: 1.6rem; font-weight: 650; }
h2 { font-size: 1.1rem; font-weight: 600; }
p { margin: 0; }
a { color: var(--accent); }
a:hover { color: var(--accent-hover); }

/* forms */

label { display: grid; gap: 4px; font-weight: 500; font-size: 0.93rem; }

input, select, button, textarea { font: inherit; }
/* what's typed or picked is plain text, not the medium of the label around it */
input, select, textarea { font-weight: 400; }

input:not([type="checkbox"]), select, textarea {
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  min-width: 0;
}

input:focus-visible, select:focus-visible, button:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 3px 0 0;
  accent-color: var(--accent);
  flex-shrink: 0;
}

button {
  padding: 8px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
button:hover { background: var(--surface-2); }
button:disabled { opacity: 0.6; cursor: default; }
/* a <details>' summary is a button too (add panels, menus, filters, dropdowns) */
summary { cursor: pointer; user-select: none; }

.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-danger { color: var(--danger); border-color: var(--danger); background: transparent; }
.btn-danger:hover { background: var(--danger-soft); }
.btn-ghost { border-color: transparent; background: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }

/* messages: slots the server patches, shown as toasts by static/toast.js */

p[role="alert"], p[role="status"] { display: none; }
.muted { color: var(--text-muted); }
.small { font-size: 0.87rem; }

/* an ⓘ whose explanation shows on hover, focus or a click (views.Info,
   static/info.js). The tip is fixed, placed by info.js; it resets the text
   styles it'd otherwise take from where the ⓘ is (a heading, a table head) */
.info-button {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  margin-left: 5px;
  vertical-align: middle;
  border-radius: 50%;
  color: var(--text-muted);
  opacity: 0.7;
  cursor: help;
}
.info-button svg { margin-top: -1px; }
.info-button:hover, .info-open .info-button { color: var(--accent); opacity: 1; }
.info-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1; }
.info-tip {
  display: none;
  position: fixed;
  z-index: 60;
  width: max-content;
  max-width: min(360px, calc(100vw - 16px));
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.12), var(--shadow);
  color: var(--text);
  font-size: 0.87rem;
  font-weight: 400;
  font-style: normal;
  line-height: 1.45;
  letter-spacing: normal;
  text-transform: none;
  text-align: left;
  white-space: normal;
  overflow-wrap: normal;
  cursor: auto;
  user-select: text;
}
.info-tip-wide { max-width: min(560px, calc(100vw - 16px)); }
.info-open .info-tip { display: block; }
/* lines of a longer tip (views.InfoTip), e.g. the cash flow sheet's */
.info-tip strong { font-weight: 600; }
.info-line, .info-point { display: block; }
.info-tip > * + .info-line, .info-tip > * + .info-point { margin-top: 6px; }
.info-point { position: relative; padding-left: 14px; }
.info-point::before { content: "•"; position: absolute; left: 2px; color: var(--text-muted); }
/* on its own in a form row, level with the inputs rather than their labels */
.form-row > .info { padding-bottom: 10px; }
/* a disabled button whose tip says why (views.DisabledButton): the span round
   it is the ⓘ, so it takes the hover the button can't */
.info-button.info-disabled { width: auto; height: auto; margin-left: 0; border-radius: var(--radius); opacity: 1; cursor: not-allowed; }
.info-disabled > button { pointer-events: none; }

/* loading (static/loading.js, views.busyAttr) */

/* a bar along the top of the window while a request or a page load is out */
.progress-bar {
  position: fixed;
  z-index: 200;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}
.progress-bar.on { opacity: 1; }
.progress-bar.on::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 40%;
  background: var(--accent);
  animation: progress-slide 1.1s ease-in-out infinite;
}
@keyframes progress-slide { from { transform: translateX(-100%); } to { transform: translateX(250%); } }

/* the button that made a request: a spinner in place of its label, which
   keeps the button's size so nothing moves */
button[aria-busy="true"] { position: relative; color: transparent !important; }
button[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 14px;
  height: 14px;
  margin: auto;
  border: 2px solid var(--text-muted);
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.btn-primary[aria-busy="true"]::after { border-color: var(--accent-text); border-right-color: transparent; }
.btn-danger[aria-busy="true"]::after { border-color: var(--danger); border-right-color: transparent; }
@keyframes spin { to { transform: rotate(360deg); } }

/* a part reloading (a table's rows, a report's results): dimmed once it's taken
   a moment (the transition's delay, so quick ones don't flash), back at once */
[aria-busy="true"]:not(button) { opacity: 0.45; cursor: progress; transition: opacity 0.2s ease 0.15s; }

@media (prefers-reduced-motion: reduce) {
  .progress-bar.on::before { width: 100%; animation: none; opacity: 0.6; }
  button[aria-busy="true"]::after { animation-duration: 1.5s; }
}

/* slots that shouldn't take space until there's something in them */
.hide-empty:empty { display: none; }

.toasts {
  position: fixed;
  z-index: 100;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 260px;
  max-width: min(560px, calc(100vw - 32px));
  padding: 10px 10px 10px 14px;
  border-left: 4px solid var(--success);
  border-radius: var(--radius);
  background: var(--text);
  color: var(--surface);
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.18), 0 2px 6px rgb(16 24 40 / 0.12);
  font-size: 0.93rem;
  pointer-events: auto;
  animation: toast-in 0.2s ease-out;
}
.toast-error { border-left-color: var(--danger); }
.toast-text { flex: 1; }
.toast-close {
  padding: 0 6px;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 1.2rem;
  line-height: 1;
  opacity: 0.7;
}
.toast-close:hover { background: transparent; opacity: 1; }
.toast-out { animation: toast-out 0.15s ease-in forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateY(12px); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(12px); } }
@media (prefers-reduced-motion: reduce) {
  .toast, .toast-out { animation-duration: 1ms; }
}

.callout {
  display: grid;
  gap: 8px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--success-soft);
  border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
}
.callout-warning {
  background: var(--warning-soft);
  border-color: color-mix(in srgb, var(--warning) 35%, transparent);
}

.code {
  font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
  font-size: 1.35rem;
  letter-spacing: 0.12em;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  justify-self: start;
  user-select: all;
}

/* header and nav */

.app-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
/* two rows: brand and user on top, the nav (which scrolls sideways if it doesn't fit) under it */
.app-header-inner {
  max-width: 1880px;
  margin: 0 auto;
  padding: 10px 24px 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 12px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 650;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}
.brand:hover { color: var(--text); }
.brand-mark {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: 0.95rem;
}

.app-nav {
  order: 3;
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 8px;
  overflow-x: auto;
  scrollbar-width: none;
}
.app-nav a {
  padding: 8px 12px 10px;
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.93rem;
  font-weight: 500;
  white-space: nowrap;
}
.app-nav a:hover { color: var(--text); }
.app-nav a[aria-current="page"] { color: var(--accent); border-bottom-color: var(--accent); }
/* groups of links (see MainNav), a thin rule between them */
.nav-group { display: flex; align-items: center; gap: 2px; }
.nav-group + .nav-group::before {
  content: "";
  flex-shrink: 0;
  width: 1px;
  height: 18px;
  margin: 0 8px 4px; /* up a little: the links have more padding below the text than above */
  background: var(--border-strong);
}
.nav-user { display: flex; align-items: center; gap: 6px; white-space: nowrap; margin-left: auto; }

/* admin dropdown: a <details>, so it works without script */
.menu { position: relative; margin-right: 6px; }
.menu-button {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 0.93rem;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.menu-button::-webkit-details-marker { display: none; }
/* chevron */
.menu-button::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.15s;
}
.menu[open] .menu-button::after { transform: rotate(-135deg); margin-top: 3px; }
.menu-button:hover, .menu[open] .menu-button { background: var(--surface-2); }
.menu-button[aria-current="page"] { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.menu-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  width: 200px; /* the admin menu's; the recent and reminders panels set their own */
  max-width: calc(100vw - 32px);
  padding: 6px;
  display: grid;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.12), var(--shadow);
  white-space: normal;
}
.menu-panel a {
  display: grid;
  gap: 1px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
}
.menu-panel a strong { font-weight: 500; }
.menu-panel a:hover { background: var(--surface-2); color: var(--text); }
.menu-panel a[aria-current="page"] { background: var(--accent-soft); }
.menu-panel a[aria-current="page"] strong { color: var(--accent); }
.avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
}

@media (max-width: 600px) {
  .nav-username { display: none; }
}

/* page */

.page {
  max-width: 1880px;
  margin: 0 auto;
  padding: 24px 24px 48px;
  display: grid;
  /* minmax(0, ...): never wider than the page, whatever's in it (a wide table
     scrolls in its own box instead, see .table-scroll); likewise .card, .stack */
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}
.page-head { display: grid; gap: 4px; }
.back { font-size: 0.9rem; text-decoration: none; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  align-content: start;
}
.card-head { display: grid; gap: 2px; }
.card-flush { padding: 0; }
.card-danger { border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); }
.card-danger h2 { color: var(--danger); }

.grid-2 {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; }
@media (max-width: 860px) {
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
}

.form-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: end; }
.form-row label { flex: 1 1 180px; }
.form-row .check { flex: 0 0 auto; padding-bottom: 9px; }
.form-actions { display: flex; align-items: center; gap: 12px; }

.check { display: flex; gap: 10px; align-items: flex-start; font-weight: 500; }
.check-text { display: grid; gap: 1px; }
.check-text .muted { font-weight: 400; font-size: 0.87rem; }
.checks { display: grid; gap: 14px; }
.check:has(input:disabled) { opacity: 0.6; }

.section-title {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
  padding-top: 16px;
}

/* tables */

/* fixed layout: column widths come from the header (or a colgroup), never from the
   rows, so they don't jump when rows are filtered or change. Columns without a width
   share what's left equally; long text wraps instead of widening its column */
table { border-collapse: collapse; width: 100%; table-layout: fixed; }
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; overflow-wrap: anywhere; }
.col-check { width: 44px; }
.col-xs { width: 120px; }
.col-sm { width: 140px; }
.col-md { width: 180px; }
.col-lg { width: 220px; }
.col-xxl { width: 300px; }
.col-date { width: 120px; }
.col-name { width: 240px; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
th {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  background: var(--surface-2);
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: color-mix(in srgb, var(--surface-2) 60%, transparent); }
td a { font-weight: 400; text-decoration: none; }
.table-plain td { padding: 8px 0; }
.table-plain tbody tr:hover td { background: none; }
.table-plain td:last-child { text-align: right; }

.badge {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--surface-2);
  color: var(--text-muted);
  white-space: nowrap;
}
.badge-accent { background: var(--accent-soft); color: var(--accent); }
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-danger { background: var(--danger-soft); color: var(--danger); }
.badge-muted { background: transparent; border: 1px solid var(--border); }
/* an employee's pay check in the accounts list (views.accountCell) */
.pay-mark { margin-left: 2px; font-weight: 700; }
.pay-ok { color: var(--success); }
.pay-bad { color: var(--danger); }

/* tabs (TabFilter) */

.tabs { display: flex; flex-wrap: wrap; gap: 4px; }
.tabs button { padding: 5px 12px; border-color: transparent; background: transparent; color: var(--text-muted); }
.tabs button:hover { background: var(--surface-2); color: var(--text); }
.tabs button[aria-selected="true"] { background: var(--accent-soft); color: var(--accent); }
.card-flush > .tabs { padding: 12px 16px; border-bottom: 1px solid var(--border); }

/* tabs of a detail page (PageTabs), links to ?tab= */
.page-tabs { padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.tabs a { padding: 5px 12px; border-radius: var(--radius-sm); color: var(--text-muted); font-weight: 500; text-decoration: none; }
.tabs a:hover { background: var(--surface-2); color: var(--text); }
.tabs a[aria-current="page"] { background: var(--accent-soft); color: var(--accent); }

/* home tiles */

.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.tile {
  display: grid;
  gap: 2px;
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--text);
  text-decoration: none;
  align-content: start;
}
.tile:hover { border-color: var(--accent); color: var(--text); }
.tile strong { font-weight: 600; }

.empty { text-align: center; padding: 48px 20px; justify-items: center; }

/* show / hide parts of a form by a checkbox in it, without script */

form:not(:has(input[name="is_employee"]:checked)) .employee-fields,
form:not(:has(input[name="is_reminder"]:checked)) .reminder-fields,
form:not(:has(input[name="split_debit_credit"]:checked)) .split-only,
form:has(input[name="split_debit_credit"]:checked) .unsplit-only,
/* employee is for suppliers only: gone once the account form's type is customer */
form:has(input[name="type"][value="customer"]) .supplier-only { display: none; }

.stack-sm { display: grid; gap: 12px; }
.btn-small { padding: 3px 10px; font-size: 0.87rem; }
textarea { resize: vertical; width: 100%; }
fieldset { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: 16px; }

/* toolbar: tabs and a search box above a table */

.toolbar { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; justify-content: space-between; }
.card-flush > .toolbar { padding: 12px 16px; border-bottom: 1px solid var(--border); }
.toolbar input[type="search"] { flex: 0 1 260px; }

/* notes on an account */

.activity-list { display: grid; align-content: start; }
.activity {
  position: relative;
  display: grid;
  gap: 1px;
  padding: 5px 8px;
  border-bottom: 1px solid var(--border);
  font-size: 0.93rem;
  scroll-margin: 8px;
}
.activity:last-child { border-bottom: 0; }
.activity:hover { background: var(--surface-2); }
/* linked to directly, e.g. from a reminder */
.activity:target { background: var(--warning-soft); box-shadow: inset 3px 0 var(--warning); }
.activity-head { display: flex; flex-wrap: wrap; gap: 2px 8px; align-items: center; }
.activity-head a { text-decoration: none; }
.activity-head .badge { padding: 0 7px; font-size: 0.75rem; }
.activity-detail { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Done / Edit float at the top right, only while the note is hovered or focused */
.activity-actions {
  position: absolute;
  top: 4px;
  right: 6px;
  display: flex;
  gap: 4px;
  padding: 2px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s;
}
.activity:hover .activity-actions,
.activity:focus-within .activity-actions { opacity: 1; pointer-events: auto; }
.activity-actions:empty { display: none; }
.activity-actions .btn-small { padding: 1px 8px; font-size: 0.8rem; }
.activity-actions form:not(.activity-edit form) { display: contents; }
.activity-edit > summary { display: inline-block; list-style: none; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); }
.activity-edit > summary::-webkit-details-marker { display: none; }
/* while editing, the actions drop into the note so the form has room */
.activity:has(.activity-edit[open]) .activity-actions { position: static; flex-wrap: wrap; padding: 4px 0 0; background: none; opacity: 1; pointer-events: auto; }
.activity-edit[open] { flex: 1 1 100%; }
.activity-edit[open] > summary { margin-bottom: 8px; background: var(--surface-2); }
/* no hover on touch screens, so the actions always show there */
/* buttons on a table row (e.g. Duplicate), showing while it's hovered */
.row-actions { float: right; margin-left: 8px; opacity: 0; }
tr:hover .row-actions, .row-actions:focus-within { opacity: 1; }
.row-actions .btn-small {
  display: inline-block;
  padding: 1px 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: 0.8rem;
}
.row-actions .btn-small:hover { background: var(--surface-2); }
.form-actions a.btn-small {
  padding: 3px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
}
.form-actions a.btn-small:hover { background: var(--surface-2); }

@media (hover: none) {
  .row-actions { opacity: 1; }
  .activity-actions { position: static; justify-self: start; padding: 2px 0 0; background: none; opacity: 1; pointer-events: auto; }
}

/* reminders bell in the header */

.icon-button { position: relative; padding: 6px 8px; }
.icon-button::after { display: none; }
.bell-count {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}
.reminders .menu-panel { width: 340px; max-height: 70vh; overflow-y: auto; }
.menu-title { padding: 6px 10px 4px; font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
.menu-empty { padding: 6px 10px 10px; }
.reminder-detail { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.overdue { color: var(--danger); font-weight: 500; }

/* long lists and tables grow with the page, which is the only thing that scrolls
   (no boxes scrolling inside it); a table's head sticks under the app header
   (--app-header-h, kept by static/filters.js) so its columns stay labelled.
   Nothing above a table may set overflow, or the head stops sticking. */

thead th, .recon-head {
  position: sticky;
  top: var(--app-header-h, 0px);
  z-index: 2;
  /* collapsed borders don't move with a stuck head, so its line is a shadow */
  box-shadow: inset 0 -1px var(--border);
}
/* a table that can be wider than the page (Table.Scroll) scrolls sideways in
   its own box, not the page. A box that scrolls can't let its head stick under
   the app header, so this table's head doesn't. .frozen columns, the first
   ones, stay put; the second's left is the first's width (.col-xxl). */
.table-scroll { overflow-x: auto; }
.table-scroll thead th { position: static; }
/* top: auto, or a frozen head keeps the app header's offset (thead th) and
   drops below its row; heads above the rows' frozen cells */
.table-scroll .frozen { position: sticky; left: 0; top: auto; z-index: 1; }
.table-scroll th.frozen { z-index: 2; }
.table-scroll .frozen + .frozen { left: 300px; box-shadow: inset -1px 0 var(--border); }
.table-scroll th.frozen + .frozen { box-shadow: inset 0 -1px var(--border), inset -1px 0 var(--border); }
.table-scroll td.frozen { background: var(--surface); }
.table-scroll tbody tr:hover td.frozen { background: color-mix(in srgb, var(--surface-2) 60%, var(--surface)); }

/* a table that starts its card keeps the card's rounded corners */
.card > table:first-child th:first-child { border-top-left-radius: var(--radius); }
.card > table:first-child th:last-child { border-top-right-radius: var(--radius); }

/* search in the header */

.app-search { position: relative; flex: 1 1 220px; max-width: 440px; margin-left: auto; }
.app-search input {
  width: 100%;
  padding: 6px 10px 6px 32px;
  background: var(--surface-2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235e6878' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E") no-repeat 10px center;
}
.app-search input:focus { background-color: var(--surface); }
.search-panel {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  min-width: min(380px, calc(100vw - 32px));
  max-height: 70vh;
  overflow-y: auto;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.12), var(--shadow);
}
.search-result {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
}
.search-result:hover, .search-result:focus { background: var(--surface-2); color: var(--text); outline: none; }
.search-result:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); }
.search-result-main { flex: 1; min-width: 0; display: grid; }
.search-result-main strong { font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-result-main .muted { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-more { padding: 2px 10px 6px; }

/* recent pages menu */

.recent-panel { width: 320px; max-height: 70vh; overflow-y: auto; }
.menu-footer { display: flex; justify-content: flex-end; padding: 4px 4px 0; border-top: 1px solid var(--border); margin-top: 4px; }

/* date picker (static/datepicker.js) */

input[data-datepicker] {
  padding-right: 32px;
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235e6878' stroke-width='2' stroke-linecap='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E") no-repeat right 10px center;
}
.datepicker {
  position: absolute;
  z-index: 50;
  width: 272px;
  padding: 10px;
  display: grid;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.14), var(--shadow);
  font-size: 0.9rem;
}
.datepicker[hidden] { display: none; }
.dp-head { display: flex; align-items: center; gap: 2px; }
.dp-title { flex: 1; text-align: center; font-weight: 600; }
.dp-nav, .dp-day, .dp-link { border-color: transparent; background: transparent; }
.dp-nav { padding: 2px 8px; color: var(--text-muted); }
.dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-dow { text-align: center; font-size: 0.75rem; font-weight: 600; color: var(--text-muted); padding: 2px 0; }
.dp-day { padding: 0; height: 32px; border-radius: var(--radius-sm); font-variant-numeric: tabular-nums; }
.dp-day:hover { background: var(--surface-2); }
.dp-other { color: var(--text-muted); opacity: 0.6; }
.dp-day[aria-current="date"] { box-shadow: inset 0 0 0 1px var(--accent); color: var(--accent); font-weight: 600; }
.dp-day.dp-active { background: var(--surface-2); }
.dp-day[aria-pressed="true"] { background: var(--accent); color: var(--accent-text); opacity: 1; }
.dp-day:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.dp-foot { display: flex; justify-content: space-between; border-top: 1px solid var(--border); padding-top: 6px; }
.dp-link { padding: 3px 8px; color: var(--accent); font-size: 0.87rem; }
.dp-link:hover { background: var(--accent-soft); }

/* login */

.login {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 16px;
}
.login .card { width: 100%; max-width: 380px; padding: 28px; gap: 20px; }
.login .brand { justify-content: center; font-size: 1.1rem; }
.login form { display: grid; gap: 14px; }
.login button[type="submit"] { width: 100%; padding: 10px; }

/* filtered tables (views.FilterTable, static/filters.js) */

.filter-table { display: block; }
/* the accounts list's heads stay on one line, cut short if they don't fit */
#accounts-filters th { white-space: nowrap; overflow-wrap: normal; overflow: hidden; text-overflow: ellipsis; }
th .th-label { vertical-align: middle; }
.col-filter { display: inline-block; vertical-align: middle; margin-left: 4px; }
.col-filter > summary {
  list-style: none;
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0.55;
}
.col-filter > summary::-webkit-details-marker { display: none; }
.col-filter > summary:hover, .col-filter[open] > summary { background: var(--surface-2); opacity: 1; }
/* lit while the filter is set: a typed value, or a picked option other than All */
.col-filter:has(input:not([type="hidden"], .ss-panel input):not(:placeholder-shown), select option:checked:not([value=""]), .search-select input[type="hidden"]:not([value=""])) > summary {
  background: var(--accent-soft);
  color: var(--accent);
  opacity: 1;
}
/* fixed, placed by filters.js, so nothing around the table clips it */
.col-filter-panel {
  position: fixed;
  z-index: 40;
  width: 240px;
  padding: 12px;
  display: grid;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.93rem;
  font-weight: 400;
  color: var(--text);
}
.col-filter-panel > button { justify-self: start; }
/* the sort, above the table */
.table-sort {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border);
}
/* a value edited in its cell (views.CustomFieldCell): looks like text until
   hovered or focused, and flashes green once saved */
input.cell-input { width: calc(100% + 14px); padding: 3px 6px; margin: -4px -7px; border-color: transparent; background: transparent; }
input.cell-input:hover { border-color: var(--border); }
input.cell-input:focus { border-color: var(--border-strong); background: var(--surface); }
input.cell-input.saved { animation: cell-saved 1.2s ease-out; }
@keyframes cell-saved { from { background: var(--success-soft); border-color: var(--success); } }

/* Delete selected (Table.WithBulkDelete), on the left, while any row is ticked */
.table-sort .bulk-delete { display: none; margin-right: auto; }
.filter-table:has(tbody input[name="ids"]:checked) .bulk-delete { display: inline-block; }
/* Change dates (views.bulkDates), shown like Delete selected, before it */
.table-sort .bulk-dates { display: none; position: relative; }
.filter-table:has(tbody input[name="ids"]:checked) .bulk-dates { display: inline-block; }
.bulk-dates > summary { display: inline-block; list-style: none; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); font-weight: 500; }
.bulk-dates > summary:hover, .bulk-dates[open] > summary { background: var(--surface-2); }
.bulk-dates > summary::-webkit-details-marker { display: none; }
.bulk-dates-panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  display: grid;
  gap: 10px;
  width: 260px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.bulk-dates-panel label { font-size: 0.87rem; }
.bulk-dates-panel input { width: 100%; min-width: 0; }
.bulk-dates-panel > button { justify-self: start; }
.col-check input { margin: 0; }
.table-sort .sort-by { display: flex; align-items: center; gap: 8px; font-weight: 500; color: var(--text-muted); }
.table-sort select { padding: 3px 8px; font-size: inherit; color: var(--text); }
/* the direction: a checkbox (sort_desc) dressed as an arrow button */
.sort-dir {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.sort-dir:hover { background: var(--surface-2); }
.sort-dir input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.sort-dir:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.sort-dir svg { grid-area: 1 / 1; }
.sort-dir input:checked ~ .sort-asc, .sort-dir input:not(:checked) ~ .sort-desc { display: none; }
.table-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
  padding: 10px 16px;
  border-top: 1px solid var(--border);
}
.table-foot [data-filter-clear-all] { margin-left: auto; }

/* search select (views.SearchSelect): a <select> with a search box */

.search-select { position: relative; }
.search-select > summary {
  list-style: none;
  padding: 8px 32px 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface) 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='%235e6878' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 10px center;
  font-weight: 400;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-select > summary::-webkit-details-marker { display: none; }
.search-select > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ss-panel {
  position: absolute;
  z-index: 45;
  top: calc(100% + 4px);
  left: 0;
  min-width: 100%;
  width: max-content;
  max-width: min(360px, calc(100vw - 32px));
  padding: 6px;
  display: grid;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.ss-options { display: grid; max-height: 260px; overflow-y: auto; }
.ss-options > button {
  border: 0;
  background: transparent;
  text-align: left;
  font-weight: 400;
  padding: 6px 8px;
  white-space: normal;
}
.ss-options > button:hover, .ss-options > button:focus-visible { background: var(--surface-2); }
.ss-options > button[aria-selected="true"] { color: var(--accent); font-weight: 600; }
.ss-options > button[hidden] { display: none; }
/* a disabled fieldset doesn't disable a <details>, so read-only forms stop it here */
fieldset:disabled .search-select { pointer-events: none; }
fieldset:disabled .search-select > summary { opacity: 0.6; }

/* a card made of parts that each start with a toolbar and end with a table
   (e.g. an account's invoices tab); no overflow, so dropdowns in it aren't clipped */
.card-section { padding: 0; gap: 0; }
.section-part + .section-part { border-top: 1px solid var(--border); }
.card-section .toolbar { padding: 12px 16px; border-bottom: 1px solid var(--border); }
.add-panel { position: relative; }
.add-panel > summary { list-style: none; }
.add-panel > summary::-webkit-details-marker { display: none; }
.add-panel-body {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 30;
  width: min(640px, calc(100vw - 32px));
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* the day of the month only matters for monthly repeating ones */
.repeating-when:not(:has(input[name="frequency"][value="monthly"])) .monthly-only { display: none; }

/* employee pay check on an account's Details tab (PayCheckStatus) */
.pay-check { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 0; }

/* messages and links that look like buttons */
.callout-danger {
  background: var(--danger-soft);
  border-color: color-mix(in srgb, var(--danger) 35%, transparent);
}
a.btn-link {
  display: inline-block;
  padding: 8px 14px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  font-weight: 500;
  text-decoration: none;
}
a.btn-link.btn-primary:hover { color: var(--accent-text); }
.inline-label { display: flex; align-items: center; gap: 8px; font-weight: 500; color: var(--text-muted); }
.inline-label select { padding: 4px 8px; color: var(--text); }
.section-label {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.money-in { color: var(--success); }
.money-out { color: var(--text); }
tr.row-danger td { background: var(--danger-soft); }

/* pieces editor (views.PiecesEditor, static/splits.js): a row per piece */
.pieces { display: grid; gap: 6px; }
.piece-list { display: grid; gap: 6px; }
.piece {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.2fr) 130px 32px;
  gap: 8px;
  align-items: center;
  scroll-margin: 80px;
}
.piece-head { font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.75rem; }
.piece input[name="piece_amount"] { width: 100%; text-align: right; font-variant-numeric: tabular-nums; }
.piece-rest { background: var(--surface-2) !important; color: var(--text-muted); }
.piece-rest.piece-bad { background: var(--danger-soft) !important; color: var(--danger); }
.piece:target, .piece-row:target td { background: var(--warning-soft); box-shadow: inset 3px 0 var(--warning); }
.piece-remove { padding: 2px 8px; font-size: 1.1rem; line-height: 1; }
.piece-foot { display: flex; align-items: center; gap: 12px; }
.piece-msg { color: var(--danger); }
.piece-template { display: none; }

/* a form's warning about a bank account whose statements are imported, shown by
   a <style> the form brings (views.TransactionForm.importWarningCSS) */
.import-bank-warning { display: none; }

/* "save as a rule" fields, shown once it's ticked */
.rule-save { display: grid; gap: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.rule-save:not(:has(input[name="save_rule"]:checked)) .rule-fields { display: none; }

/* reconcile: the card */
.recon-card { max-width: 980px; }
.recon-summary { display: grid; gap: 2px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.recon-desc { font-size: 1.25rem; font-weight: 600; overflow-wrap: anywhere; }
.recon-amount { font-size: 1.5rem; font-weight: 650; font-variant-numeric: tabular-nums; }

/* reconcile: the table, a form per row */
.recon-grid { display: grid; }
.recon-row {
  display: grid;
  grid-template-columns: 28px 100px minmax(160px, 1fr) 120px minmax(420px, 2fr) 70px;
  gap: 10px;
  align-items: start;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
}
.recon-row:last-child { border-bottom: 0; }
.recon-row:hover { background: color-mix(in srgb, var(--surface-2) 60%, transparent); }
.recon-row > span:first-child, .recon-row > span:nth-child(2), .recon-row > .num { padding-top: 8px; }
.recon-head { background: var(--surface-2); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.75rem; }
.recon-head > span { padding-top: 0 !important; }
.recon-row-desc { display: grid; gap: 2px; padding-top: 8px; overflow-wrap: anywhere; }
.recon-row-desc .badge { justify-self: start; text-decoration: none; }
.recon-row .piece-head { display: none; }
.recon-row .piece { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 110px 28px; }
.recon-rule { margin-top: 6px; }
.recon-rule > summary { color: var(--accent); }
.recon-rule .rule-save { border-top: 0; padding-top: 8px; }

/* a count on a nav link, e.g. transactions left to reconcile */
.nav-count {
  display: inline-block;
  min-width: 18px;
  margin-left: 4px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--warning-soft);
  color: var(--warning);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}
.nav-count:empty { display: none; }

/* a checkbox as an on / off switch, e.g. the reconcile table's "found by rules" */
.switch { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; cursor: pointer; }
.switch input {
  appearance: none;
  position: relative;
  width: 34px;
  height: 20px;
  margin: 0;
  border-radius: 999px;
  background: var(--border-strong);
  cursor: pointer;
  transition: background 0.15s;
}
.switch input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.15s;
}
.switch input:checked { background: var(--accent); }
.switch input:checked::after { transform: translateX(14px); }
.recon-head .col-filter-panel { font-size: 0.93rem; }

/* narrower screens: a row's pieces drop under its description rather than
   pushing the table wider than the page */
@media (max-width: 1180px) {
  .recon-row { grid-template-columns: 28px 100px minmax(0, 1fr) 120px 70px; }
  .recon-row > :nth-last-child(2) { grid-column: 2 / -1; grid-row: 2; }
  .recon-head > :nth-last-child(2) { display: none; }
}

/* reconcile: the Transfers tab (views.TransfersTab), a form per transfer piece */
.transfer-row { grid-template-columns: 100px minmax(160px, 1fr) 120px minmax(380px, 1.6fr) 90px; scroll-margin: 80px; }
.transfer-row:target { background: var(--warning-soft); box-shadow: inset 3px 0 var(--warning); }
.transfer-match { display: grid; gap: 6px; }
.transfer-cand { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.transfer-cand-text { overflow-wrap: anywhere; }
.transfer-cand-text .badge { margin-left: 4px; }
.transfer-search { display: flex; align-items: center; gap: 8px; }
.transfer-search .search-select { flex: 1 1 auto; min-width: 0; }
@media (max-width: 1180px) {
  .transfer-row { grid-template-columns: 100px minmax(0, 1fr) 120px 90px; }
  .transfer-row > :nth-last-child(2) { grid-column: 1 / -1; grid-row: 2; }
}

/* a choice of one as joined buttons, e.g. the Transfers tab's Not matched / Matched / All */
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.seg label { display: flex; margin: 0; cursor: pointer; }
.seg input { position: absolute; opacity: 0; pointer-events: none; }
.seg span { padding: 4px 12px; font-weight: 500; color: var(--text-muted); }
.seg label + label span { border-left: 1px solid var(--border); }
.seg input:checked + span { background: var(--accent-soft); color: var(--accent); }
.seg input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: -2px; }

/* a badge on a page tab, e.g. an account's balance on its Statement tab */
.tab-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.78rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tabs a[aria-current="page"] .tab-badge { background: var(--surface); color: var(--accent); }
.tab-badge:empty { display: none; }
/* a count of things to do, e.g. transfers not matched yet */
.tab-badge-warning, .tabs a[aria-current="page"] .tab-badge-warning { background: var(--warning-soft); color: var(--warning); }

/* account statements (StatementTab, Reports > Statements) */
.statement-options { flex: 1 1 auto; }
.statement-options label:not(.check) { flex: 0 1 170px; }
.statement-options label:has(.search-select) { flex: 0 1 260px; }
.statement { display: grid; gap: 16px; padding: 16px; }
.statement-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 32px; }
.statement-facts { display: flex; flex-wrap: wrap; gap: 8px 32px; margin: 0 0 0 auto; }
.statement-facts div { display: grid; gap: 0; text-align: right; }
.statement-facts dt { font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
.statement-facts dd { margin: 0; font-variant-numeric: tabular-nums; }
.statement-facts strong { font-size: 1.15rem; }
.statement-summary {
  display: grid;
  gap: 4px;
  max-width: 520px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.statement-summary .table-plain td { padding: 4px 0; border-bottom: 0; }
.statement-table { border: 1px solid var(--border); border-radius: var(--radius); }
.statement-opening td { color: var(--text-muted); font-style: italic; }
.statement-total td { font-weight: 650; border-top: 2px solid var(--border-strong); }
#statements-preview > table { border-top: 0; }

/* Reports > Statements: one account, or a group */
.statement-who:not(:has(input[name="who"][value="group"]:checked)) .who-group,
.statement-who:has(input[name="who"][value="group"]:checked) .who-account { display: none; }
.statement-who .form-row label:not(.check) { flex: 0 1 320px; }

/* the reports, as cards */
.report-tiles { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.report-tiles .tile { padding: 20px; min-height: 110px; }
.report-tiles .tile strong { font-size: 1.05rem; }

/* a modal dialog, e.g. DownloadWarning */
.dialog {
  max-width: 460px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgb(16 24 40 / 0.18);
  color: var(--text);
}
.dialog::backdrop { background: rgb(16 24 40 / 0.4); }
.dialog-actions { justify-content: flex-end; }

/* balances: negative red, positive green (amountClass) */
.amount-neg { color: var(--danger); }
.amount-pos { color: var(--success); }
a.amount-neg:hover, a.amount-pos:hover { text-decoration: underline; }

/* a row of figures (statTile), the main one larger */
.stat-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.stat-tile {
  display: grid;
  gap: 2px;
  align-content: start;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.stat-label { font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); }
.stat-value { font-size: 1.3rem; font-weight: 650; font-variant-numeric: tabular-nums; }
.stat-tile-main { background: var(--surface); border-color: var(--border-strong); box-shadow: var(--shadow); }
.stat-tile-main .stat-value { font-size: 1.6rem; }

/* pick-many dropdown (views.SearchMultiSelect, static/multiselect.js) */
.ss-check { display: flex; gap: 8px; align-items: flex-start; padding: 6px 8px; font-weight: 400; border-radius: var(--radius-sm); cursor: pointer; }
.ss-check:hover { background: var(--surface-2); }
.ss-check[hidden] { display: none; }
.ss-check:has(input:checked) { color: var(--accent); font-weight: 600; }
.ss-foot { display: flex; justify-content: space-between; gap: 8px; padding-top: 6px; border-top: 1px solid var(--border); }

/* Reports > What can I expect */
.expect-options .expect-pick { flex: 1 1 260px; }
.expect-options .expect-day { flex: 0 1 130px; }
.expect-options .expect-full { flex: 0 0 auto; padding-bottom: 9px; }
/* the day pickers, off while Full months is on */
.expect-days { display: contents; }
.expect-days:disabled .expect-day { opacity: 0.5; pointer-events: none; }
.expect-options .expect-months { flex: 0 1 150px; }
.expect-summary .stat-tiles { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.expect-table td .muted { display: block; }
#sub-balances td .muted { margin-left: 6px; }
/* each month's net as a bar either side of the middle */
.net-bar { position: relative; display: block; height: 10px; border-radius: 999px; background: var(--surface-2); }
.net-bar::after { content: ""; position: absolute; left: 50%; top: -3px; bottom: -3px; width: 1px; background: var(--border-strong); }
.net-bar-fill { position: absolute; top: 0; bottom: 0; border-radius: 999px; background: currentColor; opacity: 0.75; }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* the cash flow sheet (views.CashFlowPage) */
/* the header button: spaced like the menus beside it (.menu) */
a.header-link { margin-right: 6px; color: var(--text); text-decoration: none; }
a.header-link .bell-count:empty { display: none; }
.cf-top { display: grid; grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); gap: 20px; align-items: start; }
@media (max-width: 860px) { .cf-top { grid-template-columns: minmax(0, 1fr); } }
/* a bank left out of the total */
.cf-bank:has(td:first-child input:not(:checked)) td:not(:first-child) { opacity: 0.45; }
.cf-age { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); }
.cf-dot { width: 8px; height: 8px; border-radius: 999px; background: currentColor; }
.cf-age-today .cf-dot { color: var(--success); }
.cf-age-recent .cf-dot { color: #d99a06; }
.cf-age-old { color: var(--danger); }
.cf-totals { gap: 10px; }
.cf-total { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.cf-missing { padding: 10px 12px; margin: 0 -12px; border-radius: var(--radius-sm); background: var(--success-soft); color: var(--success); font-size: 1.1rem; }
.cf-missing.cf-short { background: var(--danger-soft); color: var(--danger); }
.cf-missing strong { font-size: 1.3rem; }
.cf-warn { padding: 6px 10px; border-radius: var(--radius-sm); background: var(--danger-soft); color: var(--danger); }
.cf-sort { padding: 0; border: 0; }
.cf-col-day { width: 60px; }
.cf-col-month { width: 150px; }
.cf-col-tick { width: 84px; text-align: center; }
.cf-col-tick input { margin: 0; }
.cf-col-actions { width: 120px; text-align: right; white-space: nowrap; }
.cf-month { display: flex; align-items: center; gap: 2px; }
.cf-month select { flex: 1; min-width: 0; padding: 3px 4px; }
.cf-month .btn-small { padding: 1px 6px; }
/* a row is tinted by its month: gone, this one or later (views.monthState) */
.cf-row:has(> .cf-month-overdue) > td { background: color-mix(in srgb, var(--danger-soft) 80%, var(--surface)); }
.cf-row:has(> .cf-month-current) > td { background: var(--surface-2); }
.cf-row:has(> .cf-month-ahead) > td { background: var(--success-soft); }
/* no amount yet: find out what it is */
.cf-items td.cf-no-amount { background: var(--danger-soft); box-shadow: inset 0 0 0 1px var(--danger); }
.cf-items td.cf-no-amount input::placeholder { color: var(--danger); font-weight: 700; }
.cf-items tfoot td { padding-top: 10px; padding-bottom: 10px; border-top: 1px solid var(--border-strong); background: var(--surface); }
.cf-items tfoot input:not([type="checkbox"]) { width: 100%; padding: 4px 6px; }

/* the weekly hours tool on an employee's Details tab (views.HoursTool) */
.hours-tool > summary { display: inline-block; list-style: none; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); }
.hours-tool > summary::-webkit-details-marker { display: none; }
.hours-tool[open] > summary { background: var(--surface-2); }
.hours-body { display: grid; gap: 10px; margin-top: 10px; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2); max-width: 720px; }
.hours-rows { display: grid; gap: 6px; }
.hours-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.hours-row select { flex: 0 0 120px; padding: 4px 6px; }
.hours-row input { padding: 4px 6px; }
.hours-row-total { min-width: 120px; }
.hours-warn { color: var(--danger); }

/* admins' status box in the header (AdminStatus): users and backups, red when
   backups have a problem */
.admin-status .menu-button { gap: 5px; font-variant-numeric: tabular-nums; }
/* fixed widths, so the header doesn't move when a value changes: the users fit
   "99/999", the backup the longest summary ("Backup failed", "No backup yet") */
.admin-status-users, .admin-status-backup { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-status-users { width: 6ch; text-align: center; }
.admin-status-backup { width: 8.2em; }
.admin-status-sep { width: 1px; height: 14px; margin: 0 3px; background: var(--border-strong); }
.admin-status-problem .menu-button { color: var(--danger); border-color: var(--danger); background: var(--danger-soft); }
.admin-status-panel { width: 320px; padding: 6px 6px 10px; }
.admin-status-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 10px 0; }
.admin-status-actions a { display: inline; padding: 0; }
.admin-status-actions a:hover { background: none; text-decoration: underline; }
.status-lines { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; margin: 0; padding: 4px 10px; font-size: 0.9rem; }
.status-lines dt { color: var(--text-muted); }
.status-lines dd { margin: 0; overflow-wrap: anywhere; }
.backup-runs-head { display: grid; gap: 8px; padding: 16px; border-bottom: 1px solid var(--border); }
.backup-runs-head h2 { margin: 0; }
.backup-runs-head .status-lines { padding: 0; justify-self: start; }
@media (max-width: 900px) {
  .admin-status-users, .admin-status-backup { display: none; }
}

/* the demo build (views.DemoBanner, views.DemoChecklist) */

.demo-banner {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 10px;
  padding: 5px 16px;
  background: var(--warning-soft);
  border-bottom: 1px solid #f3d89b;
  color: var(--warning);
  font-size: 0.85rem;
  text-align: center;
}
.login form#demo-reset, .demo-reset-done { display: grid; gap: 14px; }
.demo-reset-done h1, .demo-reset-done p { margin: 0; }
.demo-reset-done code { font-size: 1rem; user-select: all; }
.demo-reset-login { text-align: center; }

/* bottom right, over the page; its panel opens above the button */
.demo-checklist {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 40;
}
.demo-checklist-button {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  width: max-content;
  padding: 8px 14px;
  list-style: none;
  cursor: pointer;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: 999px;
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.18), var(--shadow);
  font-weight: 600;
  font-size: 0.9rem;
}
.demo-checklist-button::-webkit-details-marker { display: none; }
.demo-checklist-button:hover { background: var(--accent-hover); }
/* the button says what it does: show when hidden, hide when open */
.demo-checklist-hide { display: none; }
.demo-checklist[open] .demo-checklist-show { display: none; }
.demo-checklist[open] .demo-checklist-hide { display: inline; }
.demo-chevron { transition: transform 0.15s; }
.demo-checklist[open] .demo-chevron { transform: rotate(180deg); }
.demo-checklist-count {
  padding: 0 7px;
  background: rgb(255 255 255 / 0.2);
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
/* the one box that scrolls on its own: it floats over the page, so it can't
   grow with it */
.demo-checklist-panel {
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  width: 360px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - var(--app-header-h, 0px) - 90px);
  overflow-y: auto;
  padding: 6px 14px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgb(16 24 40 / 0.12), var(--shadow);
}
.demo-checklist-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.demo-checklist-head .btn-ghost { display: inline-flex; align-items: center; gap: 4px; }
.demo-checklist-panel .menu-title { padding-left: 0; }
.demo-checklist-note { margin: 0 0 4px; }
.demo-checklist-panel h3 { margin: 14px 0 6px; font-size: 0.88rem; }
.demo-progress { height: 6px; margin: 4px 0 8px; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.demo-progress span { display: block; height: 100%; background: var(--success); }
.demo-tasks { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.demo-tasks li { display: flex; gap: 8px; align-items: flex-start; font-size: 0.88rem; line-height: 1.4; }
.demo-tick {
  flex: none;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  border: 1.5px solid var(--border-strong);
  border-radius: 5px;
  font-size: 0.75rem;
  font-weight: 700;
}
.demo-tasks li.done .demo-tick { background: var(--success); border-color: var(--success); color: #fff; }
.demo-tasks li.done .demo-task > a:first-child { color: var(--text-muted); text-decoration: line-through; }
.demo-tasks li.by-others .demo-tick { background: var(--surface-2); border-color: var(--border-strong); color: var(--text-muted); }
.demo-by-others { display: block; }
.demo-file { display: block; margin-top: 2px; overflow-wrap: anywhere; }

/* wide screens: open, it's a column down the right and the page makes room for
   it, so it covers nothing; the button stays at its foot. Narrower, it floats
   over the page, and a click outside it hides it (static/demo.js). Keep the
   width in step with DOCKED in demo.js */
@media (min-width: 1200px) {
  body:has(#demo-checklist[open]) { padding-right: 380px; }
  .demo-checklist[open] .demo-checklist-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 380px;
    max-width: none;
    max-height: none;
    padding-bottom: 72px;
    border-width: 0 0 0 1px;
    border-radius: 0;
    box-shadow: none;
  }
}
