/* Succinct Client Desk -- application stylesheet.
   Seeded from the approved mockup; edit HERE from now on, not the mockup.
   Deep Royal Purple #4B1678 / Rich Violet #5E248D / Lavender #7A49A5
   Charcoal #2F2F2F on Warm White #F9F9F9.
   Tokens first: every colour is defined on :root and redefined for dark,
   so nothing is styled directly inside a media or [data-theme] block. */

:root{
  --paper:#F9F9F9; --surface:#FFFFFF; --surface-2:#FBFAFC; --raise:#FFFFFF;
  --ink:#2F2F2F; --ink-2:#4A4453; --muted:#6B6472; --faint:#9A93A3;
  --line:#E4E0EA; --line-strong:#CCC5D6;
  --teal:#4B1678; --teal-soft:#F0EAF7; --teal-ink:#3B0F60;
  /* The lit row. Its own token rather than --teal-soft, which also carries
     the selected nav item and the sorted column heading -- a tint that reads
     well behind eight characters of a heading is not the same tint as one
     that has to be seen across forty columns.
     Darkened on 23 September: "can the highlight color be little more dark as
     it is not looking highlighter because difference is very less in color."
     1.68:1 against a plain row, up from 1.18:1; body ink on it is 7.98:1. */
  --rowlit:#D3C0EC;
  --orchid:#7A49A5; --orchid-soft:#F4EFFA;
  --on-accent:#FFFFFF;
  --ok:#15764A; --ok-soft:#E3F1EA;
  --warn:#8A5B0C; --warn-soft:#FBF0DC;
  --late:#A8322C; --late-soft:#FBE7E5;
  --lock:#F2F0F5;
  --shadow:0 1px 2px rgba(16,26,28,.06), 0 8px 24px -12px rgba(16,26,28,.18);
  --shadow-pop:0 2px 6px rgba(16,26,28,.10), 0 18px 40px -16px rgba(16,26,28,.32);
  --r:6px;
}
@media (prefers-color-scheme: dark){ :root:not([data-theme="light"]){
  --paper:#151119; --surface:#1D1825; --surface-2:#241E2D; --raise:#2A2333;
  --ink:#EDEAF2; --ink-2:#C7C0D2; --muted:#968EA3; --faint:#6F6880;
  --line:#332C3E; --line-strong:#443C52;
  --teal:#B490DC; --teal-soft:#2C2040; --teal-ink:#D2B8ED;
  --rowlit:#453268;
  --orchid:#C49BE4; --orchid-soft:#31254A;
  --on-accent:#1A1322;
  --ok:#4FBB86; --ok-soft:#13301F;
  --warn:#D9A441; --warn-soft:#2F2412;
  --late:#E0736A; --late-soft:#331A18;
  --lock:#221C2B;
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.7);
  --shadow-pop:0 2px 8px rgba(0,0,0,.5), 0 18px 40px -16px rgba(0,0,0,.8);
}}
:root[data-theme="dark"]{
  --paper:#151119; --surface:#1D1825; --surface-2:#241E2D; --raise:#2A2333;
  --ink:#EDEAF2; --ink-2:#C7C0D2; --muted:#968EA3; --faint:#6F6880;
  --line:#332C3E; --line-strong:#443C52;
  --teal:#B490DC; --teal-soft:#2C2040; --teal-ink:#D2B8ED;
  --rowlit:#453268;
  --orchid:#C49BE4; --orchid-soft:#31254A;
  --on-accent:#1A1322;
  --ok:#4FBB86; --ok-soft:#13301F;
  --warn:#D9A441; --warn-soft:#2F2412;
  --late:#E0736A; --late-soft:#331A18;
  --lock:#221C2B;
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.7);
  --shadow-pop:0 2px 8px rgba(0,0,0,.5), 0 18px 40px -16px rgba(0,0,0,.8);
}
*{box-sizing:border-box}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:"IBM Plex Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:13.5px; line-height:1.45; -webkit-font-smoothing:antialiased;
}
h1,h2,h3{margin:0; text-wrap:balance; font-weight:600}
.serif{font-family:"Newsreader",Georgia,serif; font-weight:500; letter-spacing:-.01em}
.mono{font-family:"IBM Plex Mono",ui-monospace,monospace; font-variant-numeric:tabular-nums}
.eyebrow{font-size:10.5px; letter-spacing:.11em; text-transform:uppercase; color:var(--muted); font-weight:600}
a{color:var(--teal)}
:focus-visible{outline:2px solid var(--teal); outline-offset:1px}
@media (prefers-reduced-motion:reduce){*{animation:none!important; transition:none!important}}

/* ---------- app shell ---------- */
.app{display:grid; grid-template-columns:216px 1fr; min-height:100vh}
.rail{
  background:var(--surface); border-right:1px solid var(--line);
  display:flex; flex-direction:column; gap:2px; padding:14px 10px;
  position:sticky; top:0; height:100vh; overflow:auto;
}
.brand{display:flex; gap:9px; align-items:center; padding:4px 8px 16px}
.mark{
  width:26px; height:26px; border-radius:5px; flex:none;
  background:linear-gradient(150deg,#4B1678,#7A49A5);
  display:grid; place-items:center; color:var(--on-accent); font-weight:700; font-size:12px;
  font-family:"IBM Plex Mono",monospace;
}
/* An uploaded icon (Settings -> Brand) in place of the letter: the image
   fills the same square, on no gradient, so a logo with its own background
   is not framed in purple. */
.mark.has-img{background:none; overflow:hidden}
.mark.has-img img{width:100%; height:100%; object-fit:contain; display:block}
/* An uploaded logo stands in for the mark and the name (components/
   brand.html). Capped so a tall or very wide file still sits in the rail. */
.brand .brandlogo-wrap{display:flex; flex-direction:column; align-items:flex-start; gap:3px; min-width:0}
.brand .brandlogo{display:block; max-width:100%; max-height:44px; width:auto; height:auto; object-fit:contain}
/* The app name under the logo: small and quiet, so the logo stays the
   thing the eye lands on. */
.brand .brandapp{font-size:10.5px; color:var(--muted); letter-spacing:.02em; padding-left:2px}
.brand.has-logo > .mark,
.brand.has-logo > div:last-child{display:none}
.brand b{font-size:14px; font-weight:600; letter-spacing:-.01em; display:block; line-height:1.2}
.brand span{font-size:10.5px; color:var(--muted); display:block}
.navlabel{font-size:10px; letter-spacing:.11em; text-transform:uppercase; color:var(--faint); padding:14px 8px 5px; font-weight:600}
.nav{
  display:flex; align-items:center; gap:9px; padding:7px 9px; border-radius:var(--r);
  color:var(--ink-2); cursor:pointer; border:0; background:none; width:100%; text-align:left;
  font:inherit; font-size:13px;
}
.nav{text-decoration:none}
.nav:hover{background:var(--surface-2); color:var(--ink); text-decoration:none}
.nav[aria-selected="true"]{background:var(--teal-soft); color:var(--teal-ink); font-weight:600}
.nav .ic{width:15px; height:15px; flex:none; opacity:.85}
.nav .count{margin-left:auto; font-size:10.5px; color:var(--muted); font-family:"IBM Plex Mono",monospace}
.railfoot{margin-top:auto; padding:10px 8px 2px; border-top:1px solid var(--line); font-size:11px; color:var(--muted)}

.main{min-width:0; display:flex; flex-direction:column}
.topbar{
  position:sticky; top:0; z-index:40; background:color-mix(in srgb,var(--surface) 88%,transparent);
  backdrop-filter:blur(8px); border-bottom:1px solid var(--line);
  display:flex; align-items:center; gap:12px; padding:11px 20px;
}
.topbar h1{font-size:16px; font-weight:600; letter-spacing:-.015em}
.topbar .sub{font-size:11.5px; color:var(--muted)}
.spacer{margin-left:auto}
.who{display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted)}
.avatar{width:24px; height:24px; border-radius:50%; background:var(--orchid-soft); color:var(--orchid);
  display:grid; place-items:center; font-size:10.5px; font-weight:700}
.screen{padding:18px 20px 60px; display:none}
.screen.on{display:block}
/* ---------- toolbar ---------- */
.toolbar{
  display:flex; gap:8px; align-items:center; flex-wrap:wrap;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:8px; margin-bottom:12px; position:sticky; top:47px; z-index:30; box-shadow:var(--shadow);
}
/* ---------- a button that is only its icon ----------
   Export and Import say the same thing in a quarter of the room (20 Sep
   2026). The word stays in the page for a screen reader and on hover as the
   title, so nothing is lost but the width. Square, so a row of them reads as
   a set rather than as buttons of drifting sizes. */
.btn.icon{padding:5px; gap:0; line-height:0}
.btn.icon .ic{width:15px; height:15px}
.btn.icon .sr{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap;
}

/* A tick box in a toolbar: the box and one word, trimmed to the size of the
   word. The inline styles this replaces were three copies of the same four
   declarations. */
.field.check{gap:5px; padding:2px 6px; cursor:pointer; font-size:11.5px; color:var(--ink-2)}
.field.check input[type="checkbox"]{
  /* min-width:0 because `.field input` sets 74px for the text boxes and
     selects in a filter row; on a tick box that is 60px of nothing. */
  accent-color:var(--teal); width:13px; height:13px; min-width:0; margin:0;
  cursor:pointer;
}

/* ---------- a toolbar that stays on one line ----------
   For a screen with more controls than a row comfortably holds. The toolbar
   above is built to wrap, and wrapping puts two buttons on a line of their
   own, which reads as a second row of controls that is not one. Tighter
   padding, smaller type, and controls that shrink rather than fold.

   NO overflow on this row. A scrolling box clips in both directions -- CSS
   turns overflow-y into auto the moment overflow-x is anything but visible --
   and the multi-pick filters open a panel BELOW the row. With overflow set
   they were cut off a few pixels down, which read as filters that would not
   open at all (20 Sep 2026). It fits by letting its controls shrink instead.

   Advance Tax has used these numbers since 17 Sep; Client Profiles joined on
   20 Sep, which is why they live here rather than in one module. */
.toolbar.tight{
  padding:3px 6px; margin-bottom:7px; gap:5px; flex-wrap:nowrap;
}
/* Every control is as wide as what it holds, and the search box takes
   whatever is left over. No fixed minimums: "Status Active" and "KYC flag
   All" are different lengths, and a shared minimum either pads the short one
   or squeezes the long one. */
.toolbar.tight .field{padding:2px 6px; flex:0 1 auto; min-width:0; font-size:12px}
.toolbar.tight .field label{font-size:10px; letter-spacing:.04em}
.toolbar.tight .field select,
.toolbar.tight .field input:not([type="checkbox"]){font-size:12px; min-width:0; width:auto}
.toolbar.tight .field.search{flex:1 1 140px; min-width:110px}
.toolbar.tight .field.search input{min-width:0; width:100%}
.toolbar.tight .btn{padding:3px 9px; font-size:12px; flex:none}
.toolbar.tight .btn.icon{padding:4px}
.toolbar.tight .field.check{padding:1px 6px; font-size:11.5px}
/* The multi-pick control is a <details>, not a .field: same trim. */
.toolbar.tight .pick{flex:0 1 auto; min-width:0}
.toolbar.tight .pick>summary{padding:3px 7px; font-size:12px}
.toolbar.tight .pick>summary .lab{font-size:10px; letter-spacing:.04em}
.toolbar.tight .pick>summary .val{max-width:120px}

.field{display:flex; align-items:center; gap:6px; border:1px solid var(--line); background:var(--surface-2);
  border-radius:5px; padding:5px 8px; font-size:12.5px}
.field label{color:var(--muted); font-size:11px; letter-spacing:.03em}
.field select,.field input{border:0; background:none; color:var(--ink); font:inherit; font-size:12.5px; outline:none; min-width:74px}
.field.search{min-width:230px}
.field.search input{width:100%}
.btn{
  border:1px solid var(--line-strong); background:var(--surface); color:var(--ink);
  font:inherit; font-size:12.5px; font-weight:500; padding:6px 11px; border-radius:5px; cursor:pointer;
  display:inline-flex; align-items:center; gap:6px;
}
.btn{text-decoration:none}
.btn:hover{background:var(--surface-2)}
a.btn.primary:hover{color:var(--on-accent)}
.btn.primary{background:var(--teal); border-color:var(--teal); color:var(--on-accent)}
.btn.primary:hover{filter:brightness(1.08)}
.btn.ghost{border-color:transparent; background:none; color:var(--muted)}
.btn.ghost:hover{color:var(--ink); background:var(--surface-2)}

/* ---------- grid ---------- */
.gridwrap{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  overflow:auto; max-height:60vh; box-shadow:var(--shadow); position:relative;
}
table.grid{border-collapse:separate; border-spacing:0; width:max-content; min-width:100%; font-size:12.5px}
table.grid th,table.grid td{
  border-right:1px solid var(--line); border-bottom:1px solid var(--line);
  padding:0; white-space:nowrap; height:31px; vertical-align:middle;
}
table.grid thead th{
  position:sticky; top:0; z-index:20; background:var(--surface-2); color:var(--ink-2);
  font-weight:600; font-size:10.5px; letter-spacing:.06em; text-transform:uppercase;
  text-align:left; padding:0 9px; border-bottom:1px solid var(--line-strong); cursor:pointer; user-select:none;
}
table.grid thead th:hover{color:var(--teal-ink)}
table.grid thead th .sortcue{opacity:.3; font-size:9px; margin-left:3px}
table.grid thead th .sortcue.on{opacity:1; color:var(--teal)}
table.grid thead th.sorted{color:var(--teal-ink); background:var(--teal-soft)}
th.gp{ text-align:center; font-size:9.5px; letter-spacing:.1em; color:var(--muted); background:var(--surface); }
td .cell{display:block; padding:0 9px; height:30px; line-height:30px; overflow:hidden; text-overflow:ellipsis}
td.num{width:44px; text-align:right; color:var(--faint); background:var(--surface-2)}
td.num .cell{padding-right:10px}
tbody tr:hover td{background:var(--surface-2)}
tbody tr:hover td.sticky{background:var(--surface-2)}
/* The row being worked on.
   These grids are forty columns wide with the identity block frozen at the
   left. By the time you have scrolled out to Last FP Report Date, the row
   under the pointer and the name at the left edge are separated by the whole
   screen, and the only thing tying them together is that they are level with
   each other. One row out is a real value written to the wrong client, and
   the audit trail will faithfully record that you meant it.

   Hover is the light version -- a scanning aid, deliberately faint. This is
   the committed one: it goes on when you click a row and stays until you
   click a different one, so it survives Tabbing along the row and saving,
   which is exactly when you most want to be sure of where you are.

   A BAND, NOT A BOX. The first version ruled the top and bottom edges in
   full-strength --teal, and across forty columns two parallel lines closed by
   the cap at the left read as a drawn rectangle -- the row looked selected for
   an operation rather than simply being the one in hand. The tint carries it,
   with a single accent line at the frozen edge.

   It was too light to do that job at first: --teal-soft at 1.18:1 against a
   plain row is a difference you have to look for. --rowlit is 1.68:1, which
   is seen rather than found, and still nothing like a filled selection. */
tbody tr.active > td{background:var(--rowlit)}
/* Sticky cells carry their own opaque background so the scrolling columns
   pass underneath them. Without this the frozen name would be the one cell
   in the row NOT lit -- the half of the pairing you are trying to confirm. */
tbody tr.active > td.sticky,
tbody tr.active > td.num{background:var(--rowlit)}
tbody tr.active > td.num{color:var(--teal-ink)}
/* One accent line on the frozen left edge, and the only mark that is not
   hue: it keeps the row findable in monochrome, at low contrast, or for the
   ~8% of men with a colour vision deficiency, for whom a tint alone is not a
   difference they can rely on however far it is darkened.

   --orchid rather than --teal: a line, lighter than the near-black purple
   that made this look ruled. Overrides the member-row bar, which is the
   softer relative of this one. */
tbody tr.active > td.s0{box-shadow:inset 3px 0 0 var(--orchid)}
/* A locked cell keeps its own grey, which would punch holes in the band and
   break the one thing the band is for -- reading as a single unbroken row.
   The faint text still says "not editable". */
tbody tr.active > td.locked .cell{background:transparent}
/* A member row draws its indent bar in --teal-soft, a paler relative of the
   band. Dropped on a lit row rather than left to sit inside it: two bars at
   the same edge, one inside the other, is a border where a mark was meant. Nothing is lost -- the
   row still reads as a member from its indent and its arrow glyph, and the
   cap on the frozen edge is doing the louder job. `:not(.s0)` so the active
   cap itself, which is more specific, is not what gets cleared. */
tbody tr.member-row.active > td.sticky:not(.s0){box-shadow:none}
.sticky{position:sticky; z-index:10; background:var(--surface)}
/* Written as `table.grid thead th.sticky`, not `thead .sticky`, and that is
   the whole rule. `table.grid thead th` above sets z-index:20 and is MORE
   specific than `thead .sticky` -- so the frozen headings lost the z-index
   they were supposed to have, tied with the scrolling ones at 20, and were
   painted over by whichever came later in the DOM. The cells stuck; the
   headings slid away underneath. */
table.grid thead th.sticky{z-index:25; background:var(--surface-2)}
thead .sticky{background:var(--surface-2)}
.s0{left:0}
/* The Activity Log and the Reports screen are not arrangeable, so their one
   frozen column keeps a fixed offset. */
.s1{left:44px; border-right:1px solid var(--line-strong)}
/* The two grids that ARE arrangeable set `left` inline per column, worked out
   server-side from the widths of everything frozen before it. A fixed class
   could only ever describe one arrangement, and which columns are frozen is
   now the administrator's choice. The edge of the block is marked separately
   so the border lands on the last frozen column wherever that turns out to
   be. */
.pinned{border-right:0}
.pinend{border-right:1px solid var(--line-strong)}
/* The band above the headings. It exists because two columns can now carry
   the same heading -- last month's report pair and this month's -- and the
   only thing that distinguishes them is which month they belong to. Centred
   over the block, because a label centred over four columns reads as a
   description of the block, while the same words left-aligned in the first
   of them read as that column's own heading.

   `top:0` here and the headings pushed down to 24px, so both rows stay
   frozen when the grid scrolls. `.banded` is on the table only when the row
   is drawn -- without it the headings would sit 24px down from nothing. */
table.grid thead tr.bands th{
  top:0; z-index:22; height:24px; text-align:center; cursor:default;
  font-size:9.5px; letter-spacing:.1em; color:var(--muted);
  background:var(--surface); border-bottom:1px solid var(--line);
  position:sticky; overflow:hidden;
}
/* THE LABEL DOES NOT SET THE WIDTH. A band spans two columns, and in a table
   that sizes itself to its content a spanning cell's text is a floor under
   the columns beneath it: "Aug 2026 . previous . read only" is 207px, so
   dragging that pair narrower than 207 between them simply stopped, and the
   band and its columns stopped lining up.

   Taking the label out of the flow makes the cell's own content width zero,
   so the columns are as wide as they were asked to be and the label
   truncates instead of pushing. */
table.grid thead tr.bands th > span{
  position:absolute; inset:0; display:flex; align-items:center;
  justify-content:center; padding:0 6px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
table.grid thead tr.bands th.sticky{z-index:27; background:var(--surface)}
table.grid thead tr.bands th.g-prev{background:var(--lock)}
table.grid thead tr.bands th.g-now{background:var(--teal-soft); color:var(--teal-ink)}
table.grid.banded thead tr.labels th{top:24px}
/* The month a previous cell is actually showing, when it is not the month
   the band promises. Small and quiet: it appears on a handful of rows, and
   on those rows it is the difference between a right answer and a wrong one
   that looks right. */
.mtag{
  font-size:9.5px; letter-spacing:.05em; text-transform:uppercase;
  color:var(--faint); font-weight:600; margin-left:6px;
  border:1px solid var(--line-strong); border-radius:3px; padding:0 4px;
}
td.editable{cursor:cell}
td.editable:hover .cell{box-shadow:inset 0 0 0 1px var(--line-strong); border-radius:3px}
td.locked .cell{color:var(--faint); background:var(--lock)}
td.saved{animation:flash 1.1s ease}
@keyframes flash{0%{background:var(--ok-soft)}100%{background:transparent}}
.editing{padding:0!important; position:relative}
.editing input,.editing select{
  position:absolute; left:0; top:0; z-index:35;
  width:100%; min-width:100%; height:30px; border:2px solid var(--teal); border-radius:3px; padding:0 6px;
  font:inherit; font-size:12.5px; background:var(--raise); color:var(--ink); outline:none;
  box-shadow:var(--shadow-pop);
}
.editing select{width:auto; padding-right:22px}
.cname{color:var(--ink); font-weight:500; cursor:pointer}
.cname:hover{color:var(--teal); text-decoration:underline; text-underline-offset:2px}
.empty{color:var(--faint)}
.dv-late{color:var(--late); font-weight:600}
.dv-soon{color:var(--warn); font-weight:600}
.derived{font-style:normal}
td.locked .cell .dv-late,td.locked .cell .dv-soon{opacity:1}

/* pills */
.pill{display:inline-flex; align-items:center; gap:4px; padding:1px 7px; border-radius:20px;
  font-size:10.5px; font-weight:600; letter-spacing:.02em; line-height:17px}
.pill.ok{background:var(--ok-soft); color:var(--ok)}
.pill.warn{background:var(--warn-soft); color:var(--warn)}
.pill.late{background:var(--late-soft); color:var(--late)}
.pill.mute{background:var(--lock); color:var(--muted)}
.pill.teal{background:var(--teal-soft); color:var(--teal-ink)}
.pill.crit{background:var(--late); color:var(--on-accent)}
.pill.gone{background:var(--orchid-soft); color:var(--orchid)}
.code{font-family:"IBM Plex Mono",monospace; font-size:11px; font-weight:600; padding:1px 6px; border-radius:3px; line-height:18px; display:inline-block}
.code.c-C{background:var(--warn-soft); color:var(--warn)}
.code.c-CP{background:var(--warn-soft); color:var(--warn)}
.code.c-CR{background:var(--late-soft); color:var(--late)}
.code.c-CRP{background:var(--late-soft); color:var(--late)}
.code.c-Y{background:var(--teal-soft); color:var(--teal-ink)}
.code.c-Yes{background:var(--ok-soft); color:var(--ok)}
.code.c-Check{background:var(--orchid-soft); color:var(--orchid)}

.chipbar{display:flex; align-items:center; gap:8px; margin:-4px 0 10px; min-height:26px; flex-wrap:wrap}
.chip{display:inline-flex; align-items:center; gap:7px; background:var(--teal-soft); color:var(--teal-ink);
  border:1px solid var(--teal); border-radius:20px; padding:3px 5px 3px 11px; font-size:11.5px; font-weight:600}
.chip button{border:0; background:var(--teal); color:var(--on-accent); border-radius:50%; width:16px; height:16px;
  font:inherit; font-size:10px; line-height:1; cursor:pointer; padding:0}
.chip button:hover{filter:brightness(1.15)}
/* A message that says something was refused must not look like one that says
   it worked. Levels come straight from Django's message.tags. */
.chip.warning{background:var(--warn-soft); color:var(--warn)}
.chip.error{background:var(--late-soft); color:var(--late)}
.chip.success{background:var(--ok-soft); color:var(--ok)}
.list .row.click{cursor:pointer}
.list .row.click:hover{background:var(--surface-2)}
.card[data-view]{cursor:pointer; transition:transform .12s ease, box-shadow .12s ease}
.card[data-view]:hover{transform:translateY(-1px); box-shadow:var(--shadow-pop)}
.card .go{font-size:10.5px; color:var(--teal); font-weight:600; margin-top:5px; opacity:0}
.card[data-view]:hover .go{opacity:1}
.gridfoot{display:flex; align-items:center; gap:10px; padding:9px 2px; font-size:11.5px; color:var(--muted)}
.pager{margin-left:auto; display:flex; gap:4px}
.pager button{border:1px solid var(--line); background:var(--surface); border-radius:4px; min-width:26px; height:26px;
  font:inherit; font-size:11.5px; color:var(--ink-2); cursor:pointer}
.pager button[aria-current="true"]{background:var(--teal); border-color:var(--teal); color:var(--on-accent); font-weight:600}

/* cards */
.cards{display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:10px; margin-bottom:16px}
@media (max-width:1320px){ .cards{grid-template-columns:repeat(4,minmax(0,1fr))} }
@media (max-width:1080px){ .cards{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width:820px){ .cards{grid-template-columns:repeat(2,minmax(0,1fr))} }
.card .v{font-size:23px}
.card .k{line-height:1.25; min-height:2.5em; display:flex; align-items:flex-end}
.card{background:var(--surface); border:1px solid var(--line); border-radius:var(--r); padding:11px 12px; box-shadow:var(--shadow)}
.card .k{font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); font-weight:600}
.card .v{font-size:25px; font-weight:600; letter-spacing:-.02em; margin-top:3px; font-variant-numeric:tabular-nums}
.card .d{font-size:11px; color:var(--muted); margin-top:2px}
.card.alert{border-left:3px solid var(--late)}
.card.due{border-left:3px solid var(--warn)}
.card.good{border-left:3px solid var(--ok)}
.spark{display:flex; align-items:flex-end; gap:2px; height:22px; margin-top:6px}
.spark i{flex:1; background:var(--teal-soft); border-radius:1px}
.spark i:last-child{background:var(--teal)}

.panel{background:var(--surface); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow); overflow:hidden}
.panel > header{display:flex; align-items:center; gap:10px; padding:10px 13px; border-bottom:1px solid var(--line)}
.panel > header h2{font-size:13px; font-weight:600}
.two{display:grid; grid-template-columns:1.55fr 1fr; gap:14px; align-items:start}
@media (max-width:1180px){ .two{grid-template-columns:1fr} }
.list{display:flex; flex-direction:column}
.list .row{display:flex; gap:10px; align-items:baseline; padding:8px 13px; border-bottom:1px solid var(--line); font-size:12.5px}
.list .row:last-child{border-bottom:0}
.list .row .when{color:var(--faint); font-size:11px; width:52px; flex:none}
.list .row .what{color:var(--ink-2)}
.list .row b{font-weight:600; color:var(--ink)}
/* drawer */
.scrim{position:fixed; inset:0; background:rgba(16,26,28,.28); z-index:60; display:none}
.scrim.on{display:block}
.drawer{
  position:fixed; top:0; right:0; bottom:0; width:min(470px,94vw); background:var(--surface);
  border-left:1px solid var(--line); box-shadow:var(--shadow-pop); z-index:61;
  transform:translateX(100%); transition:transform .22s ease; display:flex; flex-direction:column;
}
.drawer.on{transform:none}
.drawer header{padding:14px 16px 10px; border-bottom:1px solid var(--line)}
.drawer .tabs{display:flex; gap:2px; padding:0 10px; border-bottom:1px solid var(--line); background:var(--surface-2)}
.drawer .tabs button{border:0; background:none; font:inherit; font-size:12px; padding:8px 10px; color:var(--muted);
  cursor:pointer; border-bottom:2px solid transparent; margin-bottom:-1px}
.drawer .tabs button[aria-selected="true"]{color:var(--teal-ink); border-bottom-color:var(--teal); font-weight:600}
.drawer .body{overflow:auto; padding:14px 16px; display:flex; flex-direction:column; gap:14px}
.kv{display:grid; grid-template-columns:130px 1fr; gap:4px 10px; font-size:12.5px}
.kv dt{color:var(--muted)}
.kv dd{margin:0; color:var(--ink)}
.dsection{border:1px solid var(--line); border-radius:var(--r); overflow:hidden}
.dsection h3{font-size:10.5px; letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  padding:7px 11px; background:var(--surface-2); border-bottom:1px solid var(--line); font-weight:600}
.dsection .inner{padding:11px}

/* toast */
.modal{position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); z-index:70;
  background:var(--surface); border:1px solid var(--line); border-radius:8px; box-shadow:var(--shadow-pop);
  width:min(430px,92vw); max-height:78vh; display:none; flex-direction:column}
.modal.on{display:flex}
.modal > header{padding:12px 14px; border-bottom:1px solid var(--line); display:flex; align-items:baseline; gap:8px}
.modal > header h2{font-size:13.5px; font-weight:600}
.modal > header .sub{font-size:11px; color:var(--muted)}
.modal > footer{padding:10px 14px; border-top:1px solid var(--line); display:flex; gap:8px; align-items:center}
.modal > footer .note{font-size:11px; color:var(--muted); margin-left:auto; text-align:right}
.collist{overflow:auto; padding:5px 0}
.colrow{display:flex; align-items:center; gap:9px; padding:5px 14px; font-size:12.5px}
.colrow:hover{background:var(--surface-2)}
.colrow input[type=checkbox]{accent-color:var(--teal); width:14px; height:14px; margin:0}
.colrow .lbl{flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.colrow .tagx{font-size:9.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--faint)}
.colrow.pinned .lbl{color:var(--muted)}
.colrow .mv{border:1px solid var(--line); background:var(--surface); border-radius:4px; width:23px; height:23px;
  font:inherit; font-size:9px; cursor:pointer; color:var(--ink-2); padding:0; flex:none}
.colrow .mv:hover:not(:disabled){border-color:var(--teal); color:var(--teal)}
.colrow .mv:disabled{opacity:.3; cursor:default}
.toasts{position:fixed; right:18px; bottom:18px; z-index:80; display:flex; flex-direction:column; gap:8px}
.toast{background:var(--raise); border:1px solid var(--line); border-left:3px solid var(--ok);
  border-radius:var(--r); box-shadow:var(--shadow-pop); padding:9px 13px; font-size:12.5px; min-width:250px;
  animation:rise .18s ease}
.toast b{display:block; font-size:12px}
.toast span{color:var(--muted); font-size:11.5px}
.toast.err{border-left-color:var(--late)}
@keyframes rise{from{opacity:0; transform:translateY(6px)}to{opacity:1; transform:none}}

/* prose / spec screen */
.prose{max-width:78ch}
.prose h2{font-size:19px; margin:26px 0 8px; letter-spacing:-.015em}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:13.5px; margin:18px 0 5px}
.prose p{margin:0 0 10px; color:var(--ink-2)}
.prose ul{margin:0 0 12px; padding-left:18px; color:var(--ink-2)}
.prose li{margin-bottom:4px}
.lead{font-size:15px; color:var(--ink-2); border-left:2px solid var(--teal); padding-left:12px; margin-bottom:20px}
.tbl{width:100%; border-collapse:collapse; font-size:12.5px; margin:6px 0 16px}
.tbl th,.tbl td{border:1px solid var(--line); padding:6px 9px; text-align:left; vertical-align:top}
.tbl th{background:var(--surface-2); font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--muted)}
.tblwrap{overflow-x:auto}
.q{border:1px solid var(--line); border-left:3px solid var(--orchid); border-radius:var(--r);
  background:var(--surface); padding:12px 14px; margin:0 0 10px; box-shadow:var(--shadow)}
.q b{display:block; font-size:13px; margin-bottom:4px}
.q p{margin:0; font-size:12.5px; color:var(--ink-2)}
.q .tag{font-family:"IBM Plex Mono",monospace; font-size:10px; color:var(--orchid); background:var(--orchid-soft);
  padding:1px 6px; border-radius:3px; margin-right:7px}
.flow{display:flex; flex-wrap:wrap; gap:6px; align-items:center; font-size:11.5px; margin:10px 0 18px}
.flow span{background:var(--surface); border:1px solid var(--line); border-radius:20px; padding:4px 11px}
.flow span.hi{background:var(--teal-soft); border-color:var(--teal); color:var(--teal-ink); font-weight:600}
.flow em{color:var(--faint); font-style:normal}
/* Three to a row, not auto-fit. auto-fit sized the columns to the number of
   fields in the group, so a two-field section stretched each input across half
   the screen to hold "60" -- and every section lined up differently from the
   one above it. A fixed three keeps the columns in the same place all the way
   down, and the cap stops them growing without limit on a wide monitor. */
.setgrid{display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:10px 16px; padding:11px 13px; max-width:1120px}
@media (max-width:1080px){.setgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:720px){.setgrid{grid-template-columns:minmax(0,1fr)}}
.setfield{display:flex; flex-direction:column; gap:3px; min-width:0}
.setfield label{font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); font-weight:600}
.setfield input,.setfield select{border:1px solid var(--line); background:var(--surface-2); border-radius:5px;
  padding:6px 8px; font:inherit; font-size:12.5px; color:var(--ink); outline:none; width:100%}
.setfield input:focus,.setfield select:focus{border-color:var(--teal); background:var(--surface)}
/* A field somebody may read but not change. Shown rather than hidden: the
   person still needs the value, and a field that appears for one role and
   vanishes for another is a screen two people cannot discuss over the phone.
   The cursor matters as much as the colour -- it is the first thing that says
   "not you" before anybody has clicked. */
.setfield input:disabled,.setfield select:disabled,.setfield textarea:disabled{
  background:var(--lock); color:var(--muted);
  border-color:var(--line); cursor:not-allowed;
}
/* A button that sits inside a list row rather than on its own. Small enough
   not to compete with the row's own content, still plainly a control. */
.btn.tiny{
  font-size:11px; padding:2px 8px; line-height:1.6;
  border-radius:4px; margin-left:8px;
}
.setfield .locknote{
  color:var(--muted); font-weight:600; font-size:11px;
  letter-spacing:.04em; text-transform:uppercase;
}
.setfield .note{font-size:10.5px; color:var(--faint); line-height:1.35}
.setfoot{display:flex; gap:8px; align-items:center; padding:0 13px 13px; font-size:11.5px; color:var(--muted)}
.hide{display:none!important}
.tl{padding:4px 0 10px}
.tlday{display:flex; align-items:center; gap:9px; padding:9px 14px 5px; position:sticky; top:0;
  background:var(--surface); border-bottom:1px solid var(--line); z-index:2}
.tlday b{font-size:12px} .tlday span{font-size:11px; color:var(--muted)}
.tlrow{display:grid; grid-template-columns:56px 16px 1fr; gap:0 10px; padding:0 14px}
.tlrow .t{font-size:11px; color:var(--faint); text-align:right; padding-top:9px;
  font-family:"IBM Plex Mono",monospace}
.tlrow .tlrail{position:relative}
.tlrow .tlrail:before{content:""; position:absolute; left:6px; top:0; bottom:0; width:1px; background:var(--line)}
.tlrow .tldot{position:absolute; left:2px; top:12px; width:9px; height:9px; border-radius:50%;
  background:var(--surface); border:2px solid var(--teal)}
.tlrow.first .tlrail:before{top:12px}
.tlrow.last .tlrail:before{bottom:auto; height:12px}
.tlbody{padding:8px 0 10px; min-width:0}
.tlbody .hd{display:flex; gap:8px; align-items:baseline; flex-wrap:wrap}
.tlbody .who{font-weight:600; font-size:12.5px}
.tlbody .meta{font-size:11px; color:var(--muted); margin-top:2px}
.tlbody .val{font-family:"IBM Plex Mono",monospace; font-size:11.5px; color:var(--ink);
  background:var(--surface-2); border:1px solid var(--line); border-radius:4px; padding:1px 6px; display:inline-block}
.hint{font-size:11.5px; color:var(--muted); display:flex; gap:6px; align-items:center; margin-bottom:10px}
.hint kbd{font-family:"IBM Plex Mono",monospace; font-size:10.5px; border:1px solid var(--line-strong);
  border-bottom-width:2px; border-radius:4px; padding:1px 5px; background:var(--surface)}

/* ---------- families ---------- */
/* Members sit under their head. The indent and the branch mark are what make a
   family read as a block rather than as unrelated rows that happen to sort together. */
/* The member indent belongs to the name, not to every frozen cell. */
tr.member-row td.namecell .cell{padding-left:6px}
.branch{color:var(--faint); margin-right:5px; font-size:11px}
tr.member-row td.num{color:var(--faint)}
tr.member-row td.sticky{box-shadow:inset 3px 0 0 var(--teal-soft)}
.tagx{font-size:9.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--faint);
  margin-left:6px}

/* ---------- report status codes ---------- */
/* Colour follows the workflow: amber while it is our move, red once we have
   chased and heard nothing, green when the report has gone. */
.code{font-family:"IBM Plex Mono",ui-monospace,monospace; font-size:11px; font-weight:600;
  padding:1px 6px; border-radius:3px; line-height:18px; display:inline-block}
.code.c-C,.code.c-CP{background:var(--warn-soft); color:var(--warn)}
.code.c-CR,.code.c-CRP{background:var(--late-soft); color:var(--late)}
.code.c-Y{background:var(--teal-soft); color:var(--teal-ink)}
.code.c-Yes{background:var(--ok-soft); color:var(--ok)}

/* ---------- activity timeline ---------- */
/* Grouped by day so the log reads as a story rather than a table. */
.tl{padding:4px 0 10px}
.tlday{display:flex; align-items:center; gap:9px; padding:10px 14px 6px; position:sticky; top:0;
  background:var(--surface); border-bottom:1px solid var(--line); z-index:2}
.tlday b{font-size:12.5px} .tlday span{font-size:11px; color:var(--muted)}
.tlrow{display:grid; grid-template-columns:56px 16px 1fr; gap:0 10px; padding:0 14px}
.tlrow .t{font-size:11px; color:var(--faint); text-align:right; padding-top:9px;
  font-family:"IBM Plex Mono",ui-monospace,monospace}
.tlrow .tlrail{position:relative}
.tlrow .tlrail:before{content:""; position:absolute; left:6px; top:0; bottom:0; width:1px;
  background:var(--line)}
.tlrow .tldot{position:absolute; left:2px; top:12px; width:9px; height:9px; border-radius:50%;
  background:var(--surface); border:2px solid var(--teal)}
.tlrow.first .tlrail:before{top:12px}
.tlrow.last .tlrail:before{height:12px; bottom:auto}
.tlbody{padding:8px 0 10px; min-width:0}
.tlbody .hd{display:flex; gap:8px; align-items:baseline; flex-wrap:wrap}
.tlbody .who{font-weight:600; font-size:12.5px}
.tlbody .meta{font-size:11px; color:var(--muted); margin-top:3px}
.tlbody .val{font-family:"IBM Plex Mono",ui-monospace,monospace; font-size:11.5px;
  color:var(--ink); background:var(--surface-2); border:1px solid var(--line);
  border-radius:4px; padding:1px 6px; display:inline-block}

/* ---------- editable cells ---------- */
/* A cell you can change has to look like one. Without an affordance a
   dropdown reads as static text, and people do not discover it. */
/* No position here. Setting position:relative on a cell that is also sticky
   turns `left` from a sticky offset into a relative shove, which slides the
   pinned column sideways over its neighbour. */
td.editable{cursor:text}
td.editable .cell{border-bottom:1px dashed var(--line-strong); margin:0 4px;
  padding-left:5px; padding-right:5px}
td.editable:hover{background:var(--teal-soft)}
td.editable:hover .cell{border-bottom-color:var(--teal); border-bottom-style:solid}

/* Choice cells get a caret, because a dropdown is not obvious from its value. */
td.editable[data-kind="choice"],
td.editable[data-kind="status"],
td.editable[data-kind="check"]{cursor:pointer}
td.editable[data-kind="choice"] .cell:after,
td.editable[data-kind="status"] .cell:after,
td.editable[data-kind="check"] .cell:after{
  content:"\25BE"; font-size:8px; color:var(--faint); margin-left:6px;
  vertical-align:1px}
td.editable[data-kind="choice"]:hover .cell:after,
td.editable[data-kind="status"]:hover .cell:after,
td.editable[data-kind="check"]:hover .cell:after{color:var(--teal)}

/* Date cells hint at the picker. */
td.editable[data-kind="date"]{cursor:pointer}

/* A calculated or read-only cell must not look clickable at all. */
td.locked{cursor:default}
td.locked .cell{border-bottom:0}

/* ---------- dragging columns into order ---------- */
tr.drag-row{cursor:grab}
tr.drag-row:active{cursor:grabbing}
tr.drag-row:hover td{background:var(--teal-soft)}
tr.dragging{opacity:.45}
tr.dragging td{background:var(--teal-soft)}
tr.just-moved td{animation:flash 1.1s ease}
tr.pinned-row td{background:var(--lock)}

/* The grip is the affordance. Without it a draggable row looks like a table. */
.grip{display:inline-block; color:var(--faint); margin-right:9px; letter-spacing:-3px;
  font-size:13px; line-height:1; vertical-align:1px; cursor:grab}
tr.drag-row:hover .grip{color:var(--teal)}

.mv{border:1px solid var(--line); background:var(--surface); border-radius:4px;
  width:24px; height:22px; font:inherit; font-size:9px; color:var(--ink-2);
  cursor:pointer; padding:0; margin-right:3px}
.mv:hover{border-color:var(--teal); color:var(--teal)}

/* Save is only interesting once something has moved. */
#column-savebar .unsaved{display:none; color:var(--warn); font-weight:600}
#column-savebar.dirty .unsaved{display:inline}
#column-savebar.dirty .settled{display:none}

/* ---------- compact cards ---------- */
/* On a working screen the cards are a summary, not the subject: shrink them so
   the grid starts higher up. */
.cards.compact{gap:8px; margin-bottom:11px}
.cards.compact .card{padding:8px 11px}
.cards.compact .k{min-height:auto; font-size:10px}
.cards.compact .v{font-size:21px; margin-top:1px}
.cards.compact .d{font-size:10.5px}
.cards.compact .go{display:none}

/* ---------- reference notes under a grid ---------- */
/* Explanation belongs near what it explains, but below it. The work is at the
   top of the screen; the reference is there when it is wanted. */
.notes{margin-top:14px; border:1px solid var(--line); border-radius:var(--r);
  background:var(--surface); box-shadow:var(--shadow)}
.notes > summary{cursor:pointer; padding:9px 13px; font-size:10.5px; font-weight:600;
  letter-spacing:.08em; text-transform:uppercase; color:var(--muted); list-style:none}
.notes > summary::-webkit-details-marker{display:none}
.notes > summary:before{content:"\25B8"; display:inline-block; margin-right:7px;
  font-size:9px; transition:transform .15s ease}
.notes[open] > summary:before{transform:rotate(90deg)}
.notes > summary:hover{color:var(--teal-ink)}
.notes-body{padding:2px 13px 12px; border-top:1px solid var(--line)}
.notes-body p{margin:9px 0 0; font-size:11.5px; color:var(--ink-2);
  line-height:1.55; max-width:110ch}

/* Settings tabs ---------------------------------------------------------
   Four errands on one screen, so the tab bar has to say which one you are
   on without shouting. The active tab is carried by a solid underline in the
   brand purple rather than a filled pill, which would compete with the
   primary buttons inside each panel. */
.tabbar{display:flex; align-items:center; gap:2px; margin-bottom:14px;
  border-bottom:1px solid var(--line); flex-wrap:wrap}
.tabbar .spacer{flex:1}
.tab{padding:9px 14px 10px; font-size:12.5px; font-weight:600;
  color:var(--muted); text-decoration:none; border-bottom:2px solid transparent;
  margin-bottom:-1px; white-space:nowrap; transition:color .12s}
.tab:hover{color:var(--ink)}
.tab.on{color:var(--teal-ink); border-bottom-color:var(--teal)}
.tabnote{font-size:11.5px; color:var(--muted); padding-bottom:9px;
  max-width:52ch; text-align:right}

/* The same bar, driving panels of one form rather than four screens (the
   client's page, 23 September). A button rather than a link, because nothing
   is being navigated to: the panels are already on the page. It borrows
   .tab's look and only undoes what a <button> brings with it. */
.tab.formtab{background:none; border:0; border-bottom:2px solid transparent;
  font-family:inherit; cursor:pointer}
/* Restated because a <button> needs its own border reset above, and that
   reset would otherwise win over .tab.on by coming later in the file --
   leaving the chosen tab coloured but with no underline. */
.tab.formtab.on{border-bottom-color:var(--teal)}
.tab.formtab .pill{margin-left:6px}

/* Section heading inside the rules panel. Was an inline style repeated in
   the template; it is one rule now so the four groups cannot drift apart. */
.setgroup{font-size:10.5px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); padding:14px 13px 0; font-weight:600}
.setgroup + .setgrid{padding-top:6px}

@media (max-width:860px){
  .tabnote{display:none}
}

/* Days since the last one went out ---------------------------------------
   Deliberately not a pill. A KYC age has a compliance threshold behind it
   and earns a colour; "days since the last report" is a fact about the
   workflow, and colouring it would imply a rule nobody has set. */
.daysago{font-family:"IBM Plex Mono",ui-monospace,monospace; font-size:11.5px;
  color:var(--ink-2)}

/* A month an edit was made FROM, rather than one it belongs to. Lighter, so
   the two read as different facts without needing a second column. */
.fromonth{color:var(--muted); font-style:italic}

/* A credential shown once ------------------------------------------------
   Deliberately loud. This is the one screen where missing something costs a
   phone call, so it does not look like the rest of the page. */
.panel.handover{border-color:var(--teal); box-shadow:0 0 0 3px var(--teal-soft)}
.creds{display:flex; gap:26px; flex-wrap:wrap}
.creds .k{display:block; font-size:10.5px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--muted); font-weight:600}
.creds .v{font-family:"IBM Plex Mono",ui-monospace,monospace; font-size:17px;
  font-weight:600; color:var(--teal-ink); user-select:all}

/* A status code the workflow does not know -- one the firm has invented.
   Neutral rather than colourless: the six known codes carry meaning in their
   colour, and an unknown one must not borrow any of it. */
.code{background:var(--surface-2); color:var(--ink-2)}

/* ---- multi-pick ---------------------------------------------------------
   A dropdown that ticks several boxes and can be searched. Written here
   rather than pulled in as a library because it is forty lines and the
   alternative is a dependency on every page that never needed one.
   The `pick` prefix is unused elsewhere in this file -- check before reusing
   a short class name, two collisions have already cost an afternoon here. */
.pick{position:relative}
.pick>summary{list-style:none; cursor:pointer; display:flex; align-items:center;
  gap:6px; border:1px solid var(--line); background:var(--surface-2);
  border-radius:7px; padding:6px 10px; font-size:12.5px; color:var(--ink);
  white-space:nowrap; user-select:none}
.pick>summary::-webkit-details-marker{display:none}
.pick>summary:hover{border-color:var(--muted)}
.pick[open]>summary{border-color:var(--teal)}
.pick>summary .lab{color:var(--muted); font-size:11px; letter-spacing:.03em}
.pick>summary .val{max-width:220px; overflow:hidden; text-overflow:ellipsis}
.pick>summary .caret{color:var(--muted); font-size:9px; margin-left:2px}
.pick.rightward>.pickmenu{left:auto; right:0}
.pickmenu{position:absolute; z-index:40; top:calc(100% + 4px); left:0;
  min-width:280px; max-width:360px; background:var(--surface);
  border:1px solid var(--line); border-radius:9px;
  box-shadow:0 10px 30px rgba(0,0,0,.14); padding:8px}
.pickmenu .pickfind{width:100%; box-sizing:border-box; border:1px solid var(--line);
  border-radius:6px; padding:6px 8px; font:inherit; font-size:12.5px;
  background:var(--surface-2); color:var(--ink); outline:none}
.pickmenu .pickfind:focus{border-color:var(--teal)}
.pickacts{display:flex; gap:8px; padding:6px 2px 4px; font-size:11.5px}
.pickacts a{color:var(--teal-ink); cursor:pointer; text-decoration:none}
.pickacts a:hover{text-decoration:underline}
.pickacts .count{margin-left:auto; color:var(--faint)}
.picklist{max-height:280px; overflow-y:auto; margin:0; padding:0}
.picklist .grp{font-size:10.5px; letter-spacing:.05em; text-transform:uppercase;
  color:var(--faint); padding:8px 6px 3px; font-weight:600}
.picklist label,.picklist a.mopt{display:flex; align-items:center; gap:8px;
  padding:5px 6px; border-radius:6px; cursor:pointer; font-size:12.5px;
  line-height:1.3}
.picklist a.mopt{text-decoration:none; color:var(--ink)}
.picklist label:hover,.picklist a.mopt:hover{background:var(--surface-2)}
.picklist input{accent-color:var(--teal); width:14px; height:14px; margin:0; flex:0 0 auto}
.picklist .sub{color:var(--faint); font-size:11px; margin-left:auto; padding-left:8px}
.picklist .none{color:var(--muted); font-size:12px; padding:10px 6px}
.pickcap{color:var(--warn); font-size:11.5px; padding:4px 6px 0}

/* ---- the client page's contact and address block -----------------------
   Two subjects, so two columns. Poured through the one three-across grid the
   rest of the form uses, they interleave -- an address line lands beside a
   phone number and the eye has to work out which belongs to what. */
.twocol{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.twocol > .col{padding:12px 14px 14px}
.twocol > .col + .col{border-left:1px solid var(--line)}
@media (max-width:900px){
  .twocol{grid-template-columns:minmax(0,1fr)}
  .twocol > .col + .col{border-left:0; border-top:1px solid var(--line)}
}
.colhead{font-size:10px; letter-spacing:.11em; text-transform:uppercase;
  color:var(--faint); font-weight:600; margin-bottom:10px}
.stack{display:flex; flex-direction:column; gap:11px}
.pair{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:11px 14px}
.half{max-width:calc(50% - 7px)}
@media (max-width:520px){.half{max-width:none}}
/* One label, two boxes: an address is one thing written on two lines, not
   two fields that happen to sit near each other. */
.addr2{display:flex; flex-direction:column; gap:6px}
/* A field the country has decided is not part of its addresses. The label
   and the reason stay; the box goes. Shown-and-empty is an invitation. */
.setfield.gone label{color:var(--faint)}
.setfield.gone input{display:none}

/* ---- the searchable picker, over a real control ------------------------
   The <select> or <input> stays in the form and keeps its name, so what is
   submitted is what the server already expected; this sits over it. Without
   JavaScript the plain control is what you get, which is the screen exactly
   as it was. */
.picked-behind{position:absolute; opacity:0; pointer-events:none; width:1px;
  height:1px}
.setfield .pickbox{position:relative; display:block; width:100%}
.picksum.field{display:flex; align-items:center; gap:6px; width:100%;
  border:1px solid var(--line); background:var(--surface-2); border-radius:5px;
  padding:6px 8px; font:inherit; font-size:12.5px; color:var(--ink);
  text-align:left; cursor:pointer}
.picksum.field:hover{border-color:var(--muted)}
.picksum.field.open{border-color:var(--teal); background:var(--surface)}
.picksum.field:disabled{background:var(--lock); color:var(--muted);
  cursor:not-allowed}
.picksum .cty{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.picksum .cty.empty{color:var(--faint)}
.picksum .dial{font-family:"IBM Plex Mono",ui-monospace,monospace;
  color:var(--muted)}
.picksum .caret{margin-left:auto; color:var(--muted); font-size:9px}
.pickbox .pickmenu{min-width:100%}
.picklist .opt{width:100%; border:0; background:none; font:inherit;
  font-size:12.5px; text-align:left; color:var(--ink); cursor:pointer;
  display:flex; align-items:center; gap:10px; padding:5px 6px;
  border-radius:6px}
.picklist .opt:hover{background:var(--surface-2)}
.picklist .opt.on{background:var(--teal-soft); color:var(--teal-ink);
  font-weight:600}
.picklist .opt .dial{min-width:46px; color:var(--muted)}
.picklist .opt.on .dial{color:var(--teal-ink)}
.hitnone{color:var(--faint); font-size:11.5px; padding:8px 6px}

/* ---- the engagement row ------------------------------------------------
   Its own row, because it asks a different KIND of question from the filters
   above it: those narrow WHO is listed, this narrows WHEN something is owed.

   It reads as a sentence -- "Show clients whose EXPIRY falls THIS FINANCIAL
   YEAR" -- and carries its own button, because two unlabelled dropdowns on a
   row with no button of its own read as inert.

   Everything else about it matches the toolbar above: same ground, same
   border, same control boxes. It is a second row of filters, and tinting it
   differently made it read as a banner instead of as something to use. */
.toolbar.engagement{
  /* NOT sticky. ``.toolbar`` sticks at top:47px, and a second sticky row at
     the same offset lands on top of the first -- which is what was cutting
     through an open Relation or Status menu. Only one row pins. */
  position:static; z-index:auto;
  align-items:center; gap:7px; padding:8px; margin:0 0 12px;
}
/* The row's name. An eyebrow rather than a heading -- it names what this
   line of controls is for, in the same small uppercase the column headings
   use, and then gets out of the way. The rule after it separates the name
   from the question without spending a whole divider on it. */
.toolbar.engagement .rowlab{
  font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--teal-ink); font-weight:600; white-space:nowrap;
  padding-right:10px; margin-right:2px; border-right:1px solid var(--line);
}
/* The words between the controls. Muted and small, because they are the
   grammar of the row rather than the part anybody is choosing. */
.toolbar.engagement .word{
  color:var(--muted); font-size:11px; letter-spacing:.03em;
  white-space:nowrap;
}
/* Exactly the box the other filters use -- same border, ground, radius and
   padding as ``.field``, so the row reads as more filters and not as a
   different kind of control. */
.toolbar.engagement select,
.toolbar.engagement input[type="date"]{
  border:1px solid var(--line); background:var(--surface-2);
  border-radius:5px; padding:5px 8px; font:inherit; font-size:12.5px;
  color:var(--ink); outline:none;
}
.toolbar.engagement select:hover,
.toolbar.engagement input[type="date"]:hover{border-color:var(--muted)}
.toolbar.engagement select:focus-visible,
.toolbar.engagement input[type="date"]:focus-visible{
  border-color:var(--teal); background:var(--surface);
}
/* Hidden until "between two dates" is the window. Not disabled-and-greyed:
   a pair of dead boxes on every visit is clutter that explains nothing. */
.toolbar.engagement .span{display:none; align-items:center; gap:6px}
.toolbar.engagement .span.on{display:flex}
.toolbar.engagement .rownote{
  color:var(--faint); font-size:11px; margin-left:auto; max-width:34ch;
  text-align:right; line-height:1.35;
}
.toolbar.engagement .btn{flex:none}
/* The note is the first thing to go: the sentence and its button are the row,
   and the note only says where the dates come from. It goes when the two date
   boxes open as well as when the window is narrow -- the row is long enough
   with a range in it to wrap onto a second line, and a wrapped sentence stops
   reading as a sentence. */
.toolbar.engagement .span.on ~ .rownote{display:none}
@media (max-width:1180px){.toolbar.engagement .rownote{display:none}}
@media (max-width:1180px){.toolbar.engagement .btn{margin-left:auto}}

/* ---- several MFU CANs --------------------------------------------------
   A text box and a button, rather than a box that turns typing into chips
   on its own: the button is what says "this field takes more than one"
   before anybody has tried it. */
.canfield{display:flex; flex-direction:column; gap:6px}
.canadd{display:grid; grid-template-columns:minmax(0,1fr) auto; gap:6px}
.btn.addcan{display:inline-flex; align-items:center; gap:5px;
  border:1px solid var(--line); background:var(--surface); border-radius:5px;
  padding:0 12px; font:inherit; font-size:12px; font-weight:600;
  color:var(--teal-ink); cursor:pointer; white-space:nowrap}
.btn.addcan:hover{border-color:var(--teal); background:var(--teal-soft)}
.btn.addcan .plus{font-size:14px; line-height:1; font-weight:400}
.chipfield{display:flex; flex-wrap:wrap; gap:5px; align-items:center}
.chipfield:empty{display:none}
.can{display:inline-flex; align-items:center; gap:6px; background:var(--surface);
  border:1px solid var(--line-strong); border-radius:20px;
  padding:2px 4px 2px 9px; font-family:"IBM Plex Mono",ui-monospace,monospace;
  font-size:11.5px; line-height:18px}
.can button{border:0; background:none; cursor:pointer; color:var(--faint);
  font:inherit; font-size:13px; line-height:1; padding:0 3px; border-radius:50%}
.can button:hover{color:var(--late); background:var(--late-soft)}
.canwhy.bad{color:var(--late); font-weight:600}
/* The cell that opens. All of them, clipped by the cell -- not the first
   plus a count, which would put one at the front as though it mattered. */
.cans{display:inline-flex; align-items:center; gap:6px; max-width:100%;
  cursor:pointer}
.cans:focus-visible{outline:2px solid var(--teal); outline-offset:1px}
.cans .joined{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  min-width:0}
.cans .more{
  flex:none; font-family:"IBM Plex Sans",system-ui,sans-serif; font-size:9.5px;
  font-weight:600; letter-spacing:.04em; color:var(--teal-ink);
  background:var(--teal-soft); border-radius:20px; padding:0 6px;
  line-height:16px;
}
.cans .caret{color:var(--muted); font-size:8px; flex:none}
/* Placed against the window, because the grid scrolls inside its own box and
   a menu drawn inside a cell is clipped at the edge of the visible grid. */
.canmenu{position:fixed; z-index:80; background:var(--surface);
  border:1px solid var(--line); border-radius:9px; padding:6px;
  box-shadow:var(--shadow-pop); min-width:190px; max-height:280px;
  overflow:auto}
.canmenu .row{display:flex; align-items:center; gap:8px; padding:5px 7px;
  border-radius:6px; font-size:12px}
.canmenu .row:hover{background:var(--surface-2)}
.canmenu .row.shown{background:var(--teal-soft); color:var(--teal-ink);
  font-weight:600}
/* Selectable, so a drag-and-copy works as well as the button does. */
.canmenu .val,.cans .joined{user-select:text; -webkit-user-select:text}
.canmenu .rowbtn{margin-left:auto; border:1px solid var(--line);
  background:var(--surface); border-radius:5px; padding:1px 7px; font:inherit;
  font-size:10px; font-weight:600; letter-spacing:.03em; color:var(--teal-ink);
  cursor:pointer; white-space:nowrap}
.canmenu .rowbtn:hover{border-color:var(--teal); background:var(--teal-soft)}
.canmenu .rowbtn.done{color:var(--ok); border-color:var(--ok);
  background:var(--ok-soft)}
.canmenu .row .tagx{font-family:"IBM Plex Sans",system-ui,sans-serif;
  font-size:9px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--teal-ink); font-weight:600}
.canmenu .foot{display:flex; align-items:center; gap:10px;
  border-top:1px solid var(--line); margin-top:5px; padding:7px 7px 2px;
  font-size:10.5px; color:var(--faint)}
/* The tick on a chip: which one the grid's column shows. */
.can .tick{border:0; background:none; cursor:pointer; padding:0 2px 0 0;
  font-size:11px; line-height:1; color:var(--faint)}
.can .tick:hover{color:var(--teal)}
.can.first{background:var(--teal-soft); border-color:var(--teal);
  color:var(--teal-ink); font-weight:600}
.can.first .tick{color:var(--teal-ink)}
.can .tagx{font-family:"IBM Plex Sans",system-ui,sans-serif; font-size:9px;
  letter-spacing:.06em; text-transform:uppercase; color:var(--teal-ink);
  font-weight:600}
/* A phone number in the grid: the code, then the number. Set back rather
   than hidden -- it is part of the number and somebody dialling from another
   country needs it, but 512 of 534 of these read +91 and a column of
   identical prefixes at full strength is a column you read past. */
.dialcode{font-family:"IBM Plex Mono",ui-monospace,monospace;
  color:var(--faint)}
.tel{font-family:"IBM Plex Mono",ui-monospace,monospace;
  font-variant-numeric:tabular-nums}
/* The code beside the number on the client's page. */
.phonebox{display:grid; grid-template-columns:132px minmax(0,1fr); gap:6px}
.phonebox .pickbox{width:auto}
.phonebox .picksum.field .cty{font-size:11.5px; color:var(--muted)}
.phonebox .picksum.field .dial{color:var(--ink)}
/* A value typed past the list rather than chosen from it. Marked, because a
   value that is not on the list is worth knowing about when somebody comes
   back to the record: it may be right, and it may be a typo nobody has
   looked at yet. */
.picklist .opt.own{border-top:1px dashed var(--line); border-radius:0 0 6px 6px;
  margin-top:4px; padding-top:8px; color:var(--teal-ink)}
.picklist .opt.own .tagx{margin-left:auto; font-size:9.5px; font-weight:600;
  letter-spacing:.05em; text-transform:uppercase; color:var(--faint)}
.picksum .own{margin-left:6px; font-size:9.5px; font-weight:600;
  letter-spacing:.05em; text-transform:uppercase; color:var(--faint);
  border:1px solid var(--line-strong); border-radius:3px; padding:0 4px}

/* What a preset resolved to. Deliberately not an input: these dates are the
   answer to "which range did I get", not something to type into. */
.rangesays{display:inline-flex; align-items:center; gap:6px; padding:6px 10px;
  border:1px dashed var(--line); border-radius:7px; background:transparent;
  color:var(--muted); font-size:12px; white-space:nowrap}

/* ---- rows-per-page ------------------------------------------------------ */
.perpage{display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap}
.perpage .lab{color:var(--muted); font-size:11px; letter-spacing:.03em;
  margin-right:2px}
.perpage .btn{padding:3px 8px; font-size:11.5px}
.gridfoot{flex-wrap:wrap; gap:10px}

/* The client edit form reuses the Settings field styling; textareas were the
   one control Settings never had. */
.setfield textarea{border:1px solid var(--line); background:var(--surface-2);
  border-radius:5px; padding:6px 8px; font:inherit; font-size:12.5px;
  color:var(--ink); outline:none; width:100%; resize:vertical}
.setfield textarea:focus{border-color:var(--teal); background:var(--surface)}

/* A count beside a nav item. Used by Approvals: a queue nobody is told about
   is a queue nothing ever leaves. */
.navcount{margin-left:auto; background:var(--warn-soft); color:var(--warn);
  border-radius:9px; padding:0 6px; font-size:10.5px; font-weight:700;
  line-height:16px; min-width:18px; text-align:center}

/* ---- collapsing the rail -------------------------------------------------
   A grid of forty columns and a fixed 216px rail fight over the same screen.
   This gives the rail back when somebody is working a long row.

   It collapses to ICONS, not to nothing: a hidden rail means navigating by
   the back button, and the whole point is to keep working. The width lives on
   .app because the grid column is what actually has to shrink -- narrowing
   only .rail would leave a 216px gap where it used to be.

   Driven by a class on <html> rather than on .app so the choice can be
   applied before first paint, from a script in <head>, without the rail
   visibly jumping. */
html.railmin .app{grid-template-columns:56px 1fr}
html.railmin .rail{padding:14px 6px; overflow:visible}
html.railmin .brand > div:last-child,
html.railmin .navlabel,
html.railmin .railfoot,
html.railmin .nav .navcount{display:none}
html.railmin .brand{padding:4px 0 14px; justify-content:center}
/* Collapsed, a wide logo cannot fit in 56px: the icon (or the letter) that
   the brand block keeps for exactly this takes its place. */
html.railmin .brand.has-logo .brandlogo-wrap{display:none}
html.railmin .brand.has-logo > .mark{display:grid}
html.railmin .nav{justify-content:center; padding:9px 0; gap:0}
html.railmin .nav .ic{width:17px; height:17px}
/* The label is still in the DOM for screen readers; it is the visible text
   that goes. Kept out of `display:none` on .nav itself so the icon survives. */
html.railmin .nav{font-size:0}
html.railmin .nav .ic{font-size:initial}
/* A tooltip, since the words are gone. */
html.railmin .nav{position:relative}
html.railmin .nav:hover::after{
  content:attr(data-label); position:absolute; left:calc(100% + 8px); top:50%;
  transform:translateY(-50%); background:var(--ink); color:var(--surface);
  padding:4px 8px; border-radius:5px; font-size:11.5px; white-space:nowrap;
  z-index:60; pointer-events:none; box-shadow:var(--shadow);
}
/* An unread count still has to be visible when the words are not. */
html.railmin .nav[data-count]:not([data-count=""])::before{
  content:""; position:absolute; top:6px; right:9px; width:7px; height:7px;
  border-radius:50%; background:var(--warn);
}

.railtoggle{
  margin-top:auto; display:flex; align-items:center; justify-content:center;
  gap:7px; border:1px solid var(--line); background:var(--surface-2);
  color:var(--muted); border-radius:var(--r); padding:7px 9px; cursor:pointer;
  font:inherit; font-size:11.5px; width:100%;
}
.railtoggle:hover{color:var(--ink); border-color:var(--muted)}
.railtoggle .arrow{transition:transform .15s ease; font-size:13px; line-height:1}
html.railmin .railtoggle .arrow{transform:rotate(180deg)}
html.railmin .railtoggle span:not(.arrow){display:none}
/* The foot sits above the toggle when expanded; when collapsed the toggle is
   the only thing left down there. */
html.railmin .rail .railfoot + .railtoggle{margin-top:auto}

/* ---------- Field access ---------- */
/* One role at a time, and the role named again above the table: by the time
   somebody has scrolled through 46 fields the picker is long gone, and
   "which role am I on?" is the question they cannot afford to get wrong. */
.fapick{display:flex; gap:16px; align-items:flex-end; flex-wrap:wrap}
.fapick .rtab{
  display:block; text-decoration:none; border:1px solid var(--line-strong);
  background:var(--surface); border-radius:7px; padding:8px 15px 9px}
.fapick .rtab b{display:block; font-size:14px; color:var(--ink)}
.fapick .rtab small{font-size:11px; color:var(--muted)}
.fapick .rtab.on{background:var(--teal); border-color:var(--teal)}
.fapick .rtab.on b, .fapick .rtab.on small{color:var(--on-accent)}
.fapick .versus{color:var(--muted); font-size:13px; padding-bottom:10px}
.fapick .fafield label{display:block; font-size:10.5px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--muted); margin-bottom:4px}
.fapick select{font:inherit; font-size:14px; font-weight:600; padding:8px 12px;
  border:1px solid var(--teal); border-radius:5px; background:var(--surface);
  color:var(--ink); min-width:240px}

.whostrip{display:flex; align-items:baseline; gap:9px; flex-wrap:wrap;
  background:var(--surface); border:1px solid var(--line);
  border-left:3px solid var(--teal); border-bottom:0;
  border-radius:7px 7px 0 0; padding:9px 14px}
.whostrip .whoword{font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted)}
.whostrip b{font-size:17px}
.whostrip .whocount{font-size:12px; color:var(--muted); margin-left:auto}

.grid tr.grouprow td{background:var(--teal-soft); font-weight:600}
.grid tr.fixedrow td{background:var(--lock)}
/* The heading somebody reads, and the name an import and the code use. Both,
   because the two are asked about in the same breath and looking one up from
   the other is otherwise a trip to a developer. */
.falabel{display:block; line-height:1.3}
.fakey{display:block; font-size:10.5px; color:var(--faint); line-height:1.3;
  font-family:"IBM Plex Mono",monospace}
/* The one cell on the desk that is a sentence rather than a value, so it is
   the one cell that wraps instead of ellipsising. */
/* The td has to wrap too, or the table layout measures the whole sentence
   and hands this column 540px it does not need. */
.grid td.meanscell{white-space:normal; max-width:290px}
.grid td .cell.means{height:auto; min-height:30px; line-height:1.45;
  white-space:normal; overflow:visible; text-overflow:clip;
  color:var(--ink-2); font-size:12.5px; padding-top:6px; padding-bottom:6px}
.grid td .cell.seghold{height:auto; line-height:1.3; padding-top:4px;
  padding-bottom:4px; overflow:visible}

/* Three states, one control. Radios rather than buttons: the browser keeps
   one of them chosen, so a half-set field cannot be posted. */
.seg{display:inline-flex; border:1px solid var(--line-strong); border-radius:4px;
  overflow:hidden}
.seg label{margin:0; cursor:pointer}
.seg input{position:absolute; opacity:0; width:0; height:0}
.seg span{display:block; font-size:11.5px; font-weight:600; color:var(--muted);
  background:var(--surface); padding:5px 10px; border-right:1px solid var(--line);
  white-space:nowrap}
.seg label:last-child span{border-right:0}
.seg label:hover span{background:var(--lock); color:var(--ink)}
.seg input:checked + span{background:var(--ok); color:var(--on-accent)}
.seg input:checked + span.no{background:var(--muted); color:var(--on-accent)}
.seg input:checked + span.appr{background:var(--warn); color:var(--on-accent)}
.seg input:focus-visible + span{outline:2px solid var(--teal); outline-offset:-2px}

#fa-savebar .unsaved{display:none; color:var(--warn)}
#fa-savebar.dirty .unsaved{display:inline}
#fa-savebar.dirty .settled{display:none}

/* A control that cannot be moved still looks like the control beside it --
   greyed, not replaced by a sentence. Consistent rows are what make a column
   readable at a glance. */
.seg.off span{background:var(--lock); color:var(--faint); cursor:default}
.seg.off input:checked + span{background:var(--line-strong); color:var(--ink-2)}
.seg.off label:hover span{background:var(--lock); color:var(--faint)}
.segwhy{display:inline-block; margin-left:7px; font-size:11px; color:var(--faint)}

/* A cell whose value goes to somebody rather than to the record. Amber where
   an editable cell is teal, so the difference is visible before the typing
   rather than explained after it. */
td.editable.waits .cell{border-bottom-color:var(--warn); border-bottom-style:dotted}
td.editable.waits:hover .cell{border-bottom-color:var(--warn); border-bottom-style:solid}
td.submitted .cell{background:var(--warn-soft); transition:background .4s}

/* ---------- the permission rows on a role ---------- */
/* The whole row is the target, and being allowed is visible from across the
   table rather than resting on one 15px tick. */
.permcell{cursor:pointer; display:flex; align-items:center; gap:8px}
tr.permrow:hover td{background:var(--teal-soft)}
tr.permrow.on td{background:var(--ok-soft)}
tr.permrow.on:hover td{background:var(--ok-soft)}
.permwhy{color:var(--muted); white-space:normal; line-height:1.4;
  height:auto; min-height:30px; padding-top:6px; padding-bottom:6px;
  overflow:visible; align-items:flex-start}
.permstate{flex:0 0 auto; font-size:10.5px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--faint); min-width:74px}
tr.permrow.on .permstate{color:var(--ok)}

/* ---- a person we are not sending a report to ---------------------------
   The row greys out and stops taking the keyboard. Deliberately the SAME
   grey the grid already uses for a calculated or read-only cell: a second
   kind of locked would be a second thing to learn, and it means the same
   thing here -- not yours to type.

   ``keepon`` is the exception, and there is exactly one of it. The Report to
   be Sent cell keeps its own ground on a greyed row, because it is the cell
   that turns the row back on; a switch that locked the cell holding it would
   be a switch nobody could throw twice. */
tr.norow td{background:var(--lock); color:var(--faint)}
tr.norow td.keepon{background:var(--surface); color:var(--ink)}
tr.norow:hover td{background:var(--lock)}
tr.norow:hover td.keepon{background:var(--surface)}

/* Yes and No, in the colour that says which, so "not being sent one" reads at
   a glance down a column of two hundred.

   No dot and no outline: the colour is already doing the work, and a ring
   plus a bullet on every one of two hundred rows is three marks saying one
   thing. Shaped like the report codes beside it, so the two columns read as
   the same kind of value rather than as two different inventions. */
.sendflag{display:inline-block; border-radius:4px; padding:1px 8px;
  font-size:11px; font-weight:600}
.sendflag.yes{background:var(--ok-soft); color:var(--ok)}
.sendflag.no{background:var(--late-soft); color:var(--late)}

/* A tile whose value is a ratio. The denominator rides with the number
   rather than dropping to the description line, because "6 of 41" is one
   fact and splitting it makes somebody hold half of it while they read. */
/* The EQ reviews tile carries two numbers -- the two halves of the month,
   each a link to the clients still due in it. The half being worked is in
   the ink colour and the other is muted, so the eye lands on what is owed
   now rather than on what is already finished. */
.card.eqsplit .v{display:flex; align-items:baseline; gap:7px}
.card.eqsplit .eqhalf{color:var(--faint); text-decoration:none}
.card.eqsplit .eqhalf.now{color:var(--ink)}
.card.eqsplit a.eqhalf:hover{color:var(--teal)}
/* The half that has not started yet: a number, not a link. */
.card.eqsplit .eqhalf.soon{cursor:default}
.card.eqsplit .eqsep{color:var(--line-strong); font-weight:400}
.card.eqsplit .d .nowlab{color:var(--ink-2); font-weight:600}

.card .v .of{font-size:12px; font-weight:500; color:var(--muted);
  margin-left:6px; letter-spacing:0}

/* ---- dragging a column edge -------------------------------------------
   A grab strip on the right edge of each heading. Wider than it looks: the
   visible line is 1px but the target is 9, because a 1px hit area is a
   1px hit area and nobody enjoys hunting for it. */
/* NO `position: relative` on the heading. It is already `position: sticky`,
   which is a positioning context of its own -- and relative would have
   overridden the sticky, unfreezing the frozen headings and sliding every one
   of them right by its own `left` offset. The grid came apart exactly that
   way the first time this was written. */
.colgrip{position:absolute; top:0; right:-4px; width:9px; height:100%;
  cursor:col-resize; z-index:2; touch-action:none}
.colgrip::after{content:""; position:absolute; top:5px; bottom:5px; left:4px;
  width:1px; background:transparent}
.colgrip:hover::after{background:var(--teal)}
/* While a drag is running, every cursor on the page is the resize cursor and
   nothing selects -- otherwise a fast drag paints the grid blue. */
body.resizing, body.resizing *{cursor:col-resize !important;
  user-select:none !important}
.gridfoot .widthreset{margin-left:8px}

/* The month the grid is showing, said once above it rather than repeated in
   a column. Quiet: it confirms what the Month filter already says, and a
   heading that shouts would be a third voice saying the same thing. */

/* ---------- sign-in page: the firm's own logo and registered name ----------
   From Settings -> Brand. The logo is capped in both directions so a tall
   square or a very wide banner both sit in the panel without pushing the
   form down. */
.signin-logo{display:block; max-width:220px; max-height:64px; width:auto; height:auto; margin:0 0 16px}
.signin-legal{margin:14px 0 0; font-size:11px; color:var(--faint); text-align:center; max-width:420px}

/* Settings -> Brand: the current logo or icon, on a checked ground so a
   transparent PNG shows its real edges. */
.brandimg{
  height:64px; display:flex; align-items:center; padding:6px 10px; margin:2px 0 4px;
  border:1px dashed var(--line-strong); border-radius:var(--r);
  background:repeating-conic-gradient(var(--surface-2) 0 25%, var(--surface) 0 50%) 0 0/14px 14px;
}
.brandimg img{max-height:100%; max-width:100%; object-fit:contain}
.brandimg .none{font-size:11.5px; color:var(--faint)}
/* "Remove the logo": a tick box and a sentence, not a field heading. */
.setfield label.removeimg{display:flex; align-items:center; gap:7px; cursor:pointer;
  text-transform:none; letter-spacing:0; font-weight:400; font-size:12px; color:var(--ink-2)}
.setfield label.removeimg input{width:auto; margin:0; accent-color:var(--teal)}

/* Settings -> Modules: the Access box and its Yes / No word side by side. */
.modaccess label.yesno{display:inline-flex; align-items:center; gap:6px; cursor:pointer;
  font-size:12px; font-weight:600; color:var(--ink-2)}
.modaccess input[type=checkbox]{accent-color:var(--teal); width:14px; height:14px; margin:0; cursor:pointer}
.modaccess input[type=checkbox]:disabled{cursor:not-allowed; opacity:.45}
/* Field access: a module tab switched off for the role (Settings -> Modules). */
.fatabs{margin-bottom:10px}
.fatabs .tab.offtab{color:var(--faint)}
.fatabs .tab .pill{margin-left:4px; font-size:9.5px}
