/* ============================================================================
   Invoicing — design system

   Reference points: a ledger book and a precision instrument. Hairline rules
   instead of drop shadows, tabular figures on every number, dense rows that
   respect an accountant's screen, one confident accent instead of a gradient.
   ========================================================================= */

/* ------------------------------------------------------------------ reset */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  tab-size: 4;
}

body {
  min-height: 100vh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video, canvas { display: block; max-width: 100%; }

input, button, textarea, select { font: inherit; color: inherit; }

button { background: none; border: none; cursor: pointer; }

a { color: inherit; }

h1, h2, h3, h4 { font-weight: 600; line-height: 1.25; text-wrap: balance; }

/* ----------------------------------------------------------------- tokens */

:root {
  /* Warm paper neutrals — a plain white ground reads as unfinished next to
     the ink and green used elsewhere. */
  --paper:        #fbfaf7;
  --surface:      #ffffff;
  --surface-sunk: #f4f2ed;
  --surface-hover:#f7f5f1;

  --ink:          #1a1917;
  --ink-2:        #4a4741;
  --ink-3:        #7a756c;
  --ink-4:        #a8a299;
  /* Small labels: the faintest grey by light; by dark that grey reads
     under 4.5:1, so they take the next one up (ink-4 stays for lines). */
  --ink-label:    var(--ink-4);

  --line:         #e5e1d8;
  --line-strong:  #d2cdc1;

  /* Bottle green: the ledger accent. Reserved for primary actions and the
     active navigation state so it keeps its meaning. */
  --accent:       #0e5240;
  --accent-hover: #0a4133;
  --accent-soft:  #e6efeb;
  --accent-line:  #b9d2c9;

  --positive:     #14663f;
  --positive-soft:#e4f0e9;
  --positive-line:#b5d5c4;

  --warning:      #8a5a09;
  --warning-soft: #fbf1de;
  --warning-line: #e8d3a6;

  --danger:       #93251f;
  --danger-soft:  #f9e9e7;
  --danger-line:  #e6bdb8;

  --overdue:      #c2410c;

  --neutral:      #5c5850;
  --neutral-soft: #efece6;
  --neutral-line: #dcd7cd;

  --focus:        #0e5240;

  /* Type */
  --font-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --font-num: ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Mono",
              "Roboto Mono", Menlo, Consolas, monospace;

  --t-11: 0.6875rem;
  --t-12: 0.75rem;
  --t-13: 0.8125rem;
  --t-14: 0.875rem;
  --t-16: 1rem;
  --t-20: 1.25rem;
  --t-26: 1.625rem;
  --t-32: 2rem;

  /* Space — 4px base */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 20px; --s-6: 24px; --s-8: 32px; --s-10: 40px; --s-12: 48px;
  /* One height for every field and every full-size button, so a row of
     them lines up top and bottom; a finger gets a little more. */
  --field-h: 34px;

  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 10px;

  --sidebar-w: 236px;
  --content-max: 1680px;
  --header-h: 56px;

  --speed: 120ms;
  --ease: cubic-bezier(0.2, 0, 0.1, 1);

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --paper:        #131311;
    --surface:      #1a1a17;
    --surface-sunk: #101010;
    --surface-hover:#22221e;

    --ink:          #eceae4;
    --ink-2:        #b8b4ab;
    --ink-3:        #8a857b;
    --ink-4:        #625e56;
    --ink-label:    var(--ink-3);

    --line:         #2c2b27;
    --line-strong:  #3d3b35;

    --accent:       #4bbf95;
    --accent-hover: #63d0a8;
    --accent-soft:  #15271f;
    --accent-line:  #23473a;

    --positive:     #5ec18d;
    --positive-soft:#152418;
    --positive-line:#25422f;

    --warning:      #d9a441;
    --warning-soft: #29200e;
    --warning-line: #4a3a18;

    --danger:       #e07a70;
    --danger-soft:  #2b1614;
    --danger-line:  #4d2723;
  --overdue:      #f0883e;
    --overdue:      #f0883e;

    --neutral:      #9d988e;
    --neutral-soft: #212120;
    --neutral-line: #35342f;

    --focus:        #4bbf95;
  }
}

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

  --paper:        #131311;
  --surface:      #1a1a17;
  --surface-sunk: #101010;
  --surface-hover:#22221e;

  --ink:          #eceae4;
  --ink-2:        #b8b4ab;
  --ink-3:        #8a857b;
  --ink-4:        #625e56;
  --ink-label:    var(--ink-3);

  --line:         #2c2b27;
  --line-strong:  #3d3b35;

  --accent:       #4bbf95;
  --accent-hover: #63d0a8;
  --accent-soft:  #15271f;
  --accent-line:  #23473a;

  --positive:     #5ec18d;
  --positive-soft:#152418;
  --positive-line:#25422f;

  --warning:      #d9a441;
  --warning-soft: #29200e;
  --warning-line: #4a3a18;

  --danger:       #e07a70;
  --danger-soft:  #2b1614;
  --danger-line:  #4d2723;

  --neutral:      #9d988e;
  --neutral-soft: #212120;
  --neutral-line: #35342f;

  --focus:        #4bbf95;
}

body {
  font-family: var(--font-ui);
  font-size: var(--t-14);
  background: var(--paper);
  color: var(--ink);
}

/* Every figure in this application is money, a count or a date: align them. */
.num, td.num, th.num, .money {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

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

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

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
}

.sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--line);
  overflow-y: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  height: var(--header-h);
  padding: 0 var(--s-4);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  text-decoration: none;
}

.brand__mark {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: var(--t-12);
  letter-spacing: -0.02em;
  flex-shrink: 0;
}

.brand__name {
  font-weight: 600;
  font-size: var(--t-13);
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Organization switcher — an accountant lives in this control. */
.org-switch {
  padding: var(--s-3) var(--s-3) var(--s-2);
  border-bottom: 1px solid var(--line);
}

.org-switch__label {
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-label);
  font-weight: 600;
  padding: 0 var(--s-2) var(--s-1);
}

.nav {
  padding: var(--s-3) var(--s-2);
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
}

.nav__section {
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-label);
  font-weight: 600;
  padding: var(--s-4) var(--s-2) var(--s-1);
}

/* A menu section folds from its title; the chevron turns with it. */
.nav__group > .nav__item + .nav__item { margin-top: 1px; }
.nav__group > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  list-style: none;
  cursor: pointer;
  border-radius: var(--r-sm);
  user-select: none;
  transition: color var(--speed) var(--ease);
}
.nav__group > summary::-webkit-details-marker { display: none; }
.nav__group > summary::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-right: 4px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--speed) var(--ease);
  opacity: 0.7;
}
.nav__group[open] > summary::after { transform: rotate(45deg); }
.nav__group > summary:hover { color: var(--ink); }
.nav__group > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.nav__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 7px var(--s-2);
  border-radius: var(--r-sm);
  color: var(--ink-2);
  text-decoration: none;
  font-size: var(--t-13);
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
}

.nav__item:hover { background: var(--surface-hover); color: var(--ink); }

.nav__item[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.nav__item svg { width: 16px; height: 16px; flex-shrink: 0; opacity: 0.85; }

.nav__badge {
  margin-left: auto;
  font-size: var(--t-11);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  background: var(--surface-sunk);
  padding: 1px 6px;
  border-radius: 20px;
}

.nav__item[aria-current="page"] .nav__badge {
  background: var(--surface);
  color: var(--accent);
}

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

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s-4);
  height: var(--header-h);
  padding: 0 var(--s-6);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--line);
}

.topbar__title {
  font-size: var(--t-14);
  font-weight: 600;
  min-width: 0;
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.topbar__spacer { margin-left: auto; }
/* The bar's title only stands in for a page that has no heading of its
   own: where the page opens with one, it would say the same word twice. */
body:has(.page-title) .topbar__title { display: none; }

.content { padding: var(--s-6); flex: 1; }
/* A very wide monitor does not need forty-centimetre table rows: the page
   stops growing at a width the eye can still sweep, and sits centred. */
.content { width: 100%; max-width: var(--content-max); margin: 0 auto; }
.content--narrow { max-width: 860px; }

.page-head {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  margin-bottom: var(--s-6);
  flex-wrap: wrap;
}

.page-head__text { min-width: 0; }
/* The section over a record's title, in the menu's own section style. */
.page-eyebrow {
  display: inline-block;
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 600;
  color: var(--ink-label);
  text-decoration: none;
  margin-bottom: 2px;
}
.page-eyebrow:hover { color: var(--ink-2); }
/* The arrows through the register: one small segmented control at the
   left end of the buttons' row, which then takes the whole width, so
   nothing else in the head can move it. */
.page-head__actions:has(> .doc-pager) { width: 100%; }
.doc-pager {
  margin-right: auto;
  grid-column: 1 / -1;
  justify-self: start;
  display: inline-flex;
  gap: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}
.doc-pager .btn {
  width: 32px;
  height: var(--field-h);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}
.doc-pager .btn + .btn { border-left: 1px solid var(--line); }
.doc-pager a.btn:hover { background: var(--surface-hover); }
.doc-pager .btn:disabled { color: var(--ink-3); opacity: .45; }

.page-title {
  font-size: var(--t-26);
  letter-spacing: -0.02em;
  font-weight: 650;
}

.page-sub {
  color: var(--ink-3);
  font-size: var(--t-13);
  margin-top: 2px;
}

/* A PDF's language beside its download button, as one pair. */
.pdf-lang { display: flex; gap: var(--s-2); align-items: center; }
.pdf-lang .select { width: auto; }
.page-head__actions {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: 100%;
  gap: var(--s-2);
  align-items: center;
}

/* One order for every row of actions, whatever the template wrote: the
   register's arrows first, a destructive action next, set apart, the main
   action last at the right end. On a phone (below) the main action goes to
   the bottom, across the width, where the thumb is. */
.page-head__actions > .doc-pager { order: -3; }
.page-head__actions > .btn--danger,
.page-head__actions > form:has(> .btn--danger) { order: -2; margin-right: var(--s-4); }
.page-head__actions > .btn--primary,
.page-head__actions > form:not(.pdf-lang):has(> .btn--primary) { order: 10; }
.pdf-lang .btn { white-space: nowrap; }

/* The buttons that close a form: cancelling and the others first, the
   main one last at the right, a destructive one alone at the left end. */
.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-2);
}
.form-actions > .btn--primary,
.form-actions > form:has(> .btn--primary) { order: 10; }
.form-actions > .btn--danger,
.form-actions > form:has(> .btn--danger) { order: -2; margin-right: auto; }

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

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

.card__head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--line);
}

.card__title { font-size: var(--t-13); font-weight: 600; }
/* A list inside a card is searched from the right end of its head, as a page's list from its filter bar. */
.card__head:has(.search) { flex-wrap: wrap; }
.card__head .search { margin-left: auto; }
.card__body { padding: var(--s-5); }
/* A thin strip above a table: a select-all box, a filter, a note. */
.card__body--strip { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
.card__foot {
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--line);
  background: var(--surface-sunk);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}

/* --------------------------------------------------------------- KPI tiles */

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-3);
  margin-bottom: var(--s-6);
}

.kpi {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-4) var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  position: relative;
  overflow: hidden;
}

/* A 2px spine carries the semantic colour instead of tinting the whole tile. */
.kpi::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--kpi-accent, var(--line-strong));
}

.kpi--positive { --kpi-accent: var(--positive); }
.kpi--danger   { --kpi-accent: var(--danger); }
.kpi--warning  { --kpi-accent: var(--warning); }
.kpi--accent   { --kpi-accent: var(--accent); }
.kpi--overdue  { --kpi-accent: var(--overdue); }
.kpi--overdue .kpi__value,
.kpi--overdue .kpi__value .amt-pos { color: var(--overdue); }

/* Tiles of label · value · note on one shared grid: a label that wraps
   pushes every tile's value down with it, so the figures stay on one line. */
.kpi-grid--aligned .kpi {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  row-gap: var(--s-1);
  align-content: start;
}
.kpi--link { color: inherit; text-decoration: none; }
.kpi--link:hover { border-color: var(--accent); }

.kpi__label {
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  font-weight: 600;
}

.kpi__value {
  font-size: var(--t-26);
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--kpi-value, var(--ink));
}

.kpi--positive .kpi__value { --kpi-value: var(--positive); }
.kpi--danger   .kpi__value { --kpi-value: var(--danger); }

.kpi__meta { font-size: var(--t-12); color: var(--ink-3); }

.kpi__count { display: flex; align-items: baseline; gap: var(--s-2); }

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

.table-wrap {
  position: relative;
  max-width: 100%;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

table.data {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--t-13);
}

table.data thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-sunk);
  text-align: left;
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  font-weight: 600;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

table.data tbody td {
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  line-height: calc(var(--field-h) - 12px);
}

table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--surface-hover); }

table.data th.num, table.data td.num,
table.data th.text-right, table.data td.text-right { text-align: right; }
/* A date or a counter: figures of equal width, on the left under its heading. */
.tnum { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* A heading over a column of figures ends where the figures end: its sort
   mark hangs in the cell's padding instead of pushing the word to the left. */
table.data th.num .th-sort, table.data th.text-right .th-sort { position: relative; }
table.data th.num .th-sort__mark, table.data th.text-right .th-sort__mark { position: absolute; left: 100%; top: 0; }

/* Numbers, dates, amounts and badges never break; the one column that is
   allowed to wrap is the descriptive one, and its secondary line stays a
   line rather than a paragraph. Squeezed tables scroll sideways instead. */
table.data td.num, table.data .mono, table.data .badge, table.data .row-actions { white-space: nowrap; }
table.data td > .small.muted {
  display: block;
  max-width: 42ch;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

table.data tfoot td {
  padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--line-strong);
  font-weight: 600;
  background: var(--surface-sunk);
}

/* The charges page's four lists share their columns, so the figures of one
   stand under those of the next. Where the card is narrower than the seven
   columns need — a phone, a tablet upright, a narrow window — each charge
   becomes a block of its own instead (a container query: the card's width
   decides, not the screen's). */
.charges-wrap { container-type: inline-size; }
table.data.charges-table { table-layout: fixed; min-width: 0; }
table.charges-table td { overflow-wrap: break-word; }
.charges-table__day { width: 8rem; }
.charges-table__client { width: 18%; }
.charges-table__for { width: 18%; }
.charges-table__amount { width: 7.5rem; }
.charges-table__state { width: 13.5rem; }
.charges-table__act { width: 6rem; }
@container (max-width: 56rem) {
  table.data.charges-table, .charges-table thead, .charges-table tbody, .charges-table tfoot { display: block; }
  .charges-table colgroup { display: none; }
  /* The headings that sort stay, as a row of links; the others say nothing
     a block does not show. */
  .charges-table thead { background: var(--surface-sunk); border-bottom: 1px solid var(--line); }
  .charges-table thead tr { display: flex; flex-wrap: wrap; }
  .charges-table thead th { border-bottom: 0; }
  .charges-table thead th:not(:has(.th-sort)) { display: none; }
  .charges-table tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "day amount" "client client" "for for" "method method" "state act";
    gap: var(--s-1) var(--s-3);
    padding: var(--s-3) var(--s-4);
    border-bottom: 1px solid var(--line);
  }
  .charges-table tbody tr:last-child { border-bottom: 0; }
  table.data.charges-table tbody td { display: block; padding: 0; border: 0; min-width: 0; text-align: left; }
  .charges-table .c-day { grid-area: day; }
  table.data.charges-table td.c-amount { grid-area: amount; text-align: right; font-weight: 600; }
  .charges-table .c-client { grid-area: client; font-weight: 500; }
  .charges-table .c-for { grid-area: for; }
  .charges-table .c-for:empty, .charges-table .c-act:empty { display: none; }
  .charges-table .c-method { grid-area: method; font-size: var(--t-12); }
  .charges-table .c-state { grid-area: state; align-self: center; }
  .charges-table .c-act { grid-area: act; align-self: center; }
  .charges-table td > .cell-link { min-width: 0; display: inline; }
  .charges-table .mono { white-space: normal; overflow-wrap: anywhere; }
  .charges-table tfoot tr { display: flex; justify-content: space-between; }
  table.data.charges-table tfoot td { flex: 1; }
  table.data.charges-table tfoot td.c-label { text-align: left; }
  .charges-table tfoot .c-rest { display: none; }
}
/* A tablet's width: the day in its own column, what and how in the middle,
   where it stands on the right, the sum and the button at the far end. */
@container (min-width: 36rem) and (max-width: 56rem) {
  .charges-table tbody tr {
    grid-template-columns: 6.5rem minmax(0, 1fr) minmax(0, 12rem) auto;
    grid-template-areas: "day client state amount" "day for state act" "day method state act";
    column-gap: var(--s-4);
  }
  .charges-table .c-state { align-self: start; }
  .charges-table .c-act { align-self: start; justify-self: end; }
}

.cell-strong { font-weight: 600; color: var(--ink); }
.cell-muted { color: var(--ink-3); }
.cell-link { color: var(--accent); text-decoration: none; font-weight: 500; }
.cell-link:hover { text-decoration: underline; }

.row-actions { display: flex; gap: var(--s-1); justify-content: flex-end; }
.row-actions .is-blank { visibility: hidden; }
/* An expense claim line: its supporting document, picked or uploaded. */
.er-paper { display: flex; gap: var(--s-1); align-items: center; }
.er-paper .select { min-width: 11rem; }

/* ----------------------------------------------------------------- badges */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: var(--t-11);
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  border: 1px solid var(--badge-line, var(--neutral-line));
  background: var(--badge-bg, var(--neutral-soft));
  color: var(--badge-fg, var(--neutral));
}

.badge::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.badge--paid, .badge--approved, .badge--issued {
  --badge-bg: var(--positive-soft);
  --badge-fg: var(--positive);
  --badge-line: var(--positive-line);
}

.badge--unpaid, .badge--sent, .badge--pending {
  --badge-bg: var(--warning-soft);
  --badge-fg: var(--warning);
  --badge-line: var(--warning-line);
}

.badge--overdue, .badge--rejected, .badge--failed {
  --badge-bg: var(--danger-soft);
  --badge-fg: var(--danger);
  --badge-line: var(--danger-line);
}

.badge--draft, .badge--cancelled, .badge--viewed {
  --badge-bg: var(--neutral-soft);
  --badge-fg: var(--neutral);
  --badge-line: var(--neutral-line);
}

.badge--partially_paid {
  --badge-bg: var(--accent-soft);
  --badge-fg: var(--accent);
  --badge-line: var(--accent-line);
}

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--field-h);
  padding: 0 var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--t-13);
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  transition: background var(--speed) var(--ease),
              border-color var(--speed) var(--ease),
              color var(--speed) var(--ease);
}

.btn:hover { background: var(--surface-hover); border-color: var(--ink-4); }

.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.5;
  pointer-events: none;
}

.btn svg { width: 15px; height: 15px; }

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 550;
}
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn--primary { color: #0b1a15; }
}
:root[data-theme="dark"] .btn--primary { color: #0b1a15; }

/* By dark, the company's initials on the light green and the idle sort
   arrows need more than light gives them to be read. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand__mark { color: #0b1a15; }
  :root:not([data-theme="light"]) .th-sort__mark--idle { opacity: 0.7; }
  :root:not([data-theme="light"]) .th-sort:hover .th-sort__mark--idle { opacity: 1; }
}
:root[data-theme="dark"] .brand__mark { color: #0b1a15; }
:root[data-theme="dark"] .th-sort__mark--idle { opacity: 0.7; }
:root[data-theme="dark"] .th-sort:hover .th-sort__mark--idle { opacity: 1; }

.btn--danger {
  color: var(--danger);
  border-color: var(--danger-line);
  background: var(--danger-soft);
}
.btn--danger:hover { background: var(--danger); color: #fff; border-color: var(--danger); }

.btn--ghost { border-color: transparent; background: transparent; }
.btn--ghost:hover { background: var(--surface-hover); border-color: var(--line); }

.btn--sm { height: 26px; padding: 0 var(--s-2); font-size: var(--t-12); }
/* The day a debit collected by hand takes the money, beside its button. */
.charge-when { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.charge-when .select { width: auto; min-width: 12rem; max-width: 20rem; }
.charge-when .input[type="date"] { width: 9.5rem; min-height: 26px; height: 26px; line-height: 24px; font-size: var(--t-12); }
.charge-when .charge-amount { width: 7rem; min-height: 26px; height: 26px; font-size: var(--t-12); }
/* The wording has a line of its own, the width of the cell, and grows when
   dragged: it is read and edited whole. */
.charge-when .charge-desc { order: 9; flex: 1 0 100%; width: 100%; min-width: 18rem; min-height: 3.2em; height: auto; resize: vertical; font-size: var(--t-12); line-height: 1.35; text-align: left; }
/* An invoice's debit form, on its own row under the part it collects: the
   wording takes the room left on the line. */
.debit-form > td { padding-top: 0; }
[data-debit-row] > tr:first-child > td, tbody:has(> .debit-form) > tr:first-child > td { border-bottom: 0; }
.debit-form .charge-when { display: flex; }
.debit-form .charge-desc { order: 0; flex: 1 1 16rem; width: auto; min-width: 12rem; }
.btn--icon { width: var(--field-h); padding: 0; }
.btn--icon.btn--sm { width: 26px; }
/* A file chooser drawn as a button: the input hides inside it, its focus shows on the button. */
.btn--file { position: relative; cursor: pointer; }
.btn--file:focus-within { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Theme toggle: one icon per mode, the current one shown. No attribute on
   <html> means the palette follows the operating system. */
.theme-toggle__icon { display: none; line-height: 0; }
:root:not([data-theme]) .theme-toggle__icon--system,
:root[data-theme="light"] .theme-toggle__icon--light,
:root[data-theme="dark"] .theme-toggle__icon--dark { display: inline-flex; }

.btn-group { display: inline-flex; gap: var(--s-2); }

/* ------------------------------------------------------------------ forms */

.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: var(--s-4); }

.field__label {
  font-size: var(--t-12);
  font-weight: 600;
  color: var(--ink-2);
}

/* A group of choices labelled like any field, not as a section. */
legend.field__label { font-size: var(--t-12); text-transform: none; letter-spacing: 0; color: var(--ink-2); padding-bottom: 0; }

.field__req { color: var(--danger); margin-left: 2px; }

/* The counterpart, for a field whose emptiness means something. */
.field__opt { font-weight: 400; color: var(--ink-label); }

/* A long list of things to tick: one per line, quiet rules between them. */
.check-list { list-style: none; margin: 0; padding: 0; max-height: 60vh; overflow-y: auto; }

/* The switcher becomes a way in to the chooser once a dropdown cannot cope. */
.org-switch__all { width: 100%; justify-content: flex-start; }
.check-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 6px 2px;
  border-bottom: 1px solid var(--line);
}
.check-row:last-child { border-bottom: 0; }
.check-row > .small { margin-left: auto; }
.check { display: flex; align-items: center; gap: var(--s-2); cursor: pointer; min-width: 0; }
.check input[disabled] + span { color: var(--ink-3); }

/* A quantity and what it counts, side by side in one cell. */
.qty-cell { display: flex; gap: 4px; align-items: center; }
/* The number must stay readable next to its unit: never narrower than
   four digits and a separator. */
.qty-cell .input { min-width: 7ch; flex: 1 1 auto; }
.qty-cell .select { flex: 0 0 auto; width: auto; max-width: 11ch; }

.field__hint { font-size: var(--t-12); color: var(--ink-3); }
.field__link { font-size: var(--t-12); color: var(--accent); text-decoration: none; display: inline-flex; align-items: center; gap: 4px; margin-top: 4px; }
.field__link:hover { text-decoration: underline; }
.field__link svg { width: 12px; height: 12px; }

/* Searchable pickers: the list floats above everything, positioned from the
   box it belongs to, so a scrolling table cannot clip it. */
.combo__list {
  position: fixed;
  z-index: 80;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.14);
  max-height: 280px;
  overflow-y: auto;
  font-size: var(--t-13);
}
.combo__item { padding: 7px 10px; border-radius: var(--r-sm); cursor: pointer; display: flex; justify-content: space-between; gap: var(--s-3); }
.combo__item[aria-selected="true"], .combo__item:hover { background: var(--surface-hover); }
.combo__sub { color: var(--ink-3); font-size: var(--t-12); white-space: nowrap; }
.combo__item--create { color: var(--accent); border-top: 1px solid var(--line); margin-top: 4px; border-radius: 0; padding-top: 9px; }
.combo__item--empty { color: var(--ink-3); cursor: default; }
.combo__item--empty:hover { background: none; }

.field__error {
  font-size: var(--t-12);
  color: var(--danger);
  display: flex;
  align-items: center;
  gap: 5px;
}
.field__error svg { width: 14px; height: 14px; flex-shrink: 0; }
/* Any icon in running text that nothing else sizes stays text-sized. */
svg[aria-hidden="true"] { max-width: 1.25em; max-height: 1.25em; }
.empty__icon svg, .stamp-block svg, .brand__mark svg { max-width: none; max-height: none; }

.input, .select, .textarea {
  height: var(--field-h);
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--t-13);
  width: 100%;
  transition: border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}

.textarea { height: auto; padding: var(--s-2) var(--s-3); min-height: 76px; resize: vertical; line-height: 1.5; }

/* Every control is the same box, whatever it holds. Date, time and number
   inputs come with a native look that ignores height and width — WebKit on
   iPhone and iPad shrinks a date field to its text and centres it its own
   way — so the native look is switched off and the box sizes are pinned. */
.input, .select { box-sizing: border-box; min-height: var(--field-h); line-height: calc(var(--field-h) - 2px); display: block; }
/* hidden means hidden, whatever display an element's own class gives it:
   .field, .btn, .input and the rest all set display and would otherwise
   beat the browser's own [hidden] rule, leaving "hidden" things on screen. */
[hidden]:not([hidden="until-found"]) { display: none !important; }
.input[hidden], .select[hidden] { display: none; }
/* Buttons too: .btn sets display, which would otherwise beat the browser's
   own [hidden] rule and leave a "hidden" button on screen. */
.btn[hidden] { display: none; }
.input[type="date"], .input[type="time"], .input[type="month"], .input[type="datetime-local"] {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
  width: 100%;
  line-height: normal;
}
/* Safari on a phone draws nothing in a date field that has no date, and so
   gives it no width: in a toolbar the field shrank to an empty square. It
   keeps a width of its own, and says what it is for while it is empty —
   app.js marks the empty ones, the words are the field's own label. Only
   there: a desktop browser already writes dd/mm/yyyy in the field. */
.input[type="date"], .input[type="month"] { min-width: 9.5rem; }
@supports (-webkit-touch-callout: none) {
  .input[type="date"].is-empty::before, .input[type="month"].is-empty::before {
    content: attr(aria-label);
    color: var(--ink-3);
    line-height: calc(var(--field-h) - 2px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .input[type="date"].is-empty:not([aria-label])::before, .input[type="month"].is-empty:not([aria-label])::before { content: "—"; }
}
.input[type="date"]::-webkit-date-and-time-value,
.input[type="time"]::-webkit-date-and-time-value,
.input[type="month"]::-webkit-date-and-time-value {
  height: calc(var(--field-h) - 2px);
  display: flex;
  align-items: center;
  text-align: left;
}
.input::-webkit-datetime-edit { padding: 0; line-height: calc(var(--field-h) - 2px); }
.input::-webkit-datetime-edit-fields-wrapper { padding: 0; }
.input::-webkit-calendar-picker-indicator { opacity: 0.6; cursor: pointer; margin-left: var(--s-2); }
.input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
/* A field with suggestions (datalist): Chrome's own arrow sits low and off
   the field's line; it wears the selects' chevron instead. The suggestions
   still open on typing, the down arrow, or a click. */
.input[list]::-webkit-calendar-picker-indicator { display: none !important; }
.input[list] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237a756c' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 14px;
  padding-right: 30px;
}
/* The search fields' clear button, in the icons' grey rather than the
   system's blue. */
.input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-left: var(--s-2);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237a756c' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4.5 4.5l7 7M11.5 4.5l-7 7'/%3E%3C/svg%3E") center / 14px no-repeat;
  opacity: 0.7;
  cursor: pointer;
}
.input[type="search"]::-webkit-search-cancel-button:hover { opacity: 1; }
.input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.input[type="number"]::-webkit-outer-spin-button,
.input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.input[type="file"] { line-height: calc(var(--field-h) - 10px); padding: 4px; }
/* The file picker's button looks like the application's own buttons, not
   the system's grey one. */
.input[type="file"]::file-selector-button {
  height: calc(var(--field-h) - 10px);
  margin: 0 var(--s-2) 0 0;
  vertical-align: top;
  line-height: calc(var(--field-h) - 12px);
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-13);
  font-weight: 500;
  cursor: pointer;
}
.input[type="file"]::file-selector-button:hover { background: var(--accent-soft); }
/* Every tick box, choice and slider in the application's green, wherever
   it sits, not only inside .checkbox. */
input[type="checkbox"], input[type="radio"], input[type="range"] { accent-color: var(--accent); }

.input:hover, .select:hover, .textarea:hover { border-color: var(--ink-4); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.input[aria-invalid="true"], .select[aria-invalid="true"] { border-color: var(--danger); }
.input[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--danger-soft); }

.input::placeholder { color: var(--ink-label); }

.select {
  appearance: none;
  /* WebKit lets a long selected option widen the page through the
     ancestors' scrollWidth even when the box itself is capped; a select
     never scrolls, so clipping costs nothing and keeps phones still. */
  overflow: hidden;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237a756c' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 14px;
  padding-right: 30px;
}

.input-group { display: flex; align-items: stretch; }
.input-group .input { border-radius: 0; }
.input-group > :first-child { border-radius: var(--r-md) 0 0 var(--r-md); }
.input-group > :last-child { border-radius: 0 var(--r-md) var(--r-md) 0; }

.input-affix {
  display: grid;
  place-items: center;
  min-height: var(--field-h);
  white-space: nowrap;
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  background: var(--surface-sunk);
  color: var(--ink-3);
  font-size: var(--t-13);
}
.input-group .input:not(:first-child) { border-left: 0; }
.input-group .input-affix:not(:first-child) { border-left: 0; }

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-4);
}

.checkbox, .radio {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-13);
  cursor: pointer;
}

.checkbox input, .radio input {
  width: 15px; height: 15px;
  accent-color: var(--accent);
  cursor: pointer;
}

fieldset { border: 0; padding: 0; }
/* Browsers pad a legend sideways: it would sit off the labels below it. */
legend { padding-inline: 0; }

legend {
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  font-weight: 600;
  padding-bottom: var(--s-2);
}

/* --------------------------------------------------------------- messages */

.alert {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--alert-line, var(--line));
  background: var(--alert-bg, var(--surface-sunk));
  color: var(--alert-fg, var(--ink-2));
  font-size: var(--t-13);
  margin-bottom: var(--s-4);
}

.alert--error   { --alert-bg: var(--danger-soft);   --alert-fg: var(--danger);   --alert-line: var(--danger-line); }
.alert--success { --alert-bg: var(--positive-soft); --alert-fg: var(--positive); --alert-line: var(--positive-line); }
.alert--warning { --alert-bg: var(--warning-soft);  --alert-fg: var(--warning);  --alert-line: var(--warning-line); }
.alert--info    { --alert-bg: var(--accent-soft);   --alert-fg: var(--accent);   --alert-line: var(--accent-line); }

.alert svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }
.alert strong { font-weight: 600; }

.empty { padding: var(--s-12) var(--s-6); text-align: center; color: var(--ink-3); }
.empty__icon { display: block; width: 40px; height: 40px; margin: 0 auto var(--s-3); color: var(--ink-3); }
.empty__icon svg { width: 100%; height: 100%; }
.empty__title { font-size: var(--t-14); font-weight: 600; color: var(--ink-2); margin-bottom: var(--s-1); }
.empty__text { font-size: var(--t-13); max-width: 42ch; margin: 0 auto var(--s-4); }

/* --------------------------------------------------------------- toolbar */

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--surface-sunk);
}

.toolbar + .table-wrap { border-radius: 0 0 var(--r-lg) var(--r-lg); }

.search { position: relative; flex: 1; min-width: 180px; max-width: 320px; }

/* The search of a filter bar keeps to the right even on a second row. */
.toolbar .search { margin-left: auto; }
/* A note with its icon in a toolbar («Esporta»): one line, icon beside. */
.toolbar > .small:has(svg) { display: inline-flex; align-items: center; gap: var(--s-1); white-space: nowrap; }

/* «Dal … Al …» of a filter bar (partials/period.html, dates_filter). */
.dates { display: inline-flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.dates__f { display: inline-flex; align-items: center; gap: var(--s-1); }
.dates__lbl { font-size: var(--t-12); color: var(--ink-3); }
.dates .input[type="date"] { width: 9.5rem; }

.search .input { padding-left: 30px; }

.search svg {
  position: absolute;
  left: 9px; top: 50%;
  transform: translateY(-50%);
  width: 14px; height: 14px;
  color: var(--ink-4);
  pointer-events: none;
}

.seg {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  padding: 2px;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
}

.seg__btn {
  padding: 3px var(--s-3);
  border-radius: var(--r-sm);
  font-size: var(--t-12);
  font-weight: 500;
  color: var(--ink-3);
  text-decoration: none;
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
}

.seg__btn:hover { color: var(--ink); }

.seg__btn[aria-selected="true"] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

/* ------------------------------------------------------------- pagination */

/* The pager of a list floats at the bottom right of the window, within reach
   however far the list has been scrolled, on every device: it keeps clear of
   a phone's rounded corners and home bar (safe areas), never grows wider
   than the screen — in a language with long words its buttons go under the
   page count rather than off the edge — and under a finger its buttons are
   a finger tall. The page keeps room under its last row so the pager never
   sits on it. */
.pager {
  --pager-gap: var(--s-5);
  position: fixed;
  /* On a monitor wider than the page, the page sits centred and the window's
     corner is a long way from the list: the pager keeps to the right edge of
     the page instead, under the column of row buttons. */
  right: max(var(--pager-gap), env(safe-area-inset-right),
             calc((100vw - var(--sidebar-w) - var(--content-max)) / 2 + var(--s-6)));
  bottom: calc(var(--pager-gap) + env(safe-area-inset-bottom));
  z-index: 40;
  box-sizing: border-box;
  max-width: calc(100vw - 2 * var(--pager-gap) - env(safe-area-inset-left) - env(safe-area-inset-right));
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-2) var(--s-2) var(--s-4);
  font-size: var(--t-12);
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 22px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.14);
}
/* A dock holds what floats under a list when there is more than the pager:
   it spans the page from margin to margin, the count at the left one —
   where the eye starts a row — and the pager at the right one, where it
   is on every list. Where the two do not fit side by side, a phone, the
   count goes above and the pager keeps its corner. The count is not a
   control: it takes no clicks, and neither does the dock's empty middle —
   they go through to whatever row lies under. */
.float-dock {
  --pager-gap: var(--s-5);
  --dock-side: max(var(--pager-gap), calc((100vw - var(--sidebar-w) - var(--content-max)) / 2 + var(--s-6)));
  position: fixed;
  left: calc(var(--sidebar-w) + max(var(--dock-side), env(safe-area-inset-left)));
  right: max(var(--dock-side), env(safe-area-inset-right));
  bottom: calc(var(--pager-gap) + env(safe-area-inset-bottom));
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s-3);
  pointer-events: none;
}
/* Under 900px the sidebar is a drawer and takes no room. */
@media (max-width: 900px) {
  .float-dock { left: max(var(--pager-gap), env(safe-area-inset-left)); }
}
.float-dock > * { pointer-events: auto; }
.float-dock .pager { position: static; max-width: 100%; margin-left: auto; }
.float-count {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-4);
  font-size: var(--t-12);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 22px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.14);
  pointer-events: none;
}
.float-count svg { width: 14px; height: 14px; flex: none; }
main:has(.float-dock) { padding-bottom: calc(var(--s-5) * 2 + 56px + 44px + env(safe-area-inset-bottom)); }
@media (max-width: 600px) {
  .float-dock { --pager-gap: var(--s-3); }
  main:has(.float-dock) { padding-bottom: calc(var(--s-3) * 2 + 104px + 44px + env(safe-area-inset-bottom)); }
}
@media print { .float-dock { display: none; } }
.pager__count { white-space: nowrap; }
/* On a narrow phone the count is written short — 2/6 — so the pager stays on
   one line in every language; the full words stay for a screen reader. */
@media (max-width: 420px) {
  .pager__count { font-size: 0; }
  .pager__count::after { content: attr(data-short); font-size: var(--t-12); font-variant-numeric: tabular-nums; }
}
.pager .btn { border-radius: 999px; flex: 0 0 auto; gap: 0.35em; }
/* First, previous, next, last: a mark and a word. Where four words would not
   fit — a phone, a narrow tablet column — the marks stand alone; the words
   stay as each button's name for a screen reader and as its tooltip. */
@media (max-width: 760px) {
  .pager__word { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .pager .btn { min-width: 34px; justify-content: center; font-size: var(--t-14); }
}
.pager__spacer { display: none; }
main:has(.pager) { padding-bottom: calc(var(--s-5) * 2 + 56px + env(safe-area-inset-bottom)); }
@media (max-width: 600px) {
  .pager { --pager-gap: var(--s-3); }
  /* Room for a pager that has wrapped onto two lines. */
  main:has(.pager) { padding-bottom: calc(var(--s-3) * 2 + 104px + env(safe-area-inset-bottom)); }
}
@media (pointer: coarse) {
  .pager .btn { min-height: 40px; padding-left: var(--s-4); padding-right: var(--s-4); }
}
@media print { .pager { display: none; } }

/* The head of an editor, title and save button together, keeps its place
   under the top bar while the form scrolls beneath it. It reaches the edges
   of the content by undoing the content's own padding. */
.page-head--sticky {
  position: sticky;
  top: var(--header-h);
  z-index: 15;
  margin: calc(-1 * var(--s-6)) calc(-1 * var(--s-6)) var(--s-6);
  padding: var(--s-4) var(--s-6);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
@media (max-width: 900px) {
  .page-head--sticky {
    margin: calc(-1 * var(--s-4)) calc(-1 * var(--s-4)) var(--s-4);
    padding: var(--s-3) var(--s-4);
  }
}
/* On a phone the head wraps to several rows and would cover half the
   screen; there it scrolls with the page as before. */
@media (max-width: 600px) {
  .page-head--sticky { position: static; }
}

.totals__note { margin: var(--s-1) 0 0; text-align: right; }

/* A notice on its way out. */
.alert--fading { opacity: 0; transition: opacity 0.7s ease; }

/* A column heading that orders the list: reads as a heading, acts as a link. */
.th-sort { color: inherit; text-decoration: none; white-space: nowrap; }
.th-sort:hover { text-decoration: underline; }
/* The arrow that says how the column orders the list, and the faint pair
   that says it can. */
.th-sort__mark { margin-left: 0.25em; }
.th-sort__mark--idle { opacity: 0.35; }
.th-sort:hover .th-sort__mark--idle { opacity: 0.7; }

/* What the editor last did on its own, beside the save button. */
.autosave-status { align-self: center; white-space: nowrap; }

/* The little corner button that opens a field in a bigger box, and the box. */
.expand-btn {
  position: fixed;
  z-index: 30;
  width: 22px;
  height: 22px;
  padding: 3px;
  border: 0;
  border-radius: 6px;
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  color: var(--ink-3);
  cursor: pointer;
}
.expand-btn:hover { color: var(--ink); background: var(--surface); }
.expand-btn svg { width: 100%; height: 100%; display: block; }

dialog.expand {
  width: min(92vw, 760px);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
}
dialog.expand::backdrop { background: rgba(0, 0, 0, 0.35); }
.expand__title { font-size: var(--t-14); font-weight: 600; margin: 0 0 var(--s-3); }
.expand__area { width: 100%; min-height: 40vh; resize: vertical; font: inherit; line-height: 1.45; }
dialog.docview {
  width: min(96vw, 980px);
  height: min(92vh, 1200px);
  margin: auto;
  inset: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  overflow: hidden;
}
dialog.docview[open] { display: flex; flex-direction: column; }
dialog.docview::backdrop { background: rgba(0, 0, 0, 0.45); }
.docview__head { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); }
.docview__title { flex: 1; min-width: 0; margin: 0; font-size: var(--t-14); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.docview__frame { flex: 1; width: 100%; border: 0; background: var(--bg); }
@media (max-width: 640px) { dialog.docview { width: 100vw; height: 100dvh; max-width: none; max-height: none; border-radius: 0; } }
.expand__row { display: flex; gap: var(--s-2); justify-content: flex-end; margin-top: var(--s-3); }

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

.lines { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--t-13); }

.lines th {
  text-align: left;
  font-size: var(--t-11);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  font-weight: 600;
  padding: 0 var(--s-2) var(--s-2);
}

/* Every heading sits flush left over its column. A right-aligned heading
   over a cell that holds a number and a unit picker lands on the picker,
   and the number below it looks untitled. */
.lines th.num { text-align: left; }

/* --line-pad is the room around a row's fields, the same on all four
   sides of the row, so a picked row's colour frames them evenly. */
.lines { --line-pad: 6px; }
.lines td { padding: var(--line-pad) var(--s-1); vertical-align: top; }
.lines td:first-child, .lines th:first-child { padding-left: var(--line-pad); }
.lines td:last-child { padding-right: var(--line-pad); }
.lines td .input, .lines td .select { font-size: var(--t-13); }
.lines td .input.num { text-align: right; }

.lines__drag {
  width: 22px;
  color: var(--ink-4);
  cursor: grab;
  text-align: center;
  padding-top: 9px;
}

.totals {
  margin-left: auto;
  width: min(340px, 100%);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  font-size: var(--t-13);
}

.totals__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-1) 0;
}

.totals__label { color: var(--ink-2); }
.totals__value { font-variant-numeric: tabular-nums; font-weight: 500; }

.totals__row--grand {
  border-top: 1px solid var(--line-strong);
  margin-top: var(--s-2);
  padding-top: var(--s-3);
  font-size: var(--t-16);
  font-weight: 650;
}

.totals__row--grand .totals__value { color: var(--accent); }

/* ------------------------------------------------------------------ misc */

.stack { display: flex; flex-direction: column; gap: var(--s-4); }
.row { display: flex; align-items: center; gap: var(--s-3); }
/* A long address in a review list breaks rather than pushing the page wide. */
.rows dd { min-width: 0; overflow-wrap: anywhere; }
code { overflow-wrap: anywhere; }
.row--wrap { flex-wrap: wrap; }
.spacer { margin-left: auto; }
.muted { color: var(--ink-3); }
.small { font-size: var(--t-12); }
.mono { font-family: var(--font-num); font-size: 0.95em; }
.nowrap { white-space: nowrap; }
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

hr.sep { border: 0; border-top: 1px solid var(--line); margin: var(--s-5) 0; }

/* Utilities.
   These exist because the Content-Security-Policy carries no 'unsafe-inline'
   for styles, so a style="" attribute in a template is blocked outright. That
   is the right trade — the same directive is what makes an injected <style> or
   handler inert — but it means spacing tweaks live here rather than in markup. */

.m-0 { margin: 0 !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-2 { margin-bottom: var(--s-2); }
.mb-3 { margin-bottom: var(--s-3); }
.mb-4 { margin-bottom: var(--s-4); }
.mb-6 { margin-bottom: var(--s-6); }
.mt-2 { margin-top: var(--s-2); }
.mt-3 { margin-top: var(--s-3); }
.mt-6 { margin-top: var(--s-6); }

.gap-2 { gap: var(--s-2); }
.items-start { align-items: flex-start; }
.num-next .input { width: 9rem; flex: none; }
.text-right { text-align: right; }

/* A table or card nested inside another surface, which should not draw its
   own frame. */
.flush { border: 0 !important; }

.totals-col { min-width: min(300px, 100%); flex: 1; }
.field-narrow { max-width: 200px; }
.select--fit { width: auto; max-width: 100%; }
.panel-narrow { max-width: 420px; min-width: 0; width: 100%; }
/* Long keys and URLs in a narrow panel scroll or wrap rather than widen it. */
.code-block { overflow-x: auto; max-width: 100%; }
.panel-narrow .mono, .card .mono li { overflow-wrap: anywhere; }

/* A block of machine-readable text shown for inspection. It scrolls inside
   its own frame so a long document cannot widen the page. */
.code-block {
  margin: 0;
  padding: var(--s-3);
  max-height: 60vh;
  overflow: auto;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-family: var(--font-num, ui-monospace, monospace);
  font-size: var(--t-12);
  line-height: 1.5;
  white-space: pre;
  tab-size: 2;
}

/* A settings screen puts the list and its editor side by side on a wide
   viewport, and stacks them once there is no room for both. */
.col-grow { flex: 1 1 460px; min-width: 0; }

/* The bank picker: one line per bank, the name on the left and its connect
   buttons in fixed columns on the right (business, then personal), so they
   line up down the list; where the list itself is narrow the buttons go
   under the name. */
.eb-banks { list-style: none; margin: var(--s-3) 0 0; padding: 0; border-top: 1px solid var(--line); container-type: inline-size; }
.eb-bank { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s-2) var(--s-4); padding: var(--s-2) 0; border-bottom: 1px solid var(--line); }
.eb-bank__name { min-width: 0; overflow-wrap: anywhere; }
/* The beta mark explains itself at once on hover, and on tap or keyboard
   focus, where a title tooltip would wait or never show. */
.eb-beta { position: relative; cursor: help; text-decoration: underline dotted; text-underline-offset: 2px; }
.eb-beta::after {
  content: attr(data-tip); position: absolute; left: 0; top: calc(100% + 6px); z-index: 20;
  width: max-content; max-width: min(18rem, 70vw); padding: 6px 8px; border-radius: 6px;
  background: var(--ink); color: var(--surface); font-family: inherit; font-size: 12px; line-height: 1.35;
  white-space: normal; text-decoration: none; box-shadow: 0 4px 12px rgb(0 0 0 / 0.15);
  display: none; pointer-events: none;
}
/* Drawn only while shown: a hidden box still widened the page on a phone. */
.eb-beta:hover::after, .eb-beta:focus::after { display: block; }

/* The balance check: a difference between the bank and the movements. */
.bal-diff { color: var(--danger); }
/* The link to the days to look at wraps rather than widen the table. */
table.data td.bal-diff-cell { white-space: normal; min-width: 11rem; }
.bal-diff-cell .small { line-height: 1.3; margin-top: 2px; }
.eb-bank__actions { display: grid; grid-template-columns: repeat(2, 11.5rem); gap: var(--s-2); }
.eb-bank__actions form { display: contents; }
.eb-bank__actions .btn { width: 100%; height: auto; min-height: var(--field-h); justify-content: center; text-align: center; line-height: 1.2; padding-block: 4px; white-space: normal; min-width: 0; overflow-wrap: anywhere; }
.eb-bank__actions .eb-psu--business { grid-column: 1; }
.eb-bank__actions .eb-psu--personal { grid-column: 2; }
@container (max-width: 620px) {
  .eb-bank { grid-template-columns: minmax(0, 1fr); }
  .eb-bank__actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The language chooser sits in the top bar and should read as a control, not
   as a form field: no frame until it is reached for. */
.lang-switch { display: inline-flex; }

/* The clock in the top bar. Closed, a quiet line of date and time; open,
   a small panel under it with the full date and the zone chooser. The
   panel is anchored to the right so it never runs off a narrow screen. */
.clock { position: relative; flex: 0 0 auto; }
.clock__summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  height: 32px;
  padding: 0 var(--s-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-size: var(--t-13);
  line-height: 1;
  color: var(--ink-2);
  white-space: nowrap;
  user-select: none;
}
.clock__summary::-webkit-details-marker { display: none; }
.clock__summary:hover, .clock[open] > .clock__summary { border-color: var(--line); background: var(--surface-hover); }
.clock__summary:focus-visible { outline: none; border-color: var(--accent); }
.clock__time { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.clock__date { font-variant-numeric: tabular-nums; }
.clock__zone { color: var(--ink-3); font-size: var(--t-12); }
/* The panel is shown only while the box is open. Said explicitly: WebKit
   hides a closed <details>' content with display: none in its own
   stylesheet, which an unconditional display: grid would override — the
   panel then hangs open on every iPhone and pushes the page wider than
   the screen. */
.clock__panel {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 320px;
  max-width: min(400px, calc(100vw - 2 * var(--s-3)));
  padding: var(--s-3);
  gap: var(--s-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
}
.clock[open] > .clock__panel { display: grid; }
.clock__full { font-size: var(--t-13); color: var(--ink); }
.clock__panel .select { width: 100%; max-width: none; }
@media (max-width: 1024px) {
  /* Room is short on a tablet: the date and the zone wait inside the panel. */
  .clock__date, .clock__zone { display: none; }
}
@media (max-width: 600px) {
  .clock__summary { padding: 0 var(--s-1); font-size: var(--t-12); }
  .clock__panel { position: fixed; top: calc(var(--header-h) + 4px); right: var(--s-3); left: var(--s-3); max-width: none; }
}

.select--bare {
  border-color: transparent;
  background-color: transparent;
  padding-inline: var(--s-2);
  padding-right: 28px;
  min-width: 0;
  width: auto;
}

.select--bare:hover { border-color: var(--line); }
.select--bare:focus-visible { border-color: var(--accent); }

/* The acceptance mark. Sized in one place so the page, the print sheet and
   the preview all show it at the same scale. */
.stamp-block {
  flex: 0 0 auto;
  width: 150px;
  max-width: 40vw;
}

.stamp-block svg { width: 100%; height: auto; display: block; }

/* A contract's running term, edited in place: the term's name, its two
   days, the save button and how the save went, on one line that wraps. */
.term-edit { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s-2) var(--s-4); }
.term-edit__term { font-weight: 600; color: var(--ink); padding-bottom: calc((var(--field-h) - 1.4em) / 2); margin-right: var(--s-2); }
.term-edit .input { width: 11.5rem; }
.term-edit__status { color: var(--ink-3); padding-bottom: calc((var(--field-h) - 1.4em) / 2); }
.term-edit__status--success { color: var(--positive); }
.term-edit__status--error { color: var(--danger); }

/* A translation under the text it translates, on a document's mask. */
.tr-box { margin-top: var(--s-1); }
.tr-box .textarea { min-height: var(--field-h); height: auto; padding-block: var(--s-2); border-color: var(--accent, var(--line-strong)); border-style: dashed; }
.tr-bar { position: sticky; top: var(--s-2); z-index: 5; }

/* A proportion bar inside a table row. Kept deliberately plain: it is there
   to make the ranking scannable, not to be a chart. */
.bar {
  height: 6px;
  min-width: 60px;
  border-radius: 3px;
  background: var(--surface-sunk);
  overflow: hidden;
}

.bar__fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: 3px;
}

/* The fill's width comes from a class rather than a style attribute: the
   Content Security Policy forbids inline styles, and one that is blocked
   leaves every bar looking full. Rounded to the nearest 5%%, which is as
   fine as a 60px bar can show anyway. */
.bar__fill--p0 { width: 0%; }
.bar__fill--p5 { width: 5%; }
.bar__fill--p10 { width: 10%; }
.bar__fill--p15 { width: 15%; }
.bar__fill--p20 { width: 20%; }
.bar__fill--p25 { width: 25%; }
.bar__fill--p30 { width: 30%; }
.bar__fill--p35 { width: 35%; }
.bar__fill--p40 { width: 40%; }
.bar__fill--p45 { width: 45%; }
.bar__fill--p50 { width: 50%; }
.bar__fill--p55 { width: 55%; }
.bar__fill--p60 { width: 60%; }
.bar__fill--p65 { width: 65%; }
.bar__fill--p70 { width: 70%; }
.bar__fill--p75 { width: 75%; }
.bar__fill--p80 { width: 80%; }
.bar__fill--p85 { width: 85%; }
.bar__fill--p90 { width: 90%; }
.bar__fill--p95 { width: 95%; }
.bar__fill--p100 { width: 100%; }

/* Small helpers that replace the last inline styles, blocked for the same
   reason. */
.w-full { width: 100%; }
.mw-480 { max-width: 480px; }
.mw-7ch { max-width: 7ch; }
.mw-8ch { max-width: 8ch; }
.stack--center { align-items: center; text-align: center; }

/* The uploaded letterhead, shown against a chequerboard so a transparent
   PNG is visibly transparent rather than mistaken for a white background. */
.logo-preview {
  display: inline-flex;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background-color: var(--surface);
  background-image:
    linear-gradient(45deg, var(--surface-sunk) 25%, transparent 25%),
    linear-gradient(-45deg, var(--surface-sunk) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--surface-sunk) 75%),
    linear-gradient(-45deg, transparent 75%, var(--surface-sunk) 75%);
  background-size: 14px 14px;
  background-position: 0 0, 0 7px, 7px -7px, -7px 0;
}

.logo-preview img {
  max-width: 320px;
  max-height: 110px;
  width: auto;
  height: auto;
}



/* Column proportions for the document line editor. Percentages rather than
   pixels so the table reflows on a narrow screen instead of clipping. */
.lines th:nth-child(1) { width: 30%; min-width: 200px; }
.lines th:nth-child(2) { width: 14%; min-width: 130px; }
.lines th:nth-child(3) { width: 10%; min-width: 80px; }
.lines th:nth-child(4) { width: 13%; min-width: 110px; }
.lines th:nth-child(5) { width: 9%; min-width: 80px; }
.lines th:nth-child(6) { width: 13%; min-width: 100px; }
.lines th:nth-child(7) { width: 9%; min-width: 80px; }
.lines th:nth-child(8) { width: 96px; }
/* A laptop beside the menu column has some 1000px for the editor: the
   description and the kind give up a little, the VAT rate gets enough to
   be read, and the row's own tools stay in sight without scrolling. */
@media (min-width: 901px) and (max-width: 1440px) {
  .lines th:nth-child(1) { min-width: 160px; }
  .lines th:nth-child(2) { min-width: 104px; }
  .lines th:nth-child(3) { min-width: 90px; }
}
/* An expense claim's lines: the description takes the room, the date,
   kind and figures only theirs. */
#erLines th:nth-child(1) { width: 150px; min-width: 140px; }
#erLines th:nth-child(2) { width: 110px; min-width: 100px; }
#erLines th:nth-child(3) { width: auto; min-width: 200px; }
#erLines th:nth-child(4) { width: 16%; min-width: 130px; }
#erLines th:nth-child(5) { width: 80px; min-width: 70px; }
#erLines th:nth-child(6) { width: 100px; min-width: 90px; }
#erLines th:nth-child(7) { width: 110px; min-width: 100px; }
#erLines th:nth-child(8) { width: 44px; min-width: 44px; }

/* The line's description grows with its text instead of scrolling inside
   a fixed height; the script sets the height as the text changes. */
.lines td textarea.input {
  height: auto;
  min-height: var(--field-h);
  /* One line of 20px sits in the middle of a box as tall as the fields
     beside it; more lines grow it downwards. */
  padding-top: calc((var(--field-h) - 22px) / 2);
  padding-bottom: calc((var(--field-h) - 22px) / 2);
  line-height: 20px;
  resize: none;
  overflow: hidden;
  white-space: pre-wrap;
}
.pre-line { white-space: pre-line; }
/* Out of the editing, a description keeps to one line, so a long one does
   not make its row taller than the rest; it opens out while it is edited. */
/* Its one line fills the box, so the next one is not glimpsed in the padding. */
.lines td textarea.input[data-autosize]:not(:focus) {
  height: var(--field-h) !important;
  padding-top: 0;
  padding-bottom: 0;
  line-height: calc(var(--field-h) - 2px);
}

/* Rows are numbered by a counter, so a move or a removal renumbers them
   with no script; a line of text takes no number. */
#lineBody { counter-reset: line; }
#lineBody > .line-row:not(.line-row--text) { counter-increment: line; }
#lineBody > .line-row > td:first-child { position: relative; padding-left: calc(var(--line-pad) + 3ch); }
#lineBody > .line-row:not(.line-row--text) > td:first-child::before {
  content: counter(line);
  position: absolute;
  left: 0;
  top: var(--line-pad);
  width: 3ch;
  text-align: right;
  line-height: var(--field-h);
  font-size: var(--t-11);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.lines:has(> #lineBody) th:first-child { padding-left: calc(var(--line-pad) + 3ch); }

/* An option is priced but not counted, and looks the part. */
.line-row--optional textarea[name="line_name"] { font-style: italic; }
.line-row--optional .line-net { color: var(--ink-3); }

/* The quantity heading names both halves of its cell: the figure and the
   unit beside it, laid out like the cell below. */
.th-split { display: flex; gap: 4px; }
.th-split > span:first-child { flex: 1 1 auto; min-width: 7ch; }
.th-split > span:last-child { flex: 0 0 auto; }
@media (max-width: 1024px) {
  .th-split { flex-direction: column; gap: 0; }
}

/* Up, down, remove: three small buttons at the end of a row. */
.line-tools { display: flex; align-items: center; min-height: var(--field-h); gap: 0; white-space: nowrap; }
/* The head of the lines card, with its tools and «Aggiungi riga», stays
   in view under the top bar and the sticky page head while the rows scroll. */
.card__head:has(#lineTools) {
  position: sticky;
  top: calc(var(--header-h) + var(--page-head-h, 0px));
  z-index: 14;
  background: var(--surface);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
@media (max-width: 600px) {
  .card__head:has(#lineTools) { top: var(--header-h); }
}
.lines-tools { display: flex; align-items: center; gap: 0; flex-wrap: wrap; }
.lines-tools__count { margin-right: var(--s-2); }
@media (max-width: 640px) { .lines-tools__count { display: none; } }
.line-row { cursor: default; }
/* Picked rows share one tint with rounded corners; a run of them reads as
   a single block, rounded only at its two ends. */
.line-row--picked > td { background: var(--accent-soft); }
.line-row--picked > td:first-child { border-radius: var(--r-md) 0 0 var(--r-md); }
.line-row--picked > td:last-child { border-radius: 0 var(--r-md) var(--r-md) 0; }
.line-row--picked + .line-row--picked > td:first-child { border-top-left-radius: 0; }
.line-row--picked + .line-row--picked > td:last-child { border-top-right-radius: 0; }
.line-row--picked:has(+ .line-row--picked) > td:first-child { border-bottom-left-radius: 0; }
.line-row--picked:has(+ .line-row--picked) > td:last-child { border-bottom-right-radius: 0; }

/* A line of text keeps its controls in the form, for the arrays to stay
   aligned, but shows none of them. */
.line-row--text .qty-cell,
.line-row--text select[name="line_tax_rate_id"],
.line-row--text input[name="line_price"],
.line-row--text .line-net { visibility: hidden; }
.doc-line--text td { font-weight: 600; }

/* The computed net sits on the same baseline as the inputs beside it. */
.lines .line-net { line-height: var(--field-h); }

.avatar-sm { width: 22px; height: 22px; font-size: 10px; }

/* One organization in the chooser. */
.org-choice {
  width: 100%;
  height: auto;
  padding: var(--s-3) var(--s-4);
  justify-content: flex-start;
  gap: var(--s-3);
}

.org-choice { white-space: normal; }
.org-choice__text { text-align: left; min-width: 0; overflow-wrap: anywhere; }
.org-choice__name { display: block; font-weight: 600; }

/* --------------------------------------------------------------- auth page */

.auth {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  padding: var(--s-6);
  background:
    radial-gradient(1000px 500px at 50% -10%, var(--accent-soft), transparent 70%),
    var(--paper);
}

.auth__card {
  width: 100%;
  min-width: 0;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-8);
}

.auth__brand { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-6); }
/* A theme's wordmark on the sign-in card, one picture per scheme. */
.auth__logo { display: block; width: auto; height: 52px; }
.auth__logo--dark { display: none; }
:root[data-theme="dark"] .auth__logo--light { display: none; }
:root[data-theme="dark"] .auth__logo--dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .auth__logo--light { display: none; }
  :root:not([data-theme="light"]) .auth__logo--dark { display: block; }
}
/* The page that moves on to another site by itself (leaveTo). */
.auth__leave { display: flex; align-items: center; gap: var(--s-2); color: var(--accent); }
/* The company's own mark, when it has uploaded one. */
.brand__logo { max-height: 56px; max-width: 220px; width: auto; height: auto; display: block; }
.auth__title { font-size: var(--t-20); letter-spacing: -0.02em; margin-bottom: var(--s-1); }
.auth__sub { color: var(--ink-3); font-size: var(--t-13); margin-bottom: var(--s-6); }
.auth__foot { margin-top: var(--s-5); text-align: center; font-size: var(--t-12); color: var(--ink-3); }
.auth__foot a { color: var(--accent); text-decoration: none; }
.auth__foot a:hover { text-decoration: underline; }
.auth__legal { flex-basis: 100%; margin-top: var(--s-2); }
.sidebar__legal { display: block; padding: var(--s-2) var(--s-3); text-decoration: none; }
.sidebar__legal:hover { text-decoration: underline; }
/* The controls row under the sign-in card: language and theme side by
   side, wrapping onto two lines when the card is narrow. */
.auth__foot--bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s-2); }

.auth .btn--primary { width: 100%; height: 36px; }

/* An offer read on a desk gets the room a document needs; the buttons keep
   a hand's width rather than stretching across it. */
.auth__card--wide { max-width: 880px; }

/* The privacy and cookie policy: a long text that must read well on a
   phone and print cleanly, in a card that otherwise holds forms. */
.legal { text-align: left; line-height: 1.55; }
.legal section { margin-top: var(--s-6); }
.legal h2 { font-size: var(--t-16); margin: 0 0 var(--s-2); letter-spacing: -0.01em; }
.legal p { margin: 0 0 var(--s-3); }
.legal__address { font-style: normal; margin: 0 0 var(--s-3); padding-left: var(--s-4); border-left: 2px solid var(--line); }
.legal__list { margin: 0 0 var(--s-3); }
.legal__list dt { font-weight: 600; margin-top: var(--s-3); }
.legal__list dd { margin: var(--s-1) 0 0; color: var(--ink-2); }
.legal__bullets { margin: 0 0 var(--s-3); padding-left: 1.25em; }
.legal__bullets li { margin-bottom: var(--s-2); }
.legal__cookies td { vertical-align: top; }
.legal__cookies td.mono { white-space: nowrap; }
.auth__card--wide .btn--primary, .auth__card--wide .btn--block { max-width: 360px; }

/* A secondary full-width action under the primary one — the passkey
   sign-in buttons, so far — matched to it in size rather than falling back
   to the compact default .btn, which reads as a stray, misaligned control
   next to a full-width submit button. */
.auth .btn--block { width: 100%; height: 36px; margin-top: var(--s-2); }

/* "or" between the password form and the passkey path: one word with a
   hairline on either side, so the two ways in read as alternatives. */
.auth__or {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin: var(--s-5) 0;
  color: var(--ink-3);
  font-size: var(--t-12);
}
.auth__or::before,
.auth__or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* The passkey section: the "or" divider, an opener button, and the
   dedicated email prompt it swaps for once pressed. The divider lives
   inside the section so that nothing passkey-related — not even a lone
   "or" — shows when WebAuthn is unavailable. */
.auth__alt .auth__or { margin-top: var(--s-5); }
.auth__alt .auth__or + .btn--block { margin-top: 0; }
.auth__passkey { margin-top: var(--s-3); }
.auth__passkey .auth__sub { margin-bottom: var(--s-4); }
/* No status yet: take no room, so the footer link sits right under Cancel. */
.auth__passkey .passkey-status:empty { display: none; }

/* The status line a passkey attempt reports into (an error, most of the
   time) — given breathing room from whatever sits above it instead of
   sitting flush against it, which the global margin reset otherwise leaves
   it. Centred only inside the auth card, where it sits under full-width
   buttons; left-aligned like the rest of the form on the account page. */
.passkey-status { margin-top: var(--s-3); color: var(--danger); min-height: 1em; }
.auth .passkey-status { text-align: center; }

/* Six-digit TOTP entry */
.code-input {
  font-family: var(--font-num);
  font-size: var(--t-20);
  letter-spacing: 0.4em;
  text-align: center;
  height: 44px;
  padding-left: 0.4em;
}

/* Text kept as typed — the clauses of a contract keep their paragraphs. */
.prewrap { white-space: pre-wrap; }

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

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }

  /* The drawer is pinned to top and bottom rather than given a height:
     on iOS 100vh is the viewport with the browser bars hidden, so a
     100vh drawer runs past the bottom bar and its last items can never
     be scrolled into view. top/bottom follow the visible viewport, and
     the safe-area inset keeps the last item above the home indicator. */
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    height: auto;
    max-height: none;
    width: var(--sidebar-w);
    z-index: 60;
    transform: translateX(-100%);
    transition: transform 180ms var(--ease);
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-bottom: env(safe-area-inset-bottom);
  }

  .sidebar[data-open="true"] { transform: none; }

  /* While the drawer is open the page behind it must not scroll: on iOS
     a scrolling body also moves the fixed drawer and the bottom bar. */
  body[data-nav-open] { overflow: hidden; position: fixed; inset: 0; width: 100%; }

  .scrim { position: fixed; inset: 0; background: rgb(0 0 0 / 0.4); z-index: 50; }

  .content { padding: var(--s-4); }
  .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }

  table.data { min-width: 560px; }
  /* A three-column schedule fits a phone without scrolling. */
  table.data--fit { min-width: 0; }
  /* The name column keeps enough room to read a name in two lines rather
     than eight; the table scrolls sideways for the rest. */
  table.data td > .cell-link, table.data td > .cell-strong { display: inline-block; min-width: 16ch; }
  .topbar { gap: var(--s-2); padding: 0 var(--s-3); }
  .topbar .select--bare { max-width: 110px; }

  /* The line editor still scrolls sideways on a phone, but with less to
     scroll: the columns give up the room a desktop can afford them. */
  .lines th:nth-child(1) { min-width: 150px; }
  .lines th:nth-child(2) { min-width: 100px; }
  .lines th:nth-child(3) { min-width: 70px; }
  .lines th:nth-child(4) { min-width: 96px; }
  .lines th:nth-child(5) { min-width: 90px; }
  .lines th:nth-child(6) { min-width: 80px; }
}

/* On a phone, upright or on its side, the unit goes under the number
   rather than beside it, so the number has the whole column and can be
   read and tapped. */
@media (max-width: 1024px) {
  .qty-cell { flex-direction: column; align-items: stretch; gap: 2px; }
  .qty-cell .input { min-width: 0; }
  .qty-cell .select { max-width: none; width: 100%; }
}

@media (max-width: 600px) {
  /* Initials are enough for the account button; the name is on the page it opens. */
  .topbar .nowrap { display: none; }
  /* The bar holds seven things on a phone: tighter gaps and a narrower
     language menu leave the page title room to be read. */
  .topbar { gap: var(--s-1); }
  .topbar .select--bare { max-width: 82px; padding-right: 22px; background-position: right 6px center; }
  /* Buttons keep their size; only the title gives way. */
  .topbar > .btn, .topbar > form, .topbar > .clock { flex: 0 0 auto; }
  /* The head's actions on a phone: a grid of two equal columns, so ten
     buttons make five even rows rather than a ragged heap. The main
     button takes a whole row at the top; a status badge and the autosave
     note each take a row of their own; a form around a button is
     transparent to the grid; a lone action spans both columns. */
  .page-head__actions {
    margin-left: 0;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-2);
  }
  .page-head__actions > form { display: contents; }
  .page-head__actions > form.pdf-lang { display: flex; grid-column: 1 / -1; order: -1; }
  .pdf-lang .btn--primary { flex: 1; }
  .page-head__actions .btn {
    width: 100%;
    min-height: 40px;
    height: auto;
    padding: var(--s-1) var(--s-2);
    white-space: normal;
    text-align: center;
    line-height: 1.25;
  }
  .page-head__actions > .btn--primary,
  .page-head__actions > form:not(.pdf-lang) > .btn--primary { grid-column: 1 / -1; order: 99; }
  .page-head__actions .pdf-lang .btn { white-space: nowrap; }
  .page-head__actions .pdf-lang .select { flex: 0 0 6.5rem; }
  .page-head__actions > .btn--danger { margin-right: 0; }
  .page-head__actions > .btn--danger,
  .page-head__actions > form > .btn--danger { grid-column: 1 / -1; order: -2; }
  /* Three buttons or fewer read better one under the other. */
  .page-head__actions:not(:has(> :nth-child(4))) { grid-template-columns: minmax(0, 1fr); }
  .form-actions { flex-direction: column; align-items: stretch; }
  .form-actions > .btn--danger, .form-actions > form:has(> .btn--danger) { margin-right: 0; }
  .form-actions .btn { width: 100%; min-height: 40px; justify-content: center; }
  .page-head__actions .btn--ghost { border-color: var(--line); }
  .page-head__actions > .badge { justify-self: center; align-self: center; }
  .page-head__actions > .autosave-status { grid-column: 1 / -1; justify-self: center; }
  .page-head__actions > .autosave-status:empty { display: none; }
  .page-head__actions > :only-child { grid-column: 1 / -1; }
}
@media (max-width: 360px) {
  /* On the narrowest phones the bar's title goes: the page heading sits
     right under it and says the same. */
  .topbar { padding: 0 var(--s-2); }
  .topbar__title { display: none; }
  .topbar .select--bare { max-width: 70px; }
  /* The search's magnifier needs the room; the phone's own bar tells the time. */
  .topbar > .clock { display: none; }
}

/* Fingers, not pointers: the small buttons in tables and toolbars grow to
   something that can actually be hit. */
@media (pointer: coarse) {
  .btn--sm { height: 36px; font-size: var(--t-13); }
  .btn--icon.btn--sm { width: 36px; }
  .seg__btn { padding: 7px var(--s-3); }
  :root { --field-h: 40px; }
  input[type="checkbox"], input[type="radio"] { width: 20px; height: 20px; }
  .nav__item, .nav__group > summary { min-height: 40px; }
}

@media (min-width: 901px) {
  .nav-toggle, .scrim { display: none; }
}

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

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

@media print {
  .sidebar, .topbar, .page-head__actions, .toolbar, .pager, .row-actions {
    display: none !important;
  }
  .app { grid-template-columns: 1fr; }
  .content { padding: 0; }
  .card, .table-wrap { border: 0; }
  table.data thead th { background: transparent; }
  body { background: #fff; }
}

/* ------------------------------------------------------------------- htmx */

.htmx-indicator { opacity: 0; transition: opacity var(--speed) var(--ease); }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }

.htmx-request.btn { pointer-events: none; opacity: 0.7; }

/* A thin progress line while a request is in flight. */
#progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 0;
  background: var(--accent);
  z-index: 100;
  transition: width 200ms var(--ease), opacity 200ms var(--ease);
  opacity: 0;
}

#progress[data-active="true"] { opacity: 1; }

/* The note that something is on its way: a page, a saved form, a bank
   read. Shown only once a wait lasts, so a quick page never flickers. */
.wait {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 110;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 8px 14px;
  border-radius: 14px;
  background: var(--ink);
  color: var(--surface);
  font-size: var(--t-13);
  line-height: 1.35;
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.18);
}
.wait__spin {
  flex: 0 0 auto;
  width: 14px; height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: wait-spin 0.8s linear infinite;
}
@keyframes wait-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .wait__spin { animation: none; border-right-color: currentColor; opacity: 0.6; }
}
@media print { .wait { display: none !important; } }

/* The papers attached to an expense: one row each, the actions at the end. */
/* The instant filter over a short list: a search box at the right, just
   above the table it narrows. */
.table-filter { display: flex; justify-content: flex-end; margin-bottom: var(--s-2); }
.table-filter .search { width: min(100%, 22rem); }

/* The inbox: the field that picks a paper's expense takes the room there is. */
.inbox-pick { white-space: normal; min-width: 18rem; }
table.data td > .small.muted.inbox-source { max-width: 60ch; }
.inbox-pick .input { flex: 1 1 14rem; min-width: 0; }
table.data td.inbox-pick > .small.muted { white-space: normal; overflow: visible; max-width: none; }
/* On a phone each paper is a block — its name, the field, the buttons —
   rather than a row to scroll sideways for. */
@media (max-width: 700px) {
  .inbox-table thead { display: none; }
  .inbox-table, .inbox-table tbody, .inbox-table tr, .inbox-table td { display: block; }
  table.data.inbox-table { min-width: 0; }
  table.data.inbox-table tbody td { border-bottom: 0; padding-top: var(--s-2); padding-bottom: var(--s-2); white-space: normal; }
  table.data.inbox-table tbody tr { border-bottom: 1px solid var(--line); padding: var(--s-2) 0; }
  .inbox-table .cell-link { overflow-wrap: anywhere; min-width: 0; }
  .inbox-pick { min-width: 0; }
}

/* The tooltip app.js shows in place of the browser's slow one. */
.tip {
  position: fixed; z-index: 90; width: max-content; max-width: min(18rem, 70vw); padding: 6px 8px;
  border-radius: 6px; background: var(--ink); color: var(--surface); font-size: 12px; line-height: 1.35;
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.15); pointer-events: none;
}
.tip[hidden] { display: none; }

/* The panel unfolded under a row of the expenses list. */
table.data tbody .row-panel > td { background: var(--surface-sunk); padding: 0; white-space: normal; }
/* The row whose panel is open stands out — a link to one document lands on
   it — and is not hidden under the sticky top bar when scrolled to. */
table.data tbody tr:has(+ .row-panel) > td { background: var(--accent-soft); }
table.data tbody tr:has(+ .row-panel) > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
table.data tbody tr[id] { scroll-margin-top: 96px; }
/* The table scrolls sideways on a phone and the panel must not: it keeps to
   the width that shows and stays put while the rows slide under it. */
.table-wrap:has(.row-panel) { container-type: inline-size; }
.row-panel__body { position: sticky; left: 0; box-sizing: border-box; width: 100cqw; max-width: 100%; padding: var(--s-4) var(--s-5); }
.row-panel__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: var(--s-5); }
/* Lists keep clear of the form under them; stacked fields rely on the grid's gap alone. */
.row-panel .doc-list { margin-bottom: var(--s-4); }
.row-panel .field-row .field { margin-bottom: 0; }
.row-panel__wide { grid-column: 1 / -1; }
.row-panel__title { font-size: inherit; margin: 0 0 var(--s-3); }
.doc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.doc-list__item { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.doc-list__item > svg { flex: 0 0 auto; color: var(--ink-3); }
.doc-list__text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }

/* A fold of a page — more filters, a summary. A closed <details> keeps its
   content hidden here too: WebKit hides it with display: none from its own
   stylesheet, which a toolbar's display: flex would otherwise override. */
.fold > summary { cursor: pointer; color: var(--ink-2); width: max-content; }
.fold:not([open]) > :not(summary) { display: none; }

/* ---- the header's search: everything in the company, from any page.
   The answer drops down while the form is open (app.js: .is-open, set on a
   touch or a letter, taken off by a touch elsewhere or Escape) — not while
   it has focus, which a phone takes away as a result is tapped. */
.gsearch { position: relative; flex: 1 1 320px; max-width: 420px; min-width: 0; }
.gsearch .search { display: block; max-width: none; min-width: 0; width: 100%; }
.gsearch .input { width: 100%; }
.gsearch__results {
  position: absolute;
  z-index: 80;
  top: calc(100% + 6px);
  left: 0;
  width: min(480px, calc(100vw - 16px));
  max-height: min(70vh, 560px);
  overflow-y: auto;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.14);
}
.gsearch__results:empty, .gsearch:not(.is-open) .gsearch__results { display: none; }
.search--wide { max-width: 560px; }
.gsearch__group + .gsearch__group { border-top: 1px solid var(--line); margin-top: 4px; padding-top: 4px; }
.gsearch__head { display: flex; justify-content: space-between; gap: var(--s-3); padding: 6px 10px 2px; font-size: var(--t-12); font-weight: 600; color: var(--ink-3); }
.gsearch__head a { color: var(--accent); font-weight: 400; text-decoration: none; }
.gsearch__head a:hover { text-decoration: underline; }
.gsearch__hit { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s-3); padding: 6px 10px; border-radius: var(--r-sm); color: var(--ink); text-decoration: none; font-size: var(--t-13); }
.gsearch__hit:hover, .gsearch__hit:focus-visible { background: var(--surface-hover); outline: none; }
.gsearch__title, .gsearch__sub { grid-column: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gsearch__title { font-weight: 500; }
.gsearch__sub { color: var(--ink-3); font-size: var(--t-12); }
.gsearch__meta { grid-column: 2; grid-row: 1 / span 2; align-self: center; color: var(--ink-3); font-size: var(--t-12); white-space: nowrap; }
.gsearch__empty { margin: 0; padding: 10px; color: var(--ink-3); font-size: var(--t-13); }
/* A phone would zoom into a box written smaller than 16px. */
@media (pointer: coarse) { .gsearch .input { font-size: var(--t-16); } }
/* On a tablet the box gives way first. */
@media (max-width: 1024px) { .gsearch { flex-basis: 200px; } }
/* On a phone it is a magnifier until touched, then it covers the bar and
   its answer takes the width of the screen. */
@media (max-width: 600px) {
  .topbar > form.gsearch { position: static; flex: 0 0 auto; }
  .gsearch .search { width: var(--field-h); }
  .gsearch .input { padding-right: 0; }
  /* Closed, the magnifier shows neither the words nor the prompt. */
  .gsearch:not(.is-open):not(:focus-within) .input, .gsearch:not(.is-open):not(:focus-within) .input::placeholder { color: transparent; }
  .gsearch:not(.is-open):not(:focus-within) .input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
  .gsearch.is-open .search, .gsearch:focus-within .search { position: absolute; z-index: 81; left: var(--s-2); right: var(--s-2); top: 50%; transform: translateY(-50%); width: auto; }
  .gsearch__results { position: fixed; top: calc(var(--header-h) + 4px); left: var(--s-2); right: var(--s-2); width: auto; }
}
@media print { .gsearch { display: none; } }

/* ---- email signature editor: a toolbar over a page-like area */
.sig-editor { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.sig-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 6px; border-bottom: 1px solid var(--line); background: var(--surface-sunk); }
.sig-group { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; }
.sig-toolbar label { position: relative; cursor: pointer; }
.sig-toolbar .select, .sig-toolbar .input { height: 30px; min-height: 30px; font-size: 13px; }
.sig-toolbar .sig-url { width: 10rem; max-width: 100%; }
.sig-swatch { display: inline-flex; align-items: center; gap: 3px; height: 30px; padding: 0 4px; border-radius: 6px; font-weight: 700; font-size: 13px; }
.sig-swatch:hover { background: var(--surface-hover); }
.sig-swatch svg { width: 16px; height: 16px; }
.sig-swatch input[type="color"] { width: 22px; height: 22px; padding: 0; -webkit-appearance: none; appearance: none; overflow: hidden; border: 0; outline: 1px solid color-mix(in srgb, var(--ink) 35%, transparent); outline-offset: 0; border-radius: 4px; background: transparent; cursor: pointer; }
/* Chrome draws its own padded, bordered box inside the swatch: a thick grey
   frame on the dark theme. Only the chosen colour is shown, edge to edge. */
.sig-swatch input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.sig-swatch input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 3px; }
.sig-swatch input[type="color"]::-moz-color-swatch { border: 0; border-radius: 3px; }
.sig-imagebar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 6px 10px; border-bottom: 1px solid var(--line); background: var(--accent-soft); }
.sig-imagebar input[type="range"] { width: 9rem; }
/* The signature is read in a mail program, on white, whatever the theme. */
.sig-area { min-height: 160px; padding: 14px 16px; background: #fff; color: #222; font: 14px/1.5 Arial, Helvetica, sans-serif; overflow-x: auto; outline: none; }
.sig-area:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); }
.sig-area img { max-width: 100%; height: auto; cursor: pointer; }
.sig-area img.is-picked { outline: 2px solid var(--accent); outline-offset: 2px; }
.sig-source { display: block; width: 100%; min-height: 220px; border: 0; border-radius: 0; font-size: 12px; }
.sig-preview { border: 1px solid var(--line); border-radius: var(--r-md); padding: 10px; background: var(--surface-sunk); }
.sig-preview__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
button.seg__btn { border: 0; background: transparent; cursor: pointer; font-family: inherit; }
.sig-mail { margin: 10px auto 0; max-width: 640px; background: #fff; color: #222; border: 1px solid #ddd; border-radius: 6px; overflow-x: auto; transition: max-width var(--speed) var(--ease); }
.sig-mail.is-mobile { max-width: 375px; }
.sig-mail__head { margin: 0; padding: 10px 14px; border-bottom: 1px solid #eee; color: #555; }
.sig-mail__head div { display: flex; gap: 8px; }
.sig-mail__head dt { min-width: 4.5em; color: #888; }
.sig-mail__head dd { margin: 0; overflow-wrap: anywhere; }
.sig-mail__body { padding: 14px; }
.sig-mail__body img { max-width: 100%; height: auto; }
.sig-mail__edit { width: 100%; min-height: 18em; background: #fff; color: #222; font-family: Arial, Helvetica, sans-serif; font-size: 14px; }
.sig-mail--text { padding: 14px; white-space: pre-wrap; font: 13px/1.5 ui-monospace, Menlo, monospace; }

/* A value and the button that copies it, side by side (partials/copy.html). */
.copy-field { display: flex; align-items: center; gap: var(--s-1); }
.copy-field > .input { flex: 1; min-width: 0; }

/* A receipt's day, editable in its row. */
.pay-date .input[type="date"] { width: 9.5rem; min-height: 26px; height: 26px; font-size: var(--t-12); }

/* Under an instalment on the printable sheet: what settled it. */
.doc-schedule__part td { padding-top: 0; padding-left: 1em; font-size: 0.85em; color: var(--ink-3, #666); }

/* The instalment generator on one line, its fields only as wide as they
   need; it wraps on a phone. */
.inst-split { align-items: center; }
.inst-split .input, .inst-split .select { width: auto; flex: 0 0 auto; }
.inst-split input[type="number"] { width: 5rem; }
.inst-split input[type="date"] { width: 10rem; }
.inst-split .select { min-width: 9rem; }

/* The export buttons at the end of a list's toolbar, and the narrow column
   of row boxes they read. */
.toolbar__end { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.cell-pick { width: 1%; padding-right: 0; }
.input-days { width: 9.5rem; }

/* A filter bar on a phone: «Dal» and «Al» side by side, half each, the
   search the whole width under them. */
@media (max-width: 600px) {
  .toolbar .dates { display: grid; grid-template-columns: 1fr 1fr; width: 100%; }
  .toolbar .dates__f { min-width: 0; }
  .toolbar .dates .input[type="date"] { width: 100%; min-width: 0; }
  .toolbar .search { flex-basis: 100%; max-width: none; }
}

/* A contract's clauses: paragraphs close together, an article's title in
   bold and set apart from the paragraph above it. */
.clauses p { margin: 0 0 .35em; white-space: pre-wrap; }
.clauses .clauses__h { font-weight: 600; margin-top: .9em; }
.clauses .clauses__h:first-child { margin-top: 0; }

/* A party's addresses, one under the other; «+» under the last. */
.emails { display: flex; flex-direction: column; gap: var(--s-1); align-items: flex-start; }
.emails > .input, .emails__row { width: 100%; }
.emails__row { display: flex; gap: var(--s-1); align-items: center; }
.emails__row .input { flex: 1 1 auto; min-width: 0; }

/* A sending's copies: the choice (none, CC, BCC) beside each address. */
.copy-row { display: flex; gap: var(--s-2); align-items: center; margin-bottom: var(--s-1); }
.copy-row .select { width: auto; }
.copy-row .input { flex: 1; min-width: 0; }
.copy-row__kind { min-width: 5.5em; }

/* Sums take the colour of their sign, everywhere they are shown. */
.amt-pos { color: var(--positive); }
.amt-neg { color: var(--danger); }
/* Money going out: an expense, a supplier, a purchase order is red even
   when stored positive; a credit received against it is money in. */
.money-out .amt-pos,
.gsearch__hit[href^="/expenses"] .amt-pos,
.gsearch__hit[href^="/orders"] .amt-pos,
.row:has(> a.cell-link[href^="/expenses/"]) .amt-pos { color: var(--danger); }
.money-out .amt-neg { color: var(--positive); }
/* A printed sheet is the paper itself: no colours. */
.sheet .amt-pos, .sheet .amt-neg { color: inherit; }
