/* Tokens. V's call, 11 Oct 2026: "make sure the UI/UX looks the same as wavesapp for now so the user don't get shock".
   The working area follows Wave's own values (read from its computed styles, Claude outputs/2026-10-11 Wave screen survey.md, "Visual style"):
   white page, ink #182127, secondary #515F66, navy sidebar #001B66, blue #0040FF for links and primary actions, pale blue #E0F2FF for selection,
   field edge #B2CFEB, pill buttons, 12px cards, 8px fields. The login door keeps the brand look. The pre-Wave light values are in PROJECT-NOTES.md (11 Oct 2026).
   Sizes are used by name (var(--type-*)) and never as pixel values. Weights are 400, 600, 700 and 900 only. */
:root{
  color-scheme:light;
  --pipe:rgba(24,33,39,.35);
  --font-ui:'DM Sans','Lato',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-brand:'Lato',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-num:var(--font-ui);
  --maxw:1440px; --gutter:18px; --radius:12px; --radius-sm:8px; --radius-xs:8px; --pill:500px;
  --type-2xs:12px; --type-xs:14px; --type-s:14px; --type-m:16px; --type-l:20px; --type-xl:33px; --type-xxl:28px;
  --hit:40px; --ease:cubic-bezier(.2,.7,.2,1); --ease-out:cubic-bezier(.23,1,.32,1); --btn-h:40px; --side-w:224px; --bar-h:56px; --row-h:56px; --page-max:1040px; --page-pad:var(--gutter);
  --bg-void:#ffffff; --bg-panel:#ffffff; --bg-panel-2:#f3f6f9; --bg-raised:#e0f2ff; --bg-inset:#ffffff;
  --divider:#dbe3ea; --line-strong:#b2cfeb;
  --text-primary:#182127; --text-secondary:#515f66; --text-tertiary:#566670; --text-nav:#001b66;
  --accent:#0040ff; --on-accent:#ffffff; --btn-strong:#ffffff; --btn-strong-hover:#e0f2ff; --accent-hover:#0033cc; --accent-soft:#e0f2ff;
  --flag:#c0352b;
  --ok-bg:#dff5e7; --ok-ink:#14612f; --warn-bg:#fdf0e7; --bad-bg:#fbe4e2; --bad-ink:#8f2d2d; --grey-bg:#eef1f4;
  --bar-bg:#e8f1fa; --bar-ink:#182127; --bar-ink-2:#515f66; --bar-line:#d3dfeb; --bar-chip:#c9dcf0;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html{background:var(--bg-void)}
html:has(body.gate){background:#0d0d0d}
body{background:var(--bg-void);color:var(--text-primary);font:400 var(--type-m)/1.35 var(--font-ui);-webkit-font-smoothing:antialiased;min-height:100vh;min-height:100dvh}
body.gate{background:#0d0d0d}
button,input,select{font:inherit;color:inherit;border:0;background:none}
a{color:var(--accent)}
button{cursor:pointer}
[hidden]{display:none!important}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
body.gate :focus-visible{outline-color:#e8e3d8}
::placeholder{color:var(--text-tertiary);opacity:1}

/* ---- Top bar: the lockup, exactly as in the product title guidelines ----
   The bar sets the mark's size (--brand-size). Every lockup measure is a fraction of it.
   The pipe's margins are the ink gap (1.0308 marks) less the neighbouring letter's side bearing, measured from the fonts by tests/lockup.test.mjs:
   after the pipe the name starts with I (left bearing .0623), so .9685em; before it the mark ends with a (right bearing .0493), so .9815em.
   The clear space after the name is 2.1221 marks less the last letter E's right bearing (.0384), so 2.0837 marks (.brand-clear). */
header.topbar{--brand-size:var(--type-l);position:relative;display:flex;align-items:center;height:56px;padding:0 var(--gutter);padding-top:env(safe-area-inset-top);box-sizing:content-box;background:var(--bar-bg);color:var(--bar-ink)}
header.topbar::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--bar-line)}
.brand-wrap{display:flex;align-items:baseline;min-width:0;height:var(--brand-size);font-size:var(--brand-size)}
/* The clear space after the name is its own flex item, so what follows (Sign out) can push it down to 14px on a phone and nothing is cut off. */
.brand-clear{flex:0 100 calc(var(--brand-size) * 2.0837);min-width:14px}
.brand-text{font-family:var(--font-brand);font-size:var(--brand-size);line-height:1;letter-spacing:0;color:var(--bar-ink);white-space:nowrap;text-decoration:none}
.brand-text .w-normal{font-weight:400} .brand-text .w-bold{font-weight:900}
.brand-pipe{flex:none;width:.0605em;height:.7233em;margin:0 .9685em 0 .9815em;background:var(--pipe);position:relative;top:.0516em}
.product{font-family:'Barlow',system-ui,sans-serif;text-decoration:none;text-transform:uppercase;font-weight:600;font-size:.85327em;line-height:1;letter-spacing:.1em;margin-right:-.1em;color:var(--bar-ink);white-space:nowrap}
.acct{display:flex;align-items:center;gap:12px;flex:0 0 auto;min-width:0;margin-left:auto}
.acct #bizMenu{display:flex;align-items:center;min-width:0}
.acct .menu-wrap{min-width:0}
/* The business switcher (Wave puts it at the right of the top bar): a white pill with the business name and a caret. The name shortens with an ellipsis. */
.biz-btn{display:inline-flex;align-items:center;gap:8px;max-width:min(300px,calc(100vw - 275px));min-height:var(--hit);padding:0 10px 0 16px;border:1px solid var(--line-strong);border-radius:var(--pill);background:var(--bg-panel);color:var(--text-nav);font-size:var(--type-s);font-weight:700;transition:background 120ms var(--ease),transform 140ms var(--ease)}
.biz-btn:active{transform:matrix(.97,0,0,.97,0,0)}
.biz-btn .pm-label{min-width:0;padding-right:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}   /* the 2px of slack: a name that fits exactly would otherwise show an ellipsis from sub-pixel rounding */
.biz-btn .caret{flex:none}
@media (hover:hover) and (pointer:fine){.biz-btn:hover{background:var(--accent-soft)}}
/* The user block inside the business menu: a round initial, then the name and the email. */
.avatar{flex:none;width:32px;height:32px;border-radius:50%;background:var(--bar-chip);color:var(--bar-ink);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:var(--type-xs);text-transform:uppercase}
.user-row{display:flex;align-items:center;gap:12px;padding:10px 12px}
.user-row .head-t,.user-row .head-s{overflow-wrap:anywhere}
.user-row>div{min-width:0}
/* The first stop for the keyboard: a button that is out of sight until it has focus, then jumps to the page. */
.skip{position:absolute;left:12px;top:-64px;z-index:30;min-height:var(--hit);padding:0 18px;border-radius:var(--pill);background:var(--accent);color:var(--on-accent);font-weight:600}
.skip:focus{top:8px}
.sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
@media (max-width:420px){header.topbar{--brand-size:calc(var(--type-l) - 2px)}.biz-btn{gap:6px;padding:0 8px 0 12px;max-width:calc(100vw - 253px)}}   /* the lockup, its gutters and the 14px of clear space keep their room; the pill takes the rest and shortens its name */
@media (min-width:960px){
  :root{--gutter:clamp(12px,3vw,28px);--page-pad:clamp(24px,4.4vw,64px)}
  header.topbar{--brand-size:var(--type-xxl);height:56px;padding:0 max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter)))}
}

/* ---- Workspace ---- */
.workspace{max-width:calc(var(--page-max) + 2 * var(--page-pad));padding:32px var(--page-pad) calc(48px + env(safe-area-inset-bottom));display:grid;grid-template-columns:minmax(0,1fr);gap:24px;align-items:start}
.panel{min-width:0;background:var(--bg-panel);border:1px solid var(--divider);border-radius:var(--radius);padding:20px;display:flex;flex-direction:column;gap:16px}
/* A panel arrives in 260ms. It only plays when the page changes, never when data arrives (the view is built once per page). */
.panel.arrive{animation:rise 260ms var(--ease)}
@keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
/* A caption over a figure or a field: sentence case, bold, the secondary ink. A caption that heads a panel is a section head: larger, primary ink. */
.eyebrow{font-size:var(--type-xs);font-weight:700;line-height:1.3;color:var(--text-secondary)}
.panel>.eyebrow,.due-head>.eyebrow{font-size:var(--type-l);font-weight:700;color:var(--text-primary)}

/* ---- Buttons ---- */
.btn{min-height:var(--hit);padding:0 20px;border:1px solid var(--accent);border-radius:var(--pill);background:var(--btn-strong);color:var(--accent);font-size:var(--type-m);font-weight:600;white-space:nowrap;transition:background 120ms var(--ease),transform 140ms var(--ease)}
.btn:active{transform:matrix(.97,0,0,.97,0,0)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.btn.small{min-height:30px;padding:0 16px;font-size:var(--type-s)}
.btn[disabled]{opacity:.45;cursor:default}
@media (hover:hover) and (pointer:fine){.btn:hover{background:var(--btn-strong-hover)}.btn.primary:hover{background:var(--accent-hover)}}

/* ---- Tables: rows are --hit tall, divided by a hairline, no zebra and no fills. The header row is the eyebrow style.
   Figures are right aligned, mono, tabular. An empty cell is blank. On a phone every row is two lines: the name and the state, then the figures. ---- */
.table{width:100%;border-collapse:collapse}
.table th{font-size:var(--type-2xs);font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-secondary);text-align:left;padding:0 12px 10px 0;border-bottom:1px solid var(--divider);white-space:nowrap;vertical-align:bottom}
.table td{min-height:56px;height:56px;padding:0 12px 0 0;border-bottom:1px solid var(--divider);vertical-align:middle;color:var(--text-secondary);font-size:var(--type-m)}
.table th.num,.table td.num{text-align:right;padding-right:0;padding-left:12px}
.table td.num{font-variant-numeric:tabular-nums}
.table th.state,.table td.state{text-align:right;padding-right:0;padding-left:12px}
.table tbody tr{transition:background 120ms var(--ease)}
@media (hover:hover) and (pointer:fine){.table tbody tr:hover{background:var(--bg-panel-2)}}
.table td .sub{display:block;font-size:var(--type-xs);color:var(--text-tertiary)}
@media (max-width:959px){
  .table,.table tbody{display:block}
  .table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .table tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));column-gap:12px;row-gap:10px;align-items:start;padding:12px 0;border-bottom:1px solid var(--divider)}
  .table td{display:block;height:auto;min-height:0;padding:0;border:0;min-width:0}
  .table td.name{grid-column:1 / 3;grid-row:1}
  .table td.state{grid-column:3;grid-row:1;text-align:right;padding:0}
  .table td.state .status{white-space:normal;text-align:right}
  .table td.num,.table td.text{text-align:left;padding:0}
  .table td.num[data-label]::before,.table td.text[data-label]::before{content:attr(data-label);display:block;font-family:var(--font-ui);font-size:var(--type-xs);font-weight:700;color:var(--text-secondary);margin-bottom:2px}
}

/* ---- Status words: coded by weight and brightness, never by colour. Red is a triangle, never a word on a panel. ---- */
.status{font-size:var(--type-2xs);font-weight:700;white-space:nowrap;display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:6px;line-height:1.4}
.status.act{color:var(--text-primary);background:repeating-linear-gradient(135deg,#eef1f4 0 4px,#e4e9ee 4px 8px)}
.status.done{color:var(--ok-ink);background:var(--ok-bg)}
.status.dead{color:var(--text-secondary);background:var(--grey-bg)}
.status.late{color:var(--bad-ink);background:repeating-linear-gradient(135deg,#fbe4e2 0 4px,#f6d3d0 4px 8px)}
.tri{flex:none;width:12px;height:11px;background:var(--flag);clip-path:polygon(50% 0,100% 100%,0 100%)}
/* A fact in a status line (Access's .note), for example "No jobs" or "Offline". Never an instruction under a button. */
.note{display:flex;align-items:center;gap:10px;min-height:20px;color:var(--text-secondary)}
.note:empty{display:none}

/* ---- Login door ---- */
#bg{position:fixed;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;display:none}
body.gate #bg{display:block}
#gate{display:none;position:relative;overflow:hidden;min-height:100vh;min-height:100dvh;align-items:center;justify-content:center;padding:24px var(--gutter);padding-top:calc(24px + env(safe-area-inset-top))}
#gate .login{display:flex;flex-direction:column;align-items:center;gap:44px;width:100%;max-width:360px;position:relative;z-index:2}
#gate .word{font-family:'Barlow',system-ui,sans-serif;font-weight:600;text-transform:uppercase;font-size:56px;line-height:1;letter-spacing:.1em;padding-left:.1em;color:#e8e3d8}
#gate .g-btn{display:inline-flex;align-items:center;justify-content:center;gap:12px;height:46px;padding:0 22px;border-radius:999px;border:1px solid rgba(232,227,216,0.22);color:#e8e3d8;font-family:var(--font-ui);font-size:var(--type-s);letter-spacing:.02em;background:transparent;transition:border-color 120ms var(--ease),background 120ms var(--ease),transform 140ms var(--ease)}
#gate .g-btn:active{transform:matrix(.97,0,0,.97,0,0)}
@media (hover:hover) and (pointer:fine){#gate .g-btn:hover{border-color:rgba(232,227,216,0.55);background:rgba(232,227,216,0.04)}}
#gate .g-btn svg{width:16px;height:16px;flex:none;opacity:.9}
/* The note is a plain fact in the page's ink. It is not red: red is a shape, never a word. */
#gate #gateNote{color:#e8e3d8;opacity:.72;font-size:var(--type-s);text-align:center;margin-top:-20px}
#gate .mark{position:absolute;left:0;right:0;bottom:calc(28px + env(safe-area-inset-bottom));display:flex;justify-content:center;z-index:2}
#gate .mark .brand-text{font-size:var(--type-xl);color:#e8e3d8;opacity:.9}
@media (min-width:960px){#gate .word{font-size:64px}#gate .mark .brand-text{font-size:30px}}
body.gate #gate{display:flex}
body.gate header.topbar,body.gate .shell,body.gate .skip{display:none}
main:focus{outline:none}

/* ---- Shell: the sidebar (Wave's grouping and sizes: 224px wide, 36px rows, parent groups open and close in place with a chevron) and the page.
   From 960px the sidebar is a column left of the page. Under 960px it is a bar of two things (the page you are on, Menu) and Menu opens the same page
   list as a panel from its corner (app.js sets data-open on the nav). While the panel is closed its links are display:none, so nothing hidden can be
   focused or adds scroll height. Never sideways scrolling. The business switcher is in the top bar at every width. ---- */
.shell{display:grid;grid-template-columns:minmax(0,1fr);align-items:start;max-width:var(--maxw);margin:0 auto}
.side a,.side .group-t{display:flex;align-items:center;height:36px;padding:0 12px;border-radius:var(--radius-sm);font-size:var(--type-s);color:var(--text-nav);text-decoration:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;transition:background 120ms var(--ease),color 120ms var(--ease)}
.side a[aria-current=page]{color:var(--text-nav);background:var(--accent-soft);font-weight:700}
.side .group{margin-top:4px}
.side .group-t{width:100%;justify-content:space-between;gap:8px;font-weight:700;text-align:left}
.side .group-t .chev{flex:none;display:inline-flex;transition:transform 150ms var(--ease-out)}
.side .group-t[aria-expanded=true] .chev{transform:rotate(90deg)}
.side .group-t:focus-visible .chev{transition:none}   /* the keyboard never animates */
.side .group-items{display:flex;flex-direction:column}
.side .group a{padding-left:28px}
.side .create{display:flex;margin:0 0 10px}
.side .create .menu-wrap{display:inline-flex}
.side .create-btn{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 18px 0 10px;border-radius:var(--pill);background:var(--accent-soft);color:var(--accent);font-size:var(--type-s);font-weight:700;transition:background 120ms var(--ease),transform 140ms var(--ease)}
.side .create-btn:active{transform:matrix(.97,0,0,.97,0,0)}
.side .create .menu{min-width:220px}
@media (hover:hover) and (pointer:fine){.side a:hover,.side .group-t:hover{background:var(--bg-panel-2)}.side a[aria-current=page]:hover{background:var(--accent-soft)}.side .create-btn:hover{background:#cfe8fb}}
@media (max-width:959px){
  .side{position:relative;display:flex;align-items:center;gap:12px;min-height:calc(var(--hit) + 8px);padding:4px var(--gutter);border-bottom:1px solid var(--divider)}
  .side .now{flex:1 1 0;min-width:0;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-size:var(--type-s);font-weight:700;line-height:1.3;color:var(--text-primary)}
  .side .side-menu{flex:none;margin-left:auto}
  .side .side-menu[aria-expanded=true]{background:var(--btn-strong-hover)}
  .side .links{display:none}
  .side[data-open] .links{display:block;position:absolute;z-index:6;left:var(--gutter);right:var(--gutter);top:calc(100% + 4px);max-height:calc(100dvh - 124px);overflow-y:auto;padding:6px;background:var(--bg-panel);border:1px solid var(--line-strong);box-shadow:0 8px 24px rgba(0,0,0,.18);border-radius:var(--radius-sm);transform-origin:top right;animation:pop 150ms var(--ease)}
  .side[data-kb] .links{animation:none}   /* opened from the keyboard: no animation */
  .side a,.side .group-t{height:48px;transition:color 120ms var(--ease),transform 140ms var(--ease)}
  .side a:active{transform:matrix(.97,0,0,.97,0,0)}
  .side .group{margin-top:4px;padding-top:4px;border-top:1px solid var(--divider)}
  .side .create{margin:2px 0 8px}
  .side .create .menu{max-width:calc(100vw - 2 * var(--gutter) - 14px)}
}
@media (min-width:960px){
  .shell{grid-template-columns:var(--side-w) minmax(0,1fr)}
  .side{display:block;position:sticky;top:0;align-self:start;padding:18px 12px 18px var(--gutter);border-right:1px solid var(--divider);min-height:calc(100dvh - var(--bar-h));max-height:100dvh;overflow-y:auto;overflow-x:hidden}
  .side .now,.side .side-menu{display:none}
  .side .create .menu{min-width:0;width:max-content;max-width:calc(var(--side-w) - var(--gutter) - 16px)}   /* the column is 224px and scrolls: a menu wider than it would be cut off at its right edge */
}
.workspace{margin:0;width:100%}

/* ---- Loading: a page that takes longer than 150ms to arrive shows a ring turning in the middle of the page (Wave's blue circle). It turns once every 600ms:
   a constant motion, so linear, and quick, so loading feels short. Nothing else repeats. ---- */
.loading{display:flex;align-items:center;justify-content:center;min-height:50dvh}
.loading-ring{width:40px;height:40px;border-radius:50%;border:4px solid var(--accent-soft);border-top-color:var(--accent);animation:load-spin 600ms linear infinite}
@keyframes load-spin{to{transform:rotate(360deg)}}

/* ---- Page head, summary strip, filters, segmented tabs ---- */
.page-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.page-head h1{font-size:var(--type-xl);font-weight:700;line-height:1.15;color:var(--text-primary)}
.head-actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
a.btn{display:inline-flex;align-items:center;text-decoration:none}
.btn.quiet{background:transparent;border-color:transparent;min-height:36px;padding:0 10px;font-size:var(--type-s);font-weight:700;color:var(--accent);text-decoration:none}
@media (hover:hover) and (pointer:fine){.btn.quiet:hover{background:var(--accent-soft)}}
/* The summary strip (Wave's card above a list): one white card, the figures side by side with a hairline between them, stacked on a phone.
   <section class="panel strip"><div class="stat"><div class="eyebrow">Overdue</div><div class="big">$0.00</div></div> ... </section> */
.strip{flex-direction:row;flex-wrap:wrap;gap:0;padding:0;overflow:hidden}
.strip .stat{flex:1 1 180px;min-width:0;padding:16px 24px}
.strip .stat+.stat{border-left:1px solid var(--divider)}
.strip .stat .eyebrow{font-size:var(--type-xs);font-weight:700;color:var(--text-secondary)}
@media (max-width:719px){.strip{flex-direction:column}.strip .stat{flex:none;padding:14px 18px}.strip .stat+.stat{border-left:0;border-top:1px solid var(--divider)}}
.stat{min-width:0}
.big{font-size:var(--type-l);font-weight:700;font-variant-numeric:tabular-nums;margin-top:4px;color:var(--text-primary)}
/* The filter row: the controls side by side (customer, status, From, To, number), one row on a desktop, wrapping on a phone. A count line sits above it:
   <div class="fcount"><span class="bubble">0</span> Active filters</div> */
.filters,.toolbar{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.fcount{display:flex;align-items:center;gap:8px;color:var(--text-secondary);font-size:var(--type-s)}
.bubble{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 6px;border-radius:var(--pill);background:#e9eef2;color:var(--text-primary);font-size:var(--type-2xs);font-weight:700;font-variant-numeric:tabular-nums}
input,select,textarea{font:inherit;color:var(--text-primary);background:var(--bg-inset);border:1px solid var(--line-strong);border-radius:var(--radius-sm);padding:0 12px;min-height:var(--hit);width:100%;color-scheme:light;transition:border-color 120ms var(--ease)}
textarea{padding:10px 12px;resize:vertical;line-height:1.4}
input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--accent);outline-offset:0;border-color:var(--accent)}
input[disabled]{background:var(--bg-panel-2);color:var(--text-secondary)}
/* Segmented tabs (Unpaid, Draft, All invoices): a light blue pill track, the chosen segment white and bold, a count bubble after the word, centred under the filters.
   <div class="seg" role="tablist"><button role="tab" aria-selected="true">Unpaid <span class="bubble">2</span></button> ... </div> */
.panel>.seg{align-self:center}
.seg{display:inline-flex;gap:2px;flex-wrap:wrap;padding:4px;background:var(--accent-soft);border-radius:var(--pill)}
.seg button .bubble{margin-left:8px;background:rgba(0,64,255,.12);color:var(--accent)}
.seg button[aria-selected=true] .bubble{background:var(--accent-soft)}
.seg button{min-height:34px;padding:0 18px;border-radius:var(--pill);font-weight:600;font-size:var(--type-s);color:var(--accent);transition:background 120ms var(--ease),color 120ms var(--ease),transform 140ms var(--ease)}
@media (hover:hover) and (pointer:fine){.seg button:hover{background:#cfe8fb}.seg button[aria-selected=true]:hover{background:var(--bg-panel)}}
.seg button:active{transform:matrix(.97,0,0,.97,0,0)}
.seg button[aria-selected=true]{background:var(--bg-panel);color:var(--text-primary);box-shadow:0 1px 2px rgba(24,33,39,.12)}
.rowlink{color:var(--accent);font-weight:700;text-decoration:none}
@media (hover:hover) and (pointer:fine){.rowlink:hover{text-decoration:underline}}
.table th.act,.table td.act{text-align:right;padding-right:0;width:1%;white-space:nowrap}
.table td.text{font-size:var(--type-s)}
@media (min-width:960px){
  .table.inv th.state{text-align:left;padding:0 18px 10px 0}
  .table.inv td.state{text-align:left;padding:0 18px 0 0}
  .table.inv th.num,.table.inv td.num{padding-right:18px}
}

/* ---- Menus: open from the button's corner in 150 ms ease-out (never when opened from the keyboard). Rows are 40px; a heading row holds a name and a second line
   (the user block); a rule is a hairline; a danger row is red. form.js popMenu builds them, splitButton and rowActions use them. ---- */
.menu-wrap{position:relative;display:inline-block}
.menu{position:absolute;right:0;top:calc(100% + 4px);z-index:5;min-width:200px;max-width:calc(100vw - 2 * var(--gutter));max-height:calc(100dvh - 96px);overflow-y:auto;list-style:none;background:var(--bg-panel);border:1px solid var(--divider);box-shadow:0 8px 24px rgba(24,33,39,.16);border-radius:var(--radius);padding:6px;transform-origin:top right;animation:pop 150ms var(--ease-out)}
.menu.pop.left{left:0;right:auto;transform-origin:top left}
.menu.pop.right{right:0;left:auto;transform-origin:top right}
.menu[data-kb]{animation:none}
.menu button,.menu .item{display:flex;align-items:center;width:100%;min-height:40px;padding:0 12px;border-radius:var(--radius-xs);font-size:var(--type-s);color:var(--text-primary);text-align:left;text-decoration:none;transition:background 120ms var(--ease)}
.menu .item:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;background:var(--accent-soft)}
.menu .item.danger{color:var(--bad-ink)}
.menu .item[disabled]{color:var(--text-tertiary);cursor:default}
.menu .item .it-t{display:block;font-weight:600}
.menu .item .it-s{display:block;color:var(--text-secondary);font-size:var(--type-xs)}
.menu .item:has(.it-t){flex-direction:column;align-items:flex-start;justify-content:center;padding-top:6px;padding-bottom:6px}
.menu .rule{height:1px;margin:6px 4px;background:var(--divider)}
.menu .head{padding:8px 12px;cursor:default}
.menu .head-t{font-weight:700;overflow-wrap:anywhere}
.menu .head-s{color:var(--text-secondary);font-size:var(--type-xs);overflow-wrap:anywhere}
.menu .head.small .head-t{font-size:var(--type-xs);font-weight:700;color:var(--text-secondary)}
.menu .head.small{padding-bottom:2px}
@media (hover:hover) and (pointer:fine){.menu button:hover,.menu .item:hover{background:var(--accent-soft)}.menu .item[disabled]:hover{background:none}}
@keyframes pop{from{opacity:0;transform:matrix(.97,0,0,.97,0,0)}to{opacity:1;transform:none}}
.biz-menu .menu{min-width:280px}
.biz-menu .head-t{font-size:var(--type-m)}
@media (max-width:959px){.menu button,.menu .item{min-height:44px}}

/* ---- Forms ---- */
.form{gap:14px}
.field{display:flex;flex-direction:column;gap:6px;min-width:0}
.field .lbl{font-size:var(--type-xs);font-weight:700;color:var(--text-secondary)}
.form .actions,.actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center;justify-content:flex-end}
.inv-form .top{display:grid;grid-template-columns:minmax(0,1fr);gap:18px}
@media (min-width:960px){.inv-form .top{grid-template-columns:minmax(0,1fr) 320px}}
.cust{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.cust .field{width:100%}
.cust-card{background:var(--bg-panel-2);border-radius:var(--radius-xs);padding:12px;width:100%;line-height:1.45}
.quick{display:grid;gap:8px;width:100%}
.meta{display:grid;gap:12px}
.lines{display:flex;flex-direction:column;gap:10px}
.l-head{display:none}
.l-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;padding:12px 0;border-top:1px solid var(--divider);align-items:center}
.l-item{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:8px}
.l-item>select,.l-item>.kind-fixed{flex:1 1 150px}
.l-item>input{flex:3 1 220px}
.l-act{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:4px}
.l-row .btn{justify-self:end}
.n{text-align:right}
input.n{font-family:var(--font-num)}
.amt{font-family:var(--font-num);font-variant-numeric:tabular-nums}
.kind-fixed{font-weight:700;min-height:44px;display:flex;align-items:center}
.l-add{display:flex;gap:10px;flex-wrap:wrap}
@media (min-width:960px){
  .l-head,.l-row{display:grid;grid-template-columns:minmax(0,1fr) 90px 120px 120px 170px;gap:10px;align-items:center}
  .l-head{font-size:var(--type-xs);font-weight:700;color:var(--text-secondary);padding-bottom:8px;border-bottom:2px solid var(--text-primary)}
  .l-item{grid-column:auto;flex-wrap:nowrap}
}
.totals{display:flex;flex-direction:column;align-items:flex-end;gap:8px}
.totals dl{display:grid;grid-template-columns:auto auto;gap:6px 28px;text-align:right}
.totals dd{font-family:var(--font-num);font-variant-numeric:tabular-nums}
.totals .due,.p-totals .due,.p-dates .due{font-weight:700}
.cur{color:var(--text-secondary);font-size:var(--type-s)}
.preview{margin-top:0}

/* ---- Invoice page: overview, three step cards, then the paper ---- */
.overview{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 18px}
.overview .r{text-align:right}
@media (min-width:960px){.overview{grid-template-columns:repeat(4,minmax(0,1fr))}}
.steps{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
@media (min-width:960px){.steps{grid-template-columns:repeat(3,minmax(0,1fr))}}
.step{background:var(--bg-panel);border:1px solid var(--divider);border-radius:var(--radius);padding:18px;display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.step-t{font-size:var(--type-l);font-weight:700}
.fact{display:flex;gap:10px;flex-wrap:wrap}
.fact .k{color:var(--text-tertiary)}

/* ---- The printed invoice: light paper, one proposal until V approves a sample (brand: Print) ---- */
.paper{background:#fff;color:#161616;border-radius:var(--radius-xs);padding:28px 22px;display:flex;flex-direction:column;gap:22px;font-size:var(--type-s);line-height:1.4;max-width:860px;width:100%;justify-self:center;box-shadow:0 0 0 1px var(--divider)}
.p-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.p-brand{font-size:var(--type-xxl);letter-spacing:0}
.p-brand .w-normal{font-weight:400}.p-brand .w-bold{font-weight:900}
.p-title{text-align:right}.p-word{font-size:36px;font-weight:300;letter-spacing:-.015em;text-transform:uppercase}.p-no{color:#555}
.p-from{line-height:1.45}
.p-meta{display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap}
.p-name{font-weight:700}
.p-dates,.p-totals{display:grid;grid-template-columns:auto auto;gap:4px 18px;text-align:right;align-content:start}
.p-dates dt,.p-totals dt{color:#555}
.p-lines{width:100%;border-collapse:collapse}
.p-lines th{background:#808080;color:#fff;text-align:left;padding:8px 10px;font-weight:700}
.p-lines td{padding:10px;vertical-align:top;border-bottom:1px solid #e4e4e4}
.p-lines th.n,.p-lines td.n{text-align:right;font-variant-numeric:tabular-nums}
.p-kind{font-weight:700}.p-desc{color:#444;white-space:pre-line}
.p-totals{justify-self:end}
.p-cap{font-weight:700;margin-bottom:4px}.p-memo{white-space:pre-line;margin-bottom:6px}
@media print{.paper{box-shadow:none}body{background:#fff}header.topbar,.side,.page-head,.overview,.steps,.actions,.note{display:none!important}.shell{display:block}.paper{max-width:none;padding:0}}

/* ---- Businesses: the first-sign-in choice, the switcher in the top bar, and the support banner (schema design 17) ---- */
#onboard{display:flex;flex-direction:column;gap:18px;width:100%;color:#e8e3d8}
#onboard .row{display:flex;flex-direction:column;gap:10px;padding:14px;border:1px solid rgba(232,227,216,0.22);border-radius:var(--radius-sm)}
#onboard .row .who{font-weight:700}
#onboard .row .by{font-size:var(--type-xs);color:rgba(232,227,216,0.72)}
#onboard .lbl{font-size:var(--type-xs);font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:rgba(232,227,216,0.72)}
#onboard input{background:rgba(0,0,0,.3);border-color:rgba(232,227,216,0.22);color-scheme:dark}
#onboard ::placeholder{color:rgba(232,227,216,0.72)}
.banner{padding:10px var(--gutter);background:var(--bg-panel-2);border-bottom:1px solid var(--divider);font-weight:700;font-size:var(--type-s)}

/* ---- Vendors and bills (ui/vendors.js, ui/bills.js): two-column form grid, tick box, short lists, bill lines, bill page facts, Record a payment ---- */
.cols2{display:grid;grid-template-columns:minmax(0,1fr);gap:14px}
.span2{grid-column:1 / -1}
.check{display:flex;align-items:center;gap:12px;min-height:var(--hit);cursor:pointer}
.check input{width:22px;height:22px;min-height:0;flex:none;padding:0;accent-color:var(--accent)}
.multi{gap:6px}
.multi-row{display:flex;gap:8px;align-items:center}
.multi-row input{flex:1 1 auto;min-width:0}
.b-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:14px 0;border-top:1px solid var(--divider);align-items:end}
.b-row .f-kind,.b-row .f-desc{grid-column:1 / -1}
.b-row .f-rm{justify-self:end}
.action-box:empty{display:none}
.facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 18px}
.fact-i{min-width:0}
.fact-i.wide{grid-column:1 / -1}
.fact-v{margin-top:4px;overflow-wrap:anywhere}
.pre{white-space:pre-line}
.row-actions{display:inline-flex;gap:4px;flex-wrap:wrap}
.when{font-size:var(--type-l);font-weight:700;margin-top:4px}
.alloc{display:flex;flex-direction:column}
.alloc-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 12px;align-items:end;padding:12px 0;border-top:1px solid var(--divider)}
.alloc-name{grid-column:1 / -1;font-weight:700}
.alloc-name .sub{display:block;font-size:var(--type-xs);font-weight:400;color:var(--text-tertiary)}
.alloc-due{display:flex;flex-direction:column;gap:6px}
.alloc-due .amt{min-height:40px;display:flex;align-items:center}
@media (max-width:959px){
  .table td.act-wide{grid-column:1 / -1;text-align:left}
  .table.inv td.act.act-wide{grid-column:1 / -1;text-align:left}   /* the payment rows' buttons sit on their own row: .table.inv td.act would put them in column 3 and push the page sideways */
  .overview.bill .r{text-align:left}
  .table.vend td.email{grid-column:1 / 3;overflow-wrap:anywhere}
  .table.bills td.num{grid-column:1 / 3}
  .table.pur td.act,.table.pays td.act{width:auto}
  .table.vend td.act{text-align:left}
  .table.vend td.act .menu-wrap{margin-left:-10px}
  .table.vend td.num{grid-column:3}
  .table.bills td.act{grid-column:3;justify-self:end}
  .table.pur td.num:empty,.table.pur td.text:empty{display:none}
  .table.blines td.name{grid-column:1 / -1}
  .table.pays td.state{grid-column:1 / -1;text-align:left}
}
@media (min-width:960px){
  .cols2{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 18px}
  .facts{grid-template-columns:repeat(4,minmax(0,1fr))}
  .b-row{grid-template-columns:repeat(12,minmax(0,1fr))}
  .b-row .f-kind{grid-column:span 3}
  .b-row .f-desc{grid-column:span 9}
  .b-row .f-qty,.b-row .f-rate,.b-row .f-amt,.b-row .f-paid,.b-row .f-to,.b-row .f-rm{grid-column:span 2}
  .alloc-row{grid-template-columns:minmax(0,1fr) 160px 160px}
  .alloc-name{grid-column:auto}
  .row-actions{flex-wrap:nowrap}
  .table.vend th.num,.table.vend td.num{padding-right:18px}
}

/* ---- Estimates (ui/estimates.js): the printed estimate's title, summary and footer, the buttons inside a step card, the job pick on the form ---- */
.p-doc{display:flex;flex-direction:column;gap:2px}
.p-doc-title{font-weight:700}
.p-summary{color:#444;white-space:pre-line}
.p-footer{border-top:1px solid #e4e4e4;padding-top:12px;color:#555;font-size:var(--type-xs);line-height:1.45}
.step-act{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.step-act:empty{display:none}
.job-box:empty{display:none}

/* ---- Products, tags and recurring invoices (ui/items.js, ui/tags.js, ui/recurring.js): item sides, tag picker, schedule grid, Due now strip, the three lists on a phone ---- */
.item-side{display:flex;flex-direction:column;gap:10px;padding-top:14px;border-top:1px solid var(--divider)}
.trio{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 12px}
.trio>.field:first-child{grid-column:1 / -1}
.sched,.cols4{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 12px;align-items:end}
.tagpick{display:flex;flex-wrap:wrap;gap:8px}
.tagbtn{min-height:44px;padding:0 14px;border-radius:var(--radius-xs);border:1px solid var(--line-strong);color:var(--text-primary);font-size:var(--type-s);transition:background 120ms var(--ease),color 120ms var(--ease),transform 140ms var(--ease)}
.tagbtn:active{transform:matrix(.97,0,0,.97,0,0)}
.tagbtn[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:700}
.tagbtn.off{color:var(--text-tertiary)}
@media (hover:hover) and (pointer:fine){.tagbtn:hover{background:var(--bg-panel-2)}.tagbtn[aria-pressed=true]:hover{background:var(--accent)}}
.tagnone{color:var(--text-tertiary);min-height:44px;display:flex;align-items:center}
.due-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.due-list{list-style:none;display:flex;flex-direction:column}
.due-list li{display:grid;grid-template-columns:minmax(0,1fr);gap:2px;padding:12px 0;border-top:1px solid var(--divider)}
.due-who{font-weight:700}
.due-when{color:var(--text-secondary);font-variant-numeric:tabular-nums}
.table.cat td:empty::before{content:none}
@media (max-width:959px){
  .table.cat tr{grid-template-columns:minmax(0,1fr) auto}
  .table.cat td.name{grid-column:1;grid-row:1}
  .table.cat td.act{grid-column:2;grid-row:1;text-align:right;align-self:center}
  .table.cat td.act .btn{margin-right:-10px}
  .table.cat td.wide{grid-column:1 / -1}
  .table.cat td.wide:empty{display:none}
  .table.rec tr{grid-template-columns:minmax(0,1fr) auto auto}
  .table.rec td.state{grid-column:2;grid-row:1;align-self:center}
  .table.rec td.act{grid-column:3}
  .table.rec td.t-title{grid-column:1 / -1}
  .table.rec td.t-sched{grid-column:1}
  .table.rec td.t-next{grid-column:2 / 4}
}
@media (min-width:960px){
  .trio{grid-template-columns:repeat(3,minmax(0,1fr))}
  .trio>.field:first-child{grid-column:auto}
  .sched{grid-template-columns:repeat(5,minmax(0,1fr))}
  .cols4{grid-template-columns:repeat(4,minmax(0,1fr))}
  .due-list li{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 180px;gap:12px;align-items:center}
  .table.cat th.num,.table.cat td.num{padding-right:18px}
  .table.rec th.state{text-align:left;padding:0 18px 10px 0}
  .table.rec td.state{text-align:left;padding:0 18px 0 0}
}

/* ---- Settings and Team (ui/settings.js): the page repaints inside one wrapper that takes no box of its own; a panel's later section heads get air above;
   the team tables share one column grid (Email, Role, then Status or Invited by, then the actions) and become two-line rows on a phone ---- */
.stack{display:contents}
.stack .panel>.eyebrow:not(:first-child){margin-top:10px}
.stack .cols4{gap:14px 18px}
.table.team td.act .row-actions{margin-right:-10px}
@media (max-width:959px){
  .table.team tr{grid-template-columns:minmax(0,1fr) auto}
  .table.team td.name{grid-column:1;grid-row:1}
  .table.team td.state{grid-column:2;grid-row:1}
  .table.team td.text{grid-column:1 / -1}
  .table.team td.text[data-label="Role"]::before{display:none}
  .table.team td.act{grid-column:1 / -1;text-align:left;width:auto}
  .table.team td.act:has(.row-actions:empty){display:none}
  .table.team td.act .row-actions{margin:0 0 0 -10px}
}
@media (min-width:960px){
  .table.team{table-layout:fixed}
  .table.team th.name{width:38%}
  .table.team th.text{width:24%}
  .table.team th.state{width:14%}
  .table.team th.act{width:24%}
  .table.team.pend th.act{width:14%}
  .table.team th.state{text-align:left;padding:0 18px 10px 0}
  .table.team td.state{text-align:left;padding:0 18px 0 0}
}

/* ---- Invoices (ui/invoices.js): the Edit columns panel, the attachment list, and the printed invoice on a phone ----
   On a phone the paper gives up some padding and its line table uses a fixed layout, so the money columns keep their width and the item column
   wraps; before this the table was wider than the paper's content box by a few pixels. */
.cols-box{display:flex;flex-direction:column;gap:14px}
.file-list{list-style:none;display:flex;flex-direction:column}
.file-list li{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 0;border-top:1px solid var(--divider)}
.file-name{display:flex;flex-direction:column;min-width:0;overflow-wrap:anywhere}
.file-name .sub{font-size:var(--type-xs);color:var(--text-tertiary)}
.p-item{overflow-wrap:anywhere}
/* The line editor's last cell holds Save as item and Remove: wide enough for both on a desktop, a full-width right-aligned row on a phone. */
@media (max-width:959px){
  .l-act{grid-column:1 / -1}
  .table.inv td.num{grid-column:1 / 3}
  .table.inv td.act{grid-column:3;width:auto}
  .table.clist tr{grid-template-columns:minmax(0,1fr) auto}
  .table.clist td.name{grid-column:1;grid-row:1}
  .table.clist td.act{grid-column:2;grid-row:1;width:auto;align-self:center}
  .table.clist td.text,.table.clist td.num{grid-column:1 / -1;overflow-wrap:anywhere}
  .table.clist td.text:empty,.table.clist td.num:empty{display:none}
}
@media (min-width:960px){.l-head,.l-row{grid-template-columns:minmax(0,1fr) 90px 120px 120px 240px}}
@media (max-width:520px){
  .overview .big{font-size:var(--type-l)}
  .paper{padding:24px 16px}
  .p-lines{table-layout:fixed}
  .p-lines th,.p-lines td{padding:8px 6px}
  .p-lines th.n{width:25%}
  .p-lines th.n:nth-child(2){width:17%}
}

/* ---- Reports (ui/reports.js): the index, report tables with a totals row, the Checks findings, Exports ---- */
.rep-index{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;align-items:start}
.rep-list{list-style:none;display:flex;flex-direction:column}
.rep-list a{display:flex;align-items:center;min-height:var(--hit);border-top:1px solid var(--divider);color:var(--text-primary);font-weight:700;text-decoration:none;transition:color 120ms var(--ease)}
@media (hover:hover) and (pointer:fine){.rep-list a:hover{color:var(--text-secondary)}}
.rep-out{display:flex;flex-direction:column;gap:14px;min-width:0}
.filters.rep-f{grid-template-columns:repeat(auto-fill,minmax(160px,220px))}
.table.rep tr.total td{font-weight:700}
.table.rep tr.total td a{font-weight:700}
.find-list{list-style:none;display:flex;flex-direction:column}
.find{display:flex;flex-direction:column;gap:4px;padding:12px 0;border-top:1px solid var(--divider)}
.find-h{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.find-c{font-weight:700}
.find-m{color:var(--text-secondary);overflow-wrap:anywhere}
.find-t{display:flex;align-items:center;gap:8px}
.finds.info .find-c{font-weight:400;color:var(--text-secondary)}
.finds.info .find-m{color:var(--text-tertiary)}
.fact-v.sum{font-family:var(--font-num)}
.find-h a{position:relative}
.find-h a::after{content:"";position:absolute;inset:-14px -8px -14px -16px}
@media (max-width:959px){
  .table.rep td.name{grid-column:1 / -1}
  .table.rep td:empty{display:none}
  .table.rep td.wide{grid-column:1 / -1}
  .filters.rep-f{grid-template-columns:minmax(0,1fr)}
  .table.rep tr.total{border-top:1px solid var(--text-tertiary)}
  .table.files td.act{grid-column:3;justify-self:end;width:auto}
}
@media (min-width:960px){
  .rep-index{grid-template-columns:repeat(2,minmax(0,1fr))}
  .table.files th.num,.table.files td.num{padding-right:18px}
  .table.rep tr.total td{border-top:1px solid var(--text-tertiary)}
}

@media (prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}
@media (prefers-reduced-motion:reduce){dialog.dlg::backdrop,dialog.dlg[open]::backdrop{animation:none!important}}   /* * does not match ::backdrop, so the dialog's fade is switched off by name */

/* ---- Finalize, payments, void and corrections (ui/invoices.js, ui/payments.js): plain lines for what a plan said, the payments that block a void ---- */
.plain{list-style:none;display:flex;flex-direction:column;gap:6px}
.plain .blocker{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:6px 0;border-top:1px solid var(--divider)}
.problems{display:flex;flex-direction:column;gap:10px}
.problems:empty{display:none}
@media (max-width:959px){
  .table.fpays td.text:empty,.table.fpays td.num:empty,.table.fpays td.act:empty{display:none}
}

/* ---- Shared components for every page (built by form.js: splitButton, openDialog, confirmDialog, rowActions, emptyState) ---- */
.btn.danger{background:#c0352b;border-color:#c0352b;color:#fff}
@media (hover:hover) and (pointer:fine){.btn.danger:hover{background:#a52b22}}
/* A split button: a pill with a caret part that opens a small menu (Wave's "Save and continue"). Works filled (btn primary) and as an outline (btn). */
.split{display:inline-flex;align-items:stretch;vertical-align:middle}
.split>.menu-wrap{display:inline-flex}
.split .split-main{border-top-right-radius:0;border-bottom-right-radius:0;padding-right:18px}
.split .split-caret{width:42px;min-height:var(--hit);padding:0;display:inline-flex;align-items:center;justify-content:center;border-top-left-radius:0;border-bottom-left-radius:0;border-left-color:rgba(255,255,255,.6)}
.split .btn:not(.primary).split-caret{border-left-color:var(--accent);margin-left:-1px}
.split .caret{flex:none}
/* The Actions cell of a table: a bold blue link and a 32px circle outline button with a caret. */
.act-cell{display:inline-flex;align-items:center;justify-content:flex-end;gap:12px}
button.rowlink{padding:0;min-height:32px;font-size:inherit}
.circle-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;min-height:32px;padding:0;border:1px solid var(--accent);border-radius:50%;background:var(--bg-panel);color:var(--accent);transition:background 120ms var(--ease),transform 140ms var(--ease)}
.circle-btn:active{transform:matrix(.97,0,0,.97,0,0)}
@media (hover:hover) and (pointer:fine){.circle-btn:hover{background:var(--accent-soft)}}
/* An empty list: a bold centred heading, a grey line and an outline pill. */
.empty{display:flex;flex-direction:column;align-items:center;gap:10px;padding:48px 16px;text-align:center}
.empty-t{font-size:var(--type-l);font-weight:700}
.empty-s{max-width:46ch;color:var(--text-secondary)}
/* The list footer: "Show: 25 per page" at the left, "1-5 of 5" and the arrow buttons at the right. */
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding-top:12px;color:var(--text-secondary);font-size:var(--type-s)}
.pager select{width:auto;min-height:36px}
.pager-nav{display:inline-flex;align-items:center;gap:8px}
/* A modal dialog: a native <dialog> in the top layer (the page behind is inert). The card arrives growing from 95% to full size with opacity in 200ms ease-out. It leaves at once. */
dialog.dlg{padding:0;border:0;background:transparent;color:var(--text-primary);overflow:visible;max-width:none;max-height:none;width:min(520px,calc(100vw - 32px));margin:auto}
dialog.dlg-s{width:min(400px,calc(100vw - 32px))}
dialog.dlg-l{width:min(880px,calc(100vw - 32px))}
dialog.dlg[open]{animation:dlg-in 200ms var(--ease-out)}
dialog.dlg::backdrop{background:rgba(24,33,39,.5)}
dialog.dlg[open]::backdrop{animation:dlg-fade 200ms ease-out}
@keyframes dlg-in{from{opacity:0;transform:matrix(.95,0,0,.95,0,0)}to{opacity:1;transform:none}}
@keyframes dlg-fade{from{opacity:0}to{opacity:1}}
body:has(dialog.dlg[open]){overflow:hidden}
.dlg-card{display:flex;flex-direction:column;max-height:calc(100dvh - 32px);background:var(--bg-panel);border-radius:var(--radius);box-shadow:0 16px 48px rgba(24,33,39,.3);overflow:hidden}
.dlg-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:20px 20px 8px 24px}
.dlg-title{font-size:var(--type-l);font-weight:700;line-height:1.3;padding-top:4px;overflow-wrap:anywhere}
.dlg-x{flex:none;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;color:var(--text-secondary);transition:background 120ms var(--ease),transform 140ms var(--ease)}
.dlg-x:active{transform:matrix(.97,0,0,.97,0,0)}
@media (hover:hover) and (pointer:fine){.dlg-x:hover{background:var(--accent-soft);color:var(--accent)}}
.dlg-body{display:flex;flex-direction:column;gap:14px;padding:8px 24px 16px;overflow-y:auto;min-height:0}
.dlg-text{color:var(--text-secondary)}
.dlg-note{padding:0 24px 8px;color:var(--text-secondary)}
.dlg-note:empty{display:none}
.dlg-foot{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:12px;padding:12px 24px 20px}
