/* ==========================================================================
   LUMORIA Console — the document composer's own stylesheet.

   Separate from app.css on purpose (ADR-032): this feature owns its files,
   and app.css is shared. Loaded after app.css in index.html, so where the
   two touch the same class the composer wins.

   Everything here uses app.css's tokens — no new colours are invented, and
   nothing is hard-coded that the brand owns.
   ========================================================================== */

/* -------------------------------------------------------- the wide drawer
   A document is a table, not a two-field form. 620px was the width every
   other drawer wanted and the one thing that made the line grid impossible:
   at 620 the description column got 270px, which is not enough to read
   "Property photography — 3–4 bed house" while a price sits beside it. */
.drawer.wide { width: min(880px, 100%); }
@media (max-width: 900px) { .drawer.wide { width: 100%; } }

/* ------------------------------------------------------------- the lines */
.dl-lab { display: flex; align-items: baseline; gap: 12px; margin: 20px 0 8px; }
.dl-lab label { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
.dl-lab .muted { font-size: 12px; margin-left: auto; }

/* One grid template, declared once and shared by the header and every row,
   which is the entire reason the columns line up. */
.dl-h, .dl-r {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) 64px 104px 96px 52px;
  gap: 10px;
  align-items: start;
}
.dl-h {
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft); font-weight: 700; padding: 0 2px 8px;
  border-bottom: 1px solid var(--line);
}
.dl-h .c { text-align: center; }
.dl-h .r { text-align: right; }

.dl-b { display: grid; gap: 2px; padding: 6px 0; }

.dl-r {
  padding: 7px 2px; border-radius: 11px; position: relative;
  transition: background var(--dur-1) var(--ease);
}
.dl-r:hover { background: var(--sand); }
.dl-r:focus-within { background: var(--sand); }
.dl-r.drag { opacity: .45; background: var(--sand-deep); }

/* The grip only earns its space on hover — a column of dots on every row is
   noise until the moment you want to move something. */
.dl-grip {
  display: grid; place-items: center; height: 38px; cursor: grab;
  opacity: 0; transition: opacity var(--dur-1) var(--ease);
}
.dl-r:hover .dl-grip, .dl-r:focus-within .dl-grip { opacity: .4; }
.dl-grip:active { cursor: grabbing; }
.dl-grip svg { width: 14px; height: 14px; stroke: var(--ink-soft); fill: none; stroke-width: 2; }

.dl-desc { display: grid; gap: 4px; min-width: 0; }
/* The canonical control block, at app density — docs/10-interface-standard.md
   §2. A line-item box is the same control as a field in a drawer; it was
   drifting at 9px/11px padding, 14px, a 1px border and a 9px radius, with a
   focus ring at a different offset from every other control in the console. */
.dl-r input {
  width: 100%; min-height: var(--ctl-h); padding: var(--ctl-pad);
  font-size: var(--ctl-size); line-height: 1.25;
  background: var(--surface); color: var(--ink);
  border: none; border-radius: var(--ctl-r);
  box-shadow: 0 0 0 1px var(--line) inset; outline: none;
  transition: box-shadow var(--dur-2) var(--ease);
}
.dl-r input::placeholder { color: var(--ink-soft); opacity: .62; }
.dl-r input:focus { outline: 2px solid var(--brass); outline-offset: 2px; box-shadow: 0 0 0 1px var(--line) inset; }
/* Subordinate to the description it belongs under, and bound to it rather
   than sitting a field-gap away. Quieter than the description, but still
   visibly a box you can type in — the first version dropped the border
   entirely and it read as a caption nobody could tell was editable.

   It stays the SAME HEIGHT as the description above it — 44px is the floor for
   every control, and a shorter box here would be a missed tap on a phone. Its
   subordination is carried by weight and colour, not by being smaller. */
.dl-r .l-detail {
  font-size: 13px; color: var(--ink-soft);
  background: transparent; box-shadow: 0 0 0 1px var(--line-2) inset;
}
.dl-r:hover .l-detail, .dl-r .l-detail:focus { background: var(--surface); }
.dl-r .l-detail:focus { box-shadow: 0 0 0 1px var(--line) inset; }

/* Qty and unit both wear their operator, so the pair reads as "× 2 · £275.00"
   with no column header to lean on — which is what makes the mobile reflow
   below legible after the header row is dropped. */
.dl-qty, .dl-unit { position: relative; display: block; }
.dl-qty span, .dl-unit span {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  font-size: 12.5px; color: var(--ink-soft); pointer-events: none;
  font-variant-numeric: tabular-nums;
}
.dl-qty input { padding-left: 24px; text-align: right; font-variant-numeric: tabular-nums; }

/* Native spinners eat ~16px off the right of a 104px box, which is enough to
   clip "275.00" into "275.0(" — the number you are about to invoice, cut in
   half by a control nobody uses on a price. */
.dl-r input[type=number]::-webkit-outer-spin-button,
.dl-r input[type=number]::-webkit-inner-spin-button { appearance: none; margin: 0; }
.dl-r input[type=number] { appearance: textfield; -moz-appearance: textfield; }

/* The unit box wears its currency, so a USD invoice cannot be typed as if it
   were pounds. */
.dl-unit input { padding-left: 26px; text-align: right; font-variant-numeric: tabular-nums; }
/* AED is three characters — give it the room rather than overlapping. */
.dl-unit:has(span:not(:empty)) input { padding-left: max(26px, 2.6em); }

/* THE COLUMN THAT WAS MISSING. */
.dl-amt {
  display: block; text-align: right; padding: 10px 2px 0 0;
  font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
  white-space: nowrap; color: var(--ink);
}
.dl-amt.neg { color: var(--bad); }

.dl-tools { display: flex; gap: 2px; padding-top: 4px; justify-content: flex-end; }
.dl-ic {
  width: 24px; height: 24px; border: 0; background: none; border-radius: 7px;
  display: grid; place-items: center; cursor: pointer; opacity: 0;
  transition: opacity var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.dl-r:hover .dl-ic, .dl-r:focus-within .dl-ic { opacity: .55; }
.dl-ic:hover, .dl-ic:focus-visible { opacity: 1; background: var(--sand-deep); }
.dl-ic:focus-visible { outline: 2px solid var(--brass); outline-offset: 1px; }
.dl-ic svg { width: 13px; height: 13px; stroke: var(--ink); fill: none; stroke-width: 2; stroke-linecap: round; }
.dl-ic.danger:hover svg { stroke: var(--bad); }

.dl-add { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 6px; border-top: 1px solid var(--line); margin-top: 4px; }

/* ------------------------------------------------------- the small screen
   The five fixed columns come to 386px before gaps, which is wider than the
   331px a 375px drawer actually has — so on a phone the grid became a
   sideways scroll through the numbers you are trying to check. Each line
   becomes a small card instead: description on its own row, then the
   arithmetic on one line beneath it. The header row goes, which is why qty
   and unit carry their own "×" and currency marks. */
@media (max-width: 620px) {
  .dl-h { display: none; }
  .dl-b { gap: 8px; }
  .dl-r {
    grid-template-columns: 78px minmax(0, 1fr) auto auto;
    grid-template-areas: "desc desc desc desc" "qty unit amt tools";
    gap: 8px; padding: 10px; align-items: center;
    background: var(--surface); box-shadow: 0 0 0 1px var(--line) inset;
  }
  .dl-r:hover { background: var(--surface); }
  .dl-grip { display: none; }
  .dl-desc { grid-area: desc; }
  .dl-qty { grid-area: qty; }
  .dl-unit { grid-area: unit; }
  .dl-amt { grid-area: amt; padding: 0 4px 0 0; }
  .dl-tools { grid-area: tools; padding: 0; }
  /* No hover on a touch screen — the controls have to be there already. */
  .dl-ic { opacity: .5; }
  .dl-r .l-detail { border-style: dashed; }
  .dt { max-width: none; }
}

/* ------------------------------------------------------------- the totals
   Right-aligned and narrow, so the eye lands on one column of figures
   instead of scanning a full-width row. */
.dt {
  margin-top: 18px; margin-left: auto; max-width: 380px;
  background: var(--surface); border-radius: 14px;
  box-shadow: 0 0 0 1px var(--line) inset; padding: 14px 16px;
}
.dt-r { display: flex; align-items: baseline; justify-content: space-between; gap: 18px; padding: 5px 0; font-size: 13.5px; color: var(--ink-soft); }
.dt-r b { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dt-r span { display: flex; align-items: center; gap: 7px; min-width: 0; }
.dt-r svg { width: 13px; height: 13px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.7; }

.dt-r.blk { color: var(--brass); }
.dt-r.blk b { color: var(--brass); }
.dt-r.off { color: var(--ink-soft); opacity: .75; }
.dt-r.warn { color: var(--bad); }
.dt-r.warn b { color: var(--bad); }

.dt-r.tot {
  margin-top: 8px; padding-top: 11px; border-top: 1px solid var(--line);
  font-size: 15px; color: var(--ink); font-weight: 700;
}
.dt-r.tot b { font-size: 20px; letter-spacing: -.02em; }

.dt-more { margin-top: 10px; }
.dt-more summary {
  cursor: pointer; font-size: 12.5px; color: var(--ink-soft);
  list-style: none; padding: 4px 0;
}
.dt-more summary::-webkit-details-marker { display: none; }
.dt-more summary::before { content: "+ "; color: var(--brass); font-weight: 700; }
.dt-more[open] summary::before { content: "− "; }
.dt-more summary:hover { color: var(--ink); }
.dt-disc { padding-top: 6px; }

/* The total, repeated in the footer beside the save button — the composer is
   taller than the drawer on a real document, so the figure you are deciding
   on must not be the thing that scrolls out of view. */
.dt-foot { font-size: 13px; color: var(--ink-soft); display: flex; align-items: baseline; gap: 8px; }
.dt-foot b { font-size: 17px; color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.015em; }

/* ================================================== THE PROPERTY SHOOT
   The configurator, at ADMIN density. It is the same object the booking page
   builds and deliberately not the same surface: /book/ is a sales page that
   spends a screen per decision, this is a panel inside a drawer that somebody
   is filling in for the fourth time today. Every lever is on screen at once
   and nothing scrolls to reveal a step.

   Spacing is the three tiers and nothing else — a thing and the thing it
   belongs to is `bound`, sibling to sibling is `flow`, a change of mode is
   `break`. The sequence down the panel is deliberately not one number:
     header → properties      bound   (the heading names what follows)
     property → property      flow
     properties → add button  bound   (the button belongs to the list)
     add → levers             break   (rooms are done; this is the finish)
     levers → receipt         break   (inputs are done; this is the answer)
     receipt → note           bound
   ------------------------------------------------------------------------ */
.pc {
  background: var(--sand); border-radius: 15px; padding: 15px 16px 16px;
  margin-bottom: var(--sp-flow);
}

.pc-h { display: flex; align-items: flex-start; gap: 11px; margin-bottom: var(--sp-bound); }
.pc-hi { flex: none; width: 26px; height: 26px; border-radius: 999px; background: var(--surface); display: grid; place-items: center; }
.pc-hi svg { width: 14px; height: 14px; stroke: var(--brass); fill: none; stroke-width: 1.7; }
.pc-ht { min-width: 0; flex: 1; }
.pc-ht b { display: block; font-size: 14px; font-weight: 700; letter-spacing: -.01em; }
.pc-ht span { display: block; font-size: 12.5px; line-height: 1.5; color: var(--ink-soft); margin-top: 2px; max-width: 62ch; }

/* ---------------------------------------------------------- one property */
.pc-props { display: grid; gap: var(--sp-flow); }
.pc-p {
  background: var(--surface); border-radius: 13px; padding: 12px 13px 13px;
  box-shadow: 0 0 0 1px var(--line) inset;
}

.pc-ph { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; margin-bottom: 11px; }
.pc-n { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft); font-weight: 700; }
/* The nickname takes the rest of the row and prints on every line of that
   property's receipt, which is what makes a two-unit quote readable.
   The canonical control block at app density — docs/10-interface-standard.md
   §2, the same geometry .dl-r input carries. It shipped at 34px/13px in the
   first cut and the layout audit called it: 44px is the floor for a control
   EVERYWHERE, and a text field is the last place to argue about it. */
.pc-lab {
  flex: 1 1 170px; min-width: 0; min-height: var(--ctl-h); padding: var(--ctl-pad);
  font-size: var(--ctl-size); line-height: 1.25; background: var(--paper); color: var(--ink);
  border: none; border-radius: var(--ctl-r); box-shadow: 0 0 0 1px var(--line) inset; outline: none;
  transition: box-shadow var(--dur-2) var(--ease);
}
.pc-lab::placeholder { color: var(--ink-soft); opacity: .6; }
.pc-lab:focus { outline: 2px solid var(--brass); outline-offset: 2px; }
/* A 44px hit area around a 13px glyph. `.dl-ic` is 24px, which is right for a
   row of them that only appears on hover; this one removes a property and has
   to be hittable with a thumb. */
.pc-x { opacity: .5; flex: none; width: var(--ctl-h); height: var(--ctl-h); border-radius: 10px; }
.pc-p:hover .pc-x { opacity: .75; }

/* A segmented control, not three buttons in a row. 44px inside a 2px frame,
   so it stands the same height as the field beside it — the standard's other
   half: a control that is a hair taller than its neighbour is the defect that
   makes good work feel unfinished. */
.pc-types { display: flex; gap: 0; background: var(--paper); border-radius: 14px; padding: 2px; box-shadow: 0 0 0 1px var(--line) inset; }
.pc-t {
  border: 0; background: none; cursor: pointer; border-radius: 12px;
  min-height: var(--ctl-h); padding: 6px 14px; font-size: 13px; font-weight: 600;
  color: var(--ink-soft);
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.pc-t:hover { color: var(--ink); }
.pc-t.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(34, 26, 17, .12); }

/* ------------------------------------------------------------- steppers
   Two columns on a drawer that is 880px wide, one when it is not. The label
   and its stepper are one object, so they sit on one row with the number
   between the two buttons rather than beside them. */
/* auto-FILL, not auto-fit. With two primary room types and a 970px drawer,
   auto-fit collapses the empty tracks and stretches each row to 470px — which
   puts half a screen of nothing between "Bedrooms" and the stepper that
   answers it. Empty tracks keep every row the width it was designed at, so a
   card with two steppers reads the same as the one underneath it with ten. */
.pc-steps { display: grid; grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); gap: 6px 16px; }
/* Capped, and the cap is the point. A track wider than the pair needs pushes
   "Bedrooms" and the stepper that answers it to opposite ends of 380px, and
   they stop reading as one object — the same defect as an address row that
   says "View address" instead of the address. The grid may stretch; the pair
   may not. */
.pc-s { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 4px 0; min-height: 48px; max-width: 340px; }
.pc-sn { font-size: 13.5px; min-width: 0; }
.pc-sn small { display: block; font-size: 11.5px; color: var(--ink-soft); line-height: 1.35; margin-top: 1px; }
.pc-s.set .pc-sn { font-weight: 600; }

.pc-sc { flex: none; display: flex; align-items: center; gap: 2px; background: var(--paper); border-radius: 14px; padding: 2px; box-shadow: 0 0 0 1px var(--line) inset; }
/* 44px square, at every width. The first cut ran 30px on desktop with a
   comment arguing that a ± pair is not a field and that ten room types should
   not each carry a 100px slab. The layout audit disagreed forty times over,
   and the standard is not ambiguous: 44px is the floor for a control
   EVERYWHERE. The room the pair now needs is bought back in the column width
   above (272px), not out of the tap target. */
.pc-b {
  width: var(--ctl-h); height: var(--ctl-h); border: 0; background: none; border-radius: 12px;
  cursor: pointer; font-size: 15px; line-height: 1; color: var(--ink);
  display: grid; place-items: center;
  transition: background var(--dur-1) var(--ease);
}
.pc-b:hover:not([disabled]) { background: var(--sand-deep); }
.pc-b[disabled] { opacity: .3; cursor: default; }
.pc-b:focus-visible { outline: 2px solid var(--brass); outline-offset: 1px; }
.pc-v { min-width: 26px; text-align: center; font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }

.pc-more { margin-top: var(--sp-bound); border-top: 1px solid var(--line-2); padding-top: 8px; }
.pc-more summary { cursor: pointer; font-size: 12.5px; color: var(--ink-soft); list-style: none; padding: 3px 0; }
.pc-more summary::-webkit-details-marker { display: none; }
.pc-more summary::before { content: "+ "; color: var(--brass); font-weight: 700; }
.pc-more[open] summary::before { content: "− "; }
.pc-more summary:hover { color: var(--ink); }

/* --------------------------------------------------------------- add-ons */
.pc-adds { display: grid; grid-template-columns: repeat(auto-fill, minmax(238px, 1fr)); gap: 4px 14px; margin-top: var(--sp-bound); }
.pc-a {
  display: flex; align-items: center; gap: 9px; padding: 6px 8px; border-radius: 9px;
  cursor: pointer; font-size: 13px; min-height: 38px;
  transition: background var(--dur-1) var(--ease);
}
.pc-a:hover { background: var(--paper); }
.pc-a.on { background: var(--paper); }
.pc-a input { width: 17px; height: 17px; flex: none; accent-color: var(--brass); }
.pc-a span { min-width: 0; flex: 1; }
.pc-a small { display: block; font-size: 11.5px; color: var(--ink-soft); line-height: 1.35; }
.pc-a b { flex: none; font-size: 12.5px; font-weight: 600; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.pc-a.on b { color: var(--brass); }

.pc-add { margin-top: var(--sp-bound); }

/* ------------------------------------------------------- finish and speed */
.pc-levers { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: var(--sp-break); }
.pc-lev > label { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-soft); margin-bottom: 7px; }
.pc-opts { display: grid; gap: 6px; }
.pc-o {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px; width: 100%;
  text-align: left; cursor: pointer; border: 0; border-radius: 11px; padding: 10px 12px;
  background: var(--surface); box-shadow: 0 0 0 1px var(--line) inset; min-height: 44px;
  transition: box-shadow var(--dur-2) var(--ease), background var(--dur-1) var(--ease);
}
.pc-o:hover { box-shadow: 0 0 0 1px var(--brass) inset; }
.pc-o.on { box-shadow: 0 0 0 2px var(--brass) inset; background: var(--paper); }
.pc-o b { font-size: 13.5px; font-weight: 600; }
.pc-o span { font-size: 13px; color: var(--ink-soft); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pc-o.on span { color: var(--brass); font-weight: 600; }

/* ------------------------------------------------------------ the receipt
   Every lever gets a row, including the ones that cost nothing. A £0 delivery
   line is not noise — it is the buyer, or the founder, seeing that the lever
   exists and that the free end of it was chosen deliberately. */
.pc-rec {
  margin-top: var(--sp-break); background: var(--surface); border-radius: 12px;
  box-shadow: 0 0 0 1px var(--line) inset; padding: 6px 13px;
}
.pc-r { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 7px 0; font-size: 13px; }
.pc-r + .pc-r { border-top: 1px solid var(--line-2); }
.pc-r span { color: var(--ink); min-width: 0; }
.pc-r small { display: block; font-size: 11.5px; color: var(--ink-soft); margin-top: 1px; }
.pc-r b { flex: none; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pc-r.off, .pc-r.off b { color: var(--brass); }

.pc-note { margin-top: var(--sp-bound); font-size: 12.5px; line-height: 1.55; color: var(--ink-soft); max-width: 72ch; }
.pc-note b { color: var(--ink); }

@media (max-width: 620px) {
  /* One column of everything. The controls need no shrinking or growing here
     — they are already at the floor, which is the point of having one. */
  .pc-levers { grid-template-columns: 1fr; }
  .pc-steps, .pc-adds { grid-template-columns: 1fr; }
}

/* ================================================================= BLACK */

/* The strip in the composer. Onyx and brass, because it is the one thing on
   this form that is not admin — it is the membership showing up where it is
   worth money. */
.blkstrip {
  display: flex; align-items: flex-start; gap: 13px;
  background: var(--onyx); color: var(--paper);
  border-radius: 13px; padding: 13px 15px; margin: -4px 0 16px;
}
.blkstrip.warn { box-shadow: 0 0 0 1px rgba(140, 47, 47, .55) inset; }
.blkstrip.quiet { background: var(--sand); color: var(--ink); }

.bs-i { flex: none; width: 26px; height: 26px; border-radius: 999px; background: rgba(205, 160, 85, .18); display: grid; place-items: center; }
.bs-i svg { width: 13px; height: 13px; stroke: var(--brass-bright); fill: none; stroke-width: 1.8; }
.blkstrip.quiet .bs-i { background: rgba(34, 26, 17, .07); }
.blkstrip.quiet .bs-i svg { stroke: var(--brass); }

.bs-t { min-width: 0; flex: 1; }
.bs-t b { display: block; font-size: 14px; font-weight: 700; letter-spacing: -.01em; }
.bs-t span { display: block; font-size: 12.5px; line-height: 1.55; color: rgba(251, 248, 241, .66); margin-top: 3px; max-width: 62ch; }
.blkstrip.quiet .bs-t span { color: var(--ink-soft); }
.blkstrip.warn .bs-t b { color: var(--brass-bright); }

.bs-tog { flex: none; display: flex; align-items: center; gap: 7px; font-size: 12.5px; cursor: pointer; color: rgba(251, 248, 241, .8); }
.bs-tog input { width: 16px; height: 16px; accent-color: var(--brass); }

/* The card in the client drawer — the answer to "don't ask me to invite
   someone who is already a member". */
.blkcard {
  margin-top: 20px; border-radius: 14px; padding: 16px 18px 14px;
  background: var(--onyx); color: var(--paper);
}
.bc-h { display: flex; align-items: center; gap: 9px; font-size: 14.5px; }
.bc-h svg { width: 15px; height: 15px; stroke: var(--brass-bright); fill: none; stroke-width: 1.8; }
.bc-seat { font-family: var(--mono); font-size: 12px; color: var(--brass-bright); letter-spacing: .04em; }
.bc-h .tag { margin-left: auto; }
.bc-g { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin: 14px 0 10px; }
.bc-g span { display: block; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: rgba(251, 248, 241, .5); }
.bc-g b { display: block; font-size: 16px; font-weight: 700; margin-top: 3px; letter-spacing: -.015em; }
.bc-g b.warn { color: var(--brass-bright); }
.bc-s { font-size: 12.5px; line-height: 1.6; color: rgba(251, 248, 241, .66); max-width: 60ch; }
.bc-s b { color: var(--brass-bright); }

.blkpill {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px;
  border-radius: 999px; background: var(--sand-deep); font-size: 12.5px; color: var(--ink-soft);
}
.blkpill svg { width: 12px; height: 12px; stroke: var(--brass); fill: none; stroke-width: 1.8; }

/* The marker on a client row. Small, and it means something different in
   each colour — hover tells you which. */
/* A name and its marker are one object, so the badge is laid out WITH the name
   rather than dropped after it on a text-node space. `.nm-b` is what lists that
   know a client's standing render; the bare `.blkdot` below keeps working for
   the observer fallback on lists that don't. */
.nm-b { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.nm-b > span:first-child { min-width: 0; overflow-wrap: anywhere; }
.nm-b .blkdot { margin-left: 0; vertical-align: baseline; }
/* `vertical-align: middle` rather than a -3px nudge: the nudge was tuned to one
   font-size and sat off-baseline at every other. */
.blkdot { display: inline-grid; place-items: center; width: 17px; height: 17px; flex: none; border-radius: 999px; background: var(--onyx); vertical-align: middle; margin-left: 5px; }
.blkdot svg { width: 9px; height: 9px; stroke: var(--brass-bright); fill: none; stroke-width: 2.2; }
.blkdot.warn { background: var(--bad); }
.blkdot.warn svg { stroke: #fff; }
.blkdot.pend { background: var(--sand-deep); }
.blkdot.pend svg { stroke: var(--ink-soft); }
.blkdot.lapsed { background: var(--sand-deep); opacity: .6; }
.blkdot.lapsed svg { stroke: var(--ink-soft); }

/* The member line on a saved document, marked as what it is rather than
   left as an unexplained negative number. */
.items-t tr.blk-line td { color: var(--brass); }
/* CENTRED BY LAYOUT, NOT BY A MAGIC OFFSET.
   This was `vertical-align: -3px` — a hand-tuned nudge that is only correct at
   one font size, one line-height and one badge diameter, and the founder
   photographed it sitting low in the quote drawer. A number chosen by eye is a
   number that goes wrong the moment anything around it changes.
   The cell becomes a flex row instead, so the badge is centred against the
   text by the layout engine and stays centred at any size. `gap` replaces the
   margin for the same reason the `.tags` cluster uses one. */
/* AN ICON GUTTER, so the badge does not push its own row out of the column.
   Vertical centring was the first fix and it was only half the problem: with
   the badge inline, "LUMORIA Black member rate" started 21px further right
   than Clean, Bedrooms and Bathrooms above it, so the one row with a mark was
   the one row out of line. Every first cell now reserves the same gutter and
   the badge sits IN it, absolutely, which means the names align whether or not
   a row has a mark. Centred by translate against the cell's own middle, so it
   stays right at any font size — no offset to hand-tune. */
.items-t td:first-child { position: relative; padding-left: 21px; }
.blk-tick { position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 15px; height: 15px;
  border-radius: 999px; background: var(--onyx); }
.blk-tick svg { width: 8px; height: 8px; stroke: var(--brass-bright); fill: none; stroke-width: 2.2; }

/* ==================================================== the catalogue picker
   A sheet pinned to the bottom of the DRAWER — not to the form, and not
   inside `.drawer-b`, which scrolls and would clip it. documents.js appends
   it as a direct child of `.drawer` for exactly that reason.

   Inline was the old shape and the old problem: opening the picker pushed
   the totals and the notes field down the page, so the thing you were
   looking at moved the moment you reached for it. */
#docCat {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  background: var(--surface); border-top: 1px solid var(--line);
  border-radius: 16px 16px 0 0; box-shadow: 0 -20px 50px -28px rgba(34, 26, 17, .5);
  max-height: 66%; display: flex; flex-direction: column;
  transform: translateY(101%); transition: transform var(--dur-3) var(--ease-out);
  pointer-events: none; margin: 0; overflow: hidden;
}
#docCat.on { transform: none; pointer-events: auto; }
#docCat .cat-h { display: flex; gap: 8px; align-items: center; padding: 12px; border-bottom: 1px solid var(--line); flex: none; }
#docCat .cat-b { overflow-y: auto; flex: 1; }
#docCat .cat-f { flex: none; padding: 9px 13px; font-size: 12px; color: var(--ink-soft); border-top: 1px solid var(--line); background: var(--paper); }
#docCat .cat-none { padding: 22px 14px; font-size: 13.5px; color: var(--ink-soft); }
