:root{
  /* IP Tracker — Navy & Slate Blue, professional contrast */
  --canvas:#c3cdda; --surface:#ffffff; --surface-2:#eef1f6; --sidebar:#0a1a33;
  --ink:#0d1b30; --muted:#46556b; --faint:#9aa6b5;
  --line:#aab6c6; --line2:#d4dce6; --hair:#edf0f4;
  --accent:#4a6b8a; --accent-600:#3f5c77; --accent-700:#324a61; --accent-ink:#ffffff;
  --accent-soft:#eaeff3; --accent-line:#c6d3df;
  --side-ink:#aeb9ca; --side-faint:#5a6478; --side-hover:rgba(255,255,255,.07);
  --green:#2f6d4f; --green-soft:#e3f0e8; --green-line:#c5e0d0;
  --amber:#8a5a14; --amber-soft:#f7eedb; --amber-line:#ecd6a8;
  --red:#a83a2c; --red-soft:#f7e4df; --red-line:#eec2b8;
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s8:32px; --s10:40px;
  --fld-gap:6px;                  /* name -> hint -> control, inside one field */
  --r-sm:7px; --r:10px; --r-lg:14px; --r-pill:999px;
  --shadow-sm:0 1px 2px rgba(13,27,48,.06);
  --shadow:0 1px 3px rgba(13,27,48,.12),0 10px 28px rgba(13,27,48,.14);
  --shadow-lg:0 2px 6px rgba(13,27,48,.08),0 16px 40px rgba(13,27,48,.12);
  --fs-display:25px; --fs-h2:15.5px; --fs-h3:13px;
  --fs-body:14px; --fs-sm:13px; --fs-xs:12px; --fs-2xs:11px;
  --ease:cubic-bezier(.4,0,.2,1);
}

*{box-sizing:border-box}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
body{margin:0;background:var(--canvas);color:var(--ink);
  font-family:'Inter',system-ui,-apple-system,"Segoe UI",Arial,sans-serif;
  font-size:var(--fs-body);line-height:1.55;letter-spacing:-.005em}
a{color:var(--accent-700);text-decoration:none;font-weight:500;transition:color .12s var(--ease)}
a:hover{text-decoration:underline}
h1{font-size:var(--fs-display);font-weight:700;letter-spacing:-.02em;margin:0;line-height:1.15}
h2{font-size:var(--fs-h2);font-weight:600;margin:0 0 var(--s3);letter-spacing:-.01em}
h3{font-size:var(--fs-h3);font-weight:600;margin:0}
.mono{font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:var(--fs-xs);font-weight:600;letter-spacing:0}
.muted{color:var(--muted)} .blank{color:var(--faint);font-style:italic}
.right{text-align:right}
small{color:var(--muted);font-size:var(--fs-xs)}

/* Layout — navy sidebar shell */
aside{position:fixed;left:0;top:0;bottom:0;width:240px;background:var(--sidebar);
  padding:var(--s5) var(--s3);display:flex;flex-direction:column;gap:var(--s5);z-index:20}
.brand{display:flex;gap:10px;align-items:center;padding:4px 8px}
.brand .logo{width:32px;height:32px;border-radius:9px;background:var(--accent);color:var(--accent-ink);
  display:grid;place-items:center;font-weight:800;font-size:13px;letter-spacing:-.02em}
.brand b{font-size:15px;font-weight:700;color:#fff;letter-spacing:-.01em}
.brand span{display:block;color:var(--side-faint);font-size:var(--fs-2xs);font-weight:500}
nav{display:flex;flex-direction:column;gap:1px}
.nav-group{color:var(--side-faint);font-size:10px;text-transform:uppercase;letter-spacing:.09em;
  font-weight:700;padding:var(--s4) 12px var(--s2)}
nav a{color:var(--side-ink);text-decoration:none;padding:9px 12px;border-radius:var(--r-sm);
  font-weight:500;font-size:var(--fs-body);display:flex;align-items:center;gap:9px;
  transition:background .12s var(--ease),color .12s var(--ease)}
nav a:hover{background:var(--side-hover);color:#fff;text-decoration:none}
nav a.active{background:var(--accent);color:var(--accent-ink);font-weight:600}
.side-foot{margin-top:auto;display:flex;flex-direction:column;gap:0}
.userbox{font-size:var(--fs-xs);color:var(--side-faint);padding:0 8px}
.userbox b{color:#fff;display:block;font-size:var(--fs-sm);font-weight:600}
.note{color:var(--side-faint);background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.06);
  padding:11px 12px;border-radius:var(--r);font-size:var(--fs-2xs);line-height:1.55}
main{margin-left:240px;padding:var(--s6) var(--s10);max-width:1340px}
header{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:var(--s6);gap:var(--s4)}
header p{margin:6px 0 0;color:var(--muted);font-size:var(--fs-sm)}
.topbar{display:flex;justify-content:space-between;align-items:center;margin:calc(var(--s6)*-1) calc(var(--s10)*-1) var(--s6);
  padding:0 var(--s10);height:56px;border-bottom:1px solid var(--line);
  background:var(--sidebar);border-bottom:1px solid rgba(255,255,255,.08);position:sticky;top:0;z-index:10}
.crumb{font-size:var(--fs-sm);color:#fff;font-weight:600}
/* The Super-Admin acting-firm selector wears the crumb's own typography so the topbar
   reads identically whether it is a label or a control. */
.crumb-switch{margin:0;display:flex}
select.crumb{background:transparent;border:1px solid rgba(255,255,255,.28);border-radius:6px;
  padding:3px 24px 3px 8px;cursor:pointer;appearance:none;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 6px center;background-size:12px}
select.crumb:hover{border-color:rgba(255,255,255,.55)}
select.crumb option{color:var(--ink);background:#fff}
/* NARROWED. A distinct fill, not just different text: the hazard this control creates is
   forgetting the session is scoped, and wording is the first thing a familiar eye skips. */
select.crumb.crumb-acting{background-color:var(--accent,#b8860b);border-color:transparent;
  box-shadow:0 0 0 1px rgba(255,255,255,.25) inset}
.topbar-sep{width:1px;height:22px;align-self:center;background:rgba(255,255,255,.16);margin:0 16px;flex-shrink:0}
.sel-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 12px;margin-bottom:10px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface)}

/* Cards & panels */
/* The stat card strip distributes its VISIBLE cards, whatever their number — the same
   treatment, for the same reason, as .m-facts below.
   It was repeat(4,1fr), a count that matched no caller: dashboard renders 3, My Day 5,
   the matter billing strip 3, finance 5. Three of those overrode it inline with their
   own hardcoded repeat(N,1fr), which is the bug wearing its fix — the count is written
   down twice per screen and neither copy knows when a card is conditional. The finance
   empty state was the visible failure: one card in a repeat(5,1fr) grid, sitting at a
   fifth of the width with four columns of slack beside it.
   auto-flow column + auto-columns creates exactly as many equal columns as there are
   cards, so a card added, removed or hidden by a condition redistributes on its own.
   minmax(0,1fr) not 1fr: 1fr floors at min-content, so one long figure would widen its
   column and squeeze the rest instead of wrapping inside it. */
.cards{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--s4);margin-bottom:var(--s6)}
/* Each card is its own wrapping context — without min-width:0 a grid item refuses to
   shrink below its content and the minmax(0,…) above is silently overridden. */
.cards>*{min-width:0}
.card,.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s5);margin-bottom:var(--s4);box-shadow:var(--shadow-sm)}
.stat{position:relative;overflow:hidden}
.stat span{font-size:var(--fs-xs);color:var(--muted);font-weight:500}
.stat b{display:block;font-size:28px;font-weight:700;margin-top:6px;letter-spacing:-.02em}
.stat.alert b{color:var(--red)} .stat.ok b{color:var(--green)} .stat.accent b{color:var(--accent-700)}
.grid2{display:grid;grid-template-columns:1.4fr 1fr;gap:var(--s4)}
.panel.flush{padding:0;overflow:hidden}
.panel-head{display:flex;justify-content:space-between;align-items:center;padding:13px 18px;
  border-bottom:1px solid var(--line);background:var(--surface-2)}
.panel-head h2{margin:0}

/* Tables */
table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
th,td{text-align:left;padding:12px 18px;border-bottom:1px solid var(--line2);vertical-align:middle}
tr:last-child td{border-bottom:none}
th{font-size:var(--fs-2xs);color:var(--muted);text-transform:uppercase;letter-spacing:.06em;font-weight:600}
tbody tr{transition:background .1s var(--ease)}
tbody tr:hover{background:#f3f6fb}
tr.rowlink{cursor:pointer}

/* Party registry: people filed under their organisation (templates/parties.html).
   The indent and the tree marker are the whole grouping as far as the reader is
   concerned — an organisation heading is a normal row, and its people are the rows that
   sit under it. A heavier top border separates one organisation from the next, so the
   groups read as blocks without needing a second header row per firm. */
tr.reg-org>td{border-top:1px solid var(--line)}
tr.reg-member>td:first-child{padding-left:34px}
.reg-tick{color:var(--muted);margin-right:7px;font-family:ui-monospace,Menlo,monospace}
tr.reg-loose td{background:var(--surface-2);font-size:var(--fs-2xs);font-weight:600;
  text-transform:uppercase;letter-spacing:.06em;padding-top:9px;padding-bottom:9px}

/* Pills & status chips */
.pill{display:inline-block;border-radius:6px;padding:3px 9px;font-size:var(--fs-2xs);font-weight:600;
  background:#e8edf3;color:var(--muted);letter-spacing:.01em}
.pill.type{font-family:ui-monospace,Menlo,monospace;border:none;background:var(--accent);color:var(--accent-ink)}
.pill.green{background:var(--green);color:#fff}
.pill.amber{background:var(--amber);color:#fff}
.pill.red{background:var(--red);color:#fff}
.pill.accent{background:var(--accent);color:var(--accent-ink)}
.conf{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:5px}
.conf.high{background:var(--green-soft);color:var(--green)}
.conf.medium{background:var(--amber-soft);color:var(--amber)}
.conf.low{background:var(--red-soft);color:var(--red)}
.xstatus{font-size:10px;font-weight:700;padding:3px 9px;border-radius:var(--r-pill);white-space:nowrap;
  display:inline-flex;align-items:center;gap:3px}
.xstatus.wait{background:var(--amber-soft);color:var(--amber)}
.xstatus.done{background:var(--green-soft);color:var(--green)}

/* ==========================================================================
   BUTTONS — TWO SIZES, DEFINED ONCE. THIS BLOCK IS THE ONLY SOURCE OF TRUTH.
   ==========================================================================
   .btn      the default. 38px tall, which is deliberately the SAME height as
             input/select below, so a button beside a field (Search, Set, Apply,
             + Add line) lines up with it instead of floating a few pixels off.
   .btn-sm   the one compact variant, for controls inside table rows and dense
             cards: the pencil/trash/reorder icons, the registry's per-row Set.

   There is no third size, and no page may invent one. Buttons used to be styled
   through a bare `button` element selector with per-page padding overrides on
   top, which produced FOURTEEN distinct rendered heights across the app — "+ New
   matter" was 32.6px in the header and 40.1px on the matters list, the same
   label at two sizes. The geometry now lives only here, and tests/test_button_
   system.py fails the build if a template ships a button carrying neither class.

   HEIGHT IS FIXED, WIDTH IS AUTO. Equal height and shape is what makes buttons
   read as one system; forcing equal width would just pad short labels. Height is
   set explicitly rather than left to padding + line-height so that a long label,
   an icon, or a different font-size cannot change it. line-height:1 plus
   centring is what keeps the label optically centred at any size.

   Colour variants (.ghost, .danger) are unchanged — this is geometry only. */
.btn,.btn-sm{
  box-sizing:border-box;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  width:auto;white-space:nowrap;
  font-family:inherit;font-weight:600;line-height:1;
  background:var(--accent);color:var(--accent-ink);border:1px solid var(--accent);
  border-radius:var(--r-sm);cursor:pointer;text-decoration:none;
  transition:background .12s var(--ease),border-color .12s var(--ease),box-shadow .12s var(--ease)}
.btn{height:38px;padding:0 15px;font-size:var(--fs-sm)}
.btn-sm{height:28px;padding:0 10px;font-size:var(--fs-xs)}
/* Icon-only: square, so a row of them reads as a set rather than as text buttons
   that happen to contain a glyph. */
.btn.icon{width:38px;padding:0}
.btn-sm.icon{width:28px;padding:0}
.btn svg{width:15px;height:15px;flex:none}
.btn-sm svg{width:13px;height:13px;flex:none}

.btn:hover,.btn-sm:hover{background:var(--accent-600);border-color:var(--accent-600);text-decoration:none}
.btn:focus-visible,.btn-sm:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-soft)}
.btn.ghost,.btn-sm.ghost{background:var(--surface);color:var(--ink);border-color:var(--line)}
.btn.ghost:hover,.btn-sm.ghost:hover{background:var(--surface-2);border-color:var(--accent-line)}
.btn.danger,.btn-sm.danger{background:var(--surface);color:var(--red);border-color:var(--red-line)}
.btn.danger:hover,.btn-sm.danger:hover{background:var(--red-soft)}
.btn[disabled],.btn-sm[disabled]{opacity:.55;cursor:not-allowed}

/* Controls that are <button> elements but are NOT buttons in this system — tabs,
   segmented switches, the settings nav, menu items, link-styled actions. They own
   their appearance completely and are exempt from the two classes above. Listed
   here only to restate font-family, which they used to inherit from the bare
   `button` selector that this block replaced. */
.mtabs button,.seg button,.set-nav button,.menu button.mitem,.ext-modes button,
.linkbtn,.clearable .clear-x,.q-more .dots{font-family:inherit}
.linkbtn{font-size:var(--fs-sm)}
.actions{margin-bottom:var(--s4);display:flex;gap:var(--s2);flex-wrap:wrap}
/* IN-ROW ACTION CLUSTER. align-items:center so a cluster containing something other
   than a fixed-height button — the file picker below — still sits on one line with the
   buttons rather than stretching them. `.end` is the right-aligned variant every table
   needs: finance.html was writing `style="justify-content:flex-end"` at each site, which
   is a system rule living in two templates. */
.row-actions{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.row-actions form{display:inline}
.row-actions.end{justify-content:flex-end}
/* Two clusters in one cell, stacked and ending at the same right edge. A cell whose
   actions genuinely do not fit on one line stacks DELIBERATELY rather than relying on
   flex-wrap, which breaks at whatever width the browser happens to have and made the
   documents table's rows different heights for no stated reason. */
.cell-stack{display:grid;gap:6px;justify-items:end}

/* COMPACT FILE PICKER — a native file input wearing the compact button.
   The bare control is the one thing in a row of .btn-sm that cannot be styled to match
   it: the browser draws its own trigger, at its own size, with the filename beside it,
   and it was the odd one out in the documents table.
   The input stays a real input — focusable, keyboard-operable, and still the thing a
   `required` validation bubble can point at — but it lies transparent ON TOP of a span
   that is drawn as a .btn-sm. Nothing is hidden with display:none, which is what breaks
   validation on a required file input. The chosen filename replaces the trigger's label
   (matter.html echoes it, exactly as the intake dropzone does); without JavaScript the
   trigger keeps its own text and the upload still works. */
.filepick{position:relative;display:inline-flex;vertical-align:middle}
/* height:auto and no padding/font-size of its own: the trigger beside it owns the
   geometry, and `*{box-sizing:border-box}` means the field's own padding cannot change
   the box that inset:0 has already fixed. Sizing a field anywhere but the two rules in
   the FIELDS block is what tests/test_field_system.py exists to prevent. */
.filepick > input[type=file]{position:absolute;inset:0;z-index:1;
  width:100%;height:auto;opacity:0;cursor:pointer}
/* The face is capped so that trigger + submit still fit .col-translation once a
   filename replaces "Choose file" — otherwise choosing a long-named file wraps the
   cluster onto a second line and the row grows under the user's hands. The full name
   stays reachable as the picker's title. */
.filepick > .filepick-face{max-width:104px;overflow:hidden}
.filepick > .filepick-face > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.filepick > input[type=file]:focus-visible + .filepick-face{box-shadow:0 0 0 3px var(--accent-soft)}
.filepick.has-file > .filepick-face{border-color:var(--accent-line);color:var(--ink)}

/* ==========================================================================
   FIELDS — TWO SIZES, DEFINED ONCE. THIS BLOCK IS THE ONLY SOURCE OF TRUTH.
   ==========================================================================
   Same rule as buttons, and deliberately the same two numbers:

     default    38px — identical to .btn, which is the whole point. A field and
                the button that acts on it (Search, Set, Apply, + Add line) sit
                on one row constantly; equal height is what makes that row read
                as a row instead of as two controls that nearly line up.
     .field-sm  28px — identical to .btn-sm, for dense panels. One compact size,
                not "a bit smaller here and a bit smaller there".

   A page may position a field (width, margin, grid placement) but may NOT
   re-declare its HEIGHT, PADDING or FONT-SIZE. That is how buttons ended up
   with fourteen heights, and fields were on the same road: the extend panel had
   quietly grown a third size at 34px. tests/test_field_system.py fails the build
   on a new one.

   TEXTAREAS ARE EXEMPT FROM THE FIXED HEIGHT and only from that — they keep the
   border, radius, font and padding of the system so a multi-line field still
   looks like a field, but their height is content-driven. A fixed height on a
   textarea would defeat the control.

   HORIZONTAL PADDING IS 11px ON EVERY CONTROL, and vertical padding is 0 on the
   single-line ones: at a fixed height a browser centres an input's text itself,
   and stating a vertical padding as well is what makes a date input sit a pixel
   off a text input beside it. The select keeps a wider padding-right, and only
   that, to clear its chevron — its text still starts on the same 11px line. */
input,select,textarea{border:1px solid var(--line);border-radius:var(--r-sm);padding:0 11px;background:#fff;
  font-family:inherit;font-size:var(--fs-sm);color:var(--ink);width:100%;height:38px;
  transition:border-color .12s var(--ease),box-shadow .12s var(--ease)}
textarea{height:auto;padding:9px 11px;line-height:1.6}

/* ==========================================================================
   FIELD ROWS — ONE GRID PATTERN, THREE SHARED ROWS. USED EVERYWHERE.
   ==========================================================================
   The problem this solves: a field whose label carries a hint ("usually blank for
   an organisation") is three lines tall, its neighbour is two, and so the two
   inputs sat at different heights — the party form's Email pushed a row lower than
   the Phone beside it. Every previous attempt at this was a nudge: `align-content:
   end` bottom-aligned the label boxes so the INPUTS lined up but the LABELS did
   not, and `.align-top` did the exact opposite. Two hacks, each fixing the half
   the other broke, chosen per row by hand.

   THE FIX IS STRUCTURAL. A field row is a grid of THREE rows — name, hint,
   control — and every field in it is a `subgrid` spanning all three, so its parts
   land on the ROW'S shared lines rather than on lines of its own:

       row 1   name      ── every label's text, on one line
       row 2   hint      ── empty for a field that has none; the row still exists
       row 3   control   ── every input/select/textarea, on one line

   A field with no hint leaves its hint cell EMPTY and its control still lands in
   row 3, because the control is placed on row 3 explicitly rather than by counting
   children. That is the whole trick, and it is why nothing here needs tuning per
   row: the alignment is a property of the grid, not of the contents.

   Row 1 is as tall as the tallest label in the row, so a label that wraps to two
   lines pushes every hint and every control in that row down together, still level.

   GAPS. Within a field the rows are var(--fld-gap) apart; between field rows it is
   the parent's row-gap, which is larger. A subgrid overrides the gutters of the
   tracks it spans, which is what lets one grid hold both spacings without either
   being a margin someone has to remember.

   A CONTROL THAT IS NOT A BARE INPUT — a number with a "%" beside it, a select
   with a note under it — wraps in `.fctl`, which is what row 3 then holds. Without
   the wrapper the extra element would be auto-placed into a row of its own and
   push the row out of shape. */
.form-grid{--cols:repeat(3,1fr);
  display:grid;grid-template-columns:var(--cols);
  column-gap:var(--s4);row-gap:0;
  /* The row spacing is a MARGIN on each field (below), not a row-gap, so the last
     band would otherwise leave that margin hanging under the form. */
  margin-bottom:calc(var(--s4)*-1)}
.form-grid.cols-2{--cols:repeat(2,1fr)}
.form-grid.cols-3{--cols:repeat(3,1fr)}
.form-grid > label{display:grid;grid-template-rows:subgrid;grid-row:span 3;
  row-gap:0;align-content:start;margin-bottom:var(--s4)}
/* The control, pinned to row 3 — the one declaration the whole pattern rests on.
   `div` is in the list on purpose and carries the general rule: a BLOCK-level child
   of a label is part of the control area (the party picker's chosen-entry chip, its
   suggestion list), while an INLINE child is part of the label's own text (the
   "(optional)" and "(AI confirms)" parentheticals) and stays on the name line. Without
   `div` the picker chip was auto-placed and landed on top of the search box it is
   meant to replace. */
.form-grid > label > :is(input,select,textarea,button,.btn,.fctl,div){grid-row:3}
/* A button sitting directly in a field row is an ACTION ON that row — Apply on the
   matters filter. It lands on the control line, but it must get there by SPANNING the
   band and sitting at its end, NOT by being pinned to row 3. Grid places items with a
   definite row before auto-placed ones, so `grid-row:3` made Apply and All cases seize
   the first free columns of row 3 and shoved every field along; spanning keeps them in
   DOM order after the fields. Ending flush with row 3 is what puts a 38px button on the
   same line as the 38px controls beside it. */
.form-grid > :is(button,.btn){grid-row:span 3;align-self:end;margin-bottom:var(--s4)}
/* Anything else that is not a field — a duplicate warning, a fieldset — takes a
   whole band rather than slotting into one row of somebody else's. */
.form-grid > :not(label):not(button):not(.btn){grid-row:span 3;margin-bottom:var(--s4)}
/* A control that needs company inside row 3. */
.fctl{display:grid;gap:var(--s1);align-content:start}
.fctl.inline{grid-auto-flow:column;justify-content:start;align-items:center;gap:6px}
.fctl.inline > input{width:80px}
.stack{display:grid;gap:var(--s3)}
label{display:grid;gap:var(--fld-gap);color:var(--muted);font-size:var(--fs-xs);font-weight:500}
/* The hint line. `.fhint`, not `.hint`, because `.hint` is already the login card's
   bordered help box further down this file. Same `f` prefix as `.fctl`. */
.fhint{color:var(--muted);font-size:var(--fs-xs);font-weight:400;line-height:1.35}
/* EVERY GAP HERE IS A MARGIN, AND THE GRID'S OWN ROW-GAP IS ZERO. A gap would be
   charged twice inside each field — once above the hint row and once below it — and it
   is charged even when that row is EMPTY, so every hintless field in the app would grow
   by two gaps for a line it does not have (this cost Settings 16px per field before it
   was caught). A margin belongs to an element, so an absent hint costs exactly nothing
   and a field closes up to name + 6px + control, hint or no hint. */
.form-grid > label > .fhint{grid-row:2;align-self:end;margin-top:var(--fld-gap)}
.form-grid > label > :is(input,select,textarea,.fctl,div){margin-top:var(--fld-gap)}
/* The compact size. Applied by opting a CONTAINER in, so a dense panel states it
   once rather than every field inside it repeating a number. */
.field-sm input,.field-sm select,input.field-sm,select.field-sm{height:28px;padding:0 8px;font-size:var(--fs-xs)}
.field-sm textarea,textarea.field-sm{padding:6px 8px;font-size:var(--fs-xs)}
.field-sm input[type=checkbox],.field-sm input[type=radio]{height:auto;padding:0}
select{appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6470' stroke-width='2'%3e%3cpath d='M6 9l6 6 6-6'/%3e%3c/svg%3e");
  background-repeat:no-repeat;background-position:right 10px center;background-size:16px;padding-right:32px;cursor:pointer}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
input::placeholder,textarea::placeholder{color:var(--faint)}

/* A LOCKED CONTROL MUST LOOK LOCKED.
   ==========================================================================
   Reported from real use: on /party/4 the Kind and Organisation selects are
   correctly disabled — a person is filed under that organisation, and an
   organisation is not filed under another one — and they were read as BROKEN.
   Nothing about them said "locked": the base rule paints every control
   background:#fff and gives every select a chevron and cursor:pointer, so the
   only difference a browser could make was to dim the text a little. A control
   that still looks like a control is an invitation to click it, and when the
   click does nothing the page looks broken rather than closed.

   FOUR SIGNALS, NOT ONE OPACITY. Fading a control says "this is faint", which
   is why the fade was misread; these say "this is not yours to change":
     · a muted BACKGROUND — the surface tone the app already uses for inert
       panels, so a locked field reads as part of the page rather than a field;
     · a lighter BORDER — --line2, the same hairline that separates rows;
     · NO CHEVRON on a select — the chevron IS the affordance, and removing it
       is what stops the control looking like it opens. The padding it cleared
       goes back, or the value sits in a gutter that is no longer there;
     · cursor:not-allowed, which answers the click before it happens.
   The VALUE STAYS LEGIBLE, at --muted rather than --faint: the whole point of
   showing a locked field is that its value is information. Never `opacity`
   here — it was the failure mode, and it dims the value along with the frame.

   READONLY IS LOCKED TOO. To a person there is no difference between a control
   they cannot open and one they cannot type in — the reference on New Matter
   and the body on an email draft are both "shown, not yours to edit" — so they
   get the same treatment rather than a second, nearly-identical look.

   THE REASON LINE UNDER THE CONTROL IS DOING THE EXPLAINING and stays where it
   is. This rule's whole job is that the control stops inviting the click; it
   never says WHY, because why is per-case and belongs in the <small> beside it.

   Checkboxes and radios are exempt from the frame — they have no frame to mute
   (the base rule strips their border and background) — and take the cursor
   alone. tests/test_field_system.py locks all of this. */
input:is([disabled],[readonly]):not([type=checkbox]):not([type=radio]),
select[disabled],
textarea:is([disabled],[readonly]){
  background-color:var(--surface-2);border-color:var(--line2);
  color:var(--muted);cursor:not-allowed;
  /* opacity:1 UNDOES THE BROWSER, and is the one place opacity is named here. A UA
     stylesheet fades a disabled control to ~0.7 — that fade IS the reported defect, and
     it also dims the value we are keeping legible. Our own colour says "locked"; this
     stops the browser saying "faint" over the top of it. */
  opacity:1}
select[disabled]{background-image:none;padding-right:11px}
input[type=checkbox]:is([disabled],[readonly]),
input[type=radio]:is([disabled],[readonly]){cursor:not-allowed}
.check{display:flex;gap:8px;align-items:center;color:var(--ink);font-size:var(--fs-sm)}
.check input{width:auto;height:auto;accent-color:var(--accent-700)}

/* Clearable search fields */
.clearable{position:relative;display:inline-flex;align-items:center}
.clearable > input{padding-right:30px}
.clearable .clear-x{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  display:none;place-items:center;width:19px;height:19px;padding:0;border:none;border-radius:50%;
  background:var(--surface-2);color:var(--muted);font-size:13px;line-height:1;cursor:pointer;
  transition:background .12s var(--ease),color .12s var(--ease)}
.clearable .clear-x:hover{background:var(--line2);color:var(--ink)}
.clearable > input:not(:placeholder-shown) + .clear-x{display:grid}

/* Misc */
.chips{display:flex;gap:var(--s2);flex-wrap:wrap}
.chips span{border:1px solid var(--line);border-radius:6px;padding:6px 10px;background:var(--surface-2);font-size:var(--fs-xs)}
.flash{margin-bottom:var(--s4)}
.flash div{background:var(--accent-soft);border:1px solid var(--accent-line);padding:11px 14px;
  border-radius:var(--r);color:var(--accent-700);font-size:var(--fs-sm)}
.stepper{display:flex;flex-direction:column;gap:3px}
.step{border-radius:8px;border-left:3px solid transparent;transition:background .12s var(--ease)}
.step:nth-child(even){background:var(--surface-2)}                 /* zebra */
.step:hover{background:var(--accent-soft)}
.step.done{border-left-color:var(--green)}
.step.current{border-left-color:var(--accent)}
.step.pending{border-left-color:var(--line2)}
.step-head{display:flex;gap:11px;align-items:center;padding:9px 12px}
.step .dot{width:18px;height:18px;border-radius:50%;flex-shrink:0;border:2px solid var(--line);
  background:#fff;display:grid;place-items:center;transition:all .12s var(--ease)}
.step.done .dot{background:var(--green);border-color:var(--green)}
.step.done .dot::after{content:"✓";color:#fff;font-size:11px;font-weight:800;line-height:1}
.step.current .dot{border-color:var(--accent);border-width:5px;box-shadow:0 0 0 3px var(--accent-soft)}
.step-main{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}
.step-main .stage{font-size:var(--fs-sm)}
.step.done .stage{color:var(--ink)}
.step.current .stage{color:var(--ink);font-weight:600}
.step.pending .stage{color:var(--muted)}
.step-meta{color:var(--muted);font-size:var(--fs-2xs)}
.step-actions{display:flex;gap:3px;align-items:center;flex-shrink:0;opacity:.5;transition:opacity .12s var(--ease)}
.step:hover .step-actions{opacity:1}
.step-actions form{display:inline-flex;margin:0}
.step-actions .btn-sm:disabled{opacity:.3;cursor:default}
.step-edit{padding:2px 12px 12px 41px}
.step-edit[hidden]{display:none}
.wf-progress{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.wf-bar{flex:1;height:7px;border-radius:var(--r-pill);background:var(--line2);overflow:hidden}
.wf-bar > i{display:block;height:100%;background:var(--accent);border-radius:inherit;transition:width .2s var(--ease)}
.wf-progress b{font-size:var(--fs-xs);color:var(--muted);font-weight:600;white-space:nowrap}
.wf-add{margin-top:10px;padding-top:12px;border-top:1px solid var(--line2)}
.tabs{display:flex;gap:0;border-bottom:1px solid var(--line);margin-bottom:var(--s5)}
.tabs a{padding:10px 2px;margin-right:24px;color:var(--muted);font-weight:500;font-size:var(--fs-sm);
  border-bottom:2px solid transparent;transition:color .12s var(--ease),border-color .12s var(--ease)}
.tabs a:hover{color:var(--ink);text-decoration:none}
.tabs a.active{color:var(--ink);font-weight:600;border-bottom-color:var(--accent)}
.gate{background:var(--amber-soft);border:1px solid var(--amber-line);border-radius:var(--r);
  padding:11px 13px;color:#7a531a;font-size:var(--fs-xs);display:flex;gap:8px;margin-top:var(--s3)}

/* Cross-reference UI */
.waitbanner{display:flex;align-items:center;gap:12px;background:var(--amber-soft);border:1px solid var(--amber-line);
  border-radius:var(--r);padding:13px 15px;margin-bottom:var(--s4)}
.waitbanner.resume{background:var(--accent-soft);border-color:var(--accent-line)}
.waitbanner .wb-ic{width:32px;height:32px;border-radius:9px;background:var(--amber);color:#fff;
  display:grid;place-items:center;flex-shrink:0;font-weight:700}
.waitbanner.resume .wb-ic{background:var(--accent);color:var(--accent-ink)}
.waitbanner .wb-t{font-weight:700;font-size:var(--fs-sm);color:#7a531a}
.waitbanner.resume .wb-t{color:var(--accent-700)}
.waitbanner .wb-s{font-size:var(--fs-xs);color:#8a6320;margin-top:1px}
.waitbanner.resume .wb-s{color:var(--accent-700)}
.waitbanner .wb-act{margin-left:auto;flex-shrink:0}
svg a .xnode-rect{transition:filter .1s var(--ease)}
svg a:hover .xnode-rect{filter:brightness(.96)}
svg a{text-decoration:none}

/* My day action buttons */
.act-btn{border-color:transparent;font-weight:700;min-width:76px}
.act-btn.draft{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.act-btn.draft:hover{background:var(--accent-600);text-decoration:none}
.act-btn.do{background:var(--sidebar);border-color:var(--sidebar);color:#fff}
.act-btn.do:hover{background:#1a2740;text-decoration:none}
.act-btn.open{background:var(--surface);border-color:var(--line);color:var(--ink)}
.act-btn.open:hover{background:var(--surface-2);text-decoration:none}
.act-btn.resume{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);min-width:0}
/* .icon-btn retired — icon buttons are `btn-sm icon ghost`, sized by the system. */
.myday-actions{display:flex;gap:6px;align-items:center;justify-content:flex-end}
.myday-actions form{display:inline-flex;margin:0}

/* Clickable dashboard cards */
a.card.stat{display:block;transition:transform .1s var(--ease),box-shadow .14s var(--ease),border-color .14s var(--ease)}
a.card.stat:hover{text-decoration:none;transform:translateY(-2px);box-shadow:var(--shadow-lg);border-color:var(--accent-line)}
a.card.stat span{color:var(--muted)} a.card.stat b{color:var(--ink)}
a.card.stat.accent b{color:var(--accent-700)} a.card.stat.alert b{color:var(--red)}

/* --- Documents on file, and the retired panel beside it ---------------------
   Both tables carry .doc-table so the Super-Admin view is the same design, not a
   second one. The two action columns are FIXED width because their contents are
   fixed: a cluster of compact buttons whose width does not depend on the document.
   Left to size themselves they took whatever the longest filename left over, which
   is what wrapped Download/Edit/Retire onto two ragged lines. */
.doc-table .col-translation{width:238px}
.doc-table .col-record{width:216px}
/* A cluster never breaks mid-cluster; the cells that hold prose still wrap freely. */
.doc-table td.right{white-space:nowrap}
/* The second line under a filename — size, "(external link)", "no file on record". */
.doc-sub{color:var(--muted);font-size:var(--fs-xs)}
/* The inline edit row, same treatment as the contact edit row: tinted so it reads as
   attached to the row above, and gone when hidden. --surface-2 is the token; this was
   `var(--panel-alt,#fafafa)`, a variable that does not exist in this stylesheet, so the
   row was quietly painting itself an off-system near-white. */
.doc-table tr.doc-edit-row[hidden]{display:none}
.doc-table tr.doc-edit-row > td{background:var(--surface-2)}
/* The permanent-deletion confirm row. Tinted red rather than grey — it is the same
   reveal pattern as the edit rows, and it must not look like one: everything else on
   this page can be undone and this cannot. */
.doc-table tr.doc-delete-row[hidden]{display:none}
.doc-table tr.doc-delete-row > td{background:var(--red-soft);
  border-top:1px solid var(--red-line)}
.doc-delete-warn{margin:0 0 10px;font-size:var(--fs-sm);color:var(--ink);line-height:1.5}
.doc-delete-actions{align-self:end;margin-bottom:var(--s4)}

/* Parties & contacts top-aligned */
.contacts-table td{vertical-align:top}
.contacts-table td .pill{margin-top:1px}
.contacts-table tr.contact-edit[hidden]{display:none}
.contacts-table tr.contact-edit > td{background:var(--surface-2)}
.dtag{display:inline-block;font-size:10px;font-weight:700;padding:2px 7px;border-radius:5px;margin:1px 3px 1px 0;
  background:var(--surface-2);color:var(--muted);border:1px solid var(--line2);white-space:nowrap}
.dtag.primary{background:var(--accent-soft);color:var(--accent-700);border-color:var(--accent-line)}
.dtag.cc{background:var(--hair);color:var(--faint)}

/* Drop zones */
.dropzone,.dropzone-sm{border:2px dashed var(--accent-line);border-radius:var(--r-lg);background:var(--accent-soft);
  text-align:center;cursor:pointer;transition:background .12s var(--ease),border-color .12s var(--ease)}
.dropzone{padding:36px 20px}
.dropzone-sm{padding:20px 16px;border-radius:var(--r)}
.dropzone.drag,.dropzone-sm.drag{background:#dce6f1;border-color:var(--accent)}
.dz-icon{font-size:26px;color:var(--accent-700)}
.dropzone-sm .dz-icon{font-size:22px}
.dz-title{font-weight:700;font-size:14px;margin-top:6px;color:var(--ink)}
.dropzone-sm .dz-title{font-size:13px;margin-top:4px}
.dz-sub{color:var(--muted);font-size:var(--fs-xs);margin-top:3px}
.dz-filename{margin-top:9px;font-weight:600;color:var(--accent-700);font-size:var(--fs-xs)}

/* Filter chips */
.filter-chip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:var(--r-pill);
  padding:5px 12px;cursor:pointer;font-size:var(--fs-xs);font-weight:600;background:var(--surface);
  user-select:none;transition:background .1s var(--ease),border-color .1s var(--ease),color .1s var(--ease)}
.filter-chip:hover{border-color:var(--accent);background:var(--accent-soft)}
.filter-chip.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.filter-chip .fc-count{font-size:10px;font-weight:700;opacity:.6;background:rgba(0,0,0,.06);padding:1px 6px;border-radius:var(--r-pill)}
.filter-chip.on .fc-count{background:rgba(0,0,0,.18);opacity:.85}
/* A facet with nothing behind it in the CURRENT scope. Dimmed rather than hidden:
   the row of types is a map of the taxonomy, and removing entries would make the
   filter bar change shape every time the scope changes. Still clickable — it says
   'nothing here', not 'you may not'. */
.filter-chip.empty{opacity:.38}
.filter-chip.empty:hover{opacity:.7;border-color:var(--line);background:transparent}

/* My Day — the FIRM COVERAGE safety net. Deliberately quieter than the personal
   queue above it: same page, different kind of claim on the reader. It is not
   'your work', it is 'the firm has a gap', so it gets a dashed edge, a muted
   ground and no severity colour on its rows. */
.coverage-group{border-style:dashed;background:var(--bg-soft,transparent)}
.coverage-group>summary{opacity:.82}
.coverage-group .cov-note{padding:2px 14px 10px;font-size:12px;color:var(--muted);max-width:70ch}
.coverage-group .q-row{opacity:.9}
.coverage-group[open]>summary{border-bottom:1px dashed var(--line)}

/* Raise-draft panel. Label-over-input pairs on a baseline, so the four controls
   read as four questions rather than a row of unlabelled boxes; the action group
   is pushed right and separated from the inputs that configure it. */
.raise-form{display:flex;gap:14px;align-items:flex-end;flex-wrap:wrap}
.raise-form .rf-field{display:flex;flex-direction:column;gap:4px}
.raise-form .rf-grow{flex:1;min-width:190px}
.raise-form .rf-grow select{width:100%}
.raise-form .rf-lab{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;line-height:1.4}
.raise-form .rf-action{margin-left:auto;padding-left:10px;border-left:1px solid var(--line)}
@media (max-width:720px){.raise-form .rf-action{margin-left:0;border-left:0;padding-left:0}}

/* Back link */
.backlink{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-sm);font-weight:600;color:var(--muted);
  text-decoration:none;padding:5px 11px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
  transition:background .12s var(--ease),border-color .12s var(--ease),color .12s var(--ease)}
.backlink:hover{color:var(--ink);border-color:var(--accent);text-decoration:none;background:var(--accent-soft)}
.backlink svg{display:block}

/* Login */
.login-wrap{margin:0;display:grid;place-items:center;min-height:100vh;background:var(--ink);
  background-image:radial-gradient(circle at 30% 20%,rgba(74,107,138,.14),transparent 45%)}
.login-card{background:var(--surface);border:1px solid var(--line);border-radius:16px;padding:36px;width:368px;
  box-shadow:0 24px 70px rgba(0,0,0,.34)}
.login-card .logo{width:42px;height:42px;border-radius:11px;background:var(--accent);color:var(--accent-ink);
  display:grid;place-items:center;font-weight:800;margin-bottom:20px;font-size:15px}
.login-card h1{font-size:21px;margin-bottom:4px}
.login-card p{color:var(--muted);margin:0 0 22px;font-size:var(--fs-sm)}
.login-card button{width:100%;justify-content:center;margin-top:8px}
.hint{margin-top:18px;font-size:var(--fs-xs);color:var(--muted);background:var(--canvas);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:10px 12px;line-height:1.6}

/* Responsive */
@media(max-width:1000px){
  aside{position:static;width:auto}
  main{margin-left:0;max-width:none;padding:var(--s4)}
  /* Narrow: one card per row. auto-flow must be reset to row, or the column rule
     above keeps every card on one line however narrow the viewport gets. */
  .cards{grid-auto-flow:row;grid-template-columns:1fr}
  .grid2{grid-template-columns:1fr}
  /* !important so one rule collapses every field row: it has to beat both the
     .cols-* classes and the bespoke ratios set inline at the usage site. The
     subgrid spans are untouched, so a stacked field keeps its three rows. */
  .form-grid{--cols:1fr!important}
  .topbar{margin:calc(var(--s4)*-1) calc(var(--s4)*-1) var(--s4);padding:0 var(--s4)}
}
@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}
/* `.form-grid label{align-content:end}` and its `.align-top` counterpart lived here.
   Both are gone: they were the two half-fixes the subgrid pattern replaces — one
   levelled the controls and skewed the labels, the other did the reverse. A textarea
   still gets a floor so a 2-row one is never shorter than the inputs beside it. */
.form-grid textarea{min-height:38px}

/* ============ My day (redesign) ============ */
.myday .cards{margin-bottom:var(--s4)}
.myday a.card.stat{padding:16px 18px;cursor:pointer}
.myday .stat::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--line2)}
.myday .stat.sev-red::before{background:var(--red)}
.myday .stat.sev-amber::before{background:var(--amber)}
.myday .stat.sev-accent::before{background:var(--accent)}
.myday .stat.sev-muted::before{background:var(--faint)}
.myday .stat > span{font-size:var(--fs-xs);color:var(--muted);font-weight:500}
.myday .stat b{display:block;font-size:30px;font-weight:700;margin-top:6px;letter-spacing:-.02em;line-height:1;font-variant-numeric:tabular-nums}
.myday .stat.sev-red b{color:var(--red)} .myday .stat.sev-amber b{color:var(--amber)}
.myday .stat.sev-accent b{color:var(--accent-700)} .myday .stat.sev-muted b{color:var(--ink)}
.myday .stat .sub{display:block;margin-top:8px;font-size:var(--fs-2xs);color:var(--faint)}

/* deadline queue */
.q-group{margin-bottom:var(--s4)}
.q-ghead{display:flex;align-items:center;gap:10px;margin:0 0 8px;padding:0 2px}
.q-ghead .tag{font-size:var(--fs-2xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em;padding:3px 10px;border-radius:var(--r-pill)}
.q-ghead .tag.red{background:var(--red-soft);color:var(--red);border:1px solid var(--red-line)}
.q-ghead .tag.amber{background:var(--amber-soft);color:var(--amber);border:1px solid var(--amber-line)}
.q-ghead .tag.accent{background:var(--accent-soft);color:var(--accent-700);border:1px solid var(--accent-line)}
.q-ghead .tag.muted{background:var(--surface-2);color:var(--muted);border:1px solid var(--line2)}
.q-ghead .cnt{font-size:var(--fs-xs);color:var(--muted);font-weight:600}
.q-list{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);overflow:visible;box-shadow:var(--shadow-sm)}
.q-row{display:grid;grid-template-columns:230px 1fr 150px 44px;gap:16px;align-items:center;padding:13px 12px 13px 15px;border-bottom:1px solid var(--line2);border-left:3px solid transparent;transition:background .1s var(--ease);cursor:pointer;position:relative}
.q-row:first-child{border-top-left-radius:var(--r-lg);border-top-right-radius:var(--r-lg)}
.q-row:last-child{border-bottom:none;border-bottom-left-radius:var(--r-lg);border-bottom-right-radius:var(--r-lg)}
.q-row:hover{background:var(--accent-soft)}
.q-row:focus-visible{outline:none;background:#eef3fb;box-shadow:inset 0 0 0 2px var(--accent-line)}
.q-row.sev-red{border-left-color:var(--red)} .q-row.sev-amber{border-left-color:var(--amber)}
.q-row.sev-accent{border-left-color:var(--accent)} .q-row.sev-muted{border-left-color:var(--line2)}
.q-id .ref{font-family:ui-monospace,Menlo,monospace;font-size:var(--fs-xs);font-weight:600;color:var(--accent-700)}
.q-row:hover .q-id .ref{text-decoration:underline}
.q-id .mark{font-size:var(--fs-sm);font-weight:600;margin-top:2px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.q-id .client{font-size:var(--fs-2xs);color:var(--muted);margin-top:1px}
.q-what .act{font-size:var(--fs-sm);color:var(--ink);font-weight:500}
.q-what .basis{font-size:var(--fs-2xs);color:var(--muted);margin-top:2px}
.q-when{text-align:right}
.q-when .date{font-size:var(--fs-sm);font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink)}
.q-when .rel{font-size:var(--fs-2xs);font-weight:600;margin-top:2px}
.q-when .rel.red{color:var(--red)} .q-when .rel.amber{color:var(--amber)}
.q-when .rel.accent{color:var(--accent-700)} .q-when .rel.muted{color:var(--faint)}
.q-more{display:flex;justify-content:flex-end;align-items:center;position:relative}
.q-more form.q-inline{margin:0}

/* triage menu */
.q-more .dots{width:30px;height:30px;padding:0;display:grid;place-items:center;border-radius:var(--r-sm);border:1px solid transparent;background:transparent;color:var(--muted);font-size:19px;line-height:1;cursor:pointer;font-weight:400}
.q-more .dots:hover{background:var(--surface-2);border-color:var(--line);color:var(--ink)}
.q-row:hover .dots{color:var(--ink)}
.menu{position:absolute;right:0;top:36px;z-index:40;min-width:210px;background:#fff;border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);padding:6px;display:none;text-align:left;cursor:default}
.menu.open{display:block}
.menu .mtitle{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);font-weight:700;padding:6px 8px 4px}
.menu form{margin:0}
.menu button.mitem{display:flex;width:100%;align-items:center;gap:9px;background:none;border:none;padding:8px;border-radius:6px;font-family:inherit;font-size:var(--fs-sm);font-weight:500;color:var(--ink);cursor:pointer;text-align:left}
.menu button.mitem:hover{background:var(--accent-soft)}
.menu button.mitem .ic{width:18px;text-align:center;color:var(--muted);font-size:13px}
.legend{font-size:var(--fs-2xs);color:var(--faint);margin-top:8px;padding:0 2px}

@media(max-width:1000px){
  .q-row{grid-template-columns:1fr;gap:8px}
  .q-when{text-align:left}
  .menu{right:auto;left:0}
}

/* My day — "Remind me later" presets + Snoozed group */
.menu .msub{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);font-weight:700;padding:8px 8px 2px;margin-top:4px;border-top:1px solid var(--line2)}
.menu .msub .msub-hint{text-transform:none;letter-spacing:0;font-weight:500;color:var(--faint)}
.menu .remind-row{display:flex;gap:5px;padding:4px 6px 4px}
.menu .remind-row form{flex:1;margin:0}
.menu .remind-row .rbtn{width:100%;justify-content:center;padding:6px 4px;font-size:var(--fs-2xs);font-weight:600;border-radius:6px;border:1px solid var(--line);background:var(--surface);color:var(--ink)}
.menu .remind-row .rbtn:hover{background:var(--accent-soft);border-color:var(--accent-line)}
.q-row.snoozed{background:var(--surface-2)}
.q-row.snoozed .mark{color:var(--muted)}
.q-when .snz{margin-top:4px;font-size:10px;font-weight:700;color:var(--muted);background:var(--surface);border:1px solid var(--line2);border-radius:var(--r-pill);padding:2px 8px;display:inline-block}
details.snoozed-group{margin-bottom:var(--s4)}
details.snoozed-group > summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:10px;padding:0 2px}
details.snoozed-group > summary::-webkit-details-marker{display:none}
details.snoozed-group > summary .chev{margin-left:auto;color:var(--faint);font-size:15px;transition:transform .15s var(--ease)}
details.snoozed-group[open] > summary .chev{transform:rotate(90deg)}
details.snoozed-group > summary + .q-list{margin-top:8px}

/* My day — Extend deadline popover */
.menu .msep{height:1px;background:var(--line2);margin:5px 4px}
.menu .mitem .chev{margin-left:auto;color:var(--faint);font-size:12px}
.ext-panel{display:none;padding:4px 6px 2px}
.ext-panel.open{display:block}
.ext-modes{display:flex;border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden;margin-bottom:9px}
.ext-modes button{flex:1;background:var(--surface-2);border:none;border-right:1px solid var(--line);padding:7px 6px;font-family:inherit;font-size:var(--fs-2xs);font-weight:600;color:var(--muted);cursor:pointer}
.ext-modes button:last-child{border-right:none}
.ext-modes button:hover{color:var(--ink)}
.ext-modes button.on{background:var(--accent);color:#fff}
.ext-field{margin-bottom:9px}
.ext-field[hidden]{display:none}
.ext-lab{display:block;font-size:var(--fs-2xs);color:var(--muted);font-weight:600;margin-bottom:5px}
.ext-inline{display:flex;align-items:center;gap:8px}
/* The panel is dense, so it opts into the compact FIELD size — it does not invent
   one. This used to read `height:34px`, a third size that existed nowhere else. */
.ext-panel input[type=number],.ext-panel input[type=date],.ext-panel select{width:100%}
.ext-inline .ext-days{width:84px}
.ext-unit{font-size:var(--fs-sm);color:var(--muted)}
.ext-result{background:var(--accent-soft);border:1px solid var(--accent-line);border-radius:var(--r-sm);padding:8px 10px;margin-bottom:9px}
.ext-rlab{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--accent-700);font-weight:700;margin-bottom:3px}
.ext-rval{font-size:var(--fs-xs);font-weight:600;line-height:1.55}
.ext-rval .rj{font-weight:700;color:var(--ink)} .ext-rval .rw{font-weight:700}
.ext-rval .rg{color:var(--muted);font-variant-numeric:tabular-nums} .ext-rval .rwe{color:var(--muted)}
.ext-reason{display:block;font-size:var(--fs-2xs);color:var(--muted);font-weight:600;margin-bottom:8px}
.ext-reason .opt{font-weight:400;color:var(--faint)}
/* Position and behaviour only — the border, radius, padding and font come from the
   field block, which they used to restate verbatim. */
.ext-reason textarea{width:100%;margin-top:4px;resize:vertical;line-height:1.5}
.ext-apply{display:flex;justify-content:flex-end}

/* ============ Matters list (redesign) ============ */
.matters-filters{margin-bottom:14px}
/* The matters filter bar is a field row like any other — it carries `.form-grid` in
   the markup and states only its own column ratio here. It used to restate the grid,
   the label rule and `align-items:end` itself, which is how it drifted out of step
   with the forms it sits above. */
.mfilter-grid{--cols:1.6fr 1.2fr 1fr 1fr auto;column-gap:12px}
.mfilter-row{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin-top:14px}
.mfilter-lab{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:700;margin-right:4px}
.fmeta{font-size:var(--fs-xs);color:var(--muted);margin-top:14px;padding-top:12px;border-top:1px solid var(--line2)}
.fmeta b{color:var(--ink)}
.matters-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:8px}
#selectToggle.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
/* selection checkbox column — always visible (select-all lives in the header) */
.matters-table .selcol{width:34px;text-align:center}
/* checkboxes/radios must NOT inherit the text-field sizing (width:100%/height:38px) */
input[type=checkbox],input[type=radio]{width:auto;height:auto;padding:0;border:0;background:none;accent-color:var(--accent-700)}
/* standard, clearly-clickable selection checkboxes on the Matters table */
.matters-table .selcol input[type=checkbox]{width:17px;height:17px;cursor:pointer;vertical-align:middle;margin:0}
.yourref{font-size:10px;color:var(--faint);font-weight:500;margin-top:2px}
/* tri-format deadline cell — same rendering as My Day */
.dlc-main{font-size:var(--fs-sm);font-weight:600;font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.dlc-rel{font-size:10px;font-weight:700}
.dlc-rel.red{color:var(--red)} .dlc-rel.amber{color:var(--amber)} .dlc-rel.accent{color:var(--accent-700)} .dlc-rel.muted{color:var(--faint)}
.dlc-sub{font-size:var(--fs-2xs);color:var(--muted);font-variant-numeric:tabular-nums;margin-top:2px}
/* The filter bar deliberately goes two-up rather than one-up on a narrow screen —
   five filters stacked is a very long column. Stated as --cols so it goes through the
   same token as every other field row; setting grid-template-columns directly here
   would silently bypass the shared collapse above. */
@media(max-width:1000px){ .mfilter-grid{--cols:1fr 1fr!important} }

/* ============ Matter detail — identity header + tabs ============ */
.mhead{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-sm);padding:18px 18px 10px;margin-bottom:var(--s4)}
.mhead-top{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--s4);flex-wrap:wrap}
.mhead-side{display:flex;flex-direction:column;align-items:flex-end;gap:10px}
.m-ident .m-refs{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 8px;margin-bottom:4px}
.m-refs .rf{display:inline-flex;align-items:baseline;gap:6px}
.m-refs .rk{font-size:10px;text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:var(--muted)}
.m-refs b.mono{font-family:ui-monospace,Menlo,monospace;font-size:13px;font-weight:700;color:var(--accent-700);letter-spacing:.02em}
.m-refs .rdot{color:var(--faint)}
/* .yourref-toggle sizing removed — it is a .btn-sm icon like every other row icon. */
.yourref-edit{display:flex;gap:8px;align-items:center;margin-top:10px;max-width:520px}
.yourref-edit[hidden]{display:none}
.yourref-edit input{flex:1}
.m-ident .mark{font-size:22px;font-weight:700;letter-spacing:-.02em;margin-top:3px;line-height:1.1}
.m-ident .client{font-size:var(--fs-sm);color:var(--muted);margin-top:3px}
.m-meta{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;justify-content:flex-end}
/* The identity ribbon distributes its VISIBLE blocks, whatever their number.
   It was repeat(6,auto): a hardcoded count AND content-sized columns. When Handling
   firm became Super-Admin-only the sixth column stayed in the template — five blocks
   bunched left with the sixth column's slack sitting empty on the right — and `auto`
   meant the five that did render were sized by their text rather than evenly.
   auto-flow column + auto-columns creates exactly as many equal columns as there are
   children, so adding or removing a block redistributes with no number to update.
   minmax(0,1fr) rather than 1fr: 1fr floors at min-content, so a long agent name would
   widen its column and squeeze its neighbours instead of wrapping inside it. */
.m-facts{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:2px 28px;margin-top:var(--s4);padding:14px 0 0;border-top:1px solid var(--line2)}
/* Each block is its own wrapping context — without min-width:0 a grid item refuses to
   shrink below its content and the minmax(0,…) above is silently overridden. */
.m-facts>div{min-width:0}
.m-facts .k{font-size:var(--fs-2xs);color:var(--muted);text-transform:uppercase;letter-spacing:.05em;font-weight:600}
.m-facts .v{font-size:var(--fs-sm);font-weight:600;margin:2px 0 10px;overflow-wrap:anywhere}
/* matter tab bar (namespaced to avoid the settings .tabs component) */
.mtabs{display:flex;gap:2px;flex-wrap:wrap;margin:0 0 16px;padding:0 6px;background:var(--surface);border:1px solid var(--line2);border-radius:var(--r-lg);box-shadow:var(--shadow-sm)}
.mtabs button{background:transparent;border:none;padding:12px 14px;border-radius:var(--r-sm) var(--r-sm) 0 0;color:var(--muted);font-weight:600;font-size:var(--fs-body);font-family:inherit;cursor:pointer;letter-spacing:-.01em;position:relative;transition:background .12s var(--ease),color .12s var(--ease)}
.mtabs button::after{content:"";position:absolute;left:10px;right:10px;bottom:-1px;height:2px;background:transparent;border-radius:2px 2px 0 0;transition:background .12s var(--ease)}
.mtabs button:hover{background:var(--surface-2);color:var(--accent-700)}
.mtabs button.active{color:var(--accent-700);font-weight:700}
.mtabs button.active::after{background:var(--accent)}
.mtabs button:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--accent-line)}
.tabpane{display:none} .tabpane.active{display:block}
/* Narrow: two equal columns, flowing in rows. auto-flow must be reset to row or
   the column rule above keeps everything on one line. */
@media(max-width:1000px){ .m-facts{grid-auto-flow:row;grid-template-columns:repeat(2,minmax(0,1fr))} .mhead-side{align-items:flex-start} }

/* ============ Matter Overview tab — info lists, timeline, panel bands ============ */
.panel-body{padding:16px 18px}
.panel-head .count{font-size:var(--fs-xs);color:var(--muted);font-weight:600}
.panel-head a.count{color:var(--accent-700);cursor:pointer}
.panel-head a.count:hover{text-decoration:underline}
.info{display:flex;flex-direction:column}
.info-row{display:grid;grid-template-columns:150px 1fr;gap:14px;align-items:baseline;padding:11px 0;border-bottom:1px solid var(--line2)}
.info-row:last-child{border-bottom:none}
.info-row .k{color:var(--muted);font-size:var(--fs-xs);font-weight:500}
.info-row .v{font-size:var(--fs-sm);font-weight:500;color:var(--ink)}
.info-row .v.num{font-weight:700;font-variant-numeric:tabular-nums}
/* Two-column fact pairing (Application & priority). Each office-issued number sits
   beside its own date instead of stacking, roughly halving the panel's height.
   COMPOSES .info-row rather than restyling it, so labels and values keep exactly the
   type, colour and rhythm they already have on party_detail — no new vocabulary. */
.info-pairs{display:grid;grid-template-columns:1fr 1fr;column-gap:26px;padding:2px 18px 6px}
.info-pairs .span2{grid-column:1 / -1}
.info-pairs .info-row{padding:10px 0}
/* Subject heading. Same token as `th` and .m-facts .k, deliberately. */
.info-pairs .grp{grid-column:1 / -1;font-size:var(--fs-2xs);color:var(--muted);
  text-transform:uppercase;letter-spacing:.06em;font-weight:600;padding:13px 0 1px}
.info-pairs .grp:first-child{padding-top:5px}
/* One column once two 150px-label rows stop fitting side by side. */
@media(max-width:860px){.info-pairs{grid-template-columns:1fr;column-gap:0}}
.timeline{display:flex;flex-direction:column}
.tl-item{display:grid;grid-template-columns:110px 1fr;gap:16px;padding:11px 0;border-bottom:1px solid var(--line2)}
.tl-item:last-child{border-bottom:none}
.tl-when{font-size:var(--fs-xs);color:var(--muted);font-variant-numeric:tabular-nums}
.tl-what{font-size:var(--fs-sm)}
.tl-what .who{color:var(--muted);font-size:var(--fs-xs);margin-top:2px}
.urg.red{color:var(--red);font-weight:600} .urg.amber{color:var(--amber);font-weight:600}
.urg.accent{color:var(--accent-700);font-weight:600} .urg.muted{color:var(--faint)}
/* header-band distinction — subtle shadow so panel headers read as a band */
.panel-head{box-shadow:0 6px 10px -6px rgba(13,27,48,.13);position:relative;z-index:1}

/* Matters — unified table top bar (Select + context-aware Export) */
.table-topbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding:11px 16px;border-bottom:1px solid var(--line);background:var(--surface-2);box-shadow:0 6px 10px -6px rgba(13,27,48,.13);position:relative;z-index:1}
.table-topbar .tt-left,.table-topbar .tt-right{display:flex;align-items:center;gap:8px}
.table-topbar #exportLabel{margin-right:2px}

/* ============ Matter Workflow tab — 3-zone stepper ============ */
/* condensed past */
.wf-done{border:1px solid var(--line2);border-radius:var(--r);background:var(--surface-2);margin:14px 0 0;overflow:hidden}
.wf-done>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:10px;padding:11px 14px;font-size:var(--fs-sm);font-weight:600;color:var(--ink)}
.wf-done>summary::-webkit-details-marker{display:none}
.wf-done>summary:hover{background:#e7ebf2}
.wf-done .di{width:20px;height:20px;border-radius:50%;background:var(--green);color:#fff;display:grid;place-items:center;font-size:11px;font-weight:800;flex-shrink:0}
.wf-done .dsub{color:var(--muted);font-weight:400;font-size:var(--fs-xs)}
.wf-done .chev{margin-left:auto;color:var(--faint);font-size:15px;transition:transform .15s var(--ease)}
.wf-done[open] .chev{transform:rotate(90deg)}
.wf-done-list{padding:0 14px 6px;background:var(--surface)}
.wf-done-row{display:flex;align-items:center;gap:8px;padding:9px 0;font-size:var(--fs-sm);color:var(--muted);border-top:1px solid var(--line2)}
.wf-done-row .dot{width:8px;height:8px;border-radius:50%;background:var(--green);flex-shrink:0}
.wf-done-row b{color:var(--ink);font-weight:600}
/* prominent current card */
.wf-current{border:1px solid var(--accent);border-radius:var(--r-lg);background:var(--surface);box-shadow:0 4px 18px rgba(13,27,48,.12);margin:14px 0;overflow:hidden}
.wf-cur-top{background:var(--accent-soft);border-bottom:1px solid var(--accent-line);padding:14px 18px}
.wf-cur-badge{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#fff;background:var(--accent);padding:3px 9px;border-radius:var(--r-pill);margin-bottom:8px}
.wf-cur-title{font-size:17px;font-weight:700;letter-spacing:-.01em;margin:0;color:var(--ink)}
.wf-cur-note{font-size:var(--fs-sm);color:var(--muted);margin-top:4px}
/* The milestone the current stage is working toward — deliberately quieter than
   the task above it, so the card reads job-first. */
.wf-cur-milestone{font-size:var(--fs-xs);color:var(--muted);margin-top:3px}
.wf-cur-mid{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;padding:16px 18px;flex-wrap:wrap}
.wf-dl-lab{font-size:10px;text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:var(--accent-700);margin-bottom:6px}
.wf-cur-mid .ext-rval{font-size:var(--fs-sm)}
.wf-cur-mid .ext-rval .rline1{font-size:17px}
.wf-cur-actions{display:flex;gap:8px;flex-wrap:wrap;align-items:center;padding:13px 18px;border-top:1px solid var(--line2);background:var(--surface-2)}
.wf-cur-actions form{margin:0}
/* light future */
.wf-upcoming{margin-top:16px}
.wf-up-lab{font-size:10px;text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:var(--muted);margin-bottom:8px}
.wf-up-list{display:flex;flex-direction:column;gap:3px}
.wf-up-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:var(--r-sm);font-size:var(--fs-sm);color:var(--muted);background:var(--surface-2)}
.wf-up-row .dot{width:9px;height:9px;border-radius:50%;border:2px solid var(--line);background:#fff;flex-shrink:0}
/* per-step action cluster — pushed right in condensed rows */
.step-actions{display:flex;gap:2px;align-items:center}
.step-actions form{margin:0;display:inline-flex}
.wf-done-row .step-actions,.wf-up-row .step-actions{margin-left:auto}
/* inline step editor (any zone) */
.step-edit{padding:12px;background:var(--surface-2);border:1px solid var(--line2);border-radius:var(--r-sm);margin:6px 0 2px}
.step-edit[hidden]{display:none}
.wf-current .step-edit{margin:0 18px 16px}
/* extend popover on the current card */
.wf-ext{padding:14px 18px;border-top:1px solid var(--line2);background:var(--surface)}
/* tri-calendar result lines (shared with My Day preview) */
.ext-rval .rline1{line-height:1.5}
.ext-rval .rline2{margin-top:3px}
.ext-rval .rj{font-family:ui-monospace,Menlo,monospace}
.ext-rval .rw{unicode-bidi:isolate}
.ext-rval .rsep{color:var(--faint);margin:0 4px}

/* stat-card sub-line (used on Billing tab too, not only My Day) */
.card.stat .sub{display:block;margin-top:6px;font-size:var(--fs-2xs);color:var(--faint)}

/* Matter Parties tab — centered Reports/Invoices columns + Bill-to tag */
.contacts-table th.ctr,.contacts-table td.ctr{text-align:center}
.contacts-table td.ctr .yes{color:var(--green);font-weight:800}
.contacts-table td.ctr .no{color:var(--faint)}
.dtag.billto{background:var(--green-soft);color:var(--green);border-color:var(--green-line)}

/* ============ Matter Docs tab — designated drafting workspace ============ */
.draftbox{border:1px solid var(--accent-line);border-radius:var(--r-lg);background:var(--accent-soft);overflow:hidden;margin-bottom:var(--s4)}
.draftbox .db-head{padding:14px 18px;border-bottom:1px solid var(--accent-line);display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}
.draftbox .db-head .tag{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--accent-700);background:var(--surface);border:1px solid var(--accent-line);padding:3px 9px;border-radius:var(--r-pill)}
.draftbody{padding:16px 18px;background:var(--surface)}
.db-controls{display:grid;grid-template-columns:1.2fr 1fr;gap:16px;align-items:end}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden;background:var(--surface-2)}
.seg button{background:none;border:none;padding:9px 16px;font-family:inherit;font-size:var(--fs-sm);font-weight:600;color:var(--muted);cursor:pointer;border-right:1px solid var(--line);transition:all .12s var(--ease)}
.seg button:last-child{border-right:none}
.seg button.on{background:var(--accent);color:#fff}
.preview{margin-top:16px;border:1px solid var(--line);border-radius:var(--r);background:#fff}
.preview .pv-head{display:flex;justify-content:space-between;align-items:center;padding:9px 14px;border-bottom:1px solid var(--line2);background:var(--surface-2);font-size:var(--fs-2xs);color:var(--muted);text-transform:uppercase;letter-spacing:.05em;font-weight:600}
.preview .pv-body{padding:16px 18px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px;line-height:1.7;white-space:pre-wrap;color:var(--ink);min-height:150px}
.preview .pv-body[dir="rtl"]{font-family:'Vazirmatn',Tahoma,sans-serif;font-size:14px;line-height:2}
.draftbox .gate{margin:14px 0 0}
@media(max-width:1000px){ .db-controls{grid-template-columns:1fr} }

/* Billing & Statements — per-currency KPI blocks */
.ccy-block{margin-bottom:var(--s2)}
.ccy-lab{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--accent-700);background:var(--accent-soft);border:1px solid var(--accent-line);display:inline-block;padding:3px 10px;border-radius:var(--r-pill);margin-bottom:10px}
.ik-dochint{padding:10px 16px;border-top:1px solid var(--line2);background:var(--surface-2);font-size:var(--fs-2xs);color:var(--muted);line-height:1.5}

/* ============ Settings — left-rail sectioned config ============ */
.set-wrap{display:grid;grid-template-columns:212px 1fr;gap:20px;align-items:start}
.set-nav{position:sticky;top:76px;display:flex;flex-direction:column;gap:2px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:8px;box-shadow:var(--shadow-sm)}
.set-nav button{display:block;width:100%;text-align:left;background:none;border:none;padding:9px 12px;border-radius:var(--r-sm);font-family:inherit;font-size:var(--fs-sm);font-weight:500;color:var(--muted);cursor:pointer;transition:background .12s var(--ease),color .12s var(--ease)}
.set-nav button:hover{background:var(--surface-2);color:var(--ink)}
.set-nav button.active{background:var(--accent);color:#fff;font-weight:600}
.set-pane{display:none} .set-pane.active{display:block}
.sa-lock{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--accent-700);background:var(--accent-soft);border:1px solid var(--accent-line);padding:3px 8px;border-radius:var(--r-pill);white-space:nowrap}
.ref-preview-inline{font-weight:700;color:var(--accent-700)}
@media(max-width:1000px){ .set-wrap{grid-template-columns:1fr} .set-nav{position:static;flex-direction:row;flex-wrap:wrap} }

/* inline link-styled submit button (e.g. Amend in a text cell) */
.linkbtn{background:none;border:none;padding:0;color:var(--accent-700);font-weight:500;font-family:inherit;cursor:pointer}
.linkbtn:hover{text-decoration:underline}

/* ---- Party registry typeahead ---------------------------------------------
   Absolutely positioned under its input; the input's label is the positioning
   context (set in matter.html). z-index keeps it above the panel border. */
.party-suggest{position:absolute;top:100%;left:0;right:0;z-index:30;margin-top:2px;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-sm);
  box-shadow:0 6px 20px rgba(16,22,38,.10);max-height:240px;overflow-y:auto}
.party-suggest button{display:block;width:100%;text-align:left;border:0;background:none;
  padding:8px 11px;font-size:var(--fs-sm);color:var(--ink);cursor:pointer;font-family:inherit}
.party-suggest button:hover{background:var(--surface-2)}
.party-suggest button + button{border-top:1px solid var(--line2)}
/* "+ New party" is pinned visually as the last, different-in-kind action: everything
   above it selects an existing entry, it alone creates one. */
.party-suggest .pp-new{border-top:1px solid var(--line);font-weight:600;color:var(--accent)}
.party-suggest .pp-none{padding:8px 11px;font-size:var(--fs-sm);color:var(--muted)}

/* --- party picker: the chosen entry (static/partypick.js) ------------------- */
/* The selected registry entry replaces the search box, so a row always shows WHICH
   record it is bound to rather than the text someone typed to find it.

   IT REPLACES A FIELD, SO IT IS THE HEIGHT OF A FIELD. min-height is the field's
   38px, not a number of its own: on "Add contact" this control sits beside the Role
   select, and at its old 32px the two sat on one row at two different heights, the
   row visibly changing shape the moment a party was picked. min- rather than a fixed
   height because a long name plus an email is allowed to wrap onto a second line —
   growing is fine, starting shorter than the control beside it is not.

   PADDING IS 4px, NOT 6px, FOR A REASON: the chip contains a .btn-sm, which is 28px.
   28 + 6 + 6 + 2 borders = 42, so the chip stood 4px PROUD of the 38px select beside
   it even with min-height set correctly — min-height cannot stop a box growing. 4px
   is the figure that makes the tallest thing inside it land exactly on 38. */
/* `hidden` has to win. partypick.js hides the chip with the ATTRIBUTE and shows the
   search box instead, but an author `display:flex` beats the UA stylesheet's
   [hidden]{display:none} — so the empty chip rendered as a stray grey box under every
   picker, selected or not. It is on the same grid row as the search box it replaces,
   which is exactly why the two must never both be visible. */
.pp-chosen[hidden]{display:none}
.pp-chosen{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:4px 8px;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface-2);
  font-size:var(--fs-sm);min-height:38px;box-sizing:border-box}
.pp-chosen-name{font-weight:600;color:var(--ink)}
.pp-chosen .pill{margin-left:auto}
.pp-required-msg{font-size:11px;color:var(--red);margin-top:4px}
form.pp-unpicked .pp-chosen,form.pp-unpicked input[data-party-pick]{border-color:var(--red)}

/* --- party picker: create modal -------------------------------------------- */
.pp-modal{position:fixed;inset:0;z-index:200;background:rgba(16,22,38,.42);
  display:flex;align-items:flex-start;justify-content:center;padding:6vh 16px;overflow-y:auto}
.pp-modal[hidden]{display:none}
.pp-modal-card{background:#fff;border-radius:var(--r-md,10px);width:100%;max-width:520px;
  box-shadow:0 18px 50px rgba(16,22,38,.24);display:flex;flex-direction:column}
.pp-modal-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 16px;border-bottom:1px solid var(--line)}
.pp-modal-body{padding:14px 16px;display:flex;flex-direction:column;gap:10px}
.pp-modal-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;
  flex-wrap:wrap;padding:12px 16px;border-top:1px solid var(--line);background:var(--surface-2);
  border-radius:0 0 var(--r-md,10px) var(--r-md,10px)}
.pp-msg{font-size:12px;color:var(--red)}
/* The quick-add duplicate hint — the EARLY half of one-name-one-party, fired on the name
   as it is typed rather than on the refusal that follows a filled-in form. AMBER, not red:
   an exact name will be refused, but a near miss ("DLA Piper" while typing "DLA Piper
   Middle East") is a perfectly legal name being questioned, and colouring the two the same
   would teach people to dismiss both. .pp-new is exempt from the two-size button system —
   these are list rows that happen to be focusable — but it is styled by `.party-suggest
   button`, and this block is not inside a .party-suggest. */
.pp-dup[hidden]{display:none}
.pp-dup{display:flex;flex-direction:column;gap:4px;padding:8px 10px;
  border:1px solid var(--amber-line);background:var(--amber-soft);color:var(--amber);
  border-radius:var(--r-sm);font-size:var(--fs-sm)}
.pp-dup .pp-new{border:0;background:none;padding:0;text-align:left;font:inherit;
  font-weight:600;color:var(--accent-700);cursor:pointer}
.pp-dup .pp-new:hover{text-decoration:underline}
.pp-dup small{color:var(--muted)}

/* --- dual Jalali/Gregorian date field (templates/_datefield.html) ---------- */
.jdate{display:inline-flex;flex-wrap:wrap;align-items:center;gap:6px}
.jdate>input{min-width:0}
.jdate .jdate-j{width:118px;font-variant-numeric:tabular-nums;letter-spacing:.01em}
.jdate .jdate-g{width:158px}
/* the flag sits on its own line so a message never reflows the two inputs */
.jdate .jdate-msg{flex-basis:100%;font-size:11px;color:var(--red);min-height:0}
.jdate.jdate-bad .jdate-j,.jdate.jdate-bad .jdate-g{border-color:var(--red)}

/* --- mark image (figurative marks) ---------------------------------------- */
/* object-fit:contain — a mark must never be cropped or distorted to fit a box. */
.markimg-thumb{max-width:120px;max-height:64px;object-fit:contain;
  border:1px solid var(--line);border-radius:6px;background:#fff;padding:3px}
.mark-line{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.markimg-head{max-width:96px;max-height:52px}

/* --- chunked upload progress ----------------------------------------------- */
/* One row per file while it travels. The bar is the only moving thing on the page,
   so it is deliberately quiet: this is reassurance during a slow upload, not a
   feature to look at. Rows persist after the upload so a dedup ("already on this
   matter") or a failure is still readable when the page has stopped changing. */
.cu-list{display:grid;gap:8px;margin:12px 0 0}
.cu-file{display:grid;grid-template-columns:1fr auto;gap:2px 12px;align-items:baseline}
.cu-name{font-size:var(--fs-sm);color:var(--ink);overflow-wrap:anywhere}
.cu-note{font-size:var(--fs-xs);color:var(--muted);font-variant-numeric:tabular-nums;
  text-align:right}
.cu-bar{grid-column:1/-1;height:4px;border-radius:var(--r-pill);background:var(--hair);
  overflow:hidden}
.cu-bar span{display:block;height:100%;width:0;background:var(--accent);
  border-radius:var(--r-pill);transition:width .18s var(--ease)}
.cu-failed .cu-bar span{background:var(--red)}
.cu-failed .cu-note{color:var(--red);text-align:left;grid-column:1/-1}
