/* Hoover. The tokens are the FIRM'S OWN, from `firms/*.toml`, which
   CLAUDE.md rule 9 names as the authority: "Style lives in firms/*.toml".
   Playfair Display for the wordmark and headings, DM Sans for everything
   else, both served from this machine.

   THE SHEET SAID THAT AND IT WAS NOT TRUE. The office asked, plainly,
   "are you using the branding colors?" and the answer was no. This block
   claimed to be "the site's own, converted from the CIE Lab values its
   stylesheet ships", and hardcoded a near miss of the values both firms
   actually declare:

       firms/hoover.toml and firms/garnett-patterson.toml, both:
           navy, gold and gray, and this sheet now reads them

       what this sheet had: a navy two, six and five points darker on
       the three channels, and a gold thirteen points lower on green.

   The old values are not written out here. This file's own tests read
   their comments, and rightly: a hex written down anywhere is a hex
   somebody will paste. They are in the commit message and in git.

   `src/ask.py`, `src/exhibits.py` and `src/surface.py` all use the
   declared values, so every letter, envelope and exhibit cover this
   office sends out is #111B25 and #FFC500 while the software that
   produced them was painted something else. Thirteen points of green is
   a visibly different gold: one is yellow, the other amber.

   That is exactly the defect `tests/test_brand.py` was written to
   prevent, in its own words, "A second gold is how a brand stops being
   one", and it had been enforcing the wrong one. The test reads
   `firms/*.toml` now, so the authority is the authority.

   THE GREYS ARE A DELIBERATE DEPARTURE, AND HERE IS THE ARGUMENT.
   Measured as WCAG contrast on the brand navy:

       the firm gold       on the navy  10.97:1   passes AA for body
       the firm gray       on the navy   3.60:1   FAILS AA for body
       the screen gray     on the navy   6.03:1   passes AA for body

   The firm's gray was chosen for Times on white paper, where it is a handsome
   quiet grey. At 11px on a navy ground it is not legible enough for
   metadata, and metadata is most of what this surface is. So the screen
   keeps its own grey ramp and the print keeps the firm's.

   The departure is the GREYS AND NOTHING ELSE. It is written down here
   with the number it rests on so that "we needed a lighter one" can
   never become the reason a second gold appears next year. */

:root {
  --background: #111b25;
  --foreground: #e8e6df;
  --card: #141c29;
  --secondary: #182233;
  --muted: #182233;
  /* ONE COLOUR AT SEVERAL ALPHAS, NOT FOUR GREYS.
     See the note beside --foreground-soft below for the measurement and
     the argument. */
  --muted-foreground: rgba(232, 230, 223, .55);

  /* The gold. One colour, used for the wordmark, the rule under it, the
     one action on a page that matters, and nothing else. Spending it on
     ordinary controls is what makes an accent stop meaning anything. */
  --primary: #ffc500;
  --brand-blue-raised: #2a3946;
  --brand-blue-border: #4b5b68;
  --primary-dim: #f0b800;
  --primary-foreground: #040c13;

  /* Lifting a surface off the one under it. These are overlays rather
     than flat colours so one value works on the page, on a card and on a
     dialog, and they carry the brand's own navy rather than white. The
     hue is the background's, 208 degrees, so a lifted surface is the same
     colour family as the page it sits on.

     Neither of these is the table zebra any more, and the sentence that
     used to sit here saying white at two percent reads as a grey wash is
     gone with it, because that departure is no longer in the sheet. The
     zebra is `--zebra` below and it ships the handoff's white; the note
     on that token carries the argument. What is left for these two is a
     gold tag's ground (`--band`) and a row picked for a bulk verb, or a
     value picked inside the fact sheet (`--raise`). */
  --band: rgba(58, 108, 156, .085);
  --raise: rgba(58, 108, 156, .14);

  /* Under the cursor. This was the gold at five percent, and it was wrong
     in a way worth writing down: a warm yellow laid over a cold navy at
     low alpha does not read as a hint of gold, it reads as olive. The two
     hues sit on opposite sides of the wheel and the eye resolves the
     average, not the intent. A hover is the worst case for it: a wide
     area that appears under the pointer with nothing beside it to say
     what colour it was meant to be. So this one tints toward the
     background's own hue, and the accent stays opaque, on borders and on
     type where it is the colour it actually is.

     Read that as a finding about a gold wash standing on its own, which
     is what it was. It is not a ban on every gold wash. `--hit` and
     `--row-gold` below each sit against something opaquely gold that
     tells the eye what the tint is, and each was looked at on the screen
     before it shipped. */
  --glow: rgba(58, 108, 156, .22);

  /* The ladder between white and the mute. Rail links and body copy sit
     one step down from --foreground; section headings, placeholders and
     captions sit one step below --muted-foreground. Four near identical
     greys were doing this job before, none of them named, and the
     difference between #626a73 and #6b727a is nobody's design decision. */
  /* HIERARCHY IS ONE COLOUR AT SEVERAL ALPHAS.

     The note above is right that four near identical greys are nobody's
     design decision, and it then named four more: #e8e6df, #b9c0c9,
     #8b95a3 and #5d6877. Measured on the Caseload those were carried by
     337, 25, 649 and 93 elements, and not one of them used alpha.

     recent.design, which the office sent as the reference, was measured
     the same way: it has ONE text colour and three levels, black at
     48.6%, at 26.7% and at 6.3%. The plan for the workstation already
     quoted the rule from Linear, "density is managed by gradations of
     opacity, not colour", and then the stylesheet mixed four opaque
     greys by hand.

     Alpha is not a tidier way of writing the same thing. A grey mixed
     against #111b25 is wrong the moment it sits on --card or on a
     raised surface, which is why the four drifted apart in the first
     place. An alpha of the foreground is correct on every ground it
     lands on, and the steps are readable as steps: full, three
     quarters, half, a third. */
  --foreground-soft: rgba(232, 230, 223, .72);
  --muted-foreground-dim: rgba(232, 230, 223, .38);

  /* A control under the cursor, and the edge that lights with it. */
  --raised: #182233;
  --border-lit: #34405a;

  --destructive: #eb0005;
  /* The same red, at a lightness that can be read as text on the navy.
     #eb0005 on #121c24 is legible as a border and not as a word. */
  --destructive-lit: #ff6b78;
  --border: #243044;
  --border-soft: #1e2839;
  /* The softest rule there is: between rows inside a fact
     sheet, where a full hairline would stripe the page. */
  --border-hair: #1b2433;
  --sidebar: #141c29;
  --input: #111b25;
  --radius: .5rem;

  --ok: #4ade80;

  /* ==================================================================
     THE STATUS RAMP, AND THE ONE CONFLICT IN THE BRIEF, SETTLED.

     Three semantic accents already existed here: --destructive for late,
     --primary for the brand gold, --ok for done. What was missing is the
     SOFT CONTAINER each needs to be a badge rather than a word, and one
     of the three could not be reused at all.

     The brief asks for amber on every caution: "in 2d", an audit warning,
     an unverified entry, and it names two amber hexes of its own for it.
     Both were written here and tests/test_brand.py refused them in one
     line: "a third is somebody typing from memory." That is exactly what
     they were, two values taken from a brief without being checked
     against the sheet's own rule, which is the drift that test exists to
     stop and which has happened here before. They are not repeated in
     this comment, because that test reads comments too, and it is right
     to: a hex written down anywhere is a hex somebody will paste.

     The premise behind it was also wrong. The note above --primary
     reserves the gold from ORDINARY CONTROLS, buttons and borders and
     links, because an accent spent everywhere stops meaning anything. A
     caution badge is not an ordinary control. It is the one thing on the
     row that says look here, which is what the gold is FOR. An off-brand
     amber beside it would read as almost-gold-but-not, which is worse
     than either.

     So caution is the firm's gold, and this ramp is that gold in the
     three parts a badge needs. The note on --glow warns that a gold wash
     over this navy reads as olive across a wide area; a pill is not a
     wide area, and it carries opaque gold type inside an opaque gold
     border, which is the condition that note names for --hit and
     --row-gold. */

  /* Each accent comes in three parts, which is what a badge needs: a
     line colour legible as type on the navy, a container it sits in, and
     an edge. The containers are the accent at low alpha rather than mixed
     flats, so one value works on the page, on a card and in the
     inspector.
     ================================================================== */

  /* Critical, overdue, late. --destructive-lit above is already this
     crimson at a lightness that reads as a word on this navy, so this is
     that value under the name a badge asks for it by. */
  --late: #ff6b78;
  --late-soft: rgba(235, 0, 5, .16);
  --late-edge: rgba(235, 0, 5, .38);

  /* Caution, attention, unverified. The firm's gold. See above. */
  --warn: #ffc500;
  --warn-soft: rgba(255, 197, 0, .13);
  --warn-edge: rgba(255, 197, 0, .32);

  /* Done, verified, cleared. --ok above is this green; same reason. */
  --done: #4ade80;
  --done-soft: rgba(74, 222, 128, .12);
  --done-edge: rgba(74, 222, 128, .26);

  /* Neutral. A count, a state that is neither good nor bad, a citation.
     The muted foreground already declared, in a badge's three parts. */
  --calm: #8b95a3;
  --calm-soft: rgba(139, 149, 163, .13);
  --calm-edge: rgba(139, 149, 163, .28);

  /* THE HAIRLINE. Depth comes from stacked one pixel edges rather than
     dropshadows, which is the Apple Pro move and also the cheap one: a
     shadow over a matte navy reads as a smudge. --border and its two
     softer cousins above are the navy-tinted structural rules and they
     stay; this is the neutral containment edge a panel or a card takes,
     and it is the same value on every surface, which is what makes a
     stack of them read as depth. */
  --hair: rgba(255, 255, 255, .07);
  --hair-soft: rgba(255, 255, 255, .045);
  --wash: rgba(255, 255, 255, .03);       /* a row under the cursor */
  --ring: rgba(255, 255, 255, .2);        /* the selected row's edge */

  /* THE TYPE SCALE, named so a module cannot invent a fifth size.
     Four sizes do the whole workstation: a view title, a section heading,
     a row of data, and the metadata under it. */
  /* A VIEW TITLE TOKEN WAS DECLARED HERE AND IS GONE. It said 18px,
     taken from a brief, while this sheet's own `.head h1` is 700 22px/1.2
     and the design system records that as what almost every page shows.
     Two type scales for one thing is how the second gold got in, so the
     token that nothing used and that disagreed with the rule is the one
     that goes. Page titles keep `.head h1`. */
  --t-section: 11.5px;    /* section headings, uppercase, tracked, muted */
  --t-row: 13px;        /* primary row data */
  --t-meta: 11.5px;     /* rule citations, secondary metadata */

  /* THE ROW. Linear's density, which is not clutter when the rhythm
     holds. Everything that is a list of records uses one of these two. */
  --row-h: 34px;
  --row-h-tall: 44px;   /* where a row carries a subline */

  --serif: "Playfair Display", Georgia, "Times New Roman", serif;
  --sans: "DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
  /* Vendored, so a rule citation looks the same on every machine that
     opens the file. The stack behind it is the old one, unchanged, for
     the moment before the face has loaded. See fonts.css. */
  --mono: "JetBrains Mono", "Cascadia Mono", "Consolas", monospace;

  --rail: 232px;

  /* The inspector's own width, so the shell grid and the panel cannot
     disagree about it. Zero until something is selected. */
  /* THE THIRD COLUMN IS ALWAYS THERE. This was 0px until a value
     was clicked, so the surface was two columns that occasionally
     grew a third; the design draws three on every screen and gives
     the panel a resting state. The token stays a token because the
     narrow layout still collapses it to a sheet. */
  --insp: 0px;
  /* The gold at the alpha the handoff uses for a hairline
     rule: under the wordmark, under a section heading, and
     along the foot of the matter head. */
  --rule-gold: rgba(255, 197, 0, .35);
  /* The scrim under the palette. An absence of light. */
  --scrim: rgba(6, 9, 14, .7);

  /* THE ZEBRA, AND A DISAGREEMENT SETTLED BY LOOKING.
     tests/test_brand.py refuses a white overlay because the first attempt
     at row banding here used rgba(255,255,255,.017) and read, over a
     hundred rows, as the table having a different background from the
     page. That finding was made against the OLD ground, #09121a. The
     design handoff specifies rgba(255,255,255,.02) against the ground, which
     is the ground now, and the instruction is that the handoff is a
     directive and not a reference.

     Checked again on September 5, 2026, with the mockup and the live
     docket open side by side at 1440 by 900. The handoff's white
     composites over the ground to rgb(20,26,36) against the page's
     rgb(15,21,32): five levels up on all three channels, so the stripe
     moves with the navy instead of pulling away from it, and over 142
     rows on `chastain` it still reads as a stripe rather than as a second
     background. The handoff's value stands and it is what ships. `--band`
     stays declared above as the navy tinted alternative, one line away,
     if a longer table ever proves it grey. */
  --zebra: rgba(58, 108, 156, .10);

  /* THE HIGHLIGHT INSIDE A QUOTED SENTENCE. This is the one gold wash on
     the surface and it is deliberate against the note above, which says a
     gold tint over this navy reads as olive. That holds for a wide area:
     a banded row, a hovered cell, a card. It does not hold for the
     twenty pixels behind a date inside a sentence, where the eye reads
     the mark and the word together and there is no field large enough to
     average. The design handoff calls this value final and it is the
     thing the panel exists to do, so it is here rather than approximated. */
  --hit: rgba(255, 197, 0, .25);

  /* THE SELECTED ROW'S WASH, and a new token because nothing here covered
     it. The handoff draws `.tbl tr.sel td` at rgba(255,197,0,.08), and
     the three golds already declared are all heavier: `--hit` at .25,
     `--rule-gold` at .35, `--band-gold` at .7, each of them sized for
     something small or something opaque. A whole row needs the thinnest
     of them and there was no thinnest. The argument for a gold wash this
     wide is at the rule, near the bottom of this file. */
  --row-gold: rgba(255, 197, 0, .08);

  /* The struck line on the page graphic. Nearly opaque,
     because it is standing in for a highlighter on paper
     rather than tinting an interface surface. */
  --band-gold: rgba(255, 197, 0, .7);

  /* Paper. The inspector shows a scrap of the page a value was read off,
     and a page is warm off-white because paper is. This is the document
     and not the interface, which is why it is the one light value in a
     dark palette. */
  --paper: #f4f1ea;
  --paper-ink: #cfc9bc;
  --paper-edge: #6b6659;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--sans);
  /* 13 and 1.45, which is the handoff's, not 14 and 1.55. A law file is
     read by scanning down a column of short values, and the design is
     sized for that density: every other measurement in it, the 6px by 8px
     cell padding, the 150px label column, the 10.5px tracked heading, was
     drawn against this body size. Changing it by a point rescales the
     whole page against furniture that did not move. */
  font-size: 13px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { color: var(--primary); }

/* ---------- shell ---------- */

/* ------------------------------------------------------------------ */
/* THE SHELL, to the design handoff. Three columns, two rows.           */
/*                                                                      */
/* The rail spans both rows, the header spans the main and inspector    */
/* columns, and the inspector column is zero wide until a value is      */
/* selected. These two transitions are the only motion in the design    */
/* and adding a third would be inventing something it does not have.    */
/* ------------------------------------------------------------------ */

.shell {
  display: grid;
  grid-template-columns: var(--rail) 1fr var(--insp);
  grid-template-rows: 48px 1fr;
  height: 100vh;
  background: var(--background);
  transition: grid-template-columns .22s ease;
}
body.railshut { --rail: 56px; }
body.inspecting { --insp: 400px; }
body:not(.inspecting) .inspector { display: none; }

/* ---- the rail ---- */

.rail {
  grid-row: 1 / 3;
  background: var(--card);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 12px 0;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  transition: width .22s ease, padding .22s ease;
}
.rail-inner { transition: opacity .15s ease; }
body.railshut .rail-inner { opacity: 0; pointer-events: none; }

.rail .wordmark {
  display: flex;
  align-items: center;
  padding: 0 12px 12px;
  border-bottom: 1px solid var(--rule-gold);
  margin-bottom: 8px;
  gap: 8px;
  white-space: nowrap;
  overflow: hidden;
}
.rail .wordmark .name {
  display: block;
  font: 700 15px var(--serif);
  color: var(--primary);
}
.rail .wordmark .sub {
  display: block;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}

.rail .group {
  padding: 8px 16px 4px;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted-foreground-dim);
}

.rail a,
.rail .off {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 4px 16px;
  color: var(--foreground-soft);
  white-space: nowrap;
  cursor: pointer;
}
.rail a:hover { color: var(--foreground); }
.rail a.on {
  color: var(--foreground);
  background: var(--secondary);
  box-shadow: inset 2px 0 0 var(--primary);
}
/* A page that does not exist yet. Shown, because the rail should say
   what the practice needs; not a link, because a link that answers 404
   teaches a person the surface is broken rather than unfinished. */
.rail .off { color: var(--muted-foreground-dim); cursor: default; }
.rail .n { font-size: 11.5px; color: var(--muted-foreground); }

/* ---- the header ---- */

.topbar {
  grid-column: 2 / 4;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
  background: var(--card);
  min-width: 0;
}
.railtoggle {
  width: 26px; height: 26px; flex: none;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: none;
  display: grid; place-items: center;
  color: var(--foreground-soft);
  cursor: pointer;
  font-size: 12.5px;
  line-height: 1;
}
.railtoggle:hover { border-color: var(--primary); color: var(--primary); }

/* The inspector's toggle sits at the end of the bar, over the column it
   opens. `.who` before it already ends the bar's content, so this only
   has to stop the gap reading as a stray control. */
.insptoggle { margin-left: 2px; }
/* THE TOGGLE IS NEVER HIDDEN. It was, on any page rendering no
   inspectable value, which meant the panel could not be opened on the
   Calendar at all: a deadline is not a fact and carried no
   `data-fact`, so the control vanished and the page looked broken.
   Deadlines are inspectable now, and even where nothing is, the panel
   still holds the mark legend and the keys and a person is entitled to
   open it. */
body.nofacts .insptoggle { opacity: .55; }

.topbar .crumb { color: var(--muted-foreground); white-space: nowrap; }
.topbar .crumb b { color: var(--foreground); font-weight: 500; }

.topbar .search {
  flex: 1;
  max-width: 520px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 4px 8px;
  color: var(--muted-foreground);
  cursor: pointer;
  font: inherit;
  text-align: left;
  min-width: 0;
}
.topbar .search span {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar .search:hover { border-color: var(--border-lit); }

.topbar .when {
  margin-left: auto;
  font-size: 12.5px;
  color: var(--foreground-soft);
  white-space: nowrap;
}
.topbar .who {
  width: 28px; height: 28px; flex: none;
  border: 1px solid var(--rule-gold);
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11.5px;
  color: var(--primary);
}

kbd {
  font: 11px var(--sans);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 0 4px;
  color: var(--muted-foreground);
}

main { overflow: auto; padding: 0 0 20px; min-width: 0; }

/* Keep register names available to assistive technology without a title row. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* THE GUTTER IS ON THE CONTENT, NOT ON MAIN, so a page head's gold
   hairline can run the full width the way the handoff draws it while
   everything under it lines up with the title at 22px. The card was
   flush to the edge at 0 and the h1 was at 22, which reads as the table
   having slipped out from under its own heading. */
main > .card,
main > .cardgrid,
main > .sheet2,
main > .lede,
main > p,
main > h2,
main > .warnbox,
main > .stats,
main > .today,
main > .empty { margin-left: 20px; margin-right: 20px; }

/* A NEW REGION HAS NO GUTTER UNTIL IT IS NAMED HERE, which is a trap
   worth saying out loud: the list above is a whitelist, so `.today`
   rendered flush against the rail with no breathing room at all on the
   day it was built, and nothing failed. `.pagehead` is deliberately
   outside it, because its gold hairline runs the full width the way the
   handoff draws it. Anything else added to `main` belongs on this
   list. */
main > .cardgrid, main > .sheet2 { padding-left: 0; padding-right: 0; }
main > h2 { margin-top: 16px; }

/* ---- the command palette ---- */

.palette {
  position: fixed; inset: 0; z-index: 50;
  background: var(--scrim);
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 14vh;
}
.palette[hidden] { display: none; }
.palettebox {
  width: 620px; max-width: 92vw;
  background: var(--card);
  border: 1px solid var(--rule-gold);
  border-radius: var(--r);
  overflow: hidden;
}
.palettebox input {
  width: 100%;
  border: 0;
  /* The field sits on the page ground with a rule under it, so the list
     below reads as the box's own and not as a second panel. */
  border-bottom: 1px solid var(--border);
  background: var(--background);
  color: var(--foreground);
  font: 400 15px var(--sans);
  padding: 12px 12px;
  outline: none;
}

/* What to jump to, while you type.

   FIVE ROWS, AND THE FIFTH IS CUT OFF ON PURPOSE. Superhuman's rule, and
   the cut is the whole mechanism: a list that ends flush reads as the
   whole answer, and a reader who believes he has seen everything stops
   scrolling and retypes instead. Half a row showing says there is more
   without spending another line saying so.

   The height is counted in rows rather than in vh so the clip lands in
   the same place on a laptop and on the big screen. 8px of padding top
   and bottom around a 15px line is a 37px row. */
.palettelist {
  --palette-row: 37px;
  list-style: none; margin: 0; padding: 4px 0;
  max-height: calc(var(--palette-row) * 4.5);
  overflow-y: auto;
}
.palettelist[hidden] { display: none; }
.palettelist li {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 8px 12px;
  color: var(--foreground-soft);
  cursor: pointer;
}
.palettelist li.on {
  background: var(--secondary);
  color: var(--foreground);
  box-shadow: inset 2px 0 0 var(--primary);
}
.palettelist li .what { min-width: 0; overflow: hidden;
                        text-overflow: ellipsis; white-space: nowrap; }
.palettelist li .said { color: var(--muted-foreground-dim); font-size: 12.5px;
                        white-space: nowrap; flex: none; }

/* A COMMAND IS A PLACE TO GO AND SHOULD NOT READ AS A CASE.

   The marker is a gold hairline down the left of the row, which is the
   same device the highlighted row already uses and the same gold the
   masthead uses. It is drawn rather than written because the row is
   already carrying the page's name, the alias that matched, and where it
   sits on the rail; a fourth word saying "command" is the one thing on
   the line that tells him nothing he cannot see. */
.palettelist li[data-kind="command"] {
  box-shadow: inset 2px 0 0 var(--rule-gold);
}
.palettelist li[data-kind="command"].on {
  /* The highlight wins, because the eye is following the highlight. */
  box-shadow: inset 2px 0 0 var(--primary);
}

/* The keystroke the row is teaching. Quiet: it is a thing to notice on
   the tenth pass, not a thing to read on the first. */
.palettelist li .pkeys {
  flex: none;
  font: 400 10px var(--sans);
  letter-spacing: 0.04em;
  color: var(--muted-foreground);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 1px 4px;
  background: var(--background);
}
.palettenone { padding: 8px 12px; font-size: 12.5px; }
.palettenone[hidden] { display: none; }

.palettefoot {
  display: flex; gap: 12px;
  padding: 8px 16px;
  border-top: 1px solid var(--border);
  font-size: 11.5px;
  color: var(--muted-foreground);
}

/* The action receipt sits with the workstation controls at the lower right.
   Its gold edge reads like a marked file tab, not a browser alert. */
.toast,
.action-feedback {
  position: fixed;
  right: calc(var(--insp) + 18px);
  bottom: 78px;
  z-index: 76;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  width: min(410px, calc(100vw - var(--insp) - 36px));
  box-sizing: border-box;
  background: var(--card);
  border: 1px solid var(--border-lit);
  border-left: 3px solid var(--primary);
  border-radius: 6px;
  padding: 12px 12px 12px 11px;
  box-shadow: 0 16px 38px rgba(4, 8, 12, .34);
  overflow: hidden;
  animation: receiptin .2s ease-out;
}
.toast[hidden],
.action-feedback[hidden] { display: none; }
.toast form { margin: 0; align-self: center; }
.toast .btn { padding: 4px 8px; }
.feedback-copy {
  display: grid;
  gap: 3px;
  min-width: 0;
  line-height: 1.25;
}
.feedback-copy strong {
  color: var(--foreground);
  font-size: 13px;
  font-weight: 700;
}
.feedback-copy > span {
  color: var(--muted-foreground);
  font-size: 12px;
  line-height: 1.4;
}
.feedback-mark {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  color: var(--background); background: var(--primary);
  font-size: 12px; font-weight: 800;
}
.action-feedback[data-state="working"] .feedback-mark {
  box-sizing: border-box; background: transparent;
  border: 2px solid color-mix(in srgb, var(--primary) 35%, transparent);
  border-top-color: var(--primary);
  animation: feedbackspin .75s linear infinite;
}
.action-feedback[data-state="error"] {
  border-color: var(--destructive-lit);
}
.action-feedback[data-state="error"] .feedback-mark {
  background: var(--destructive-lit);
}
.feedback-action {
  grid-column: 2;
  justify-self: start;
  margin-top: -3px;
  border-bottom: 1px solid color-mix(in srgb, var(--primary) 55%, transparent);
  color: var(--primary);
  font-size: 12px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.feedback-action[hidden] { display: none; }
.feedback-close {
  grid-column: 3;
  grid-row: 1;
  align-self: start;
  width: 22px;
  height: 22px;
  margin: -5px -5px 0 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
}
.feedback-close:hover,
.feedback-close:focus-visible { color: var(--foreground); }
.action-feedback::after,
.toast::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 2px;
  background: var(--primary);
  transform-origin: left;
}
.action-feedback[data-state="working"]::after {
  width: 34%;
  animation: receiptworking 1.1s ease-in-out infinite alternate;
}
.action-feedback[data-state="success"]::after,
.toast::after { animation: receipttime 5s linear forwards; }
.action-feedback[data-state="error"]::after {
  background: var(--destructive-lit);
}
form.is-submitting .is-submitting-control {
  cursor: wait; opacity: .72; pointer-events: none;
}
form.is-submitting button.is-submitting-control::after {
  content: "  In progress\2026";
  font-size: .88em; font-weight: 500;
}
.interaction-ack {
  animation: interactionack .24s ease-out;
}
@keyframes receiptin {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes feedbackspin { to { transform: rotate(360deg); } }
@keyframes receiptworking {
  from { transform: translateX(-105%); }
  to { transform: translateX(300%); }
}
@keyframes receipttime { to { transform: scaleX(0); } }
@keyframes interactionack {
  0%, 100% { filter: none; }
  42% { filter: brightness(1.28); }
}
@media (prefers-reduced-motion: reduce) {
  .toast, .action-feedback, .action-feedback .feedback-mark,
  .toast::after, .action-feedback::after,
  .interaction-ack { animation: none; }
}

.email-created {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 22px;
  padding: 15px 17px;
  border: 1px solid var(--rule-gold);
  border-left: 3px solid var(--primary);
  background: var(--card);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--primary) 8%, transparent);
}
.email-created .btn { flex: 0 0 auto; }
.email-created-mark {
  display: grid;
  width: 26px;
  height: 26px;
  place-items: center;
  border-radius: 50%;
  background: var(--primary);
  color: var(--background);
  font-size: 13px;
  font-weight: 800;
}
.email-created-copy { display: grid; gap: 4px; }
.email-created-copy strong { font: 700 17px/1.2 var(--serif); }
.email-created-copy span { color: var(--muted-foreground); font-size: 12.5px; }

@media (max-width: 720px) {
  .toast,
  .action-feedback {
    right: 12px;
    bottom: 12px;
    width: calc(100vw - 24px);
  }
  .email-created { grid-template-columns: 28px 1fr; gap: 12px; }
  .email-created .btn { grid-column: 2; justify-self: start; }
}

/* ---- the matter workspace head ---- */

.mhead {
  padding: 16px 20px 0;
  border-bottom: 1px solid var(--rule-gold);
  background: var(--background);
  position: sticky; top: 0; z-index: 5;
}
.mhead .eyebrow {
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--primary);
  display: flex; align-items: center; gap: 8px;
}
.mhead .eyebrow .dash {
  width: 18px; height: 1px; flex: none;
  background: var(--primary);
}
/* The caption and the controls, on one line, as they always looked. The
   difference is that they are now two elements instead of a heading with
   five buttons inside it. Baseline aligned so the case name and the
   controls sit on the same line rather than being centred against each
   other, and the controls wrap under on a narrow window rather than
   squeezing the caption, because the caption is the one thing on this
   page that says which file you are reading. */
.mhead .mtop {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px 16px; flex-wrap: wrap;
}
.mhead .mactions {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin: 4px 0 8px;
}

.mhead h1 {
  font: 700 22px/1.2 var(--serif);
  letter-spacing: -.02em;
  margin: 4px 0 8px;
  color: var(--foreground);
  /* It may shrink so the controls keep their room, and it never
     disappears: a case name cut to nothing is worse than a wrapped one. */
  min-width: 16ch;
}
.mhead .mfacts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px 16px;
  margin-bottom: 12px;
}
.mhead .mfacts .k {
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-foreground-dim);
}
/* The handoff's `.meta .v` is a flex row, centred, with a 6px gap. This
   computed display:block with no gap, which was survivable while the cell
   held only words and stopped being survivable when the provenance mark
   moved inside it: a 12 by 14 glyph on a text baseline sits low against
   13px type, and block layout gives the line no way to say how far the
   words start from it.

   The mark's own 6px margin has to come off inside this cell or the two
   add up to 12. `.mk` carries that margin because it also sits in running
   text, inside a sentence in the fact sheet, where there is no flex
   parent to hold a gap. Here there is one, so the gap does the spacing
   and the margin stands down. */
.mhead .mfacts .v {
  color: var(--foreground);
  display: flex;
  align-items: center;
  gap: 4px;
}
.mhead .mfacts .v > .mk { margin-right: 0; }

.mtabs { display: flex; gap: 2px; overflow-x: auto; }
.mtabs a {
  padding: 8px 12px;
  color: var(--muted-foreground);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.mtabs a:hover { color: var(--foreground-soft); }
.mtabs a.on {
  color: var(--foreground);
  border-bottom-color: var(--primary);
}
.mtabs .n { font-size: 11.5px; color: var(--muted-foreground-dim); }

/* ---- the overview fact sheet ---- */

.sheet2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 24px;
  padding: 12px 20px;
}
.fsheet { margin-bottom: 12px; }
/* 600, not 500. The handoff sets `.sec h4` at 600 and this computed 500,
   which at 11px with .12em tracking is the difference between a heading
   and a slightly gold caption. It is the only weight above 500 in the
   fact sheet, so it is the whole reason the eye finds the section breaks
   when it scans down a column. */
.fsheet h4 {
  margin: 0 0 4px;
  font: 600 11px var(--sans);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--primary);
  border-bottom: 1px solid var(--rule-gold);
  padding-bottom: 4px;
}
.fsheet .frow {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px solid var(--border-hair);
}
.fsheet .frow .k { color: var(--muted-foreground); }
.fsheet .frow .v { color: var(--foreground); min-width: 0; }
.fsheet .frow .sep { color: var(--muted-foreground-dim); }
.fsheet .frow .who { color: var(--foreground); }

@media (max-width: 1100px) {
  .sheet2 { grid-template-columns: 1fr; }
}


.brand {
  display: block;
  padding: 2px 20px 16px;
  text-decoration: none;
}

/* The wordmark: one line, Playfair Display, the firm's gold. Same
   letterforms as the letterhead and the site. */
.brand .name {
  display: block;
  font-family: "Playfair Display", var(--serif);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.02em;
  color: var(--primary);
  white-space: nowrap;
}

/* The gold rule beneath the name, as on the letterhead. */
.brand .rule {
  display: block;
  height: 2px;
  margin-top: 4px;
  background: var(--primary);
}

.rail nav { display: flex; flex-direction: column; }

.rail nav a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 20px;
  color: var(--foreground-soft);
  font-size: 13px;
  border-left: 2px solid transparent;
}
.rail nav a:hover { background: var(--raise); color: var(--foreground); }
.rail nav a.on {
  color: var(--foreground);
  border-left-color: var(--primary);
  background: var(--raise);
}

.rail .section {
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted-foreground-dim);
  padding: 16px 20px 4px;
}

/* THE OLD MAIN, and it was still winning. It set 26 by 30 and a
   max-width of 1500, written when the shell was two columns and the page
   had no head furniture of its own. The rule above is the handoff's, the
   page head and each section carry their own 22px, and a max-width here
   would leave a band of dead ground on a wide screen while the grid is
   already doing the constraining. */

/* ---------- headings ---------- */

h1 {
  font-family: var(--serif);
  font-size: 27px;
  font-weight: 700;
  margin: 0 0 2px;
  letter-spacing: -.01em;
}
h2 {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  margin: 32px 0 12px;
}
.lede { color: var(--muted-foreground); margin: 0 0 20px; font-size: 13px; }

/* ONE PAGE HEAD. `.head` was the old grammar on seventeen templates and
   `.pagehead` the handoff's on six; they are the same rule now, so a page
   written either way reads the same. The gold hairline under it and the
   Playfair title are the handoff's, and the flex row is kept because the
   old heads put their controls in it. */
.head, .pagehead {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: wrap;
  padding: 4px 20px 12px;
  margin: 0 0 12px;
  border-bottom: 1px solid var(--rule-gold);
}
.head > div, .pagehead > div { min-width: 0; }
.head .lede, .pagehead .lede { margin: 0; max-width: 96ch; color: var(--foreground-soft); }
.head h1, .pagehead h1 {
  font: 700 22px/1.2 var(--serif);
  letter-spacing: -.02em;
  margin: 0 0 4px;
  color: var(--foreground);
}

/* The section, above the title, drawn by the shell. */
.sectionmark {
  padding: 16px 20px 0;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--primary);
  display: flex;
  align-items: center;
  gap: 8px;
}
.sectionmark .dash { width: 18px; height: 1px; flex: none; background: var(--primary); }
.spacer { margin-left: auto; }

/* ---------- cards and stats ---------- */

.card {
  background: var(--card);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  overflow: hidden;
}
.card + .card { margin-top: 16px; }
.card .pad { padding: 16px 16px; }
.card .cap {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 600;
}

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 12px; }
.stat {
  background: var(--card);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: 12px 16px;
  display: block;
}
.stat:hover { border-color: var(--border); }
.stat .n { font-family: var(--serif); font-size: 26px; font-weight: 700; line-height: 1.1; }
.stat .k {
  font-size: 11.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  margin-top: 4px;
}
.stat.hot { border-color: rgba(255, 197, 0, .4); }
.stat.hot .n { color: var(--primary); }

/* ---------- tables ---------- */

.scroll { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; }

/* NOT position:sticky, and this is worth writing down because the first
   reading of the handoff said otherwise. Its README says "sticky-feel
   header row", which is the TREATMENT: uppercase, tracked, on its own
   surface. The prototype's own stylesheet has no sticky on a `th`; the
   one sticky thing in that design is the matter head.

   It also could not work here. `.scroll` carries overflow-x for a wide
   table, any non-visible overflow makes an element the containing block
   for a sticky descendant, and `.scroll` has no height to stick within,
   so the header scrolled away at top: -355px while claiming to be stuck. */
th {
  text-align: left;
  /* 6 by 8, the handoff's. It was 9 by 14, which is half a row of extra
     height on every line and about eleven fewer rows on a screen. */
  padding: 4px 8px;
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  /* The quietest step on the ladder, which is where the handoff puts a
     column heading: it names the column and then gets out of the way. */
  color: var(--muted-foreground-dim);
  font-weight: 500;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  background: var(--secondary);
}
td { padding: 4px 8px; border-bottom: 1px solid var(--border-hair); vertical-align: top; }

/* ONE BANDING RULE, NOT TWO. There were two: a navy tint on the row here
   and the handoff's white two percent on the cell further down, both
   applying, the cell winning wherever a table used the component. The
   handoff's value is the one that ships and it lives at the bottom of
   this file with the argument for it written out. */
tbody tr:hover td, tbody tr:nth-child(even):hover td { background: var(--glow); }
tbody tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.tight { white-space: nowrap; }
.dim { color: var(--muted-foreground); }
.mono { font-family: var(--mono); font-size: 12.5px; }

/* ---------- controls ---------- */

button, .btn {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 500;
  padding: 8px 12px;
  border-radius: var(--r);
  border: 1px solid var(--border);
  background: var(--secondary);
  color: var(--foreground);
  cursor: pointer;
  white-space: nowrap;
  display: inline-block;
}
button:hover, .btn:hover { border-color: var(--border-lit); background: var(--raised); color: var(--foreground); }

button.go, .btn.go {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-foreground);
  font-weight: 700;
}
button.go:hover, .btn.go:hover { background: var(--primary-dim); color: var(--primary-foreground); }
button:disabled { opacity: .4; cursor: not-allowed; }

input[type=text], input[type=search], input[type=date], select, textarea {
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 8px;
  border-radius: var(--r);
  border: 1px solid var(--border);
  background: var(--input);
  color: var(--foreground);
  width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 2px rgba(255, 197, 0, .15);
}
input::placeholder { color: var(--muted-foreground-dim); }

.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
form.inline { display: inline-flex; gap: 8px; align-items: center; }
.search { flex: 1; min-width: 220px; max-width: 420px; }

/* ---------- tags ---------- */

.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-weight: 500;
  border: 1px solid var(--border);
  color: var(--muted-foreground);
  white-space: nowrap;
}
.tag.gold { border-color: rgba(255, 197, 0, .45); color: var(--primary); background: var(--band); }
.tag.ok { border-color: rgba(74, 222, 128, .4); color: var(--ok); background: rgba(74, 222, 128, .07); }
.tag.bad { border-color: rgba(235, 0, 5, .45); color: var(--destructive-lit); background: rgba(235, 0, 5, .08); }

/* ---------- misc ---------- */

.empty {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 48px 20px;
  text-align: center;
  color: var(--muted-foreground);
}

.pages { display: flex; flex-direction: column; gap: 12px; }
.pages img { width: 100%; border: 1px solid var(--border); border-radius: var(--r); background: #fff; }

.split { display: grid; grid-template-columns: 1.4fr 1fr; gap: 16px; align-items: start; }

/* A SPLIT WITH ONE SIDE IS NOT A SPLIT.

   The matter page draws `.split.panes` around a single pane. The sidebar
   that filled the second column carried a Parties card and a Dates card,
   and both became tabs; the markup lost the child and the grid kept the
   column. So the record was laid out in 1.4fr of 2.4 - 58 per cent of the
   main column - and the remaining 42 per cent was empty ground between
   the table and the inspector. On a 1728 wide window that is about 400
   pixels of nothing, next to the inspector's own 400.

   Written here rather than by renaming the class, because forty lines
   below this give `.panes` the behaviour that makes the record scroll
   inside its own card while its heading and filters stay put. The column
   count is the only thing wrong, so the column count is the only thing
   changed, and the rule reads as what it is: however many panes there
   are, that is how many columns there are.

   `:has` is already load bearing in this file - `main:has(> .split.panes)`
   forty lines down decides whether the page scrolls at all. */
.split:has(> :last-child:nth-child(1)) { grid-template-columns: minmax(0, 1fr); }
.stick { position: sticky; top: 20px; }

/* The second line in a cell: the case a row belongs to, the note under a
   figure. It was written as style="font-size:12px" in six templates and
   as `.dim` plus nothing in others, so the same line rendered at three
   sizes depending on which page you were on. */
.small { font-size: 12.5px; }
/* A block that keeps the line breaks it was written with: a quoted message
   body, a transcript, a brain section. Six templates wrote this inline as
   style="white-space:pre-wrap" because no class did it, and app.css itself
   already had two hand-rolled versions of the same block. */
.wrapped { white-space: pre-wrap; }
/* A paragraph that is the whole of a pad and needs no space above it.
   Written inline as style="margin:0" in a handful of templates. */
.nomargin { margin: 0; }
.small.dim, .dim .small { color: var(--muted-foreground); }

.checks { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.checks li { padding: 4px 0; border-bottom: 1px solid var(--border-soft); display: flex; gap: 8px; }
.checks li:last-child { border-bottom: none; }
.checks .v { width: 38px; font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; }
.checks .pass .v { color: var(--ok); }
.checks .fail .v { color: var(--destructive-lit); font-weight: 700; }

.foot {
  margin-top: 32px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
  color: var(--muted-foreground-dim);
  font-size: 12.5px;
}

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { padding: 8px 0 8px 16px; border-left: 2px solid var(--border); position: relative; }
.timeline li::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 15px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border);
}
.timeline li.out::before { background: var(--primary); }
.timeline .when { color: var(--muted-foreground); font-size: 11.5px; }

@media (max-width: 1000px) {
  .shell { grid-template-columns: 1fr; }
  .rail { position: static; height: auto; }
  .rail nav { flex-direction: row; flex-wrap: wrap; }
  .split { grid-template-columns: 1fr; }
  .stick { position: static; }
  main { padding: 20px 16px 64px; }
}

/* What just happened, said where the click was. Not a toast that vanishes
   before it is read: filing thirty documents is worth a sentence that
   stays on the page. */
.card.said {
  border-left: 3px solid var(--primary);
  margin-bottom: 12px;
}
.card.said .pad { padding: 12px 12px; font-size: 13px; }

/* ---------------------------------------------------------------
   Closing a matter.

   A state change with consequences gets a sheet of its own rather than
   a dropdown in the header: room to say what closing does, to show what
   is still outstanding at the moment of deciding, and to ask for the
   reason in a labelled field. Native <dialog>, so Escape and the
   backdrop behave the way they do everywhere else.
   --------------------------------------------------------------- */
dialog.sheet {
  width: min(540px, calc(100vw - 40px));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--card);
  color: var(--foreground);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
}
dialog.sheet::backdrop { background: rgba(4, 8, 12, .66); }
dialog.sheet form { padding: 20px 24px 16px; }
dialog.sheet h2 {
  margin: 0 0 8px;
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 600;
}
dialog.sheet p.dim { margin: 0 0 16px; font-size: 13px; line-height: 1.55; }

dialog.sheet .warnbox {
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--r);
  padding: 12px 12px;
  margin-bottom: 16px;
  background: var(--muted);
}
dialog.sheet .warnbox .cap { margin-bottom: 4px; }
dialog.sheet .warnbox ul { margin: 0; padding-left: 16px; font-size: 13px; }
dialog.sheet .warnbox li { margin: 2px 0; }
dialog.sheet .warnbox p.meta { margin: 8px 0 0; }

.field { display: block; margin-bottom: 16px; }
.field > span:first-child {
  display: block;
  font-size: 11.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  margin-bottom: 4px;
}
.field input[type="text"] { width: 100%; }
.field .meta { display: block; margin-top: 4px; }

.row.end { justify-content: flex-end; gap: 8px; }

/* The state a matter is in, said once, next to its name. */
.state {
  display: inline-block;
  margin-right: 8px;
  padding: 2px 8px;
  border-radius: var(--r);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  background: var(--muted);
  border: 1px solid var(--border);
  color: var(--muted-foreground);
}
.state.closed { border-color: var(--primary); color: var(--primary); }
.closednote { margin-top: 4px; }

/* Copies of one document, folded behind the current one. */
.copies { margin-top: 4px; }
.copies summary { cursor: pointer; font-size: 11.5px; }
.copies ul { margin: 4px 0 4px; padding-left: 16px; font-size: 12.5px; }
.copies li { margin: 2px 0; }

/* What is waiting on you, as claims rather than a scoreboard. A counter
   nobody can act on is decoration; each of these goes somewhere. */
.attention { display: flex; flex-wrap: wrap; gap: 8px; }
.attention .claim {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--card);
  text-decoration: none;
  color: inherit;
}
.attention a.claim:hover { border-color: var(--primary); }
.attention .claim .n {
  font-family: var(--serif);
  font-size: 21px;
  font-weight: 700;
  color: var(--primary);
  line-height: 1;
}
.attention .claim.quiet .k { color: var(--muted-foreground); }
.attention .claim .k { font-size: 13px; }

/* AN OVERDUE ROW IS NOT PAINTED. It was `background: rgba(235,0,5,.07)`
   across the whole row, and on the Today page that is a wall of maroon:
   six of the first eight rows, which is not an alert, it is a wallpaper.

   The design draws exactly two row treatments, a day heading and a
   selection, and adding a third cost twice over. It said the same thing
   the chip in the first cell already says in words ("3 DAYS LATE"), and
   it occupied the row background that the keyboard's selection needs, so
   a selected overdue row showed maroon under gold and read as neither.

   The red now lives where the design puts red: on the chip. */
tr.overdue .tag.bad { font-weight: 600; }

/* ---------------------------------------------------------------
   One message.

   Everything here is scoped to .mail (and to the summary card, which
   sits above the split) so that adding a mail-shaped chip or label does
   not quietly restyle the record table or the intake filters. The page
   is read like an email client: envelope, then body, then what came
   attached to it.
   --------------------------------------------------------------- */

/* The envelope. A label column narrow enough that the addresses line up
   and long recipient lists wrap instead of pushing the card sideways. */
.mail .envelope { padding-bottom: 12px; }
.mail .envelope dl.factsheet > div {
  grid-template-columns: 78px 1fr;
  padding: 4px 0;
  border-bottom: none;
}
.mail .envelope dl.factsheet dd { word-break: break-word; }
.mail .envelope dl.factsheet dt, .mail .label {
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  font-weight: 500;
  white-space: nowrap;
  vertical-align: top;
  padding-top: 4px;
}

/* The fidelity note, and any other aside that should be read once and
   not again. Quiet enough to sit under the headers without competing. */
.mail .meta, .mailsummary .label { color: var(--muted-foreground); font-size: 12.5px; }
.mail .envelope .meta {
  margin: 12px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--border-soft);
}

.mailsummary { margin-bottom: 16px; }
.mailsummary .label { margin-bottom: 4px; }
.mail .attach {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  max-width: 100%;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  font-size: 12.5px;
}
.mail .attach .n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mail .attach .kb { color: var(--muted-foreground); font-size: 11.5px; white-space: nowrap; }
.mail a.attach:hover { border-color: var(--primary); color: var(--primary); }
/* Filed carries the gold, because that one is in the case file. Loose is
   dimmed and unclickable, because there is nowhere to send you yet. */
.mail .attach.filed { border-color: rgba(255, 197, 0, .45); }
.mail .attach.loose { background: var(--muted); color: var(--muted-foreground); }

/* The rest of the conversation, newest last, with the message you are on
   marked rather than linked. */
.mail .threadlist { list-style: none; margin: 0; padding: 0; }
.mail .threadlist li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 12.5px;
}
.mail .threadlist li:last-child { border-bottom: none; }
.mail .threadlist li a { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.mail .threadlist li.now { background: var(--raise); }
.mail .threadlist .when { color: var(--muted-foreground); white-space: nowrap; }
.mail .threadlist .who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mail .threadlist .tag { margin-left: auto; }

/* Correspondence in the record. The subject line is how the sender filed
   the message, not what they wrote, so the line above the summary says
   who wrote to whom and the link says what was said. */
.corr {
  font-size: 11.5px;
  letter-spacing: .03em;
  color: var(--muted-foreground);
  margin-bottom: 4px;
}
.corr .who { color: var(--foreground); }
.corr .arrow { margin: 0 4px; opacity: .65; }
a.says { display: inline-block; line-height: 1.45; }

/* The record reads down the page in time order, so the date column is
   fixed and quiet and the substance gets the width. */
table.record td.when { width: 92px; white-space: nowrap; vertical-align: top; }
table.record td.shelf { width: 130px; white-space: nowrap; color: var(--muted-foreground); }
table.record td { vertical-align: top; padding-top: 8px; padding-bottom: 8px; }

/* The folders, as a filter over one timeline rather than nine drawers. */
.filters { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px 12px 4px; }
.filters .chip {
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 12.5px;
  text-decoration: none;
  color: var(--muted-foreground);
}
.filters .chip:hover { border-color: var(--primary); color: var(--foreground); }
.filters .chip.on {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-foreground);
  font-weight: 600;
}

.factline { font-size: 13px; margin: 4px 0; }
.factline strong { color: var(--muted-foreground); font-weight: 500; margin-right: 4px; }
.factline.pending span { opacity: .8; }
.factline.pending .meta { margin-left: 4px; }

/* A count tile is a promise that there is somewhere to go. When the tile
   is a link, it says so the way the claims on the home page say it: the
   gold border on hover, and a pointer under the cursor. */
a.stat {
  cursor: pointer;
  transition: border-color .12s ease;
}
a.stat:hover { border-color: var(--primary); }
a.stat:hover .n { color: var(--primary); }

/* A tile that goes nowhere must not answer to the cursor. A surface that
   lifts under the mouse and then does nothing reads as a broken button
   rather than as a number, so this one stays flat and keeps the arrow. */
.stat:not(a) { cursor: default; }
.stat:not(a):hover { border-color: var(--border-soft); }

/* Counts in a table column are the same promise in a narrower space. They
   take the ordinary link colour on hover rather than a border, because a
   cell has no border of its own to light up. */
td.num a { text-decoration: none; }
td.num a:hover { color: var(--primary); }

/* What the draft could not know. Each one is a marked blank in the text
   above rather than a guess, so the list is the work left to do. */
ul.questions { margin: 0; padding-left: 16px; font-size: 13px; }
ul.questions li { margin: 4px 0; line-height: 1.45; }

/* a date now reads the way it is written in a letter, so "September 30,
   2026" sits where "2026-09-30" used to. it is roughly twice as wide and
   it has spaces in it, which means a table column that was comfortable
   will break a date across two lines and read as two dates. every cell
   below holds a spoken date and was not already nowrap. */
td.daycell, span.daycell { white-space: nowrap; }

/* the record column was sized for ten numeric characters. longhand needs
   the room, and the substance column has it to give. */
table.record td.when { width: 148px; }

/* where the hour still matters, the sweeps, the say log, the envelope on
   a message, it trails the spoken date quietly rather than competing
   with it. the numerals line up because a clock is a number. */
.clock {
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
  font-size: .92em;
  margin-left: 2px;
}

/* What the documents have said about a case, grouped the way the
   question comes: what is the date of loss, who is the adjuster, what
   are the limits. A flat list of forty rows answers none of those. */
.knowgroup { margin-bottom: 12px; }
.knowgroup:last-child { margin-bottom: 0; }
.kindname {
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  border-bottom: 1px solid var(--border-soft);
  padding-bottom: 4px;
  margin-bottom: 4px;
}
.factline .src { display: inline; margin-left: 4px; }
.factline .src summary { display: inline; cursor: pointer; }
.factline .src div { margin: 4px 0 4px; line-height: 1.45; }

/* An unconfirmed fact is a suggestion. It reads quieter than a confirmed
   one and carries the button that settles it. */
.factline.pending { opacity: .82; }
.factline form.confirm { display: inline; margin-left: 4px; }
button.tiny {
  padding: 1px 8px;
  font-size: 10.5px;
  letter-spacing: .04em;
}

/* The record's headers. A case is read forwards through time, so the date
   sorts by default, but a file also gets asked what discovery is in it
   and what is still a draft, and those are orderings rather than
   searches.

   The link styling that used to sit here went with the `col()` macro in
   matter.html that produced it. Three templates each wrote their own sort
   header and this was one of the three; the one table's header is a button
   and is styled once, above. */
table.record thead th { padding: 8px 8px; }

/* the executive summary at the top of a case. it is prose and it gets
   read, not scanned, so it is set wider in the line and lighter in the
   colour than the fact rows underneath it, and it sits apart from them
   rather than reading as the first row of the list. */
.brief .summary {
  font-size: 13px;
  line-height: 1.62;
  margin: 0 0 8px;
  color: var(--foreground);
}

/* the control that pays for a rewrite. it is quiet on purpose: the
   summary is already there when the page loads, and this is only for
   when somebody wants it said again. the note beside it says which of
   the two it is looking at, because an assembled summary and a written
   one read differently and the reader should know which. */
.brief form.rewrite {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border-soft);
}
.brief form.rewrite .meta { font-size: 11.5px; }

/* one heading per question a file gets asked, shut until it is asked.
   nine open drawers is the wall of rows this replaced, so the summary
   line has to carry enough on its own to be worth opening: the heading
   and how much is under it. the marker is the browser's, turned to the
   side, because a disclosure triangle is already understood. */
details.topic {
  border-top: 1px solid var(--border-soft);
  padding: 8px 0 4px;
}
details.topic:first-of-type { border-top: none; }
details.topic > summary {
  cursor: pointer;
  list-style: none;
  font-size: 12.5px;
  letter-spacing: .02em;
  color: var(--foreground);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
}
details.topic > summary::-webkit-details-marker { display: none; }
details.topic > summary::before {
  content: "\25B8";
  color: var(--muted-foreground);
  font-size: 9px;
  transition: transform .12s ease;
  display: inline-block;
}
details.topic[open] > summary::before { transform: rotate(90deg); }
details.topic > summary:hover { color: var(--primary); }

/* the shut heading has to answer the question on its own, so the line
   beside the name carries the substance and there is no count anywhere:
   a count says how much there is to read, which is the opposite of the
   help wanted here. it wraps under the name rather than truncating,
   because a half sentence is worse than two lines. */
details.topic > summary .name {
  color: var(--foreground);
  white-space: nowrap;
}
details.topic > summary .line {
  color: var(--muted-foreground);
  font-size: 11.5px;
  line-height: 1.45;
  font-weight: 400;
  /* beside the name when the column is wide enough for it, on its own
     row underneath when it is not, which in this sidebar is most of the
     time. a sentence cut off at the column edge is not readable and the
     whole point of it is that it can be read without opening anything. */
  flex: 1 1 240px;
  min-width: 0;
}
/* open, the facts underneath say it at length, so the line would be the
   same sentence twice. */
details.topic[open] > summary .line { display: none; }

/* an open heading is groups of facts under an annotation, not rows. the
   annotation is what the group establishes taken together, so it reads
   first and in the foreground colour, and the facts under it are the
   working underneath the answer. */
details.topic .group { margin: 8px 0 12px 16px; }
details.topic .group:last-child { margin-bottom: 4px; }
details.topic .group .note {
  margin: 0 0 4px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--foreground);
}

/* the facts themselves, once a heading is open. indented to the width of
   the marker so they read as belonging to the heading rather than to the
   card, and given air above and below so an open topic does not look
   like the same wall of rows in a narrower column. */
details.topic .factline { margin: 4px 0 4px 16px; line-height: 1.5; }
details.topic .factline:first-of-type { margin-top: 8px; }
details.topic .factline:last-child { margin-bottom: 4px; }
/* inside a group the indent is already the group's, and indenting twice
   in a sidebar this narrow costs a word off every line. */
details.topic .group .factline { margin-left: 0; }
details.topic .group .factline:first-of-type { margin-top: 0; }

/* the case against the draft, sitting between the letter and the button
   that puts it on letterhead. a blocking finding takes the destructive
   colour because it is the one thing on the page that is not a matter of
   taste: the button beside it is disabled and the letter is not going
   anywhere until it is answered. */
.auditbox {
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--r);
  padding: 12px 12px;
  margin-bottom: 12px;
  background: var(--muted);
}
.auditbox.stop { border-left-color: var(--destructive); }
.auditbox .cap { margin-bottom: 4px; }
.auditbox.stop .cap { color: var(--destructive); }
.auditbox ul { margin: 0; padding-left: 16px; font-size: 13px; }
.auditbox li { margin: 8px 0; line-height: 1.45; }
.auditbox li:first-child { margin-top: 0; }
.auditbox p.meta { margin: 8px 0 0; }

/* the words the finding is about, lifted off the draft. monospaced so a
   figure lines up with the figure in the letter above it, and quoted so
   nobody reads it as the audit's own prose. */
.auditbox .quoted {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted-foreground);
}
.auditbox .quoted::before { content: "\201C"; }
.auditbox .quoted::after { content: "\201D"; }
.audit-override { border-left: 3px solid var(--primary); padding-left: 12px; }
.audit-override > summary { color: var(--foreground); cursor: pointer; font-weight: 700; }
.audit-override > summary:hover { color: var(--primary); }
.audit-override form { margin-top: 12px; }
.audit-override label { display: block; font-size: 12px; font-weight: 700; margin-bottom: 6px; }
.audit-override textarea { min-height: 76px; width: 100%; }

/* ---------------------------------------------------------------
   The site's own typographic system, applied here.

   Three devices carry the firm's identity, and they were only roughly
   approximated before: headings set tight in Playfair, a small label in
   gold with wide tracking above a section, and a six pixel radius rather
   than eight. Measured off the firm's stylesheet rather than judged by
   eye, so the tool and the site are the same design.
   --------------------------------------------------------------- */

:root { --radius: .375rem; }

h1 { letter-spacing: -.021em; font-size: 28px; }
h2 { letter-spacing: -.015em; }

/* The eyebrow. On the site it sits above the hero as a gold, wide
   tracked line reading ALABAMA, GEORGIA, SOUTH CAROLINA, and above each
   section as SPECIALTIES. It is the most recognisable thing the firm
   does with type, and a card heading is the same job here. */
.card .cap {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}
.card .cap .spacer {
  letter-spacing: 0;
  text-transform: none;
  font-size: 12.5px;
}

/* A card that is the subject of the page keeps the serif, because a
   document's own name is not a label. */
.card .cap.title {
  font-family: var(--serif);
  font-size: 15px;
  letter-spacing: -.01em;
  text-transform: none;
  color: var(--foreground);
}

.card, .btn, button, input, select, textarea, dialog.sheet,
.attention .claim, .auditbox, .warnbox { border-radius: var(--radius); }

/* The gold rule. Under the wordmark, and under the page heading, the
   same device the site uses beneath its header bar. */

/* ---------------------------------------------------------------
   Writing, watched.

   The account of the work reads as prose, because that is what it is:
   a colleague saying what the file shows and what is about to be
   written. It is set narrower and lighter than the interface around
   it so it reads rather than scans, and it grows downward while the
   drafter writes.                                                */

.working {
  font-size: 15px;
  line-height: 1.72;
  max-width: 66ch;
  white-space: pre-wrap;
  color: var(--foreground-soft);
}
.working:empty::after {
  content: "Reading the file.";
  color: var(--muted-foreground-dim);
}

/* What the machinery did, under the prose. Counts and page totals: the
   facts of the run, kept small and out of the way of the argument. */
.steps { list-style: none; margin: 16px 0 0; padding: 0; }
.steps li {
  font-size: 12.5px;
  color: var(--muted-foreground);
  padding: 4px 0 4px 16px;
  position: relative;
}
.steps li::before {
  content: "";
  position: absolute;
  left: 2px; top: 11px;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--primary);
  opacity: .55;
}

/* The rendered pages, which is the document itself and not a preview
   of one. Wide, on white, with a rule so the paper reads as paper. */
.pages img {
  display: block;
  width: 100%;
  margin: 0 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: #fff;
}

/* ---------------------------------------------------------------
   The case page, in two columns that scroll apart.

   A matter with a hundred and thirty entries put the record and the
   case summary on one scroll. Reading down to the March
   correspondence took the parties, the dates and the summary off the
   top of the screen with it, so every glance from an entry to the
   adjuster's name was a scroll up and a scroll back down to the line
   that had been under the eye. The two columns are two readings of
   the same file and they are read against each other, so each one
   holds its own place.

   Below, the page itself stops scrolling: the caption and the
   controls stay where they were put and the two panes divide what is
   left of the window between them. main is reached through :has()
   because the shell is shared with every other page and only this one
   is laid out this way. Where :has() is not understood, none of this
   applies and the page scrolls as it always did.

   The section sits inside a window size rather than being written
   flat and then unpicked in a narrow query, and there is a second
   size below it where the two columns have to share differently.
   Outside either bound none of it applies and the sheet's own rules
   are what is left: the single stacked column on a narrow window, the
   sticky panel on a short one. Both are better answers than two boxes
   of four rows each, which is what dividing a window this size by
   height actually gives you.
   --------------------------------------------------------------- */

@media (min-width: 1001px) and (min-height: 561px) {

  main:has(> .split.panes) {
    display: flex;
    flex-direction: column;
    height: 100vh;
    /* the eighty pixels under an ordinary page keep the last row of a
       long table off the bottom edge of the window. nothing here
       scrolls past the bottom of the window, so they are dead space
       taken off both panes. */
    padding-bottom: 24px;
    overflow: hidden;
  }

  .split.panes {
    flex: 1 1 auto;
    min-height: 0;
    /* the sheet starts a split at the top and lets each side run as
       long as it needs to. these two are the height of the window
       instead, because a pane is only a pane if it has a bottom. */
    align-items: stretch;
  }

  /* the panes divide the height, not the width: the columns keep the
     widths the sheet already gives them. that is worth being explicit
     about, because the obvious hygiene here is min-width: 0 on both
     sides and it silently reproportions the page. the record's own
     content is what has been holding that column open all along, at
     1280 it is 640 pixels against a nominal 1.4fr of 547, and taking
     the floor away hands ninety pixels to the panel, drops the title
     column from 204 to 142 and makes the record half as long again.
     a grid item is at least as wide as its content, though, and a
     column that will not yield is a column that can push the page
     sideways, so the panel is the one that gives here, and the query
     below this one says what happens when it has nothing left to
     give. */
  .panes > .pane { min-height: 0; }
  .panes > .pane.stack { min-width: 0; }

  /* the record is one card, and it fills the pane so that its heading,
     the folder filters and the column headers stay put while the rows
     move underneath them. the card is clamped rather than stretched: a
     matter with four documents keeps a card four rows deep instead of
     an empty one ruled off at the bottom of the screen. */
  .panes > .pane.deep { display: flex; flex-direction: column; }
  .panes > .pane.deep > .card {
    flex: 0 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  .panes > .pane.deep > .card > .cap,
  .panes > .pane.deep > .card > .filters { flex: 0 0 auto; }
  .panes > .pane.deep > .card > .scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    /* the bar is given a lane of its own rather than taking one from
       the table. the record's columns are already at the narrowest
       they can be set, so the ten pixels a scrollbar takes out of the
       box came off the table and put a horizontal bar under it as
       well. asking for the lane whether or not it is occupied also
       stops the table stepping sideways on the day a matter gets long
       enough to scroll. */
    scrollbar-gutter: stable;
  }

  /* the column headers are the sort controls, so they are worth
     keeping on screen through a hundred rows. the rule under them is
     drawn as an inset shadow as well as a border: a collapsed table
     border belongs to the row rather than to the cell, so it stays
     behind with the first row that scrolls away and the headers end up
     sitting on the record with nothing between them. */
  .panes .record thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    box-shadow: inset 0 -1px 0 var(--border);
  }

  /* the other column is three cards read in order rather than one long
     one, so it scrolls as a column and the cards keep their own
     heights inside it. the sticky panel is switched off here: it was
     holding the summary against a page scroll that no longer happens,
     and sticking to a box that is itself the thing being scrolled does
     nothing but fight it. */
  .panes > .pane.stack {
    position: static;
    overflow-y: auto;
    /* the same lane, for the same reason: opening a heading in the
       summary is enough to bring the bar in, and without the lane
       every card in the column jumps ten pixels left as it arrives. */
    scrollbar-gutter: stable;
  }
}

/* Where there is not room for both.

   The record asking for the width its own columns need is right up to
   the point where what is left cannot hold a sentence. At a window of
   1010 the rail takes 244, the record takes 652 and the panel is left
   with 26 pixels, which is a stripe of single letters down the side of
   the case. Under about 1260 the record gives way instead: it falls
   back to its nominal share and scrolls sideways inside its own card,
   which is contained, reversible and the job that .scroll has always
   done, while the summary stays wide enough to read. */
@media (min-width: 1001px) and (max-width: 1259px) and (min-height: 561px) {
  /* the panel takes what it needs and the record takes the rest, rather
     than the two of them splitting the shortfall by ratio: at 1200 that
     left the summary 355 pixels it had no use for while the record was
     scrolling sideways at 500. 280 is what the panel is given at the
     width just above this one, so nothing jumps as the window crosses
     it. */
  .split.panes { grid-template-columns: minmax(0, 1fr) 280px; }
  .panes > .pane.deep { min-width: 0; }
}

/* The bars themselves, in the palette.

   The default is a light grey rail with a mid grey thumb, which on
   this navy reads as a strip of somebody else's interface down the
   side of every card, and there are now several of them on a case
   page. The track is the recessed navy the inputs and the rail use,
   the thumb is the border colour, and it lights to the lit border
   under the cursor: the same two steps every other edge in here
   takes. Both spellings are given because the standard properties
   only landed in Chromium recently and the office runs whatever
   Windows updated to last.

   The two properties do not behave alike, which cost a pass to find:
   scrollbar-color inherits and scrollbar-width does not. Set on the
   root alone, the case page came out in the right colours and still
   at the browser's full fifteen pixels, so the width is asked for
   everywhere the way the box model is. */
html { scrollbar-color: var(--border) transparent; }
* { scrollbar-width: thin; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border);
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--border-lit); }
::-webkit-scrollbar-corner { background: transparent; }

/* A document the file is waiting for, proposed before anybody asked. */
.proposal {
  padding: 12px 0;
  border-bottom: 1px solid var(--border-soft);
}
.proposal:last-child { border-bottom: none; padding-bottom: 0; }
.proposal:first-child { padding-top: 0; }
.proposaltop {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 4px;
}
.proposaltop strong { font-size: 15px; }
.proposaltop .tag { margin-left: auto; white-space: nowrap; }
.proposal .meta { font-size: 12.5px; }
.proposal .take {
  margin-top: 8px;
  font-size: 12.5px;
  padding: 4px 12px;
}

/* ---------------------------------------------------------------------
   The case brain on a matter page.

   The measure is the whole point of the first rule. This card sits above
   the two column split, so it spans the page, and on a wide monitor that
   put single paragraphs of three hundred words onto lines of a hundred
   and fifty characters. Sixty to seventy five is what a person reads
   without losing their place, so the prose is held to 74ch and the card
   is allowed to be wider than its own text.

   No gold anywhere below. The palette spends that on the wordmark and the
   one action that matters, and a section heading is not that. Risks get
   the destructive red on a left edge only, at the lightness the palette
   already proved readable on this navy, because the one thing here that
   should catch an eye across the room is the thing that loses the case. */
.card.brain .pad { padding-bottom: 4px; }

.card.brain p,
.card.brain li { max-width: 74ch; }

.card.brain p.lead {
  margin: 0 0 4px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--foreground);
}

.brainsec { margin-top: 16px; }
.brainsec > .secname {
  font-size: 11.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted-foreground-dim);
  margin-bottom: 4px;
}
.brainsec p {
  margin: 0;
  font-size: 13px;
  line-height: 1.58;
  color: var(--muted-foreground);
}
.brainsec ol,
.brainsec ul { margin: 0; padding-left: 16px; }
.brainsec li {
  font-size: 13px;
  line-height: 1.55;
  margin: 4px 0;
  color: var(--muted-foreground);
}

/* The actions are the only part of this card that asks the reader to do
   something, so they are the only part set in the foreground colour. */
.brainsec.act li { color: var(--foreground); }
.brainsec.act li::marker { color: var(--muted-foreground-dim); }

.brainsec.risky {
  border-left: 2px solid var(--destructive);
  padding-left: 12px;
  margin-left: 1px;
}
.brainsec.risky > .secname { color: var(--destructive-lit); }

/* Shut sections inside this card carry their own count on the summary
   line, so a heading never has to be opened to find out it is empty. */
.card.brain details.topic { margin-top: 12px; }
.card.brain ul.brainlist { margin: 0; padding-left: 16px; }
.card.brain ul.brainlist li {
  font-size: 13px;
  line-height: 1.55;
  margin: 4px 0;
  color: var(--muted-foreground);
}

.analysis-brief .analysis-columns,
.analysis-brief .analysis-assessment-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px;
  margin-top: 18px;
}
.analysis-brief .analysis-columns > section,
.analysis-brief .analysis-panel {
  padding: 14px 16px;
  border: 1px solid var(--border);
  background: var(--card);
}
.analysis-brief .analysis-columns ol,
.analysis-brief .analysis-columns ul,
.analysis-brief .analysis-panel ol,
.analysis-brief .analysis-panel ul {
  margin: 9px 0 0;
  padding-left: 18px;
}
.analysis-brief .analysis-columns li,
.analysis-brief .analysis-panel li { margin: 0 0 7px; }
.analysis-brief .analysis-posture { max-width: 100ch; }
.analysis-brief .analysis-panel p { line-height: 1.55; }
.analysis-source-row {
  display: grid;
  gap: 3px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border-soft);
}
.analysis-source-row:last-child { border-bottom: 0; }
.analysis-background { margin-top: 18px; }
.analysis-background summary,
.analysis-evidence > summary {
  cursor: pointer;
  color: var(--muted-foreground);
}
.analysis-evidence {
  margin: 14px 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  background: var(--card);
}
.analysis-evidence > summary { font-weight: 600; }
.analysis-brief .analysis-status {
  margin: 18px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
  color: var(--muted-foreground);
  font-size: 12px;
}
@media (max-width: 800px) {
  .analysis-brief .analysis-columns,
  .analysis-brief .analysis-assessment-grid { grid-template-columns: 1fr; }
}

.financial-keyfigures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px;
}
.financial-figure {
  padding: 12px 14px;
  border: 1px solid var(--border);
  background: var(--card);
}
.financial-figure .k {
  color: var(--muted-foreground);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.financial-figure .v { margin-top: 5px; font-size: 17px; }
.financial-caution {
  max-width: 90ch;
  margin: 16px 0 0;
  color: var(--muted-foreground);
  font-size: 12px;
  line-height: 1.5;
}
.financial-sections {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}
.financial-section .financial-note { margin: 0; max-width: 92ch; }
.financial-section .financial-empty { margin: 0; }
.financial-unresolved { border-color: var(--warning-border, var(--border)); }
.financial-missing-list {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 10px;
}
.financial-missing-list span {
  padding: 5px 8px;
  border: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 12px;
}

/* The disagreement card. Same restraint as the brain card: no gold, and
   the destructive red only on the edge, because this is the one thing on
   a matter page that has to be settled before anything below it can be
   relied on. Wider than the brain card's measure is not a problem here -
   these are short statements of two values, not prose. */
.card.disagree { border-color: var(--destructive); }
.card.disagree > .cap { color: var(--destructive-lit); }
.card.disagree .brainsec { margin-top: 12px; }
.card.disagree .brainsec:first-child { margin-top: 2px; }
.card.disagree .brainsec > .secname { color: var(--muted-foreground); }
.card.disagree p { margin: 0; font-size: 13px; line-height: 1.55;
                   color: var(--muted-foreground); max-width: 86ch; }
.card.disagree strong { color: var(--foreground); font-weight: 500; }
.card.disagree ul { margin: 4px 0 0; padding-left: 16px; }
.card.disagree li { font-size: 13px; line-height: 1.5; margin: 4px 0;
                    color: var(--muted-foreground-dim); }

/* ==================================================================
   THE ONE TABLE AND THE ONE MARK

   Before this block there were four table classes across forty one
   table elements, three separate sort-header macros, and no export
   anywhere. The element rules above still carry the visual system, the
   banding and the figures; what follows is the grammar that sits around
   them: the filter bar, the sortable header, the footer count, and the
   provenance glyph that stands beside a value.
   ================================================================== */

.onetable { display: block; }

/* THE HEADER STAYS WHERE THE READER LEFT IT.

   Four hundred rows down the Calendar the columns had scrolled off, so a
   date in the fourth column was a date in no column at all. Every list
   this office uses freezes its header: Excel does, Explorer does, Outlook
   does, Alacourt does. The scroll box is the positioning context, so this
   works whether the page scrolls or the table does.

   The background is opaque on purpose. A translucent header lets rows
   read through it as they pass under, which is worse than no header. */
.onetable .scroll { max-height: 78vh; overflow: auto; }
.onetable thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--card);
  box-shadow: inset 0 -1px var(--border);
}

/* Column names must remain readable on the dark header surface. */
html[data-theme="dark"] .onetable thead th {
  color: var(--foreground);
}

/* A ROW OPENS THE THING IT IS ABOUT.

   In Explorer, Outlook, Alacourt and every practice tool, clicking a row
   opens it. Here the reader had to find the one word in the row that was
   a link, which is a small cost paid several hundred times a day. The
   cursor says so, and `table.js` does the work: only rows that carry a
   plain link, and never when the click landed on a control. */
.onetable tbody tr.opens { cursor: pointer; }
.onetable tbody tr.opens:hover td { background: var(--raise); }

/* The bar over the table. It holds the filter, the count and the export
   and nothing else; the chips that narrow a view belong to the page,
   above this, because what they narrow BY is the page's own question. */
.tablebar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-soft);
}
.tablebar .tablefilter {
  width: auto;
  min-width: 210px;
  max-width: 320px;
  padding: 4px 8px;
  font-size: 12.5px;
}
.tablebar .spacer { margin-left: auto; }
.tablebar .tablecount { font-size: 12.5px; white-space: nowrap; }
.tablebar .tablecsv { padding: 4px 8px; font-size: 12.5px; }

/* The header is a button rather than a link, because sorting what is on
   the screen is not going anywhere, and a button is where the keyboard
   already expects to land. */
th > button.sorter {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 0;
  border-radius: var(--r);
  padding: 0;
  margin: 0;
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
th > button.sorter:hover { background: none; color: var(--foreground); }
th > button.sorter:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
th > button.sorter.sorted { color: var(--primary); }
th > button.sorter .caret { font-size: 8px; line-height: 1; }
th.num > button.sorter { flex-direction: row-reverse; }

/* A day, a band, a heading over a run of rows. It is a reading order
   rather than data, so it stands down under a sort or a filter. */
tbody tr.group td,
tbody tr.group:nth-child(even) td {
  background: var(--secondary);
  color: var(--primary);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .06em;
  padding: 4px 12px;
}

.tableempty { padding: 16px 12px; margin: 0; font-size: 13px; }

/* ---------- the provenance mark ----------

   Shape says whose contention it is, weight says how that was decided.
   Drawn in the type colour, never in a colour of its own, so it prints in
   black and white and leaves the gold on borders and type where the brand
   rule keeps it.

   The measured shape of this ledger on September 5, 2026: 6,860 facts of
   10,875 were decided by reading a title, so most of a column renders
   hairline. That is what the file is, and it is not a defect to be
   styled away. */
.mk {
  width: 12px;
  height: 14px;
  flex: none;
  display: inline-block;
  vertical-align: -2px;
  margin-right: 4px;
  color: inherit;
  border-radius: var(--r);
}
.mk svg { width: 12px; height: 14px; display: block; overflow: visible; }
.mk .f { fill: currentColor; stroke: currentColor; stroke-width: 1.2; }
.mk .dot { fill: currentColor; }
.mk .bar { fill: currentColor; }
.mk.side .f { fill: none; stroke-width: 1.4; }
.mk.title .f { fill: none; stroke-width: .7; opacity: .8; }
.mk.derived .f { fill: none; stroke-width: 1.2; }
.mk.unread .f { fill: none; stroke-width: 1; opacity: .6; }
.mk:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* A gap in the file. Not an empty cell: the screen says the file does not
   hold it, which is a different statement from a value nobody has read. */
/* WHAT THE FILE DOES NOT HOLD. `white-space: nowrap` was right when this
   only ever said "not in file", and wrong the moment it carried a
   sentence: the matter header's "the file disagrees with itself" ran 26px
   past its cell and the limitations reason ran 317px past, at 1440 wide.
   The mockup's own `.nif` declares no white-space. It wraps, and the
   short form is too short to wrap anyway. */
.nif { color: var(--muted-foreground-dim); }

/* WHERE ON THE PAPER A VALUE WAS READ. Set beside the sentence it was read
   out of, in the Read Off column, because the two are one answer. Tabular
   figures so a column of page numbers lines up, and the same dim weight as
   the rest of that cell's furniture: the page is provenance, not the value,
   and must not compete with it. */
.pg { color: var(--muted-foreground-dim); font-variant-numeric: tabular-nums;
      white-space: nowrap; }

/* A THREAD THIS OFFICE SPOKE LAST ON. Not an alarm: it is a normal state
   for most of a working file, and a red badge on forty rows would train the
   eye to skip it. The same dim register as the rest of the row's furniture,
   set off only by the rule around it. */
/* A DATE THE FILE ITSELF DOUBTS. This one does carry weight, unlike
   `.await`: fourteen live deadlines have a written reason to think the date
   is wrong and two of them are a month out on court-commanded compliance
   dates. It is still a mark and not a banner, because the sentence in the
   title is the thing worth reading and a banner would push it off. */
/* A VALUE THE FILE ITSELF DISAGREES WITH, and a value still asked about.
   The same register as `.doubt`, which is the same kind of statement: not
   that the value is wrong, but that the file has not settled it. `.asked`
   is quieter, because an open question is ordinary and a contradiction
   between two certains is not. */
.disputed { color: var(--warn); font-size: .82em; white-space: nowrap;
            border-bottom: 1px dotted currentColor; cursor: help;
            margin-left: .4em; }
.asked { color: var(--muted-foreground-dim); font-size: .82em;
         white-space: nowrap; border-bottom: 1px dotted currentColor;
         cursor: help; margin-left: .4em; }

.doubt { color: var(--warn); font-size: .82em; white-space: nowrap;
         border-bottom: 1px dotted currentColor; cursor: help;
         margin-left: .4em; }

.await { color: var(--muted-foreground-dim); font-size: .82em;
         border: 1px solid var(--border, currentColor); border-radius: 3px;
         padding: 0 .3em; margin-left: .4em; white-space: nowrap; }
/* THE DASH IS THE MOCKUP'S OWN AND IS NOT A BREACH OF THE EM DASH RULE,
   which has been raised against it once and will be again. The handoff
   declares this rule with that character in it, and here it is written
   as an escape so it never appears literally in a source file.

   The rule is about PROSE, what a person or a model writes. This is a
   typographic marker on a state, like the rule under a heading, and the
   state it marks is "the file does not say".

   Which is also where the line falls. `nif()` is for an ABSENCE. Routing
   a value through it because the value reads badly puts this dash in
   front of something the file does hold, and that is the thing to catch:
   it happened once, to the Kind of Claim row on the brain page. */
.nif::before { content: "\2014\00a0"; }

.marklegend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 4px 16px;
  font-size: 12.5px;
  color: var(--foreground-soft);
}
.marklegend > div { display: flex; align-items: center; }

/* Printed, the marks are the reason a printout carries its provenance, so
   they go black on white with everything else. */
@media print {
  .tablebar, .tableempty { display: none !important; }
  .mk .f, .mk .dot, .mk .bar { fill: #000; stroke: #000; }
  .mk.side .f, .mk.title .f, .mk.derived .f, .mk.unread .f { fill: none; }
  /* Black thinned, rather than a grey nobody named. A second colour in
     the sheet is how a palette stops being one. */
  th, td { color: #000; border-color: rgba(0, 0, 0, .35);
           background: none !important; }
}

/* A claim on the reader is a sentence with somewhere to go, not a record
   with columns, so it is a list and not a table. It was a table, which put
   a filter box and an export over five sentences the moment every list on
   the surface became the one table. */
ul.claims { list-style: none; margin: 0; padding: 4px 0; }
ul.claims li {
  padding: 8px 16px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 13px;
}
ul.claims li:last-child { border-bottom: none; }
ul.claims li a { display: block; }
ul.claims li a:hover { color: var(--primary); }

/* A fact sheet is one label against one value, which is not a table of
   records and does not become one to satisfy a rule about tables. There
   are no columns to sort and nothing to filter; the marks and the "not in
   file" reading are the same as everywhere else. */
dl.factsheet { margin: 0; padding: 4px 0; }
dl.factsheet > div {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: 12px;
  padding: 4px 16px;
  border-bottom: 1px solid var(--border-soft);
}
dl.factsheet > div:last-child { border-bottom: none; }
dl.factsheet dt { color: var(--muted-foreground); }
dl.factsheet dd { margin: 0; }
@media (max-width: 700px) {
  dl.factsheet > div { grid-template-columns: 1fr; gap: 2px; }
}

/* Counts of what a draft may say, nested one level: the four under
   "assertable" are the same facts split by how their stance was decided,
   so they are indented under it rather than listed beside it. */
dl.factsheet.counts > div { grid-template-columns: 320px 1fr; }
dl.factsheet.counts > div.under > dt { padding-left: 1.5rem; }
dl.factsheet.counts dt a:hover { color: var(--primary); }

/* A form is labelled fields, laid out as fields. It was a table, which is
   how a form comes to look like a record. */
.formsheet { display: grid; gap: 8px; }
.formsheet > label { display: grid; gap: 4px; }
.formsheet > label > span {
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}
.formsheet select, .formsheet input { width: 100%; }

/* The sentence a value was read off, kept whole in the page so the export
   carries the sentence rather than its first ninety characters, and folded
   to three lines so a hundred-word quotation does not set the row height
   for the whole table. It opens under the cursor. */
td.clamp {
  max-width: 46ch;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
tr:hover td.clamp {
  -webkit-line-clamp: unset;
  line-clamp: unset;
  overflow: visible;
}


/* ------------------------------------------------------------------ */
/* The inspector. Click a value, see the sentence it was read out of.   */
/* Built to the design handoff, whose README calls this panel final.    */
/* ------------------------------------------------------------------ */

.inspector {
  border-left: 1px solid var(--border);
  background: var(--card);
  overflow-y: auto; overflow-x: hidden; min-width: 0;
  position: sticky; top: 0; height: 100vh;
}
.inspector[hidden] { display: none; }
.inspector [hidden] { display: none !important; }

/* Set by inspector.js on a page that renders no value with provenance.
   The column goes, the panel goes with it, and the record gets the width.
   See the note at the top of inspector.js. */
body.noinspect { --insp: 0px; }
body.noinspect .inspector { display: none; }
.inspector .irest .marklegend { display: grid;
  grid-template-columns: 1fr; gap: 4px 12px; font-size: 12.5px;
  color: var(--foreground-soft); }
.inspector .ikeys span:nth-child(odd) { color: var(--muted-foreground);
  font-variant-numeric: tabular-nums; }

.inspector .ihead {
  padding: 12px 16px 8px;
  border-bottom: 1px solid var(--border);
  position: relative;
}
.inspector .eyebrow {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--primary); display: flex; align-items: center; gap: 8px;
}
.inspector .eyebrow .dash {
  width: 18px; height: 1px; background: var(--primary); display: inline-block;
}
.inspector .ititle {
  font: 700 15px/1.25 var(--serif); color: var(--foreground); margin: 4px 0 2px;
}
/* The provenance line is GOLD and carries the glyph, so the panel says
   whose this is in the same grammar the table does. */
.inspector .iprov {
  font-size: 12.5px; color: var(--primary);
  display: flex; align-items: center; gap: 4px;
}
.inspector .iprov .mk { color: var(--primary); }

.inspector .iclose {
  position: absolute; top: 8px; right: 8px; width: 28px; height: 28px;
  display: grid; place-items: center; color: var(--muted-foreground);
  cursor: pointer; font-size: 22px; line-height: 1; border-radius: var(--r);
  background: transparent; border: 0; padding: 0;
}
.inspector .iclose:hover, .inspector .iclose:focus {
  color: var(--foreground); background: var(--secondary);
}

.inspector .ibody { padding: 12px 16px; font-size: 13px; }

.inspector .ilabel {
  margin: 12px 0 4px; font: 500 10.5px var(--sans);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted-foreground-dim);
}
.inspector .ilabel:first-child { margin-top: 0; }

/* The sentence, with the value picked out of it.

   8 by 10, the handoff's `.quote`. This computed 9px 11px, a pixel out on
   both axes, which is nothing on its own and is exactly how a panel ends
   up on a grid of its own: the inspector is 400px wide and every other
   measurement in it, the 12 by 16 body padding and the 110px label
   column, was drawn against the handoff's number. */
.inspector .iquote {
  background: var(--background);
  border-left: 2px solid var(--primary);
  padding: 8px 8px; color: var(--foreground-soft);
  font-size: 12.5px; line-height: 1.5;
}
.inspector .iquote mark {
  background: var(--hit); color: var(--foreground); padding: 0 2px;
}
.inspector .iquote mark[hidden] { display: none; }

/* THE PAGE, DRAWN FROM THE PAGE IT CITES.

   A clean rectangle at a page's own proportions, holding that page's real
   line widths, with the cited line struck in gold. The corner fold that
   used to sit on it was an ornament pretending the drawing was a
   photograph, and the office said so.

   The line shapes carry through, so the rectangle reads as the KIND of
   paper it is before a word of the citation: a caption block is centred
   and short, a numbered averment starts hard left with a figure, a
   signature block is indented and ragged, prose runs full measure. That
   is what a lawyer reads off a real page held at arm's length. */
.inspector .ipage {
  width: 236px; margin: 8px auto 0; aspect-ratio: 8.5 / 11;
  background: var(--paper); border: 1px solid var(--paper-edge);
  border-radius: 1px; padding: 12px 16px;
  display: flex; flex-direction: column; gap: 4px; overflow: hidden;
}
.inspector .ipage[hidden] { display: none; }
.inspector .ipage i {
  flex: 0 0 auto; height: 2px; background: var(--paper-ink); opacity: .42;
}
/* A heading sits away from the left edge, like the thing it is. */
.inspector .ipage i.centred { margin-left: auto; margin-right: auto; opacity: .6; }
.inspector .ipage i.indented { margin-left: 34%; }
/* An averment starts hard left and is the page's most regular rhythm. */
.inspector .ipage i.numbered { opacity: .55; }
.inspector .ipage i.hit {
  height: 6px; background: var(--band-gold); opacity: 1; margin: 2px 0;
}

/* The citation. A page and a line, because the pagination is real. */
.inspector .ipagecite {
  margin-top: 8px; text-align: center; font-size: 11.5px;
  color: var(--foreground-soft); font-variant-numeric: tabular-nums;
}
.inspector .ipagecite[hidden] { display: none; }
.inspector .ipagecite b { font-weight: 500; color: var(--foreground); }
.inspector .ipagecite span {
  display: block; margin-top: 4px; font-size: 10.5px;
  color: var(--muted-foreground-dim);
}

/* Said plainly when the value is not in the sentence it is cited from.
   232 facts hold a scalar that is simply not in their own quote, and one
   of them is a date of birth computed from an age. */
.inspector .inohit {
  margin: 8px 0 0; font-size: 12.5px; line-height: 1.45;
  color: var(--destructive-lit);
}
.inspector .isect{border-top:1px solid var(--border-soft);margin-top:13px;padding-top:2px}.inspector .isect>summary{cursor:pointer;list-style:none}.inspector .isect>summary::-webkit-details-marker{display:none}.inspector .isect>summary::after{color:var(--primary);content:"−";float:right}.inspector .isect:not([open])>summary::after{content:"+"}.inspector .isect .isaid{margin:7px 0}

.inspector .igrid {
  display: grid; grid-template-columns: 110px 1fr; gap: 4px 8px;
  font-size: 12.5px; color: var(--foreground);
}
.inspector .igrid > span:nth-child(odd) { color: var(--muted-foreground); }

.inspector .iacts { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 12px; }
.inspector .iacts button, .inspector .iacts .btn {
  border: 1px solid var(--border); background: none; border-radius: var(--r);
  padding: 4px 12px; font: 500 12.5px var(--sans);
  color: var(--foreground-soft); cursor: pointer; text-decoration: none;
}
.inspector .iacts .go {
  border-color: var(--primary); background: var(--primary);
  color: var(--primary-foreground); font-weight: 600;
}
/* A control that cannot act yet says so on hover and looks it. */
.inspector .iacts button[disabled] { opacity: .5; cursor: not-allowed; }
.inspector .istatus { position: relative; }
.inspector .istatus[hidden] { display: none; }
.inspector .istatus > summary {
  list-style: none; border: 1px solid var(--primary); border-radius: var(--r);
  padding: 4px 22px 4px 12px; color: var(--primary-foreground);
  background: var(--primary); cursor: pointer; font: 600 12.5px var(--sans);
  position: relative;
}
.inspector .istatus > summary::-webkit-details-marker { display: none; }
.inspector .istatus > summary::after {
  content: ""; position: absolute; right: 9px; top: 8px; width: 5px; height: 5px;
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: rotate(45deg);
}
.inspector .istatus[open] > summary::after { top: 11px; transform: rotate(225deg); }
.inspector .istatusmenu {
  position: absolute; left: 0; bottom: calc(100% + 6px); z-index: 4;
  width: 190px; padding: 4px; border: 1px solid var(--border-lit);
  border-radius: var(--r); background: var(--card);
  box-shadow: 0 12px 30px rgba(4, 8, 12, .35);
}
.inspector .istatusmenu button {
  display: block; width: 100%; border: 0; padding: 7px 9px; text-align: left;
  color: var(--foreground); background: transparent;
}
.inspector .istatusmenu button:hover,
.inspector .istatusmenu button:focus-visible {
  color: var(--primary); background: var(--secondary); outline: none;
}
.inspector .istatusmenu button[hidden] { display: none; }

/* A value with provenance. The whole thing is the target, mark and text
   together, because that is what a person sees as the value. */
/* WHAT CAN BE CLICKED HAS TO LOOK LIKE IT CAN BE CLICKED.
   The office: "stuff that is interactable by inspector needs to show the
   use that it is. rn i cant tell what i can click or not". It was
   `dotted transparent`, which is an underline that appears only once the
   pointer is already on it, so the only way to find a readable value was
   to sweep the mouse across the page. And `data-deadline` carried no
   affordance at all, so every date on the Calendar opened a panel and
   none of them said so.
   The rest state is a dim dotted rule, which reads as "there is more
   here" without turning a table into a page of links. */
.val[data-fact],
.val[data-deadline] {
  cursor: pointer;
  border-bottom: 1px dotted var(--border-lit);
}
.val[data-fact]:hover,
.val[data-deadline]:hover {
  border-bottom-color: var(--primary);
  border-bottom-style: solid;
  color: var(--primary);
}
/* Keyboard reaches them too, and has to be able to see where it is. */
.val[data-fact]:focus-visible,
.val[data-deadline]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--r);
}
.val[data-fact].sel:not(.inspect-word),
.val[data-deadline].sel:not(.inspect-word) {
  background: var(--raise);
  box-shadow: inset 2px 0 var(--primary);
}

@media (max-width: 1200px) {
  /* Below this the panel would leave the record too narrow to read, so it
     lies over the page rather than beside it. */
  body.inspecting { --insp: 0px; }
  .inspector {
    position: fixed; right: 0; top: 0; width: min(400px, 92vw);
    z-index: 40; box-shadow: -18px 0 40px rgba(4, 8, 12, .5);
  }

  /* AND A DRAWER RESTS CLOSED.
     _inspector.html explains why the panel is always present: the design
     draws three columns, and the resting state carries the mark legend,
     which is the one thing on this surface a person has to learn. That
     reasoning holds for the sticky third column above 1200px and does not
     survive the rule five lines up, which turns the panel into a fixed
     overlay.
     Opened on a 1024 by 768 laptop, Today showed a 400px legend lying
     over the case list: "deposition of Def", "The client to Call", "trial
     date, current" and, under the trial, "Also written down" then
     "originally set" on its own line. The lawyer's first sight of his own
     Saturday morning was a key list and a column of glyph definitions,
     and every row behind it was cut mid-word.
     A legend that occludes the case teaches nobody. `body.inspecting` is
     already set when a value is clicked and removed on Close, so the
     drawer opens on the click that asks for it. */
  body:not(.inspecting) .inspector { display: none; }
}


/* ------------------------------------------------------------------ */
/* Who set a date. Not a stance, so not a mark, but the same question.  */
/* ------------------------------------------------------------------ */

/* `done-right` carries 26 deadlines: 19 proposed and 7 unknown, and NOT
   ONE entered by a court. Until the authority reached the page all 26
   read as the court's own calendar. A date one side asked for must not
   look like an order. */
/* The third step, and the only one that keeps its capitals would be a
   one word label. This is not: it reads "On the court's calendar",
   "Under a subpoena", "Source not on file". A phrase set in capitals is
   a phrase nobody reads twice. */
.auth {
  font-size: 11.5px; letter-spacing: 0;
  color: var(--foreground-soft); white-space: nowrap;
}
.auth.weak {
  color: var(--primary);
  border-bottom: 1px dotted var(--primary);
}


/* ------------------------------------------------------------------ */
/* A practice-wide page, to the handoff's recipe: gold eyebrow, a       */
/* Playfair h1, the context note, all under a gold hairline rule.       */
/* ------------------------------------------------------------------ */

.pagehead .lede b { color: var(--foreground); font-weight: 500; }

/* Reports and System use a card grid rather than a table, because a
   single figure in a one column table is a list pretending to be a grid. */
.cardgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  padding: 12px 20px;
}
.report {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 12px 16px;
}
.report .n {
  font: 700 26px/1.1 var(--serif);
  color: var(--foreground);
}
.report .t {
  margin-top: 2px;
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--primary);
}
.report .note {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--muted-foreground);
}
/* The query behind the figure, shut until asked for. A number nobody can
   check is the thing this system exists to be the opposite of, and one
   that shouts its SQL at every reader is a number nobody reads. */
.report details { margin-top: 8px; }
.report summary {
  font-size: 11.5px; color: var(--muted-foreground-dim); cursor: pointer;
}
.report code {
  display: block;
  margin-top: 4px;
  font: 11px/1.5 var(--mono);
  color: var(--foreground-soft);
  background: var(--background);
  border-left: 2px solid var(--border);
  padding: 4px 8px;
  white-space: pre-wrap;
  word-break: break-word;
}

.routes { display: flex; flex-wrap: wrap; gap: 4px; }
.routes code {
  font: 11px var(--mono);
  color: var(--foreground-soft);
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 2px 4px;
}


/* The handoff styles these and they are part of the design rather than
   browser furniture: a pale default scrollbar on a dark page reads as a
   scar down the right hand side. */
html { scrollbar-color: var(--border) transparent; }
* { scrollbar-width: thin; box-sizing: border-box; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border);
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* The handoff's zebra, rgba(255,255,255,.02), held in `--zebra` with the
   argument for it written out at the token. */
.onetable tbody tr:nth-child(even) td { background: var(--zebra); }
/* A row picked for a bulk verb with `x`. Distinct from `sel`, which is
   only where the keyboard is standing: one is a cursor, the other is a
   choice, and drawing them the same way is how somebody strikes the
   wrong four facts. */
.onetable tr.picked td {
  background: var(--raise);
  box-shadow: inset 3px 0 var(--primary), inset 0 0 0 1px var(--border-lit);
}
.onetable tr.picked.sel td { box-shadow: inset 3px 0 var(--primary); }

/* THE SELECTED ROW, AND THE OLIVE NOTE ADJUDICATED. Two things were
   wrong, both measured on /matter/chastain at 1440 by 900 against the
   mockup open beside it.

   The alpha first. The handoff draws this at rgba(255,197,0,.08). What
   shipped was `--hit`, the same gold at .25, three times the wash. Over
   the ground it composites to red 75, green 62, blue 24, and that is
   precisely the olive the note at `--glow` warns about, sitting in the
   one rule the note should have caught. The handoff's .08 composites to
   red 34, green 34, blue 29: red and green within a level of each other,
   blue five below, a row a shade warmer than the page rather than a
   khaki slab. On screen the two
   rows are not close, and the quieter one is the handoff's. So the olive
   finding is not overruled here, it argues for the handoff's number.

   The reason it holds at .08 and failed as a hover is the gold bar. An
   opaque 2px of the accent runs down the inside edge of this row, so the
   eye is told what the tint is before it has to guess. `--glow` had
   nothing beside it doing that job.

   Then the specificity. `.onetable tbody tr:nth-child(even) td` scores
   0,2,3; this rule scored 0,2,2. Every even row lost its selection
   background to the zebra and showed only the bar, so half the table
   selected differently from the other half. The handoff writes
   `!important` on `.tbl tr.sel td` for that exact reason and it is copied
   rather than worked around. It also settles a picked row that is under
   the cursor, which used to come out gold on the odd rows and zebra on
   the even ones; the 3px bar set above is what still says picked. */
.onetable tr.sel td {
  background: var(--row-gold) !important;
  box-shadow: inset 2px 0 0 var(--primary);
}
/* A value's hover in the handoff is gold, both the rule and the text. */
.val:hover { border-bottom-color: var(--primary); color: var(--primary); }


/* What a folded name absorbed. Shut by default: the count is the signal
   and the names are what you open when the count looks wrong. */
ul.folded { margin: 4px 0 0; padding-left: 16px; }
ul.folded li { font-size: 12.5px; color: var(--foreground-soft); }
ul.folded li .dim { display: block; font-size: 11.5px; }


/* HOW MANY DOCUMENTS SAID IT. Five facts on `chastain` read "September
   1945" for one date of birth, off five documents under five labels. The
   ledger is right to hold five readings and the line has room for one, so
   the line carries the answer and the count of papers behind it.
   Corroboration is worth seeing: a date on four documents is not the same
   as a date on one. */
.times {
  font-size: 10.5px;
  color: var(--muted-foreground-dim);
  margin-left: 4px;
  vertical-align: 1px;
}


/* WHO THE VALUE IS ABOUT, where the value is a predicate rather than a
   name. "released from liability" under a heading reading Carrier is
   unreadable; "State Farm Mutual Automobile Insurance: released from
   liability" is a sentence. The subject is quieter than the value because
   the value is the answer. */
.subj { color: var(--muted-foreground); }
.subj::after { content: ": "; }


/* The components sheet on Damages. Wider label column than the
   inspector's, because "Coverage Aggregate Shared" is a long name for a
   thing that has to be said in full: an aggregate shared with every other
   claimant is not a number this case can have, and shortening it to
   "Aggregate" is how `tuggle` read as a four million dollar file. */
.igrid.components { grid-template-columns: 220px 1fr; }


/* A list of spellings for one thing. Each is a chip so the eye can count
   them, wrapped rather than run together, and the ones past the third are
   behind a click because the count is the signal and the values are the
   detail. */
.spellings { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; }
.spellings details { width: 100%; }
.spellings summary { font-size: 11.5px; color: var(--muted-foreground-dim); cursor: pointer; }
.spellings details .auth { margin-right: 8px; }


/* The correction form inside the inspector, shut until asked for. */
.icorrection {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.icorrection[hidden] { display: none; }
.icorrection .field { display: block; margin-bottom: 8px; }
.icorrection .field span {
  display: block;
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted-foreground-dim);
  margin-bottom: 4px;
}
.icorrection input,
.icorrection select,
.icorrection textarea {
  width: 100%;
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 4px 8px;
  color: var(--foreground);
  font: inherit;
}
.icorrection input:focus,
.icorrection select:focus,
.icorrection textarea:focus { border-color: var(--primary); outline: none; }
.icorrection .meta { margin: 0 0 8px; font-size: 12.5px; }
.icorrection button { margin-right: 4px; }

/* One group on its own tab: a single column, because a sheet of one
   section split across two leaves a hole down the right of the page. */
.sheet2.one { grid-template-columns: 1fr; max-width: 96ch; }


/* Putting a note on a file. */
.notesform .field { display: block; margin-bottom: 8px; max-width: 76ch; }
.notesform .field span {
  display: block;
  font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted-foreground-dim);
  margin-bottom: 4px;
}
.notesform textarea, .notesform input[type="text"] {
  width: 100%;
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 8px 8px;
  color: var(--foreground);
  font: inherit;
  resize: vertical;
}
.notesform textarea:focus, .notesform input:focus {
  border-color: var(--primary); outline: none;
}

/* THE MARK-WRONG CONTROL. One cross per Overview row, invisible until the
   row is hovered: the page is for reading, and this is for the one row in
   fifty that is wrong. See web/static/wrong.js. */
.frow .wrongmark {
  border: 0; background: none; cursor: pointer; padding: 0 0 0 4px;
  color: transparent; font-size: 13px; line-height: 1;
}
.frow:hover .wrongmark { color: var(--muted-foreground); }
.frow .wrongmark:hover, .frow .wrongmark:focus {
  color: var(--primary); outline: none;
}
.wrongbox {
  grid-column: 1 / -1; margin: 4px 0 8px;
  padding: 12px 12px; border: 1px solid var(--primary);
  border-radius: var(--r); background: var(--raise);
}
.wrongbox textarea {
  width: 100%; margin: 4px 0 8px; min-height: 62px;
  background: var(--background); color: var(--foreground);
  border: 1px solid var(--border); border-radius: var(--r); padding: 8px;
  font: inherit;
}
.wrongbox .meta { margin: 0 0 2px; }

/* --------------------------------------------------------------------- */
/* TODAY. One column, capped, four sections, no table furniture.          */
/*                                                                       */
/* The region was a two column grid: a table on the left with a filter    */
/* box and a CSV export, and a column on the right that filled with this  */
/* program's own backlog, because a second column is where things nobody  */
/* reads accumulate. One column cannot do that.                          */
/*                                                                       */
/* DENSE, BECAUSE IT IS READ AT SEVEN IN THE MORNING. The first cut gave  */
/* each row 9 pixels of padding above and below a 15 pixel serif, which   */
/* put three entries where a screen has room for a dozen and made the     */
/* sections look like separate pages. Everything here is tuned to fit the */
/* practice's whole week on one screen without scrolling.                 */
/* --------------------------------------------------------------------- */
.today { max-width: 1000px; }

.today .dueband { margin: 0 0 16px; }
/* THREE STEPS, SO THE EYE CAN RANK WITHOUT READING.
   The office: "is the current text design hierarchy helping the user
   consume and use the platform ... this rn is making me fatigued sort of
   ... but its not a too much density problem." It is not. It was that
   NOTHING WAS RANKED. The section heading, the date under it, the
   authority chip and the stat label were all 10.5 to 11px, uppercase,
   letter-spaced, differing only in colour, so a Today row read THIS WEEK
   then SEPTEMBER 10, 2026 then COMMANDED then NOTHING HAPPENED, four
   levels of capitals stacked and no level at all.
   Capitals also cost reading speed: word shape is what the eye matches
   on and capitals flatten every word to a rectangle. They earn their
   place on a one or two word LABEL and nowhere else.
   So: a section heading looks like a heading, in size and weight rather
   than in volume. */
.today .dueband h4 {
  margin: 0 0 4px; font-size: 15px; letter-spacing: 0;
  color: var(--foreground); font-weight: 600;
}

/* The date, written once above the rows it governs. */
/* The second step. A date is data a reader recognises by its shape, and
   setting it in capitals removes the shape and gains nothing. */
.today .dueday {
  margin: 12px 0 2px; font-size: 12.5px; letter-spacing: 0;
  color: var(--muted-foreground);
}
.today .dueday:first-child { margin-top: 2px; }

.today .duerows { display: grid; grid-template-columns: 1fr; }

/* Matter, what, authority, when. No header row: four sections of three
   rows do not need one, and each column is legible from its content. */
/* A COLUMN FOR THE TICK, NOT ONE STOLEN FROM THE ROW. A checkbox was
   put in as a fifth child of a four column grid, so every cell shifted
   one place left: the matter took the tick's width, the sentence took
   116px and wrapped every three words, and the day count fell onto its
   own line. */
.today .duerow {
  display: grid;
  grid-template-columns: 26px 210px minmax(0, 1fr) 116px 72px;
  gap: 0 12px; align-items: baseline;
  padding: 4px 0; border-bottom: 1px solid var(--border);
  font-size: 13px; line-height: 1.4;
}
.today .duerow > .tick { align-self: center; }
/* A row with no tick still lines up under the ones that have one. */
.today .duerow > .duematter:first-child { grid-column: 2; }
.today .duerow:last-child { border-bottom: 0; }

/* The matter leads, in the serif: a lawyer scans by case name, and this
   had been the grey subtitle underneath the description. Sized to sit on
   the same baseline as the text beside it rather than to tower over it. */
.today .duematter {
  font-family: var(--serif, Georgia, "Times New Roman", serif);
  font-size: 13px; color: var(--foreground); text-decoration: none;
  overflow-wrap: anywhere;
}
.today .duematter:hover { color: var(--primary); }

/* A long entry wraps under itself and nothing truncates mid-word. */
.today .duewhat { color: var(--foreground-soft); overflow-wrap: anywhere; }

/* THE ONE SATURATED COLOUR IN THE REGION IS THE AUTHORITY, because it is
   the only thing here that says whether the date binds him. Measured
   before this: Court Order rendered in the old mid grey, and
   "Not recorded" rendered the accent. The only authority that binds him
   was the quietest thing in its column. That inversion is what once let
   fifteen deadlines of unknown authority print like court orders. */
.today .dueauth { font-size: 11.5px; }
.today .dueauth .auth {
  border: 0; padding: 0; background: none;
  color: var(--foreground-soft);
}
.today .dueauth .auth[data-auth="court order"],
.today .dueauth .auth[data-auth="commanded"] {
  color: var(--primary); font-weight: 600;
}
.today .dueauth .auth[data-auth="unknown"] { color: var(--muted-foreground); }

/* Plain text, right aligned, no box and no red. The chips were the
   loudest objects on the page and carried the least on it. */
.today .duewhen {
  /* PINNED, BECAUSE THE SENTENCE BELOW IT TOOK THE REST OF THE ROW.
     `.duenext` spans `2 / -1`, which is right: the act that clears a
     quiet file is a sentence and not a three word chip. But it is the
     fourth child of five, so the fifth had nowhere left to go on the
     first row and auto-placement dropped it onto a second one, in
     column 1, which is the 26 pixel tick column. "311 days idle" is 64
     pixels of nowrap text in a 26 pixel box, so every quiet row on the
     morning page was spilling its day count out over the tick.

     The narrow layout below already pinned this and the wide one never
     did, which is why it survived: the page is correct on a phone and
     wrong on the screen he actually opens it on. */
  grid-column: 5; grid-row: 1;
  text-align: right; font-size: 11.5px; color: var(--muted-foreground);
  white-space: nowrap;
}
.today .duerow.quiet .duewhat { color: var(--muted-foreground); }

/* THE ACT THAT CLEARS IT GETS A LINE, NOT A COLUMN. It is a sentence,
   and the sentences run from "follow up, or call" to "alias summons, or
   move for service by publication". It sat in the 116 pixel column the
   calendar uses for a three word authority chip. */
.today .duenext {
  grid-column: 2 / -1;
  font-size: 12.5px;
  color: var(--muted-foreground);
}
.today .duenext:empty { display: none; }

@media (max-width: 900px) {
  .today .duerow { grid-template-columns: 26px minmax(0, 1fr) auto;
                   gap: 2px 12px; }
  .today .duerow > .duematter:first-child { grid-column: 2; }
  .today .duewhat { grid-column: 2 / -1; }
  .today .dueauth { grid-column: 2 / -1; }
  .today .duenext { grid-column: 2 / -1; }
  .today .duewhen { grid-column: 3; grid-row: 1; }
}

/* ------------------------------------------------------ sorting the roster

   The page is a run of piles, each with a heading that ticks all of it,
   and a bar at the foot that follows the reader down. A verdict chosen
   at the top of a hundred rows and applied at the bottom is a verdict
   nobody can see when they press it. */

.pile .cap .tickall { display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer; }
.pile .cap .tickall span { font: inherit; color: inherit; }
/* THE PILE SOMEBODY ASKED FOR, marked so the eye lands on it.

   Today says seven files are over on paper and offers "Close it", which
   opens the roster at `#over`. Arriving at the right heading with nothing
   to distinguish it from the eight headings above reads as arriving in
   the wrong place. One gold edge, which is what the firm's gold is for:
   this is the thing you came here to do. */
.pile.asked { border-left: 2px solid var(--primary); }
.pile.asked .cap { color: var(--foreground); }

.pile .instruction { color: var(--muted-foreground); font-size: 13px;
  margin: 0; padding: 8px 16px 4px; max-width: 74ch; }

table.roster { width: 100%; border-collapse: collapse; margin: 4px 0 4px; }
table.roster td { padding: 4px 8px; border-top: 1px solid var(--border);
  vertical-align: baseline; }
table.roster tr:first-child td { border-top: 0; }
table.roster td.tick { width: 30px; padding-left: 16px; }
table.roster td label { cursor: pointer; }
table.roster tr:hover { background: var(--muted); }
table.roster .peek { margin-left: 8px; font-size: 11.5px; opacity: 0;
  color: var(--muted-foreground); }
table.roster tr:hover .peek { opacity: 1; }
.quiet { color: var(--muted-foreground); text-decoration: none; }
.quiet:hover { color: var(--foreground); }
.linky { background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--primary); font: inherit; font-size: 12.5px; }
form.inline { display: inline; }

/* THERE IS NO --panel IN THIS SHEET AND THERE NEVER WAS, so the bar
   painted with nothing behind it and the roster scrolled through it. The
   card colour is what every other raised surface here uses. */
/* IT APPEARS WHEN SOMETHING IS TICKED, AND NOT BEFORE.
   It was `sticky; bottom: 0`, so a bar sat across the foot of every list
   whether or not anything was selected, permanently covering the last
   row to offer an action nobody had asked for. It is now a floating bar
   that rises when there is a selection and leaves when there is not, and
   it is only as wide as what it says. */
.applybar {
  position: fixed; left: 50%; bottom: 22px; z-index: 40;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  max-width: min(760px, calc(100vw - 48px));
  padding: 12px 16px;
  background: var(--card);
  border: 1px solid var(--border-lit);
  border-radius: var(--r-lg);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .62);
  /* Out of the way, out of the tab order, and not read aloud, until it
     has something to act on. */
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translate(-50%, 14px);
  transition: opacity .14s ease, transform .14s ease, visibility .14s;
}
.applybar.live {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translate(-50%, 0);
}
@media (prefers-reduced-motion: reduce) {
  .applybar { transition: none; }
}
/* The cross that empties the selection, beside the count it empties. */
.applybar .clearpick {
  border: 0; background: none; color: var(--muted-foreground);
  font-size: 17px; line-height: 1; cursor: pointer; padding: 0 2px;
}
.applybar .clearpick:hover { color: var(--foreground); }
.applybar .verdicts button.clearpick {
  font-size: 12.5px; padding: 4px 8px;
  border: 1px solid var(--border); border-radius: var(--r);
}
/* The destructive verdict looks like one rather than sharing a button
   with the harmless ones. */
.applybar .go.danger {
  background: transparent; color: var(--primary);
  border: 1px solid var(--primary);
}
.applybar .go.danger:hover { background: var(--raise); }
/* A ticked row looks ticked, so a run down a long list is visible and a
   mistake is visible with it. */
tr.picked > td, .duerow.picked, .proposal.picked {
  background: var(--raise);
}
.duerow.picked { box-shadow: inset 2px 0 var(--primary); }
.applybar .counted { font-size: 13px; color: var(--muted-foreground); }
.applybar .counted b { color: var(--muted-foreground); font-size: 15px; }
.applybar.live .counted b { color: var(--primary); }
.applybar .verdicts { display: flex; gap: 12px; flex-wrap: wrap;
  font-size: 12.5px; }
.applybar .verdicts label { display: inline-flex; align-items: center;
  gap: 4px; cursor: pointer; color: var(--muted-foreground); }
.applybar .why-off { display: none; }
.applybar.striking .why-off { display: inline-block; }
.applybar select { font: inherit; font-size: 12.5px; padding: 4px 4px;
  background: var(--background); color: var(--foreground);
  border: 1px solid var(--border); border-radius: var(--r); }
.applybar .why { flex: 1 1 180px; min-width: 140px; }
.applybar .verdicts { margin-left: auto; }

/* Adding a document from the case's own page. The control sits with the
   caption because that is where a person is looking when they have a
   paper for this file in their hand. */
.mhead h1 .addhere { display: inline-block; margin-left: 12px;
  vertical-align: middle; }
.mhead h1 .addhere .btn { font-size: 12.5px; padding: 4px 12px;
  font-weight: 500; }

/* WHAT AN UPLOAD IS DOING WHILE IT DOES IT. A zip of a client's records
   takes a minute to go up and another to be turned into readable pages,
   and the page used to say nothing for either: the office sent one and
   had "no idea if it worked". A bar, a count and a sentence. */
.addstate { margin: 8px 0 0; max-width: 460px; font-weight: 400; }
.addbar {
  height: 4px; border-radius: var(--r); overflow: hidden;
  background: var(--border);
}
.addbar span {
  display: block; height: 100%; width: 0;
  background: var(--primary);
  transition: width .18s ease;
}
.addsaid {
  margin-top: 4px; font-size: 12.5px; letter-spacing: 0;
  text-transform: none; color: var(--muted-foreground);
}
.addsaid.good { color: var(--primary); }
.addsaid.bad { color: var(--destructive-lit); }

/* A correction, in the lawyer's own words, on What You Said. It is the
   substance of the row and gets the weight; the heading and what the
   page was showing sit above it in the quiet style. */
.saidit { margin-top: 4px; font-size: 13px; color: var(--foreground);
  max-width: 88ch; }

/* --------------------------------------------------------- the composer

   The Write page opens on the thing a person came to do. What was here
   was a three-row textarea under a form label under a fact sheet, which
   is a search box pretending to be a place to think.

   The card is the writing surface: the matter picker and the file's
   weight sit on its top edge in the quiet style, the box itself is the
   substance, and the starters and the send sit on the bottom edge. No
   internal borders, because the whole card is one control. */

.composer { padding: 0; overflow: hidden; }
.composer form { display: block; }

.composehead {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--card) 88%, black);
}
.composehead .whichcase {
  flex: 1 1 auto; max-width: 460px;
  background: transparent; border: 1px solid transparent;
  color: var(--foreground); font: inherit; font-size: 13px;
  font-weight: 500; padding: 4px 8px; border-radius: var(--r);
}
.composehead .whichcase:hover { border-color: var(--border); }
.composehead .whichcase:focus { border-color: var(--primary); outline: none; }
.composehead .readin { font-size: 12.5px; color: var(--muted-foreground); }

.composer textarea#instruction {
  display: block; width: 100%; box-sizing: border-box;
  min-height: 154px; max-height: 62vh;
  padding: 16px 20px 12px;
  border: 0; outline: none; resize: none;
  background: transparent; color: var(--foreground);
  font-family: var(--sans, inherit); font-size: 15px; line-height: 1.62;
}
.composer textarea#instruction::placeholder {
  color: var(--muted-foreground); opacity: .72;
}
.firm-choice {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin: 0 0 0 auto;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--secondary);
}
.firm-choice legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.firm-choice label { cursor: pointer; margin: 0; }
.firm-choice input { position: absolute; opacity: 0; pointer-events: none; }
.firm-choice span {
  display: block;
  padding: 6px 9px;
  border-radius: 5px;
  color: var(--muted-foreground);
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.firm-choice input:checked + span { background: var(--primary); color: var(--primary-foreground); }
.firm-choice input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 1px; }
.draft-setting {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0; color: var(--muted-foreground);
  font-size: 10px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; white-space: nowrap;
}
.draft-setting select {
  min-width: 132px; padding: 6px 28px 6px 8px;
  border: 1px solid var(--border); border-radius: 7px;
  background: var(--secondary); color: var(--foreground);
  font: 500 12px/1.2 var(--sans, inherit); letter-spacing: 0;
  text-transform: none;
}
.signature-choice {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0; padding: 6px 9px;
  border: 1px solid var(--border); border-radius: 7px;
  color: var(--muted-foreground); font-size: 12px; white-space: nowrap;
}
.signature-choice input { accent-color: var(--primary); }
.signature-choice:has(input:checked) {
  border-color: var(--primary); color: var(--foreground);
}

/* WHAT HAS ALREADY BEEN ASKED OF THIS DOCUMENT.
   A revision is a turn in a conversation about one document, so the turns
   before it stay on screen. Quiet: this is context for the box beneath it,
   not the subject of the page. */
.turns {
  margin: 0; padding: 12px 20px 0 40px;
  list-style: decimal; color: var(--muted-foreground);
  font-size: 13px; line-height: 1.55;
}
.turns li { padding-bottom: 4px; }
.turns li::marker { font-variant-numeric: tabular-nums; }

/* The examples, as buttons rather than as a placeholder that vanishes the
   moment anybody types, which is exactly when an example is wanted. */
.starters { display: flex; flex-wrap: wrap; gap: 4px; padding: 2px 16px 12px; }
.starter {
  background: transparent; cursor: pointer;
  border: 1px solid var(--border); border-radius: 999px;
  color: var(--muted-foreground); font: inherit; font-size: 12.5px;
  padding: 4px 12px;
}
.starter:hover { border-color: var(--primary); color: var(--foreground); }

.composefoot {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--card) 88%, black);
}
.composefoot .hint { font-size: 11.5px; color: var(--muted-foreground); }
.composefoot .hint kbd {
  border: 1px solid var(--border); border-radius: var(--r);
  padding: 1px 4px; margin: 0 1px; font-size: 10.5px;
}
.composefoot .spacer { flex: 1 1 auto; }

/* A caption runs long. "Chastain, Riley Christina v. Ghee, Marshall
   Douglas et al" ran under the select's own arrow and came out clipped
   mid-word with no arrow visible. */
.composehead .whichcase { text-overflow: ellipsis; min-width: 0; }
.composehead .readin { flex: 0 0 auto; text-align: right; max-width: 30%; }

/* ------------------------------------------------ document generation

   One document, three legible states. The brief contracts while the job is
   running, the working state owns the page until paper exists, and the
   rendered pages own it afterwards. Provider machinery stays in a folded
   log rather than becoming the interface. */
.composer.is-generating { border-color: var(--border-soft); }
.composer.is-generating .composehead { border-bottom: 0; }
.active-brief {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 14px;
  align-items: baseline;
  padding: 13px 18px 15px;
  border-top: 1px solid var(--border-soft);
}
.active-brief-label {
  color: var(--primary);
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
}
.active-brief strong {
  color: var(--foreground);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.45;
}
.composer.has-job:not(.is-generating) textarea#instruction {
  min-height: 82px;
  padding-top: 13px;
  padding-bottom: 10px;
}
.composer.has-job:not(.is-generating) .composefoot { padding-block: 9px; }

.draft-progress {
  position: relative;
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) 220px;
  gap: 22px;
  align-items: center;
  max-width: 1040px;
  min-height: 310px;
  margin: clamp(28px, 7vh, 76px) auto 0;
  padding: clamp(28px, 4vw, 48px);
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: color-mix(in srgb, var(--card) 95%, var(--secondary));
  box-shadow: 0 24px 70px rgba(0,0,0,.18);
}
.draft-progress::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--primary) 18%, transparent) 30%,
    color-mix(in srgb, var(--primary) 78%, white) 50%,
    color-mix(in srgb, var(--primary) 18%, transparent) 70%,
    transparent 100%
  );
  background-size: 62% 100%;
  background-repeat: no-repeat;
  filter: drop-shadow(0 1px 4px color-mix(in srgb, var(--primary) 20%, transparent));
  opacity: .78;
  animation: draftSweep 7.2s cubic-bezier(.45, 0, .55, 1) infinite;
}
.draft-progress-mark {
  display: grid;
  place-items: center;
  width: 42px;
  height: 52px;
  border: 1px solid var(--border-lit);
  border-radius: 3px;
  color: var(--primary);
  font: 700 22px/1 var(--serif);
  box-shadow: inset 0 -3px var(--primary);
}
.draft-progress-copy { min-width: 0; }
.draft-progress-line {
  display: flex;
  align-items: center;
  gap: 12px;
  font: 700 clamp(25px, 3vw, 36px)/1.05 var(--serif);
}
.draft-progress-line strong {
  color: var(--foreground);
  opacity: 1;
  transform: translateY(0);
  transition: opacity .32s ease, transform .32s ease;
  will-change: opacity, transform;
}
.draft-progress-line strong.is-changing {
  opacity: 0;
  transform: translateY(3px);
}
.draft-stage-dots {
  display: inline-block;
  width: 1.6em;
  margin-left: -.3em;
  color: var(--foreground-soft);
  letter-spacing: .08em;
  text-align: left;
}
.draft-progress-copy > p {
  max-width: 58ch;
  margin: 10px 0 0;
  color: var(--foreground-soft);
  font-size: 14px;
  line-height: 1.55;
}
.draft-heartbeat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 9px;
  color: var(--muted-foreground-dim);
  font-size: 10.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
}
.draft-heartbeat-state { width: 9.2em; }
.draft-heartbeat-time {
  display: inline-block;
  width: 5ch;
  color: inherit;
  font-family: Consolas, "Courier New", monospace;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: 0;
  text-align: center;
}
.draft-heartbeat-status { width: 4.8em; }
.draft-heartbeat::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin: 0 7px 1px 0;
  border-radius: 50%;
  background: var(--primary);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 45%, transparent);
  animation: heartbeatPulse 1.45s ease-out infinite;
}
.process-log { margin-top: 20px; color: var(--muted-foreground); }
.process-log summary {
  width: max-content;
  cursor: pointer;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.process-log .working { margin-top: 12px; font-size: 12.5px; line-height: 1.55; }
.process-log .steps { margin-top: 8px; }
.paper-ghost {
  min-height: 225px;
  padding: 30px 24px;
  border: 1px solid var(--border-lit);
  border-radius: 3px;
  background: color-mix(in srgb, var(--foreground) 7%, var(--card));
  box-shadow: 13px 14px 0 -6px color-mix(in srgb, var(--secondary) 75%, transparent);
}
.paper-ghost i {
  display: block;
  width: 100%;
  height: 7px;
  margin-bottom: 15px;
  border-radius: 2px;
  background: linear-gradient(
    100deg,
    var(--border) 0 34%,
    color-mix(in srgb, var(--border-lit) 58%, var(--foreground-soft)) 50%,
    var(--border) 66% 100%
  );
  background-size: 240% 100%;
  transform-origin: left center;
  will-change: background-position, opacity;
  animation: paperGhostShimmer 1.8s cubic-bezier(.4, 0, .2, 1) infinite;
}
.paper-ghost i:first-child {
  width: 54%;
  height: 10px;
  margin-bottom: 28px;
  background: linear-gradient(
    90deg,
    var(--primary-dim),
    color-mix(in srgb, var(--primary) 76%, white),
    var(--primary-dim)
  );
  background-size: 220% 100%;
  will-change: background-position, opacity, transform;
  animation: paperGhostLead 2.2s ease-in-out infinite;
}
.paper-ghost i:nth-child(2) { animation-delay: -.12s; }
.paper-ghost i:nth-child(3) { width: 88%; animation-delay: -.24s; }
.paper-ghost i:nth-child(4) { width: 70%; animation-delay: -.36s; }
.paper-ghost i:nth-child(5) { width: 42%; margin-top: 35px; animation-delay: -.48s; }
@keyframes draftSweep {
  0%, 10% { background-position: -165% 0; }
  86%, 100% { background-position: 265% 0; }
}
@keyframes paperGhostShimmer {
  0% { background-position: 190% 0; opacity: .62; }
  45%, 55% { opacity: 1; }
  100% { background-position: -190% 0; opacity: .72; }
}
@keyframes paperGhostLead {
  0%, 100% { background-position: 180% 0; opacity: .64; transform: scaleX(.94); }
  50% { background-position: -80% 0; opacity: 1; transform: scaleX(1); }
}
@keyframes heartbeatPulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 45%, transparent); }
  70%, 100% { box-shadow: 0 0 0 7px transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .draft-progress::before,
  .draft-heartbeat::before,
  .paper-ghost i { animation: none; }
  .draft-progress-line strong { transition: none; will-change: auto; }
  .paper-ghost i { opacity: .78; will-change: auto; }
  .paper-ghost i:first-child { opacity: .72; transform: none; }
}

.draft-outcome {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  margin: 0 0 14px;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius);
  background: var(--card);
}
.draft-outcome-mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--primary-foreground);
  font-weight: 900;
}
.draft-outcome strong { display: block; font: 700 16px/1.15 var(--serif); }
.draft-outcome div span { display: block; margin-top: 3px; color: var(--muted-foreground); font-size: 12px; }
.draft-outcome a, .draft-outcome button {
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--primary) 55%, transparent);
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
  font: 700 11px var(--sans);
  padding: 5px 2px;
}
.draft-outcome.failed { border-left-color: var(--destructive); }
.draft-outcome.failed .draft-outcome-mark { background: var(--destructive); color: white; }
.draft-result { grid-template-columns: minmax(0, 1.7fr) minmax(280px, .55fr); }
.draft-result > div:first-child { min-width: 0; }
.draft-result #lettercard { margin-top: 0 !important; }
.draft-result .pages { max-width: 900px; margin: 0 auto; }
.draft-stopped { border-left: 3px solid var(--destructive); }

@media (max-width: 840px) {
  .draft-progress { grid-template-columns: 38px 1fr; min-height: 240px; }
  .paper-ghost { display: none; }
  .draft-result { grid-template-columns: 1fr; }
  .draft-outcome { grid-template-columns: 28px 1fr; }
  .draft-outcome > :last-child { grid-column: 2; justify-self: start; }
}

/* ---------------------------------------------- where the file stands

   Four ladders side by side. The rung the file is on is the answer and
   takes the gold; everything round it is quiet. The office asked for
   more of the gold and this is where it earns its place, on the one
   word per column a reader is looking for. */

.ladders {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1px; background: var(--border);
  border-top: 1px solid var(--border);
}
.ladders .rung { background: var(--card); padding: 12px 16px 16px; }
.ladders .k {
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted-foreground); margin-bottom: 8px;
}
.ladders .at {
  font-size: 17px; font-weight: 600; color: var(--primary);
  line-height: 1.2; text-transform: capitalize;
}
.ladders .since { font-size: 12.5px; color: var(--muted-foreground); margin-top: 4px; }
.ladders .off {
  font-size: 11.5px; color: var(--muted-foreground); margin-top: 8px;
  opacity: .78; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ------------------------------------------- what a count has to prove

   A count is a row of elements and the only thing a reader hunts for is
   the one that is empty. So an element with nothing behind it is the
   only one that carries a colour, and the gold marks the count it sits
   in rather than shouting on every line. */

.countblock { border-top: 1px solid var(--border); padding: 12px 16px 16px; }
.countblock.wanting { box-shadow: inset 3px 0 0 var(--primary); }
.counthead { font-size: 13px; margin-bottom: 8px; }
.counthead b { color: var(--primary); margin-right: 8px; font-weight: 600; }
.counthead .auth.weak { margin-left: 8px; }

.elements { display: grid; gap: 4px; }
.element {
  display: grid; grid-template-columns: 140px 118px 1fr auto;
  gap: 12px; align-items: baseline; font-size: 12.5px;
}
.element .name { color: var(--foreground); text-transform: capitalize; }
.element .stands { color: var(--muted-foreground); font-size: 11.5px; }
.element .means { color: var(--muted-foreground); font-size: 11.5px; }
.element .n { color: var(--muted-foreground); font-size: 11.5px; }
.element.nothingonfile .name { color: var(--primary); font-weight: 600; }
.element.nothingonfile .stands { color: var(--primary); }
.element.notindispute .name,
.element.notindispute .stands { opacity: .6; }

@media (max-width: 780px) {
  .element { grid-template-columns: 1fr; gap: 2px; }
}

/* Paging the docket. A page holding 1,152 and showing 500 was showing
   500, and offered a filter over words it did not print. */
.pager { display: flex; align-items: center; gap: 16px; }
.pager a { font-size: 13px; }
.pager .meta { margin-left: auto; }

/* A quoted message body is preformatted and says so in the markup, so it
   still has to wrap like prose rather than run off the side. */
pre.wrapped { white-space: pre-wrap; word-break: break-word; margin: 0; }

/* A limitations period that filing stopped. Quiet on purpose: it is the
   commonest state on the roster, 28 of 75, and it is not work. */
.stopped { color: var(--muted-foreground); font-size: 12.5px; }

/* Where the file stands: one row per track, the rung in gold and the
   newest movement carrying the width. The four-box version said about
   thirty words in sixteen lines. */
table.tracks { width: 100%; border-collapse: collapse; }
table.tracks td { padding: 8px 8px; border-top: 1px solid var(--border);
  vertical-align: baseline; font-size: 13px; }
table.tracks tr:first-child td { border-top: 0; }
table.tracks .k { width: 108px; color: var(--muted-foreground);
  font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; }
table.tracks .at { width: 150px; color: var(--primary); font-weight: 600;
  text-transform: capitalize; }
table.tracks .since { width: 150px; color: var(--muted-foreground);
  font-size: 12.5px; white-space: nowrap; }
table.tracks .moved { color: var(--muted-foreground); font-size: 12.5px; }
table.tracks .moved b { color: var(--foreground); font-weight: 500;
  margin-right: 8px; white-space: nowrap; }
/* THE TRACK'S NAME IS NOT THE THING TO DROP WHEN THE PANE NARROWS. It
   was hidden first, which left three gold words in a column with nothing
   saying which of the case, the treatment and the damages each was. The
   date it was reached goes instead: the newest movement carries a date
   of its own. */
@media (max-width: 900px) {
  table.tracks .since { display: none; }
  table.tracks .k { width: 92px; }
  table.tracks .at { width: 120px; }
}

/* The panel speaks before it lists. See surface._spoken_about_a_date. */
.inspector .isaid {
  margin: 8px 0 12px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--foreground-soft);
}
.inspector .idetails {
  display: grid;
  gap: 6px;
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
  color: var(--foreground-soft);
  font-size: 12.5px;
  line-height: 1.45;
}
.inspector .idetails[hidden] { display: none; }
.inspector .idetails li { padding-left: 13px; position: relative; }
.inspector .idetails li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 5px;
  height: 1px;
  background: var(--primary);
}

/* Where the kind of contact changes. See contactspage.html: the book is
   ordered by what somebody is to this practice, not by their initial. */
tr.bandrow > td {
  padding-top: 16px;
  font-size: 11.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  border-bottom: 1px solid var(--border-lit);
}

/* --------------------------------------------------------- on a phone

   THE OFFICE: "Totally useless as a platform on mobile viewport."

   THE RAIL WAS ONE PIXEL WIDE. `.shell` drops to a single column below
   1000px, and the topbar is placed at `grid-column: 2 / 4`, so it makes
   its own implicit tracks and the rail is squeezed into whatever is
   left, which measured 1px at 411 wide. Every other page in the
   building was unreachable: not hidden behind a control, gone.

   So the rail becomes a drawer. It lies over the page and is opened by
   the control that has always opened it, in the bar, and `railshut` is
   already the class that control toggles and already the resting state.

   AND THE BAR HAD FOUR THINGS IN IT AND ROOM FOR TWO. The search box
   printed "Search matters, parties, case and claim numbers, documents"
   over the date, which printed over the avatar. On a phone the bar
   carries the way back, where you are, and who you are; the search
   keeps its control and loses its sentence.
   ------------------------------------------------------------------ */
@media (max-width: 760px) {
  .shell {
    grid-template-columns: 1fr;
    grid-template-rows: 48px 1fr;
  }
  .topbar { grid-column: 1 / -1; padding: 0 8px; gap: 8px; }

  .rail {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: 250px;
    height: 100%;
    z-index: 70;
    /* The firm's name is the first thing in the drawer and it was
       half off the top edge: the base rail carries its own vertical
       padding and this added to it rather than replacing it. */
    padding: 16px 0 24px;
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .rail .rail-inner { opacity: 1; }
  .rail nav { flex-direction: column; flex-wrap: nowrap; }
  body:not(.railshut) .rail {
    transform: none;
    box-shadow: 18px 0 44px rgba(4, 8, 12, .6);
  }

  /* The bar. */
  .topbar .search {
    flex: none;
    width: 34px;
    max-width: none;
    padding: 4px;
    justify-content: center;
  }
  .topbar .search span,
  .topbar .search kbd { display: none; }
  .topbar .search::before { content: "\1F50D"; font-size: 13px; }
  .topbar .when { display: none; }
  .topbar .crumb {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-right: auto;
  }

  main { padding: 16px 12px 64px; }

  /* A TABLE OF RECORDS SCROLLS, IT DOES NOT CRUSH. `.scroll` has
     carried overflow-x since it was written, and without a floor on the
     table's width the columns compressed instead: a date column of 60
     pixels broke "September" across two lines and the column holding
     the buttons a person came to press was off the edge entirely. */
  .onetable table { min-width: 33rem; }
  .onetable .scroll { -webkit-overflow-scrolling: touch; }
  .tablebar { flex-wrap: wrap; gap: 4px 8px; }
  .tablebar .tablefilter { flex: 1; min-width: 10rem; }

  /* Headings and prose keep their measure without setting one. */
  .pagehead h1 { font-size: 26px; }
  h2 { font-size: 17px; }
  .note, .lede { max-width: none; }

  /* THIRTEEN TABS AND ROOM FOR THREE, WITH NOTHING SAYING SO. The bar
     scrolls, 1,151 pixels of it through a 307 pixel window, and a
     reader who cannot see that it scrolls has a matter page with three
     tabs on it. A fade at the edge is the whole of the hint needed. */
  .mtabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Safari on a phone is the browser this matters on and it still
       wants the prefix. Without it the fade is simply absent, which is
       the state this rule exists to fix. */
    -webkit-mask-image: linear-gradient(to right, #000 88%, transparent);
    mask-image: linear-gradient(to right, #000 88%, transparent 100%);
  }
  .mtabs::-webkit-scrollbar { display: none; }
  .mtabs a { white-space: nowrap; }

  /* The floating verdict bar is as wide as the phone, less its margins. */
  .applybar {
    max-width: calc(100vw - 20px);
    bottom: 12px;
    padding: 8px 12px;
    gap: 8px 12px;
  }
}

/* Two hundred and fifty pixels of drawer over a 375 pixel screen still
   leaves the page visible behind it, which is the point: the reader can
   see they are on top of something and tap it away. */
@media (max-width: 420px) {
  .rail { width: 78vw; }
}

/* ---------------------------------------------- where this case stands

   The panel that answers "what is happening on this case" above the
   sheet that answers "what is in the file". See matter.html. */
.stands { margin: 0 0 24px; }
.stands h2 { margin: 0 0 12px; }
.stands .band {
  border: 1px solid var(--border);
  border-radius: var(--r);
  margin-bottom: 8px;
  overflow: hidden;
}
.stands .band.bad { border-left: 3px solid var(--primary); }
.stands .cap {
  padding: 8px 12px;
  background: var(--muted);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-foreground);
  border-bottom: 1px solid var(--border);
}
.stands .standrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 190px 132px;
  gap: 2px 16px;
  padding: 8px 12px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  line-height: 1.45;
}
.stands .standrow:first-of-type { border-top: 0; }
.stands .standrow .what { color: var(--foreground-soft); }
.stands .standrow .what b { color: var(--foreground); font-weight: 600; }
.stands .standrow .cure { font-size: 12.5px; color: var(--muted-foreground); }
.stands .standrow .when {
  font-size: 12.5px; text-align: right; white-space: nowrap;
  color: var(--muted-foreground);
}
.stands .standrow.late .when { color: var(--primary); }
.stands .quoted { font-style: italic; }

/* On a phone each row is three lines rather than three columns, and the
   date leads because it is what is scanned for. */
@media (max-width: 760px) {
  .stands .standrow {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 2px 8px;
  }
  .stands .standrow .what { grid-column: 1 / -1; grid-row: 2; }
  .stands .standrow .cure { grid-column: 1 / -1; grid-row: 3; }
  .stands .standrow .when { grid-column: 2; grid-row: 1; text-align: right; }
}
/* The band for what is true and is not work. Quieter than the rest, and
   below it. */
.stands .band.quietband .cap { color: var(--muted-foreground-dim); }
.stands .band.quietband .standrow .what { color: var(--muted-foreground); }

/* A row that can be ticked keeps a column for the tick, so the rows that
   cannot still line up under the ones that can. */
.stands .standrow.pickable {
  grid-template-columns: 26px minmax(0, 1fr) 190px 132px;
}
.stands .standrow.pickable .tick { align-self: center; }
@media (max-width: 760px) {
  .stands .standrow.pickable { grid-template-columns: 26px minmax(0,1fr) auto; }
  .stands .standrow.pickable .what { grid-column: 2 / -1; grid-row: 2; }
  .stands .standrow.pickable .cure { grid-column: 2 / -1; grid-row: 3; }
  .stands .standrow.pickable .when { grid-column: 3; grid-row: 1; }
}

/* ------------------------------------------------ the drawer on a phone

   THREE FAULTS THE OFFICE FOUND ON A REAL HANDSET, none of which showed
   in emulation.

   It covered its own toggle, so the drawer could be opened and not
   closed. `shell.js` closes it on a tap outside and on Escape; this
   dims what it covers, so it reads as a thing lying over the page
   rather than as the page itself.

   It took 78vw, 323 points of a 414 point screen, leaving a sliver of
   the page as the only hint there was anything behind it.

   And iOS puts a fixed element under the browser's own chrome unless it
   is told about the safe area, which clipped the firm's name off the
   top of it. `dvh` for the same reason: 100vh on iOS is the height the
   page WOULD have with the URL bar hidden, so the foot of the rail sat
   below the screen. */
@media (max-width: 760px) {
  .rail {
    width: min(80vw, 300px);
    top: env(safe-area-inset-top, 0px);
    height: calc(100% - env(safe-area-inset-top, 0px));
    height: calc(100dvh - env(safe-area-inset-top, 0px));
    padding-top: 20px;
    padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  }
  body:not(.railshut) .shell::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 60;
    background: rgba(4, 8, 12, .55);
  }
}


/* THE PAPER BESIDE THE LIST. See documentspage.html: selecting a row in
   any file browser shows the thing, and here it was a navigation away and
   back. The pane takes its own share of the width and gives it back when
   it is closed, so the list is full width until there is something to
   look at. */
.docsplit { display: flex; gap: 16px; align-items: flex-start; }
.docsplit > .card { flex: 1 1 auto; min-width: 0; }
.docpane {
  flex: 0 0 clamp(340px, 42vw, 640px);
  position: sticky; top: 12px;
  display: flex; flex-direction: column;
  height: calc(100vh - 120px);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.docpanehead {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 8px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.docpanehead b {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 22ch;
}
.docpane iframe { flex: 1 1 auto; width: 100%; border: 0; background: var(--paper); }

/* A narrow screen has no room for two columns, so the pane goes under the
   list rather than squeezing both. */
@media (max-width: 1100px) {
  .docsplit { display: block; }
  .docpane { width: 100%; height: 70vh; margin-top: 16px; position: static; }
}


/* THE AGENDA. Days that carry something, in order, with the day's number
   large enough to find and the entries beside it. See deadlines.html for
   why this is a list and not a month grid. */
.agenda { display: flex; flex-direction: column; }
.agendaday {
  display: grid;
  grid-template-columns: 62px 1fr auto;
  gap: 12px; align-items: start;
  padding: 8px 12px;
  border-top: 1px solid var(--border-hair);
}
.agendaday:first-child { border-top: 0; }
.agendawhen { text-align: center; line-height: 1.15; }
.agendawhen b { display: block; font-size: 20px; font-family: var(--serif); }
.agendawhen span { display: block; font-size: 11.5px; color: var(--muted-foreground); }
.agendawhat { min-width: 0; }
.agendaline { padding: 2px 0; font-size: 13px; }
.agendaline a { margin-right: 8px; }
.agendadays { white-space: nowrap; font-size: 12.5px; }
.agendaday.gone .agendawhen b { color: var(--destructive-lit); }
.agendaday.gone .agendadays { color: var(--destructive-lit); }
.agendaday.now { background: var(--row-gold); }
.agendaday.now .agendawhen b { color: var(--primary); }

/* ================================================================
   PRACTICE DESK SHELL

   The approved desk uses one mast across the top rather than a permanent
   navigation rail.  The application remains server-rendered: these rules
   change the frame around each route, never the record each route reads.
   ================================================================ */

/* work-footer.css fills the viewport below the persistent muted radio. */
html { color-scheme: light; zoom: .95; }
html[data-theme="dark"] { color-scheme: dark; }

/* Light is the desk's resting mode. The mast and inspector deliberately
   remain navy: they are application furniture around warm paper. */
html:not([data-theme="dark"]) {
  /* Cool workstation canvas, white reading surfaces, and an opaque text
     ramp.  The old warm translucent grays changed contrast from row to row
     and made a dense register look fogged rather than quiet. */
  --background: #eef2f6;
  --foreground: #172b3d;
  --card: #ffffff;
  --secondary: #e9eef3;
  --muted: #e9eef3;
  --foreground-soft: #34495c;
  --muted-foreground: #536577;
  --muted-foreground-dim: #667789;
  --raised: #f7f9fb;
  --border: #c7d1db;
  --border-soft: #d9e1e8;
  --border-hair: #e3e9ee;
  --border-lit: #87919a;
  --hair: rgba(23, 43, 61, .16);
  --hair-soft: rgba(23, 43, 61, .10);
  --wash: #edf3f8;
  --ring: rgba(23, 43, 61, .30);
  --zebra: #f5f8fb;
  --glow: #e7f0f7;
  --raise: #e7f0f7;
  --scrim: rgba(17, 27, 37, .58);
  --late: #a61b2b;
  --calm: #5d676c;
  --light-blue-bar: #111b25;
  --light-blue-deep: #111b25;
  --light-blue-outline: #4b5b68;
  --light-blue-select: #e8edf1;
}

.shell {
  --mast-h: 64px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--insp);
  grid-template-rows: var(--mast-h) minmax(0, 1fr);
  height: 100vh;
  height: 100dvh;
  background: var(--background);
  transition: grid-template-columns .22s ease;
}

.topbar.mast {
  position: relative;
  grid-column: 1 / -1;
  grid-row: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: 285px minmax(390px, 1fr) auto;
  align-items: stretch;
  gap: 0;
  padding: 0;
  background: rgba(29, 39, 50, .99);
  border-bottom: 0;
  color: #e8e6df;
  z-index: 45;
}

.mastbrand {
  grid-column: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: 0 24px;
  border-right: 0;
  overflow: hidden;
  white-space: nowrap;
}
.mastbrand .name {
  overflow: hidden;
  text-overflow: ellipsis;
  color: #ffc500;
  font: 700 20px/1.2 var(--serif);
  letter-spacing: -.012em;
  text-rendering: optimizeLegibility;
}
.mastbrand .sub {
  margin-top: 6px;
  color: rgba(232, 230, 223, .76);
  font-size: 9px;
  font-weight: 650;
  line-height: 1;
  letter-spacing: .22em;
  text-transform: uppercase;
}

.primarynav {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  height: 100%;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: clamp(22px, 2.3vw, 34px);
  align-self: stretch;
  min-width: 0;
  padding: 0;
}
.primarynav a {
  position: relative;
  display: grid;
  place-items: center;
  width: auto;
  min-width: 0;
  flex: 0 0 auto;
  padding: 0;
  color: #e8e6df;
  font-size: 13.5px;
  font-weight: 650;
  letter-spacing: .02em;
}
.primarynav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: #ffc500;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .22s ease;
}
.primarynav a:hover,
.primarynav a:focus-visible,
.primarynav a.on { color: #ffc500; }
.primarynav a:hover::after,
.primarynav a:focus-visible::after,
.primarynav a.on::after { transform: scaleX(1); }
.primarynav a:focus-visible { outline: 1px solid rgba(255, 197, 0, .65); outline-offset: -5px; }

.masttools {
  grid-column: 3;
  align-self: stretch;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 9px;
  min-width: 0;
  padding: 0 14px;
  border-left: 0;
}
.mast .when {
  flex: 0 0 auto;
  align-self: center;
  width: 390px;
  min-width: 390px;
  margin: 0 60px 0 0;
  color: rgba(232, 230, 223, .82);
  font: 13px/1.2 var(--sans);
  font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  text-align: left;
  white-space: nowrap;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 11ch;
  align-items: center;
  column-gap: 36px;
  transform: translateX(-48px);
}
.mast .liveclock-date {
  overflow: hidden;
  text-align: right;
  text-overflow: clip;
}
.mast .liveclock-time {
  width: 11ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.mast .who,
.mast .masticon,
.mast .railtoggle {
  width: 29px;
  height: 29px;
  flex: none;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .20);
  border-radius: 50%;
  background: rgba(58, 108, 156, .12);
  color: #e8e6df;
  font: 11px/1 var(--sans);
  cursor: pointer;
}
.mast .who { border-color: rgba(255, 255, 255, .30); }
.account-menu {
  position: relative;
  flex: none;
}
.account-menu > summary {
  list-style: none;
}
.account-menu > summary::-webkit-details-marker { display: none; }
.account-menu[open] > .who,
.account-menu > .who:hover,
.account-menu > .who:focus-visible {
  border-color: #ffc500;
  color: #ffc500;
  outline: none;
}
.account-popover {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 90;
  width: 190px;
  padding: 12px;
  display: grid;
  gap: 5px;
  border: 1px solid #3b4d5a;
  border-radius: 7px;
  background: #1d2732;
  color: #e8e6df;
  box-shadow: 0 14px 38px rgba(4, 8, 12, .38);
  font: 12px/1.35 var(--sans);
}
.account-popover strong { font-size: 13px; }
.account-popover > span { color: rgba(232, 230, 223, .60); }
.account-popover form { margin-top: 6px; }
.account-popover .workspace-scope {
  display: grid;
  gap: 6px;
  padding: 8px 0 10px;
  border-top: 1px solid rgba(255, 255, 255, .12);
  border-bottom: 1px solid rgba(255, 255, 255, .12);
}
.account-popover .workspace-scope > span {
  color: rgba(232, 230, 223, .60);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.account-popover .workspace-scope label {
  display: flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
}
.account-popover .workspace-scope input { accent-color: #ffc500; }
.account-popover button,
.account-popover a {
  width: 100%;
  min-height: 32px;
  display: grid;
  place-items: center;
  padding: 0 10px;
  border: 1px solid rgba(255, 197, 0, .58);
  border-radius: 5px;
  background: rgba(255, 197, 0, .08);
  color: #ffc500;
  font: 700 12px/1 var(--sans);
  cursor: pointer;
}
.account-popover button:hover,
.account-popover button:focus-visible,
.account-popover a:hover,
.account-popover a:focus-visible {
  background: #ffc500;
  color: #111b25;
  outline: none;
}
.mast .theme-toggle { color: #ffc500; font-size: 13px; }
.mast .masticon:hover,
.mast .masticon:focus-visible,
.mast .railtoggle:hover,
.mast .railtoggle:focus-visible { border-color: #ffc500; color: #ffc500; outline: none; }
.mast .masticon.search {
  position: fixed;
  right: calc(var(--insp) + 136px);
  bottom: 18px;
  z-index: 70;
  width: 38px;
  height: 38px;
  max-width: none;
  gap: 0;
  background: #1d2732;
  border-color: rgba(255, 197, 0, .55);
  box-shadow: 0 8px 22px rgba(29, 39, 50, .24);
  transition: right .22s ease, border-color .15s ease, color .15s ease;
}
.assistant-launch{background:#ffc500;border:1px solid rgba(17,27,37,.22);border-radius:50%;bottom:18px;box-shadow:0 12px 30px rgba(17,27,37,.26),inset 0 1px rgba(255,255,255,.55);color:#1d2732;cursor:pointer;display:grid;height:48px;padding:0;place-items:center;position:fixed;right:calc(var(--insp) + 18px);transition:right .22s ease,transform .2s ease,box-shadow .2s ease,opacity .15s ease;width:48px;z-index:74}.assistant-launch:hover,.assistant-launch:focus-visible{box-shadow:0 16px 36px rgba(17,27,37,.32),inset 0 1px rgba(255,255,255,.55);outline:none;transform:translateY(-2px)}.assistant-launch[aria-expanded="true"]{opacity:0;pointer-events:none;transform:translateY(8px)}.assistant-launch svg{height:21px;stroke-width:1.8;width:21px}.assistant-dock{--background:#15232e;--foreground:#f4f0e6;--foreground-soft:#c7d0d6;--muted-foreground:#aeb9c0;--muted-foreground-dim:#94a2ac;--card:#172631;--secondary:#203441;--muted:#203441;--border:#3b4d5a;--border-soft:#2d404d;--border-lit:#647682;background:var(--background);border:1px solid #3b4d5a;border-radius:10px;bottom:18px;box-shadow:0 22px 60px rgba(4,8,12,.45);color:var(--foreground);display:flex;flex-direction:column;height:min(620px,calc(100dvh - 36px));overflow:hidden;position:fixed;right:calc(var(--insp) + 18px);transition:right .22s ease;width:min(430px,calc(100vw - 24px));z-index:73}.assistant-dock[hidden]{display:none}.assistant-dock>header{align-items:center;background:#203441;border-bottom:1px solid #3b4d5a;display:flex;justify-content:space-between;padding:13px 15px}.assistant-dock>header div{display:grid;gap:4px}.assistant-dock>header small{color:#ffc500;font:700 9px/1 Arial,sans-serif;letter-spacing:.13em;text-transform:uppercase}.assistant-dock>header strong{font:700 18px/1.1 Georgia,"Times New Roman",serif}.assistant-dock>header button{background:none;border:0;color:#c7d0d6;cursor:pointer;font-size:22px}.assistant-dock .chat{height:auto;min-height:0;flex:1}.assistant-dock .chat-thread{padding:16px}.assistant-dock .chat-column{max-width:none}.assistant-dock .chat-empty{padding-top:24px}.assistant-dock .chat-empty h2{font-size:22px}.assistant-dock .chat-composer{background:#15232e;border-top:1px solid #2d404d;padding:13px 14px 14px}.assistant-dock .chat-box{border-color:#526572;border-radius:8px;min-height:92px;padding:11px 12px 10px}.assistant-dock .chat-box:focus-within{border-color:#ffc500;box-shadow:0 0 0 1px rgba(255,197,0,.22)}.assistant-dock .chat-box textarea{color:#f4f0e6;font-size:14px;line-height:1.45;min-height:40px;padding:0 1px 8px}.assistant-dock .chat-box textarea::placeholder{color:#aeb9c0;opacity:1}.assistant-dock .chat-actions{min-height:30px;padding-top:3px}.assistant-dock .chat-send{height:32px;width:32px}.assistant-dock .chat-hint{display:none}.assistant-dock .chat-turn{margin-bottom:18px}.assistant-dock .chat-prose{font-size:13.5px;line-height:1.55}
.mast .masticon.search > span { display: block; flex: none; font-size: 15px; }
.mast .masticon.search kbd { display: none; }

.workspace-menu { position: relative; }
.workspace-menu > summary {
  list-style: none;
  min-height: 29px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 9px;
  border: 1px solid rgba(255,255,255,.16);
  border-radius: 6px;
  color: rgba(232,230,223,.78);
  font-size: 11px;
  cursor: pointer;
}
.workspace-menu > summary::-webkit-details-marker { display: none; }
.workspace-menu > summary::after { content: "+"; color: #ffc500; }
.workspace-menu[open] > summary,
.workspace-menu > summary:hover { border-color: rgba(255,197,0,.55); color: #fff; }
.workspace-menu[open] > summary::after { content: "\2212"; }
.workspace-popover {
  position: absolute;
  top: calc(100% + 9px);
  right: 0;
  width: min(620px, calc(100vw - 24px));
  display: grid;
  grid-template-columns: repeat(4, minmax(120px, 1fr));
  gap: 1px;
  padding: 1px;
  border: 1px solid var(--brand-blue-border);
  border-radius: 7px;
  background: var(--brand-blue-raised);
  box-shadow: 0 18px 48px rgba(4, 8, 12, .34);
  overflow: hidden;
  z-index: 80;
}
.workspace-popover section { min-width: 0; padding: 10px; background: #1d2732; }
.workspace-popover h2 {
  margin: 0 0 6px;
  color: rgba(232,230,223,.42);
  font: 700 9px/1.2 var(--sans);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.workspace-popover a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 4px;
  color: rgba(232,230,223,.78);
  font-size: 11.5px;
}
.workspace-popover a:hover { color: #ffc500; }
.workspace-popover .n { color: rgba(232,230,223,.46); font-variant-numeric: tabular-nums; }

/* Light mode changes the reading surfaces below the mast, not the mast
   itself. Keeping one navy frame and one geometry prevents a theme change
   from moving navigation, tools, or the live clock. */
html:not([data-theme="dark"]) .onetable {
  overflow: hidden;
  border: 1px solid #cbbda7;
  border-radius: 7px;
  background: #f8f3e9;
  box-shadow: 0 0 0 1px rgba(24,87,136,.06);
}
html:not([data-theme="dark"]) .onetable thead th {
  background: #141c29;
  border-bottom-color: var(--light-blue-outline);
  box-shadow: inset 0 -1px var(--light-blue-outline);
  color: #fff;
}
html:not([data-theme="dark"]) .onetable tr.sel td,
html:not([data-theme="dark"]) .onetable tr.picked td {
  background: #ead9bc !important;
  box-shadow: inset 0 -2px 0 var(--primary);
  color: var(--foreground);
}
html:not([data-theme="dark"]) .onetable tbody td {
  background: #f8f3e9;
  border-bottom-color: #cbbda7;
}
html:not([data-theme="dark"]) .onetable tbody tr:nth-child(even) td {
  background: #f3ecdf;
}
html:not([data-theme="dark"]) .onetable tbody tr.group td {
  background: #eee5d7;
}
html:not([data-theme="dark"]) .onetable tbody tr:not(.group):hover td {
  background: #efe2cf;
}
html:not([data-theme="dark"]) .onetable tbody tr.opens td {
  transition: background-color .16s ease, box-shadow .16s ease;
}
html:not([data-theme="dark"]) .onetable tbody tr.opens:hover td {
  background: #efe2cf;
  box-shadow: inset 0 -1px 0 rgba(255,197,0,.72);
}
html:not([data-theme="dark"]) .val[data-fact]:hover,
html:not([data-theme="dark"]) .val[data-deadline]:hover {
  border-bottom-color: transparent;
  color: inherit;
  text-decoration: underline var(--primary) 2px;
  text-underline-offset: .24em;
}
html:not([data-theme="dark"]) .val[data-fact].sel:not(.inspect-word),
html:not([data-theme="dark"]) .val[data-deadline].sel:not(.inspect-word) {
  background: var(--light-blue-select);
  box-shadow: inset 0 -2px 0 var(--primary);
  color: var(--foreground);
}

@media (prefers-reduced-motion: reduce) {
  html:not([data-theme="dark"]) .primarynav a::after,
  html:not([data-theme="dark"]) .onetable tbody tr.opens td {
    transition: none;
  }
}

.shell > main {
  grid-column: 1;
  grid-row: 2;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  background: var(--background);
}
.shell > .inspector {
  grid-column: 2;
  grid-row: 2;
  height: 100%;
  top: 0;
  /* A wide register may own a scrollable canvas. Keep that canvas from
     painting over an Inspector that is already open and populated. */
  position: relative;
  z-index: 20;
  /* The inspector stays a dark evidence surface in both themes. */
  --background: #1d2732;
  --foreground: #e8e6df;
  --card: #223442;
  --secondary: #263947;
  --muted: #263947;
  --foreground-soft: rgba(232, 230, 223, .72);
  --muted-foreground: rgba(232, 230, 223, .55);
  --muted-foreground-dim: rgba(232, 230, 223, .38);
  --border: #334755;
  --border-soft: #2a3d4b;
  --border-lit: #536675;
}

@media (max-width: 1200px) {
  .shell > .inspector {
    top: var(--mast-h);
    height: calc(100vh - var(--mast-h));
    height: calc(100dvh - var(--mast-h));
  }
}

@media (max-width: 1180px) {
  .topbar.mast { grid-template-columns: 230px minmax(360px, 1fr) auto; }
  .mast .when { display: none; }
  .primarynav {
    position: static;
    width: auto;
    height: auto;
    transform: none;
    grid-column: 2;
    gap: clamp(14px, 2vw, 24px);
  }
  .primarynav a { width: auto; min-width: 0; flex: 0 0 auto; padding: 0; }
}

@media (max-width: 820px) {
  .shell { --mast-h: 100px; }
  .topbar.mast {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: 52px 48px;
  }
  .mastbrand { grid-column: 1; grid-row: 1; border-right: 0; padding-inline: 14px; }
  .masttools { grid-column: 2; grid-row: 1; padding-inline: 10px; }
  .primarynav {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-content: stretch;
    gap: 0;
    border-top: 1px solid rgba(255,255,255,.055);
    padding: 0 4px;
  }
  .primarynav a { flex: 1 1 0; min-width: 0; padding: 0 3px; font-size: 11px; }
  .workspace-popover { grid-template-columns: repeat(2, minmax(120px, 1fr)); }
  .mast .masticon.search { right: 12px; bottom: 12px; width: 36px; height: 36px; }
  .mast .masticon.search > span { font-size: 13px; }
  .shell > .inspector {
    top: var(--mast-h);
    height: calc(100dvh - var(--mast-h));
  }
}

@media (max-width: 470px) {
  .mastbrand .name { font-size: 15px; }
  .mastbrand .sub { letter-spacing: .22em; }
  .primarynav a { font-size: 9.5px; letter-spacing: 0; }
  .workspace-menu > summary { width: 29px; justify-content: center; padding: 0; font-size: 0; }
  .workspace-menu > summary::before { content: "\22EF"; font-size: 16px; }
  .workspace-menu > summary::after { display: none; }
  .workspace-popover { position: fixed; top: 48px; right: 8px; }
}

/* Calls is a bounded register; the complete call remains one click away in
   the transcript Inspector rather than making a preview row a wall of text. */
.calls-desk .call-summary {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

html[data-theme="dark"] .calls-desk .call-open {
  border-bottom-color: rgba(255,197,0,.42);
  color: #f3f0e8;
}

@media (max-width: 820px) {
  body.inspecting .assistant-launch { display: none; }
}

/* Responsive contract for every page.  Dense evidence tables keep their
   own horizontal scroller; the document itself must never become wider than
   the viewport.  The orientation rules below keep the same contract when a
   phone is rotated, where height is the tighter constraint. */
html, body { max-width: 100%; overflow-x: hidden; }
/* 100%, not 100vw: html is zoomed to .95, and 100vw inside it renders
   as 95% of the window, which left a blank strip down the right. */
.app-host, .app-view-root { min-width: 0; max-width: 100%; }
#app-view { display: block; min-width: 0; max-width: 100%; }
.shell > main { min-width: 0; overflow-x: hidden; }
.shell > main > * { min-width: 0; max-width: 100%; }
.card, .sheet, .sheet2, .panel, .pagehead, .head, .tablebar,
.applybar, .formrow, .actionbar { min-width: 0; max-width: 100%; }
input, select, textarea, button { max-width: 100%; }
img, svg, video, canvas { max-width: 100%; }

@media (max-width: 760px) {
  .shell > main { padding-inline: max(12px, env(safe-area-inset-left)) max(12px, env(safe-area-inset-right)); }
  .pagehead, .head, .tablebar, .applybar, .actionbar { flex-wrap: wrap; }
  .pagehead > *, .head > *, .tablebar > *, .applybar > *, .actionbar > * { min-width: 0; }
  .pagehead h1, .head h1, .pagehead h2, .head h2 { overflow-wrap: anywhere; }
  .buttonrow, .actions, .toolbar { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .formrow { grid-template-columns: 1fr; }
  .formrow > label, .formrow > .field { min-width: 0; }
}

/* Landscape phones and short split-screen windows.  Keep the navigation
   usable while returning vertical space to the page and footer. */
@media (orientation: landscape) and (max-width: 900px) and (max-height: 600px) {
  .shell { --mast-h: 64px; }
  .topbar.mast { grid-template-rows: 34px 30px; }
  .mastbrand { padding-inline: 10px; }
  .mastbrand .name { font-size: 14px; }
  .mastbrand .sub, .mast .when { display: none; }
  .masttools { padding-inline: 6px; }
  .primarynav a { font-size: 10px; }
  .shell > .inspector { top: var(--mast-h); height: calc(100dvh - var(--mast-h)); }
  .shell > main { padding-top: 10px; padding-bottom: 10px; }
  .assistant-dock { bottom: 8px; height: calc(100dvh - 16px); }
}
