/* ═══════════════════════════════════════════════════════════════════════════
 * ui.css - the portal's shared UI primitives: one pill, one checkbox, one tooltip, all built from
 * whole device pixels. Loaded BEFORE app.css on every portal page (index.html, invite.html); ui.js
 * (before app.js) supplies --dpr and runs the tooltips. Fix or restyle a primitive HERE and it changes
 * everywhere; app.css (later, so it wins) only adds what is specific to one page.
 *
 *   PILL      .ui-pill (+ .is-active / .is-on-hold / .is-completed / .is-closed / .is-rejected / .is-received)
 *             Every pill, chip and badge in the portal shares ONE geometry. The older class names in the
 *             list below (.contact-stage-pill, .trx-flag, .stage-select, ...) are members of it, so they
 *             need no markup change and declare no height, padding or line-height of their own - only
 *             their colours, font and, when not the standard 22px pill, --pill-h (total height) and
 *             --pill-px (room at each side, border included). A new pill: use .ui-pill.
 *   BUTTON    every .btn (all variants and sizes) and every avatar (.avatar, .contact-avatar, ...): the label / the
 *             initials are centred to within half a device pixel at any scaling; nothing to add per page.
 *   CHECKBOX  every input[type="checkbox"]: nothing to add.
 *   TOOLTIP   every title attribute: nothing to add (ui.js draws it as .ui-tip: the white surface of the page with
 *             the blue border and halo of a selected field - not inverted).
 * ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Device-pixel unit ──
     --dpr is window.devicePixelRatio (ui.js sets it at load and on resize); --dp is exactly ONE
     physical pixel, in CSS px. A length written N * var(--dp), or rounded to a multiple of it with
     round(nearest, <length>, var(--dp)), is a whole number of device pixels at any display scaling or
     browser zoom (114%, 125%, 150% ...). Pills and checkboxes are built from such lengths, so the text
     or tick inside a box keeps the same whole-pixel spot in every row; sizes given in plain CSS px land
     on fractions of a pixel at those scalings, and the label and the tick then rode one to two pixels
     high or low, differently from row to row. The 1.00005 keeps the product a hair above N (0.005%:
     under 1/64 px even at 32 device pixels) so the browser's 1/64-pixel rounding lands on exactly N,
     not on N - 1/64. */
  --dpr: 1;
  --dp: calc(1.00005px / var(--dpr));

  --pill-radius:           7px;   /* rounded rectangles, as in the status indicators the user picked (2026-10-17); was a 999px capsule */

  /* ── Status palette (user 2026-10-18, second pass) ──
     One colour per MEANING, the same on every page: the seven of the reference picture (failed red, expired slate, submitted
     purple, in review orange, success green, pending amber, in progress blue) and six more so the tax-return stages stop
     sharing (sky = intake, indigo = ready to start, teal = mailed, olive = delivered, fuchsia = signature, pink = on hold).
     Each tone has its colour (--t-x: the fill and the icon), its -ink (the text on a light tint) and, where the fill is light,
     its own text colour on the fill (--t-x-on). Pending amber is lighter than before ("a tad bit lighter so it's more
     distinguishable from the red"), so it carries dark text on the fill (white on it would fall under 4.5:1). */
  --t-red:     #d92d20;  --t-red-ink:     #b42318;
  --t-slate:   #5f6b7a;  --t-slate-ink:   #475467;
  --t-purple:  #6941c6;  --t-purple-ink:  #53389e;
  --t-orange:  #c4320a;  --t-orange-ink:  #93370d;
  --t-green:   #067647;  --t-green-ink:   #05603a;
  --t-amber:   #f79009;  --t-amber-ink:   #8a4b04;  --t-amber-on: #3d2002;  --t-amber-mark: #dc6803;
  --t-blue:    #0067d1;  --t-blue-ink:    #004ea2;
  --t-sky:     #026aa2;  --t-sky-ink:     #065986;
  --t-indigo:  #4338ca;  --t-indigo-ink:  #3730a3;
  --t-teal:    #0f766e;  --t-teal-ink:    #115e59;
  --t-olive:   #4d7c0f;  --t-olive-ink:   #3f6212;
  --t-fuchsia: #9f1ab1;  --t-fuchsia-ink: #821890;
  --t-pink:    #c11574;  --t-pink-ink:    #9e165f;
  /* The older names, kept for the few rules that read a colour outside a pill (a notice bar, a count). */
  --pill-active-bg: var(--t-blue);      --pill-active-border: var(--t-blue);      --pill-active-fg: #ffffff;
  --pill-onhold-bg: var(--t-amber);     --pill-onhold-border: var(--t-amber);     --pill-onhold-fg: var(--t-amber-on);
  --pill-completed-bg: var(--t-green);  --pill-completed-border: var(--t-green);  --pill-completed-fg: #ffffff;
  --pill-closed-bg: var(--t-slate);     --pill-closed-border: var(--t-slate);     --pill-closed-fg: #ffffff;
  --pill-rejected-bg: var(--t-red);     --pill-rejected-border: var(--t-red);     --pill-rejected-fg: #ffffff;
  --pill-received-bg: var(--t-purple);  --pill-received-border: var(--t-purple);  --pill-received-fg: #ffffff;
  --pill-unpushed-bg: var(--t-orange);  --pill-unpushed-border: var(--t-orange);  --pill-unpushed-fg: #ffffff;
  --pill-neutral-bg: var(--t-slate);    --pill-neutral-fg: #ffffff;
  --pill-info-bg: var(--t-blue);        --pill-info-fg: #ffffff;
  --pill-outline-border: #d0d5dd;

  /* The light-blue ring of a selected field (.input:focus, the tag box, the editors ...), of the tooltip and
     the border of an unchecked checkbox. One colour: change it here. */
  --blue-halo: #a2d7ff;

  /* The status icons of the filled pills (a mask: drawn in the pill's text colour). The -white set is for a <select> pill
     (.stage-select), which cannot hold a ::before and wears its icon as a background image. */
  --ico-x: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9 9l6 6M15 9l-6 6'/%3E%3C/svg%3E");
  --ico-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5l2.7 2.7L16 10'/%3E%3C/svg%3E");
  --ico-clock: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5V12l3 2'/%3E%3C/svg%3E");
  --ico-warn: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.8L2.9 19.6h18.2z'/%3E%3Cpath d='M12 10v4.2M12 17.1v.1'/%3E%3C/svg%3E");
  --ico-spin: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M136,32V64a8,8,0,0,1-16,0V32a8,8,0,0,1,16,0Zm37.25,58.75a8,8,0,0,0,5.66-2.35l22.63-22.62a8,8,0,0,0-11.32-11.32L167.6,77.09a8,8,0,0,0,5.65,13.66ZM224,120H192a8,8,0,0,0,0,16h32a8,8,0,0,0,0-16Zm-45.09,47.6a8,8,0,0,0-11.31,11.31l22.62,22.63a8,8,0,0,0,11.32-11.32ZM128,184a8,8,0,0,0-8,8v32a8,8,0,0,0,16,0V192A8,8,0,0,0,128,184ZM77.09,167.6,54.46,190.22a8,8,0,0,0,11.32,11.32L88.4,178.91A8,8,0,0,0,77.09,167.6ZM72,128a8,8,0,0,0-8-8H32a8,8,0,0,0,0,16H64A8,8,0,0,0,72,128ZM65.78,54.46A8,8,0,0,0,54.46,65.78L77.09,88.4A8,8,0,0,0,88.4,77.09Z'/%3E%3C/svg%3E");   /* Phosphor spinner (regular) */
  --ico-plane: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 3L10.5 13.5M21 3l-6.5 18-4-7.5L3 9.5z'/%3E%3C/svg%3E");
  --ico-review: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19.5 12a7.5 7.5 0 1 1-2.2-5.3M19.5 4.5v4h-4'/%3E%3C/svg%3E");
  --ico-inbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M200,32H163.74a47.92,47.92,0,0,0-71.48,0H56A16,16,0,0,0,40,48V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm-72,0a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm32,128H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm0-32H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Z'/%3E%3C/svg%3E");   /* Phosphor clipboard-text (fill): Intake, as in the sidebar (user 2026-10-18) */
  --ico-play: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M10 8.5v7l5.5-3.5z'/%3E%3C/svg%3E");
  --ico-pause: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M10 9v6M14 9v6'/%3E%3C/svg%3E");
  --ico-pen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20h4L19.5 8.5l-4-4L4 16z'/%3E%3Cpath d='M13.5 6.5l4 4'/%3E%3C/svg%3E");
  --ico-mail: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6h18v12H3z'/%3E%3Cpath d='M3.5 6.5L12 13l8.5-6.5'/%3E%3C/svg%3E");
  --ico-box: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3l8 4.5v9L12 21l-8-4.5v-9z'/%3E%3Cpath d='M4 7.5l8 4.5 8-4.5M12 12v9'/%3E%3C/svg%3E");
  --ico-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12h8'/%3E%3C/svg%3E");
  --ico-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8-5.2-2.7-5.2 2.7 1-5.8-4.3-4.1 5.9-.9z'/%3E%3C/svg%3E");
  --ico-draft: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6v18h12V7z'/%3E%3Cpath d='M14 3v4h4M9 13h6M9 17h4'/%3E%3C/svg%3E");
  --ico-folder-open: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M245,110.64A16,16,0,0,0,232,104H216V88a16,16,0,0,0-16-16H130.67L102.94,51.2a16.14,16.14,0,0,0-9.6-3.2H40A16,16,0,0,0,24,64V208h0a8,8,0,0,0,8,8H211.1a8,8,0,0,0,7.59-5.47l28.49-85.47A16.05,16.05,0,0,0,245,110.64ZM93.34,64,123.2,86.4A8,8,0,0,0,128,88h72v16H69.77a16,16,0,0,0-15.18,10.94L40,158.7V64Z'/%3E%3C/svg%3E");   /* Phosphor folder-open (fill): a matter that is Open */
  --ico-folder-dashed: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M96,208a8,8,0,0,1-8,8H39.38A15.4,15.4,0,0,1,24,200.62V192a8,8,0,0,1,16,0v8H88A8,8,0,0,1,96,208Zm64-8H128a8,8,0,0,0,0,16h32a8,8,0,0,0,0-16Zm64-56a8,8,0,0,0-8,8v48H200a8,8,0,0,0,0,16h16.89A15.13,15.13,0,0,0,232,200.89V152A8,8,0,0,0,224,144Zm-8-72H168a8,8,0,0,0,0,16h48v24a8,8,0,0,0,16,0V88A16,16,0,0,0,216,72ZM32,88h96a8,8,0,0,0,5.66-13.66L104,44.69A15.86,15.86,0,0,0,92.69,40H40A16,16,0,0,0,24,56V80A8,8,0,0,0,32,88Zm0,72a8,8,0,0,0,8-8V120a8,8,0,0,0-16,0v32A8,8,0,0,0,32,160Z'/%3E%3C/svg%3E");   /* folder-dashed (fill): Pending */
  --ico-folder: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M216,72H131.31L104,44.69A15.88,15.88,0,0,0,92.69,40H40A16,16,0,0,0,24,56V200.62A15.41,15.41,0,0,0,39.39,216h177.5A15.13,15.13,0,0,0,232,200.89V88A16,16,0,0,0,216,72ZM40,56H92.69l16,16H40Z'/%3E%3C/svg%3E");   /* folder (fill): Closed */
  --ico-tray-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM90.34,98.34l32-32a8,8,0,0,1,11.32,0l32,32a8,8,0,0,1-11.32,11.32L136,91.31V152a8,8,0,0,1-16,0V91.31l-18.34,18.35A8,8,0,0,1,90.34,98.34ZM208,208H48V168H76.69L96,187.31A15.86,15.86,0,0,0,107.31,192h41.38A15.86,15.86,0,0,0,160,187.31L179.31,168H208v40Z'/%3E%3C/svg%3E");   /* Phosphor tray-arrow-up (fill): a questionnaire the client submitted */
  --ico-truck: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M255.43,117l-14-35A15.93,15.93,0,0,0,226.58,72H192V64a8,8,0,0,0-8-8H32A16,16,0,0,0,16,72V184a16,16,0,0,0,16,16H49a32,32,0,0,0,62,0h50a32,32,0,0,0,62,0h17a16,16,0,0,0,16-16V120A8.13,8.13,0,0,0,255.43,117ZM80,208a16,16,0,1,1,16-16A16,16,0,0,1,80,208ZM32,136V72H176v64Zm160,72a16,16,0,1,1,16-16A16,16,0,0,1,192,208Zm0-96V88h34.58l9.6,24Z'/%3E%3C/svg%3E");   /* truck (fill): a mailing in transit */
  --ico-tag: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M243.31,136,144,36.69A15.86,15.86,0,0,0,132.69,32H40a8,8,0,0,0-8,8v92.69A15.86,15.86,0,0,0,36.69,144L136,243.31a16,16,0,0,0,22.63,0l84.68-84.68a16,16,0,0,0,0-22.63ZM84,96A12,12,0,1,1,96,84,12,12,0,0,1,84,96Z'/%3E%3C/svg%3E");   /* tag (fill): a mailing's label created */
  --ico-return: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'%3E%3Cpath d='M232,144a64.07,64.07,0,0,1-64,64H80a8,8,0,0,1,0-16h88a48,48,0,0,0,0-96H88v40a8,8,0,0,1-13.66,5.66l-48-48a8,8,0,0,1,0-11.32l48-48A8,8,0,0,1,88,40V80h80A64.07,64.07,0,0,1,232,144Z'/%3E%3C/svg%3E");   /* arrow-u-up-left (fill): returned to sender */

  /* Checkbox: 16 CSS px as a whole number of device pixels (a fractional box was painted 16, 17 or 18
     pixels tall from one row to the next, and the tick moved with it); the tick sits --cb-lift above the
     box centre (its glyph is below its own centre and its weight is at the bottom vertex, so a centred
     tick read low: measured 0.7-1.8 device px). Plain px where round() is not supported: a custom property
     the browser cannot use leaves `width` unset, and an appearance:none box with no width is a 2px sliver. */
  --cb: 16px;
  --cb-lift: 1px;
}
@supports (width: round(nearest, 1px, 1px)) {
  :root {
    --cb: round(nearest, 16px, var(--dp));
    --cb-lift: round(nearest, calc(0.06 * var(--cb)), var(--dp));
  }
}

/* ── Pill ─────────────────────────────────────────────────────────────────── */
/* One geometry for every pill, chip and badge. Height = border + room above + the font's own line box
 * + room below + border, each a WHOLE number of device pixels, so the label sits at the same spot in
 * every pill at any scaling (a fixed height with line-height: 1 landed on fractions of a pixel: the
 * label rode 1-2 device pixels high or low from one row to the next). The room above is what is left
 * of --pill-h (the pill's total height, 22px unless a family says otherwise) after the line box, split
 * in two; the room below is ONE device pixel more, which lifts the label half a pixel: the optical
 * centre of mixed-case text (its lowercase mass sits below the capitals' centre). --pill-px is the
 * room at each side including the 1px border. height: fit-content so a flex parent can not stretch it. */
.ui-pill,
.contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
.fl-pill, .fl-dep, .cc-chip, .cal-mnum, .co-att-badge, .co-vm-tag, .co-day,
.sidebar-badge, .contact-tabbar .tab .tab-badge, .em-client-pill, .matter-billrecipient, .tpl-chip,
.irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
.ai-chip, .scorer-report .pill, .status-pill {
  --pill-pad: round(nearest, max(0px, calc((var(--pill-h, 22px) - 1.21em) / 2 - 1.5 * var(--dp))), var(--dp));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: fit-content;
  padding: var(--pill-pad) max(0px, calc(var(--pill-px, 11px) - 1px)) calc(var(--pill-pad) + var(--dp));
  border: 1px solid var(--pill-bd, transparent);   /* a toned pill's border (see Pill colours); transparent for the counts */
  border-radius: var(--pill-radius);
  line-height: normal;   /* the font's own ascent + descent, whole device pixels: no half-leading to round */
  white-space: nowrap;
  flex-shrink: 0;
}
.ui-pill, .contact-stage-pill { font-size: var(--fs-sm); }

/* ── Pill colours: one tone per meaning, three looks (user 2026-10-18) ─────────────────────────────────────────────────
 * A pill sets only its TONE (--tone, and --tone-ink for its text on a light tint); the look is chosen once for the whole
 * page by Settings > Appearance > Status pills (`data-pill-style` on <html>, set by ui.js from localStorage `pill-style`):
 *   filled  (default)  the tone as the fill, white text (dark on the light amber), white icon
 *   tint               a light wash of the tone, its darker ink as text, the icon in the tone
 *   outline            white with a grey border and dark text; only the icon carries the tone
 * Families set --tone (never a background / color of their own), so all three looks work for every pill and chip. :where()
 * keeps the base at no specificity, so a family rule's --tone wins and a state class wins over both. The
 * counts on dark chrome (.sidebar-badge, the tab badge, .cal-mnum, .co-att-badge) keep their own colours. */
:where(.ui-pill, .contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
  .fl-pill, .fl-dep, .cc-chip, .co-vm-tag, .co-day, .em-client-pill, .matter-billrecipient, .tpl-chip,
  .irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
  .ai-chip, .scorer-report .pill, .status-pill) {
  --tone: var(--t-slate);
  --tone-ink: color-mix(in srgb, var(--tone) 72%, #000);
  --tone-on: #ffffff;
  --tone-mark: var(--tone);
  --pill-bg: var(--tone);
  --pill-bd: var(--tone);
  --pill-fg: var(--tone-on);
  --pill-ic: var(--pill-fg);
  background-color: var(--pill-bg);
  border-color: var(--pill-bd);
  color: var(--pill-fg);
}
:root[data-pill-style="tint"] :where(.ui-pill, .contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
  .fl-pill, .fl-dep, .cc-chip, .co-vm-tag, .co-day, .em-client-pill, .matter-billrecipient, .tpl-chip,
  .irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
  .ai-chip, .scorer-report .pill, .status-pill) {
  --pill-bg: color-mix(in srgb, var(--tone) 11%, #fff);
  --pill-bd: color-mix(in srgb, var(--tone) 32%, #fff);
  --pill-fg: var(--tone-ink);
  --pill-ic: var(--tone-mark);
}
:root[data-pill-style="outline"] :where(.ui-pill, .contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
  .fl-pill, .fl-dep, .cc-chip, .co-vm-tag, .co-day, .em-client-pill, .matter-billrecipient, .tpl-chip,
  .irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
  .ai-chip, .scorer-report .pill, .status-pill) {
  --pill-bg: #ffffff;
  --pill-bd: var(--pill-outline-border);
  --pill-fg: var(--text-primary, #1f2937);
  --pill-ic: var(--tone-mark);
}
/* The Settings > Appearance samples show each look whatever the page's own: .pill-look[data-pill-style] outranks :root. */
.pill-look.pill-look[data-pill-style="filled"] :where(.ui-pill, .contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
  .fl-pill, .fl-dep, .cc-chip, .co-vm-tag, .co-day, .em-client-pill, .matter-billrecipient, .tpl-chip,
  .irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
  .ai-chip, .scorer-report .pill, .status-pill) {
  --pill-bg: var(--tone);
  --pill-bd: var(--tone);
  --pill-fg: var(--tone-on);
  --pill-ic: var(--pill-fg);
}
.pill-look.pill-look[data-pill-style="tint"] :where(.ui-pill, .contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
  .fl-pill, .fl-dep, .cc-chip, .co-vm-tag, .co-day, .em-client-pill, .matter-billrecipient, .tpl-chip,
  .irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
  .ai-chip, .scorer-report .pill, .status-pill) {
  --pill-bg: color-mix(in srgb, var(--tone) 11%, #fff);
  --pill-bd: color-mix(in srgb, var(--tone) 32%, #fff);
  --pill-fg: var(--tone-ink);
  --pill-ic: var(--tone-mark);
}
.pill-look.pill-look[data-pill-style="outline"] :where(.ui-pill, .contact-stage-pill, .stage-select, .trx-flag, .docs-shared-pill, .contact-badge, .contact-copy-chip,
  .fl-pill, .fl-dep, .cc-chip, .co-vm-tag, .co-day, .em-client-pill, .matter-billrecipient, .tpl-chip,
  .irs-dest-badge, .trx-chip, .trx-type-card-count, .ms-track-demo, .ms-live-chip, .ai-ask-badge,
  .ai-chip, .scorer-report .pill, .status-pill) {
  --pill-bg: #ffffff;
  --pill-bd: var(--pill-outline-border);
  --pill-fg: var(--text-primary, #1f2937);
  --pill-ic: var(--tone-mark);
}
.ui-pill, .contact-stage-pill { font-weight: var(--fw-medium); }

/* The states. Every page names a state, never a colour: is-active (working on it), is-on-hold / is-pending (waiting on
 * someone), is-completed / is-done, is-closed, is-none (not needed), is-draft, is-rejected / is-failed, is-received /
 * is-sent, is-unpushed / is-review (in review), is-intake, is-new, is-ready (ready to start), is-hold (on hold),
 * is-signature, is-mailed, is-delivered, is-label / is-transit / is-returned (Mail & Ship), is-submitted (the client sent it in: In review's orange, tray-arrow-up); a MATTER's own status is-matter-open / -pending / -closed (the folder icons, user
 * 2026-10-18). Tax-return stages get theirs from stageToneClass() in app.js. */
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-active, :is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-progress, .status-pill.in-progress, .trx-flag-active { --tone: var(--t-blue); --tone-ink: var(--t-blue-ink); --pill-ico: var(--ico-spin); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-on-hold, :is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-pending, .status-pill.pending, .trx-flag-onhold, .trx-flag-amber { --tone: var(--t-amber); --tone-ink: var(--t-amber-ink); --tone-on: var(--t-amber-on); --tone-mark: var(--t-amber-mark); --pill-ico: var(--ico-warn); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-completed, :is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-done, .status-pill.completed, .trx-flag-completed, .trx-flag-ok { --tone: var(--t-green); --tone-ink: var(--t-green-ink); --pill-ico: var(--ico-check); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-closed, .trx-flag-closed, .trx-flag-gray { --tone: var(--t-slate); --tone-ink: var(--t-slate-ink); --pill-ico: var(--ico-clock); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-none { --tone: var(--t-slate); --tone-ink: var(--t-slate-ink); --pill-ico: var(--ico-minus); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-draft { --tone: var(--t-slate); --tone-ink: var(--t-slate-ink); --pill-ico: var(--ico-draft); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-rejected, :is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-failed, .trx-flag-red { --tone: var(--t-red); --tone-ink: var(--t-red-ink); --pill-ico: var(--ico-x); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-received, :is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-sent { --tone: var(--t-purple); --tone-ink: var(--t-purple-ink); --pill-ico: var(--ico-plane); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-unpushed, :is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-review { --tone: var(--t-orange); --tone-ink: var(--t-orange-ink); --pill-ico: var(--ico-review); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-intake { --tone: var(--t-sky); --tone-ink: var(--t-sky-ink); --pill-ico: var(--ico-inbox); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-new { --tone: var(--t-sky); --tone-ink: var(--t-sky-ink); --pill-ico: var(--ico-star); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-ready { --tone: var(--t-indigo); --tone-ink: var(--t-indigo-ink); --pill-ico: var(--ico-play); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-hold { --tone: var(--t-pink); --tone-ink: var(--t-pink-ink); --pill-ico: var(--ico-pause); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-signature { --tone: var(--t-fuchsia); --tone-ink: var(--t-fuchsia-ink); --pill-ico: var(--ico-pen); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-mailed { --tone: var(--t-teal); --tone-ink: var(--t-teal-ink); --pill-ico: var(--ico-mail); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-delivered { --tone: var(--t-olive); --tone-ink: var(--t-olive-ink); --pill-ico: var(--ico-box); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-matter-open { --tone: var(--t-blue); --tone-ink: var(--t-blue-ink); --pill-ico: var(--ico-folder-open); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-matter-pending { --tone: var(--t-amber); --tone-ink: var(--t-amber-ink); --tone-on: var(--t-amber-on); --tone-mark: var(--t-amber-mark); --pill-ico: var(--ico-folder-dashed); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-matter-closed { --tone: var(--t-slate); --tone-ink: var(--t-slate-ink); --pill-ico: var(--ico-folder); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-submitted { --tone: var(--t-orange); --tone-ink: var(--t-orange-ink); --pill-ico: var(--ico-tray-up); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-label { --tone: var(--t-indigo); --tone-ink: var(--t-indigo-ink); --pill-ico: var(--ico-tag); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-transit { --tone: var(--t-blue); --tone-ink: var(--t-blue-ink); --pill-ico: var(--ico-truck); --pill-ico-display: inline-block; }
:is(.ui-pill, .contact-stage-pill, .stage-select, .status-pill, .trx-flag, .docs-shared-pill, .contact-badge).is-returned { --tone: var(--t-red); --tone-ink: var(--t-red-ink); --pill-ico: var(--ico-return); --pill-ico-display: inline-block; }
.no-icon, .eng-tabcount { --pill-ico-display: none !important; }
/* The icon, before the label, centred on the line box (the capitals' centre in Inter), in --pill-ic. A <select> pill shows it
 * on its enhanced trigger (a button, .ui-select-trigger.stage-select). */
.ui-pill::before, .contact-stage-pill::before, .status-pill::before, .trx-flag::before, .docs-shared-pill::before,
.contact-badge::before, .ui-select-trigger.stage-select::before {
  content: '';
  display: var(--pill-ico-display, none);
  flex: none;
  width: 1.1em;
  height: 1.1em;
  margin-right: 0.35em;
  margin-left: -0.15em;
  background: var(--pill-ic);
  -webkit-mask: var(--pill-ico) center / contain no-repeat;
  mask: var(--pill-ico) center / contain no-repeat;
}
/* No state (a count, a plain pill): --pill-ico-display stays unset, so no icon and no room kept for one. */

/* ── Text centred in a box: buttons and avatars ──────────────────────────────────────────────────────────
 * Why: at 114-150% display scaling a label in a fixed-height button and the initials in a fixed-size avatar sat one to
 * two device pixels HIGH, by a different amount from row to row (measured on screenshots at 114%: buttons 1.0-1.5 px,
 * avatars 1.0-2.0 px, with up to 1 px of spread between rows). The browser rounds the font's ascent and descent to
 * whole device pixels, FLOORS the half-leading of a line box taller than the text, and snaps the box and its text
 * separately.
 * How, without touching a box's nominal size: (1) the box is an EVEN number of device pixels tall (--ev-N: N CSS px
 * rounded to an even count), (2) its line box is an EVEN number of pixels, so centring the line box leaves a whole
 * number of pixels above and below it, and (3) the text is moved by the whole number of pixels its capital letters
 * are still off centre (--ctr-k), worked out from Inter's own metrics the way the browser rounds them:
 *   --ctr-a / --ctr-d   ascent / descent as the browser rounds them (0.96875em / 0.24121em, to a device pixel)
 *   --ctr-e             where the capitals' centre lands against the box centre before the nudge: half the gap between
 *                       ascent and descent, less half a pixel when the line box is an odd number of pixels taller than
 *                       the text (the floored half-leading), less half the cap height (0.72754em / 2)
 *   --ctr-k             the nudge, whole pixels (+ = down): padding-top of 2k moves centred content down k, padding-bottom
 *                       of 2k moves it up k. Verified on screenshots at 100 / 114 / 125 / 150 / 175%: the capitals sit
 *                       within half a device pixel of centre, and identically in every row.
 * The mod() term adds half a pixel before it takes the remainder, so the exact multiples of a device pixel that float
 * arithmetic nudges below themselves never read as "odd". Icons inside a button are moved back by the same nudge
 * so they stay geometrically centred. The vertical padding is !important on purpose: a page rule's padding shorthand
 * must not undo the nudge (a button's height is fixed, so its vertical padding means nothing else). */
:root {
  /* N CSS px as an EVEN number of device pixels (N itself without round()). Sizes of boxes that centre text. */
  --ev-24: 24px; --ev-28: 28px; --ev-30: 30px; --ev-32: 32px; --ev-34: 34px; --ev-36: 36px;
  --ev-38: 38px; --ev-40: 40px; --ev-48: 48px; --ev-96: 96px;
}
@supports (width: round(nearest, 1px, 1px)) and (width: mod(3px, 2px)) {
  :root {
    --ev-24: round(nearest, 24px, calc(2 * var(--dp)));
    --ev-28: round(nearest, 28px, calc(2 * var(--dp)));
    --ev-30: round(nearest, 30px, calc(2 * var(--dp)));
    --ev-32: round(nearest, 32px, calc(2 * var(--dp)));
    --ev-34: round(nearest, 34px, calc(2 * var(--dp)));
    --ev-36: round(nearest, 36px, calc(2 * var(--dp)));
    --ev-38: round(nearest, 38px, calc(2 * var(--dp)));
    --ev-40: round(nearest, 40px, calc(2 * var(--dp)));
    --ev-48: round(nearest, 48px, calc(2 * var(--dp)));
    --ev-96: round(nearest, 96px, calc(2 * var(--dp)));
  }
  .btn, .avatar, .contact-avatar, .matter-contact-avatar, .profile-avatar-stack {
    --ctr-a: round(nearest, 0.96875em, var(--dp));
    --ctr-d: round(nearest, 0.24121em, var(--dp));
    --ctr-e: calc((var(--ctr-a) - var(--ctr-d)) / 2 - mod(calc(var(--ctr-a) + var(--ctr-d) + 0.5 * var(--dp)), calc(2 * var(--dp))) / 2 + 0.25 * var(--dp) - 0.36377em);
    --ctr-k: round(nearest, calc(-1 * var(--ctr-e)), var(--dp));
    line-height: round(up, 1.25em, calc(2 * var(--dp)));
    padding-top: max(0px, calc(2 * var(--ctr-k)));
    padding-bottom: max(0px, calc(-2 * var(--ctr-k)));
  }
  .btn {
    padding-top: max(0px, calc(2 * var(--ctr-k))) !important;
    padding-bottom: max(0px, calc(-2 * var(--ctr-k))) !important;
  }
  .btn > .icon, .btn > svg {
    margin-top: max(0px, calc(-2 * var(--ctr-k)));
    margin-bottom: max(0px, calc(2 * var(--ctr-k)));
  }
}
/* The heights of every standard control (buttons, search boxes, selects): even device pixels (--ev-38, --ev-28). */
:root {
  --control-h-sm: var(--ev-28);   /* small buttons (.btn-sm) */
  --control-h:    var(--ev-38);   /* all standard buttons (toolbar, footer, base) */
}

/* ── Checkbox ─────────────────────────────────────────────────────────────────
 * Clio-style custom checkbox. Three visible states:
 *   - unchecked        - white box, light-blue (--blue-halo) rounded border
 *   - checked + focus  - #0067d1 fill, white check, soft #0067d1 halo
 *   - checked + blur   - #0067d1 fill, white check, no halo
 *
 * `appearance: none` strips the native control so we can draw the box + checkmark ourselves. The check
 * is a CSS mask of /img/icons/check-bold.svg (Phosphor) painted in white over the blue ::after fill.
 * The :focus halo uses an outline (renders OUTSIDE the box even when overflow:hidden is on an ancestor)
 * instead of box-shadow so it survives table-cell clipping.
 *
 * The SIZE is !important on purpose. This sheet loads BEFORE app.css, so a page rule written for "its input"
 * (`.x input { width: auto }`, 14px, 100%) wins at equal specificity: when this rule moved here from app.css
 * (2026-09-30) the tick box of every confirm dialog (Create shipment, Buy postage, Start merge), of the
 * questionnaire page picker and of a contact's Yes / No custom field collapsed to a 2px sliver, because an
 * appearance:none box has no width of its own. A checkbox is ONE size; nothing per page may change it
 * (device-pixel-ui.test.mjs fails on a page rule that tries). */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: var(--cb) !important;
  height: var(--cb) !important;
  margin: 0;
  padding: 0;
  border: 1.5px solid var(--blue-halo);
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  vertical-align: middle;
  transition: background-color 80ms, border-color 80ms, box-shadow 80ms;
}
/* Higher-specificity overrides for the same selector pattern used by the data-table cell rules -
 * keeps focus / hover / checked styling winning even where .data-table tbody td input[type="checkbox"]
 * is already targeted. */
input[type="checkbox"]:hover,
.data-table tbody td input[type="checkbox"]:hover {
  border-color: var(--blue);
}
input[type="checkbox"]:checked,
.data-table tbody td input[type="checkbox"]:checked {
  background: var(--blue);
  border-color: var(--blue);
}
input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: #fff;
  /* check-bold.svg at 90% of the box, lifted --cb-lift whole device pixels above centre. */
  -webkit-mask: url('/img/icons/check-bold.svg') 50% calc(50% - var(--cb-lift)) / 90% no-repeat;
          mask: url('/img/icons/check-bold.svg') 50% calc(50% - var(--cb-lift)) / 90% no-repeat;
}
/* Indeterminate (some-but-not-all rows selected - e.g. the Documents "select all" header when a
 * subset is checked). appearance:none strips the native dash, so draw a white horizontal bar over the
 * blue fill, mirroring the :checked tick. Matches Clio's tri-state header checkbox. The bar is whole
 * device pixels and centred with auto margins (a transform would land it on half a pixel). */
input[type="checkbox"]:indeterminate,
.data-table tbody td input[type="checkbox"]:indeterminate {
  background: var(--blue);
  border-color: var(--blue);
}
input[type="checkbox"]:indeterminate::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: round(nearest, 8px, var(--dp));
  height: round(nearest, 2px, var(--dp));
  background: #fff;
  border-radius: 1px;
}
/* Busy state: used while a POA write is in flight. Blocks further clicks WITHOUT calling
 * checkboxEl.disabled = true, which would blur the input and kill the focus halo. */
input[type="checkbox"].cb-busy {
  pointer-events: none;
}
/* Focus halo. Covers both `:focus` (any focus, including mouse-click) and `:focus-visible`
 * (keyboard-only focus) - older browsers and Safari are inconsistent about which one fires for
 * checkbox clicks, and we want the halo visible in both cases. Solid #0067d1 with a 2 px gap so the
 * halo reads as a discrete ring around the box. */
input[type="checkbox"]:focus,
input[type="checkbox"]:focus-visible,
.data-table tbody td input[type="checkbox"]:focus,
.data-table tbody td input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

/* ── Tooltip ──────────────────────────────────────────────────────────────────
 * Every element's title, drawn under the element (above it when there is no room) by ui.js. It is dressed
 * like a selected field and NOT inverted (user 2026-09-30: "use the blue halo ... don't make it inverted"):
 * the page's white surface and dark text, the blue border and the light-blue halo of .input:focus.
 * pointer-events: none so it never gets in the way of a click. */
.ui-tip {
  position: fixed; left: 0; top: 0; z-index: 100000;
  max-width: 320px; padding: 6px 10px;
  border: 1px solid var(--blue, #0067d1); border-radius: var(--r, 6px);
  background: var(--surface, #fff); color: var(--text-primary, #1e2535);
  box-shadow: 0 0 0 2px var(--blue-halo);
  font-size: var(--fs-sm, 12px); line-height: 16px;
  white-space: pre-line; overflow-wrap: anywhere;
  pointer-events: none; visibility: hidden; opacity: 0;
  transition: opacity 80ms ease-out;
}
.ui-tip.is-on { visibility: visible; opacity: 1; }
@media (prefers-reduced-motion: reduce) { .ui-tip { transition: none; } }

/* ── Spinner ──────────────────────────────────────────────────────────────────
 * Every loading mark is the Phosphor spinner (regular), turning; it replaced the bordered circle notches (user 2026-10-18).
 * .ui-spinner draws it in the text colour; size it with width / height. Still under prefers-reduced-motion. */
.ui-spinner {
  display: inline-block; width: 1em; height: 1em; flex: none; background: currentColor;
  -webkit-mask: var(--ico-spin) center / contain no-repeat; mask: var(--ico-spin) center / contain no-repeat;
  animation: ui-spin 1s steps(8) infinite;
}
@keyframes ui-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ui-spinner { animation: none; } }
