/* CaseRover type system v1 — 2026-07-31
   7 sizes, 4 weights, one family, one uppercase-label spec.
   Absolute px everywhere: never size a child in em, or the 10.5625px class returns.
   Ship note: bump framework.assets.version + AssetVersioningTest::ASSET_FINGERPRINT. */

/* The family is self-hosted: two variable woff2 files under public/fonts/, built from
   the OFL upstream (google/fonts ofl/publicsans) with fontTools varLib.instancer +
   pyftsubset - wght clamped to 300-700 with a 400 default, subset to latin +
   latin-ext. License text ships beside them at public/fonts/OFL.txt.

   One file per style covers every weight the ladder uses, so there is no @import and
   no third-party request: the Google Fonts <link> this replaced cost a DNS lookup, a
   TLS handshake and a render-blocking stylesheet before the first byte of font data.
   base_admin.html.twig preloads the roman face, because this file is the last
   stylesheet in the head and the preload scanner would otherwise not reach the
   @font-face until the CSSOM is built.

   No unicode-range: each file IS the subset, so declaring a narrower range than the
   file contains would strand the latin-ext glyphs it was built to carry.

   Rebuilding: instance to wght=300:400:700, subset to latin + latin-ext, and give the
   new file a NEW NAME. These url()s are literal, so framework.assets.version cannot
   bust them the way it busts asset() URLs, and the fonts are served under the same
   ten-year cache header as everything else in public/ - a rebuilt font at the same
   filename would never reach a browser that has the old one. Renaming here also
   edits this stylesheet, which is what the digest and the version bump then cover. */

@font-face{font-family:"Public Sans";
  src:url(/fonts/public-sans-var-latin.woff2) format("woff2");
  font-weight:300 700;font-style:normal;font-display:swap}
@font-face{font-family:"Public Sans";
  src:url(/fonts/public-sans-var-italic-latin.woff2) format("woff2");
  font-weight:300 700;font-style:italic;font-display:swap}

:root{
  --cr-font: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif;

  /* the ladder — 7 steps, nothing between them */
  --cr-size-display: 24px;   /* money meter, dropzone            */
  --cr-size-title:   20px;   /* page title / breadcrumb head     */
  --cr-size-head:    16px;   /* card heading                     */
  --cr-size-prose:   15px;   /* long-form reading text (/docs) - the only 15px surface.
                                RENAMED 2026-08-01: declared as the *ident* step, named
                                for the identity strip, which turned out to want 16 -
                                one step down rather than two, because 15 would take 2px
                                off the most-read line in the app to satisfy a token.
                                The old-name alias briefly kept beside it had no
                                consumer and is gone (review 2026-08-01) - a second name
                                for one step is how "7 sizes" quietly becomes eight. */
  --cr-size-body:    14px;   /* base                             */
  --cr-size-data:    13px;   /* table + ledger rows. DECIDED 2026-07-31:
                                the cases list moves from 14px to this. */
  --cr-size-label:   11px;   /* uppercase labels, badges — FLOOR */

  --cr-w-reg:400;   /* @kind font */
  --cr-w-med:500;   /* @kind font */
  --cr-w-semi:600;  /* @kind font */
  --cr-w-bold:700;  /* @kind font */

  --cr-lh-tight:1.15; /* @kind font */
  --cr-lh-data:1.35;  /* @kind font */
  --cr-lh-body:1.45;  /* @kind font */
  --cr-lh-prose:1.65; /* @kind font */  /* long-form reading only — /docs. Addendum ruling 2. */

  --cr-track-display:-.02em;   /* -0.48px at 24 */
  --cr-track-title:-.01em;
  --cr-track-label:.06em;      /* 0.66px at 11 — the one uppercase tracking */
  --cr-track-ident:.01em;

  /* label grey re-derived for 11px: old #98a4b3 is 2.6:1 on #fff and fails.
     Re-run ContrastTokenCssTest against these. */
  --cr-ink:#2f3b49; --cr-ink-2:#4b5b6d; --cr-label-ink:#67788c;
}

body{font-family:var(--cr-font);font-size:var(--cr-size-body);font-weight:var(--cr-w-reg);line-height:var(--cr-lh-body);color:var(--cr-ink-2)}
/* tabular-nums is NOT on body — it would inherit into "Other Filings", which
   deliberately doesn't have it. Applied per-class instead. */

.cr-display{font-size:var(--cr-size-display);font-weight:var(--cr-w-bold);letter-spacing:var(--cr-track-display);line-height:var(--cr-lh-tight);font-variant-numeric:tabular-nums;color:var(--cr-ink)}
.cr-title{font-size:var(--cr-size-title);font-weight:var(--cr-w-semi);letter-spacing:var(--cr-track-title);line-height:var(--cr-lh-tight);color:var(--cr-ink)}
.cr-title-prefix{font-weight:var(--cr-w-reg);color:var(--cr-label-ink)} /* replaces .fw-light 300 + .text-muted; the
                                                                           breadcrumb prefix is small text, so it takes
                                                                           the AA-passing grey rather than a lighter one */
.cr-head{font-size:var(--cr-size-head);font-weight:var(--cr-w-semi);line-height:1.25;color:var(--cr-ink)}
.cr-ident{font-size:var(--cr-size-prose);font-weight:var(--cr-w-bold);letter-spacing:var(--cr-track-ident);line-height:1.3;color:var(--cr-ink);font-variant-numeric:tabular-nums}
.cr-body{font-size:var(--cr-size-body);font-weight:var(--cr-w-reg);line-height:var(--cr-lh-body)}
.cr-body-strong{font-size:var(--cr-size-body);font-weight:var(--cr-w-semi);line-height:var(--cr-lh-body);color:var(--cr-ink)}
.cr-data{font-size:var(--cr-size-data);font-weight:var(--cr-w-reg);line-height:var(--cr-lh-data);font-variant-numeric:tabular-nums}
.cr-data-strong{font-size:var(--cr-size-data);font-weight:var(--cr-w-semi);line-height:var(--cr-lh-data);font-variant-numeric:tabular-nums;color:var(--cr-ink)}
.cr-money{font-size:var(--cr-size-data);font-weight:var(--cr-w-bold);line-height:var(--cr-lh-data);font-variant-numeric:tabular-nums;color:var(--cr-ink)}

/* ONE uppercase label spec. Replaces all five surface variants:
   field labels, milestone captions, table headers, ledger keys, badge text. */
.cr-label{font-size:var(--cr-size-label);font-weight:var(--cr-w-semi);line-height:14px;
  letter-spacing:var(--cr-track-label);text-transform:uppercase;color:var(--cr-label-ink)}
.cr-label--ink{color:var(--cr-ink-2)}                                 /* on tinted rows */
.cr-badge{font-size:var(--cr-size-label);font-weight:var(--cr-w-semi);line-height:14px;
  letter-spacing:.04em;text-transform:uppercase;padding:1px 6px;border-radius:4px;display:inline-block;white-space:nowrap}

/* The identifier idiom — no second family. Use instead of a .mono class. */
.cr-ident-inline{font-weight:var(--cr-w-med);letter-spacing:.01em;font-variant-numeric:tabular-nums lining-nums}

/* THE IDIOM MUST NOT RESTATE A SURFACE'S OWN WEIGHT.
   Reported 2026-08-01: on Case Details the copyable values read LIGHTER than
   the ones beside them - claim/policy/index at 500, every other field value at
   700 - which looks like copyability is being signalled by weight. It is not;
   it is the idiom's 500 (0,1,0) beating the panel's own .field-value rule,
   which applies to the parent and so never reaches the marker inside it.
   Round 4 introduced that when it put the idiom on three values that had been
   700 since the panel was built.

   The idiom's job on this surface is tabular lining figures and a little
   tracking, so identifiers align and 0/O read apart. Weight belongs to the
   surface - the same reasoning that keeps the injured party name on whatever
   type the identity strip gave it. Scoped rather than removing the idiom's
   default weight outright, since a standalone .cr-ident-inline elsewhere has
   no surface weight to inherit. */
.case-details .field .field-value .cr-ident-inline,
.case-details .field .field-value.cr-ident-inline {
  font-weight: inherit;
}

/* Deliberate omission, kept: "Other Filings" never sets font-variant-numeric.
   _filings_table.html.twig:205 is a COMMENT explaining that omission — there is no
   declaration there to change. So: do not add tnum to that list, and do not let the
   body-level tabular-nums below inherit into it. That means the body rule must NOT be
   global; scope it to tables and money, as below. */
.cr-no-tnum{font-variant-numeric:normal}  /* only if a future global rule forces it */

/* Retired: font-weight:650 (.neg-head, the settlement ledger's header row) -> 700.
   Retired: .fw-light / weight 300 anywhere in the UI.
   Retired sizes: 26 25.6 22 19.2 19 18 17 16.8 15.2 12.5 12 11.9 11.5 11.375 10.5625 10. */

/* ══ App integration ═══════════════════════════════════════════════════════
   Everything above is the canonical spec, authored by the design package and
   left verbatim. Everything below wires this app's EXISTING selectors onto it.

   Why selectors and not classes: the template tests pin exact class="..."
   strings, Sonata generates much of the markup from the ShowMapper, and
   style.css:161 is an eight-class chain that a 0,1,0 .cr-label could never
   out-specify. So the retired declarations are deleted at source and each
   selector is listed here instead - no competing rule is left behind for
   specificity to arbitrate. New markup should use the .cr-* classes. */

/* ── The one uppercase label spec ──────────────────────────────────────────
   Eleven rules collapse to this; each used its own size, weight and tracking
   (12/500/1px, 11/700/.5px, 10/700/.06em, 11.5/600/1px ...). Two of the
   eleven were byte-identical duplicates of a sibling and are simply gone.
   The brand wordmark is deliberately absent from this list: it is a wordmark,
   not a label, and it keeps its own 15px/0.8px treatment in style.css. */
.sonata-ba-view .object-show .field .field-label,
.card.sonata-ba .card-body .case-section.information .object-show .field .field-label,
.active-filing-panel .field-label,
.case-details .case-details-caption,
.case-details .case-pinned-label,
.case-details .case-pinned-bar .case-pinned-status,
.active-filing-panel .filing-track-label,
.neg-ledger .neg-det-key,
.neg-ledger .neg-foot-key,
.sonata-ba-list-fragment tfoot .table-totals-label,
.cr-auth-label,
.docs-toc-heading,
.docs-drawer-eyebrow {
  font-size: var(--cr-size-label);
  font-weight: var(--cr-w-semi);
  line-height: 14px;
  letter-spacing: var(--cr-track-label);
  text-transform: uppercase;
  color: var(--cr-label-ink);
}

/* Colour is the one thing a label surface may keep, and these four do: a
   label on a tinted row needs the darker ink, the ledger keys ride the
   ledger-local tokens that ContrastTokenCssTest pins, and the drawer eyebrow
   is accented on purpose. Restated after the shared rule because they lose on
   source order otherwise - the metrics converge, the colour does not. */
.case-details .case-pinned-bar .case-pinned-status,
.sonata-ba-list-fragment tfoot .table-totals-label,
.cr-auth-label { color: var(--cr-ink-2); }
.neg-ledger .neg-det-key,
.neg-ledger .neg-foot-key { color: var(--neg-faint); }
.docs-toc-heading { color: var(--docs-muted); }
.docs-drawer-eyebrow { color: var(--docs-primary); }

/* ── The badge box ─────────────────────────────────────────────────────────
   BadgeContrastLayoutTest pins badge COLOURS and nothing else - no height,
   padding, line-height or size assertion anywhere in it - so the box is ours.
   Colour stays with the theme and with the app-wide contrast repair inlined
   in base_admin.html.twig; only the metrics come from here.

   text-transform is deliberately NOT among them, and .cr-badge's uppercase
   must never be widened onto this selector. `.badge` is worn app-wide by text
   that is content rather than a label: the case-status chip renders a firm's
   own Term names (`3a - Billing - Denied`), the filing state badge renders a
   sentence (`Withdrawn - with prejudice`), the ledger renders `{{ n }} rounds`
   and a `|capitalize`d status. Uppercasing those discards casing an operator
   chose and makes short runs spell out letter-by-letter in a screen reader.
   New markup that IS a short tag opts in with .cr-badge. */
.badge {
  font-size: var(--cr-size-label);
  font-weight: var(--cr-w-semi);
  line-height: 14px;
  letter-spacing: .04em;
  padding: 1px 6px;
}

/* ── The data step ─────────────────────────────────────────────────────────
   13px, decided 2026-07-31. Scoped to Bootstrap's .table and DataTables, so
   the two frozen documents (which use .doc-table, never .table) are untouched
   and print.css keeps its pt sizes. font-variant-numeric is deliberately NOT
   set here and never on body: it would inherit into "Other Filings", whose
   omission of it is deliberate (see _filings_table.html.twig). */
.table > :not(caption) > * > *,
table.dataTable > :is(thead, tbody, tfoot) > tr > :is(th, td) {
  font-size: var(--cr-size-data);
}

/* ══ Addendum 2026-08-01 ═══════════════════════════════════════════════════
   Two rulings from the design package, closing the questions in its
   NOTES-open-questions.md. Neither adds a size to the ladder - a scale that
   grows an exception per surface stops being a scale. */

/* ── Ruling 1: the 11px floor governs TEXT ─────────────────────────────────
   A single glyph inside a bounded shape is an ICON and is out of scope. The
   exception is closed by four conditions, ALL of which must hold:

     (a) exactly one character, and
     (b) it is an affordance - nothing is read from it, and
     (c) it sits in a bounded shape that is itself the target, and
     (d) an accessible name carries the meaning, OR the glyph is hidden from
         assistive technology and the meaning is named elsewhere.

   Condition (d) was widened 2026-08-01: it originally named `aria-label` as
   the only mechanism, which the shipped markup satisfies by a stronger route
   and would have failed on a literal reading. The `?` mark is
   `aria-hidden="true"` inside a focusable `.cr-help` whose accessible name
   comes from the `.cr-help-text` sentence - so nothing reads the glyph and
   removing it would lose no information, which is the actual point of the
   condition. Fail any one and it is text and takes the 11px floor.

   Restated in px. The ban on relative units is absolute and covers sanctioned
   exceptions too: `.625rem` drifts with a root-size change, `10px` does not.

   The real defect here was never the type - it was the TARGET. A 16px circle
   is a 16px hit target and WCAG 2.2 SC 2.5.8 (AA) wants 24x24 CSS px. The
   ::after grows the target inside the existing circle: transparent, absolutely
   positioned, so there is no visual change and no reflow. Declared here rather
   than in the fragment because the fragment's <style> renders later and would
   win on source order at equal specificity. */
.cr-help-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: 1px solid var(--bs-border-color, #d9dee3);
  border-radius: 50%;
  font-size: 10px;                 /* SANCTIONED icon exception - was .625rem */
  font-weight: var(--cr-w-semi);
  line-height: 1;
  color: var(--cr-label-ink);
  position: relative;
}
.cr-help-mark::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  transform: translate(-50%, -50%);
}

/* ── Ruling 2: /docs is the same ladder at different steps ─────────────────
   Not a second scale. The ladder governs SIZE; it never governed leading or
   measure, and running prose needs its own of both - hence --cr-lh-prose and
   the measure token, not a --docs-* type scale.

   Body prose is 15px, not 14: reading text sits a step above data text, 15 is
   already on the ladder, and it is within 0.2px of today so the guide does not
   reflow. Every rem/em converts to px, because `0.95rem` / `1.6rem` / `0.85em`
   are precisely the mechanism that produced 15.2 / 25.6 and the fractional
   chain the original audit found. `code` was the worst of them: being `em` it
   rendered ~21.8px inside an h1 and ~12.9px inside a paragraph - one rule, two
   sizes, neither on the ladder.

   The measure (`--docs-measure`) stays declared in docs.css, which is also
   where `.docs-content` keeps its own `max-width` - ContentWidthUncapTest pins
   both there, since that measure is the only thing holding guide prose to a
   readable width now the page container has none. */
.docs-content { font-size: var(--cr-size-prose); line-height: var(--cr-lh-prose); }
.docs-content h1 {
  font-size: var(--cr-size-display);
  font-weight: var(--cr-w-bold);
  line-height: var(--cr-lh-tight);
  letter-spacing: var(--cr-track-display);
}
.docs-content h2 {
  font-size: var(--cr-size-title);
  font-weight: var(--cr-w-semi);
  line-height: 1.3;
  letter-spacing: var(--cr-track-title);
}
.docs-content h3 { font-size: var(--cr-size-head); font-weight: var(--cr-w-semi); line-height: 1.35; }
.docs-content code { font-size: var(--cr-size-data); }
.docs-content table { font-size: var(--cr-size-data); font-variant-numeric: tabular-nums; }
.docs-content hr + p { font-size: var(--cr-size-data); color: var(--docs-muted); }

/* The drawer is a panel, not a page: the same steps, one down. */
.docs-drawer .docs-content { font-size: var(--cr-size-body); }
.docs-drawer .docs-content h2 { font-size: var(--cr-size-head); }
.docs-drawer .docs-content h3 { font-size: var(--cr-size-body); font-weight: var(--cr-w-semi); }
.docs-drawer .offcanvas-title {
  font-size: var(--cr-size-head);
  font-weight: var(--cr-w-semi);
  line-height: 1.25;
}

/* ══ Addendum 2026-08-01 (second) - the case screen's one-off sizes ════════
   The convergence had covered labels, badges, the data step and the retired
   weights, and stopped. It never reached the money display, the identity
   strip or the fold control, because the original audit inventoried sizes BY
   FREQUENCY: labels appeared 34 times, badges ~200, the data step 993 - and
   each of these appears once. A frequency-ordered audit is blind to the
   one-off, and the "Retired sizes" line above reads like a decision when it
   was a list of numbers with nothing wired to them.

   Sharpest version: two of the one-offs were --cr-size-display's own
   documented examples. The token is commented "money meter, dropzone"; the
   meter rendered 22px and the dropzone 26px. A token whose named use cases do
   not use it is not a token, it is a comment.

   THESE ARE NOT DROP-IN OVERRIDES. information.html.twig emits its <style> in
   the BODY, after this sheet is linked in <head>, at the same specificity - so
   on a tie the template wins on source order and nothing here applies. The
   four declarations it used to carry (identity value 1.0625rem, money balance
   1.375rem, sub-line .75rem, fold control .75rem) are deleted there rather
   than shadowed: raising specificity here would "work" and leave two competing
   declarations for one surface, which is the condition this exercise exists to
   remove.

   THE GOVERNING RULE, which is the part worth keeping: the question is not who
   wrote the declaration, it is WHOSE CONTENT the element renders.

     Renders app content  -> the ladder governs it, whatever stylesheet sized it.
     Renders theme chrome -> the ladder does not reach it. Leave vendor alone.

   `h5.card-title` draws OUR headings ("Case Details", "Filings", "Bills");
   Sneat merely sizes them. `.dz-message` draws OUR upload copy, and the display
   token names the dropzone outright. Both governed. `.btn-sm` and `.page-link`
   are control chrome the theme owns end to end - overriding those piecemeal
   leaves a half-converted theme, which is worse than an unconverted one. */

/* 22px -> the display step the token was written for. The token stays 24
   rather than moving down to 22: 22/20 is too narrow an interval to read as a
   step, 24/20 is the one that does. */
.case-details .case-money-balance {
  font-size: var(--cr-size-display);
  font-weight: var(--cr-w-bold);
  letter-spacing: var(--cr-track-display);
  line-height: var(--cr-lh-tight);
  font-variant-numeric: tabular-nums;
}

/* 17px -> 16, NOT 15. The template comment is right that these three are what
   an operator identifies the case by, and 15 would cost 2px on the most-read
   line in the app to satisfy a token. 16 keeps the strip above body (14) and
   data (13) and separates it from the 16/600 card heading by weight, not size. */
.case-details .case-details-identity .field-value {
  font-size: var(--cr-size-head);
  font-weight: var(--cr-w-bold);
  line-height: 1.35;
}

/* The 12px cluster -> 13. 12 is not a step; the neighbours are 13 and 11, and
   11 is the UPPERCASE-LABEL floor, which neither of these is - both are
   sentence case. Subordination comes from colour and weight, not from a size
   nobody else uses. */
.case-details .case-money-subline {
  font-size: var(--cr-size-data);
  font-weight: var(--cr-w-reg);
  display: block;
  color: var(--bs-secondary-color, #6c757d);
}
/* Weight 600 survives the deletion - it is a control and wants the emphasis.
   The letter-spacing: .02em does not: tracking is for uppercase, this is
   sentence case. No min-height: padding .3125rem .5625rem plus a 1px border
   already makes this ~27px, which clears WCAG 2.2 SC 2.5.8 on its own. */
.case-empty-fields-toggle {
  font-size: var(--cr-size-data);
  font-weight: var(--cr-w-semi);
  letter-spacing: normal;
}

/* Theme-drawn APP CONTENT, overridden per the governing rule. */
.card-title,
h5.card-title {
  font-size: var(--cr-size-head);
  font-weight: var(--cr-w-semi);
  line-height: 1.25;
}
.dz-message {
  font-size: var(--cr-size-display);
  font-weight: var(--cr-w-bold);
  letter-spacing: var(--cr-track-display);
  line-height: var(--cr-lh-tight);
}
/* NOT overridden, deliberately: .btn-sm, .page-link and the rest of Sneat's
   control chrome. Vendor chrome is its own class of thing. */

/* ══ Addendum 2026-08-01 (third) - the click-to-copy markers (round 4) ═════
   COPYABILITY IS A PROPERTY OF THE IDENTIFIER IDIOM. Everything wearing
   .cr-ident-inline is copyable by default: the copy module and its .cr-copy
   button styles (round 4, Task 6) key on ".cr-copyable, .cr-ident-inline",
   never on .cr-copyable alone, so the next identifier gets copy for free
   and needs no second decision.

   .cr-copyable ALONE is the opt-in for a value that should copy WITHOUT
   wearing identifier type. Exactly one value does: the injured party name
   (user decision 2026-08-01, overriding the design package's exclusion of
   patient names). Hanging the name off .cr-ident-inline instead would set a
   person's name in tabular figures with identifier tracking - so the rule
   below must never gain a font declaration; the name keeps whatever type
   its surface gave it (the identity strip's 16px/700).

   Money, links and prose take NEITHER class. A copy click on a link would
   fight navigation - why provider and insurer stay plain, and why the AAA
   case number's copy yields on the filings where it renders as a link (the
   idiom still types the number there; only the copy upgrade stands down).

   Markers, not styling: at rest a copyable value is identical to plain text
   (pattern 3 - the affordance appears on hover, arriving with Task 6's
   .cr-copy upgrade). The one shared declaration is the corner radius the
   hover and copied tints will round to; with no background it paints
   nothing today. tests/Template/CopyableFieldsTest.php pins who wears
   which class, in both directions. */
.cr-copyable,
.cr-ident-inline { border-radius: 5px }

/* ── The .cr-copy upgrade (round 4, Task 6) ────────────────────────────────
   case-copy.js rebuilds each marker as a real <button> carrying the marker's
   own classes plus .cr-copy, so Enter/Space and focus come from the element
   rather than a role. These rules are the whole affordance; without the
   script a marker stays plain text and none of this paints.

   The box is the spec'd pattern 3: padding 4px 7px cancelled by an equal
   negative margin, so at rest the button occupies exactly the text's
   footprint - zero layout shift - while the padded box clears WCAG 2.2
   SC 2.5.8's 24x24 CSS px together with min-height/min-width.

   The glyph slot is absolutely positioned PAST the button's right edge:
   in flow, its arrival on hover and the icon-to-COPIED swap (two different
   widths) would both move layout, and "no toast, no movement" is the spec.
   These declarations live here and nowhere else - a template <style>
   restating them renders after this sheet and would win on source order
   (the round-3 cascade trap). */
.cr-copy {
  position: relative;
  display: inline-block;
  padding: 4px 7px;
  margin: -4px -7px;
  border: 0;
  border-radius: 5px;
  min-height: 24px;
  min-width: 24px;
  background: none;
  color: inherit;
  text-align: inherit;
  vertical-align: baseline;
  cursor: pointer;
  user-select: text; /* the accepted trade keeps double-click word-select;
                        WebKit's button default would take even that */
}
/* Zero-specificity font reset: an author rule beats the UA button font on
   origin alone, while 0,0,0 loses to .cr-ident-inline's own 0,1,0
   declarations (weight 500, .01em, tabular figures) regardless of source
   order. A class-specificity `font: inherit` here would strip the idiom's
   type off every upgraded identifier; this way the injured party name
   inherits its strip's 16px/700 and the identifiers keep their idiom. */
:where(.cr-copy) {
  font: inherit;
  letter-spacing: inherit;
}
/* A long value must WRAP inside its cell, exactly as it did before the copy
   upgrade. Reported from a real case (a 16-digit claim number): the plain
   value wrapped and stayed inside its 133px cell, the upgraded one overflowed
   it by 46px into the Policy Number column beside it. The cause is the button
   being an inline-block - an atomic box that sizes to its content - where the
   value it replaced was a block that could break. `max-width: 100%` plus an
   explicit break restores the old behaviour; `min-width: 24px` from the box
   above stays, since it is the SC 2.5.8 floor for a short value. */
.cr-copy {
  /* NOT `max-width: 100%`. Under border-box that caps the button at the
     parent's width INCLUDING its own 14px of horizontal padding - the padding
     the negative margin exists to cancel - so the button gets 14px less room
     for text than the plain value had. Measured: it broke the breadcrumb case
     id "6-12614" onto two lines inside an 86px crumb, because 86 - 14 = 72px
     of content for a 79px string, and the hyphen is a break opportunity.
     Adding the padding back makes the bound mean "the parent's text width",
     which is what the negative margin already implies visually. */
  max-width: calc(100% + 14px);
  /* break-word, not `anywhere`: both let a long unbroken identifier break, but
     `anywhere` also shrinks the element's MIN-CONTENT width, which invites
     exactly this class of collapse in any narrow flex or grid parent. */
  overflow-wrap: break-word;
}
.cr-copy:hover { background: #f2f3f8; }
.cr-copy:focus-visible { outline: 2px solid #696cff; outline-offset: 1px; }
.cr-copy.is-copied { background: #e8f9de; }
.cr-copy.is-copy-failed { background: #fdeaea; }

.cr-copy-glyph {
  position: absolute;
  left: 100%;
  top: 50%;
  transform: translateY(-50%);
  display: none;
  margin-left: 3px;
  font-size: var(--cr-size-body);  /* the 14px glyph */
  line-height: 1;
  opacity: .55;
  white-space: nowrap;
  pointer-events: none;            /* it hangs outside the box; it must never
                                      steal a click from what sits beneath */
}
.cr-copy:hover .cr-copy-glyph,
.cr-copy:focus-visible .cr-copy-glyph,
.cr-copy.is-copied .cr-copy-glyph,
.cr-copy.is-copy-failed .cr-copy-glyph { display: block; }

/* The filing panel's meta row is a dense inline strip, and the glyph hangs
   18px past its value while the row's column gap leaves only 19px - measured,
   the icon painted 2px onto the NEXT item's label ("...2968 [icon]FILED AT").
   The item that HAS a copy affordance reserves the room, so the rest of the
   strip keeps the density the panel is built for.

   Declared HERE and not in the panel's own <style> block: a template rule
   naming .cr-copy renders after this sheet and wins on source order at equal
   specificity, which is the round-3 cascade trap - CopyableFieldsTest bans
   .cr-copy from Twig outright, predicate or not. */
.active-filing-panel .filing-meta-item:has(.cr-copyable, .cr-ident-inline) {
  padding-right: 24px;
}

/* Same reservation on the breadcrumb, for the same reason and by the same
   measurement: the active crumb is the case id - the most-pasted string in the
   app - and the search field begins 16px after it, so the glyph painted 12px
   onto the field's visible box. Reserving here rather than adding margin to
   the search wrapper: the wrapper's geometry is its own decision (the 32rem
   cap and the 767.98px un-cap), and the room is needed because of what the
   BREADCRUMB now carries. The search field moves right as a consequence.

   BOTH reservations key on the MARKER classes, never on .cr-copy. .cr-copy is
   added by case-copy.js at upgrade time, so a rule keyed on it does not match
   the server-rendered HTML: the room appears only once the script has run, and
   the search field visibly jumps. Measured before this was corrected - the
   field moved 232px -> 256px on every case-screen load, and Chrome's
   layout-shift observer named .case-search-wrapper and .filing-meta-item as
   the sources. The markers ARE in the first paint, and the upgraded button
   keeps them, so the predicate holds in both states and nothing moves. */
.navbar-nav .breadcrumb:has(.cr-copyable, .cr-ident-inline) {
  padding-right: 24px;
}

/* THE RESULT ICON IS PART OF THE FLASH, not a mark floating beside it.
   The tint is a background on the button, and the glyph slot hangs OUTSIDE
   that box - so without this the check sat on white next to a green pill and
   read as two separate things (reported 2026-08-01). Carrying the same tint
   onto the slot and closing the 3px offset makes one continuous shape; the
   left radius is squared so the two boxes meet without a seam.

   Tinting the slot rather than reserving space inside the button: reserved
   padding would put the button's own hit area 20px past its text, over the
   neighbouring item, so a click near "Filed At" would copy the AAA number. */
.cr-copy.is-copied .cr-copy-glyph,
.cr-copy.is-copy-failed .cr-copy-glyph {
  margin-left: 0;
  padding: 4px 6px 4px 2px;
  border-radius: 0 5px 5px 0;
}
.cr-copy.is-copied .cr-copy-glyph { background: #e8f9de; }
.cr-copy.is-copy-failed .cr-copy-glyph { background: #fdeaea; }

/* The slot hangs 18px past the button's right edge. Measured gaps to the next
   item: 19px in the filing meta row, 18px in a Case Details cell, 9px in the
   breadcrumb - so it lands in the inter-item gap, at worst a few pixels onto a
   neighbour's padding, for 1400ms.

   An earlier fix flipped the slot INSIDE the button when the room was tight.
   That was written when the result was the ~45px word COPIED and the overlap
   was 30px of a neighbour's actual text. Now that the result is an 18px icon
   the trade has inverted: inside placement covered the tail of the value the
   operator had just copied (reported: "41-21-1192-29 v" for ...-2968), which
   is worse than a transient overhang into a gap. It also mis-fired everywhere
   outside Case Details, because it measured room to the button's PARENT and on
   the filing panel that parent is a span that shrink-wraps the button. */


/* The result is an ICON in the copy glyph's own 14px slot, not a word.
   Design revision 2026-08-01: the earlier `COPIED` / `FAILED` wording is
   dropped because swapping a 14px glyph for a ~45px word widens the slot, and
   in a narrow panel that lands on the next column. The check is exactly as
   wide as the glyph it replaces, so the state change costs no width at all -
   which is the same defect this app had patched by repositioning the slot
   instead - a workaround the icon made unnecessary, and which is gone.

   Icons, so the 11px floor does not apply: the type system's icon exception
   covers a single glyph in a bounded shape whose meaning is named elsewhere,
   and the shared aria-live region is what announces the outcome either way.
   The failure ink #b02a37 is 6.50:1 on white (re-derived by hand) and is kept
   from the previous treatment - both clipboard paths refusing must never leave
   a button that clicks and does nothing. */
.cr-copy-done,
.cr-copy-fail {
  display: none;
  font-size: var(--cr-size-body);  /* the same 14px slot as bx-copy */
  line-height: 1;
  color: #3d7b1c;
}
.cr-copy-fail { color: #b02a37; }

/* One box for all three glyphs. Measured: bx-copy advances 18.5px while
   bx-check and bx-x advance 14.1px, so "same width" is not free just because
   the font-size matches. On the absolutely-positioned pattern-3 slot a
   narrower result is harmless, but the GHOST ICON is in flow next to its
   value - there the 4px difference would move the row on every copy, which is
   exactly the "no movement" the spec asks for. Fixing the advance makes the
   swap inert on both patterns, and makes the flip threshold below a constant
   rather than something that depends on which glyph is showing.

   Width only - NOT display. `display: inline-block` here would be 0,2,0 and
   would out-specify the 0,1,0 `display: none` above, showing the check and the
   cross permanently. The visible-state rules below carry inline-block instead,
   and the copy glyph gets its own. */
.cr-copy-glyph > .bx,
.cr-copy-icon > .bx {
  width: 18px;
  text-align: center;
}
.cr-copy-glyph > .bx-copy,
.cr-copy-icon > .bx-copy { display: inline-block; }
.cr-copy.is-copied .cr-copy-glyph,
.cr-copy.is-copy-failed .cr-copy-glyph { opacity: 1; }
/* Hide the COPY glyph specifically, not every .bx in the slot: since the
   result became an icon, the check and the cross are .bx elements too, and a
   bare `> .bx` here hid the very thing it was swapping to. */
.cr-copy.is-copied .cr-copy-glyph > .bx-copy,
.cr-copy.is-copy-failed .cr-copy-glyph > .bx-copy { display: none; }
.cr-copy.is-copied .cr-copy-done { display: inline-block; }
.cr-copy.is-copy-failed .cr-copy-fail { display: inline-block; }

/* ── The ghost icon: copy on a LINKED identifier ───────────────────────────
   Pattern 3 ("the value is the button") only applies where the value has no
   click of its own. NEVER STEAL A LINK'S CLICK: when the AAA case number
   carries a portal URL it renders as an anchor, and clicking the blue text
   must navigate, always - wrapping it in a copy button would make the most
   common gesture do the less common thing. So the field splits into two
   targets: the anchor keeps its click, and copy moves to a small button
   beside it (design clarification 2026-08-01).

   The icon is VISIBLE AT REST (opacity .45), not hover-only like pattern 3's
   glyph. That is the whole point: the value itself no longer copies, so the
   affordance has to be discoverable without hovering. It is also the signal
   that this field behaves differently from every other identifier.

   Box: padding 4px against an equal negative margin, so the icon adds no
   height to the line; 22px painted, and the line-height carries the target
   past WCAG 2.2 SC 2.5.8's 24px. The host is inline-flex so the icon can
   never wrap away from the value it belongs to.

   COPIED / FAILED reuse the pattern-3 classes above - same 11px/600/.06em,
   same inks, same 1400ms - so the two patterns cannot drift apart. */
.cr-copy-host {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cr-copy-icon {
  display: inline-flex;
  align-items: center;
  padding: 4px;
  margin: -4px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: inherit;
  font-size: var(--cr-size-body);  /* the 14px glyph */
  line-height: 1;
  opacity: .45;
  cursor: pointer;
}
.cr-copy-icon:hover,
.cr-copy-icon:focus-visible {
  opacity: 1;
  background: #eef0ff;
}
.cr-copy-icon:focus-visible { outline: 2px solid #696cff; outline-offset: 1px; }
.cr-copy-icon.is-copied,
.cr-copy-icon.is-copy-failed { opacity: 1; background: none; }
.cr-copy-icon.is-copied > .bx-copy,
.cr-copy-icon.is-copy-failed > .bx-copy { display: none; }
.cr-copy-icon.is-copied .cr-copy-done { display: inline-block; }
.cr-copy-icon.is-copy-failed .cr-copy-fail { display: inline-block; }
