/* ==========================================================================
   Shared/table-cells.css — THE one cell vocabulary for every DATA table
   --------------------------------------------------------------------------
   Domain-neutral, surface-agnostic. `.admin-table`, `.crm-table` and
   `.client-table` all carry these classes on their `<th>`/`<td>`.

   WHY IT EXISTS: `table-engine.js` already EMITS this exact vocabulary
   (`classify()`/`formatTable()`, lines 87-152: cell-text / -number / -date /
   -center / -checkbox / -actions / -image / -mono / -truncate). The names were
   always domain-neutral in the shared engine — only the CSS backing them was
   admin-private. Cycle 10 consolidated the JS and left the CSS behind; this
   file finishes that job. It is not a new invention.

   WHAT LIVES HERE: only facts DERIVED FROM THE COLUMN'S TYPE — alignment,
   white-space, overflow, and the monospace treatment. Identical on every
   surface because they follow from the data, not from the design.

   WHAT DOES **NOT** LIVE HERE:
   • WIDTHS. The width VALUES are shared tokens (`--col-*` in base/base.css),
     but the APPLICATION mechanism differs and must: `.admin-table` is a flex
     column whose thead and every `tbody tr` are their own `display: table`
     context (Admin/modules/_components.css), so `<colgroup>` never reaches it
     and admin pins width on the th AND the td. `.crm-table` and `.client-table`
     are real tables where `<col>` works.
   • ACTIONS / IMAGE ALIGNMENT — domain TASTE, not type semantics: admin centers
     its actions column, CRM right-aligns via `.crm-table-cell-actions`. There is
     no single correct shared value, so only the `white-space` fact is shared.
     (Note on the cascade: `_Layout.cshtml` loads site.css BEFORE the per-domain
     sheet in `@RenderSection("Styles")`, so a domain rule of equal specificity
     wins anyway — hoisting the alignment would not have been dangerous, merely
     misleading. The reason to keep it out is that no shared value is correct.)
   • COLOURS. Never (CSS Hard Rule 19); this file has none.

   ── TWO OBLIGATIONS ON ANY SURFACE THAT ADOPTS THIS VOCABULARY ──────────

   1. DROP YOUR ELEMENT-LEVEL `text-align` BASELINE. These classes are BARE
      (0,1,0) on purpose — domain-neutral. A surface baseline like
      `.admin-table thead th { text-align: center }` is (0,1,2) and would beat
      them outright, so the vocabulary would silently do nothing (or worse,
      re-center columns that used to align by type). Admin's was removed
      2026-08-05 for exactly this.

      ⚠ BUT THE DROP IS ONLY SAFE WHERE EVERY `th` ENDS UP CLASSIFIED, and that
      caveat is the whole difference between the surfaces. A bare `<th>` centers
      by UA default. Admin's baseline could go because admin's adapter runs
      `autoFormat: true` and classifies 100% of its tables, so no admin header is
      ever left unclassified. CRM's adapter runs autoFormat OFF and almost no CRM
      table declares a class — so deleting CRM's baseline TODAY would center the
      headers of ~41 tables to fix 4. Removing a baseline is a TRADE, not a
      cleanup: check the surface's classification coverage first.

      STILL BLOCKING for the surfaces not yet adopted:
        • `.crm-table thead th { text-align: left }`  — Crm/modules/_data.css:92
          → CRM numeric headers cannot right-align until this goes. See the
            coverage caveat above — this one needs the backfill (or a scoped
            `:not([class*="cell-"])` variant, an OPEN design question) alongside it.
        • `.client-table thead th { text-align: center }` — ClientApp/client-base.css:741
        • `.client-table tbody td { text-align: left }`   — ClientApp/client-base.css:750
          → the client surface has TWO, not one. The `tbody td` rule means the
            vocabulary is COMPLETELY INERT on client body cells until it goes
            (that is the whole point of adopting it there — e.g. Billing invoice
            amounts). `.client-table` also has NO engine adapter at all, so it has
            zero classification coverage — the caveat above applies in full.

   2. RE-LIST THESE CLASSES IN YOUR MOBILE-STACK BLOCK. In stack mode a cell
      must go full-width/auto, but a compound selector such as
      `.admin-table td.cell-number` (0,2,1) beats `.admin-table tbody td`
      (0,1,2). Admin already does this (its `@container` block); any adopting
      surface needs the same companion list or the vocabulary breaks its own
      card layout.

   WHO SETS THE CLASSES: admin's adapter injects them at runtime
   (`autoFormat: true`); every other surface states them declaratively in
   markup. They are NOT sniffed at runtime on CRM — `autoFormat` is admin-only
   and stays off there (the engine's heuristics are admin-markup-shaped).
   PLANNED (not yet built — see COMMONALITY_AUDIT/CRM_TABLE_AUTOFORMAT_PROPOSAL.md):
   the area-general generator will emit these from the SQL column type, so
   generated pages carry them without hand-authoring.

   Loaded via site.css, which every surface already links.
   ========================================================================== */

/* Text — the default. Stated explicitly so a column can be reclassified to it. */
.cell-text {
    text-align: left;
}

/* Numeric columns align right so digits line up on the decimal. */
.cell-number {
    text-align: right;
}

/* Dates are short and must not wrap mid-value. */
.cell-date {
    text-align: left;
    white-space: nowrap;
}

/* Booleans / small glyph columns. */
.cell-center {
    text-align: center;
}

.cell-checkbox {
    text-align: center;
}

/* Actions: the WHITE-SPACE fact only — a button row must never wrap mid-control.
   Alignment stays with the owning surface (see the header note). */
.cell-actions {
    white-space: nowrap;
}

/* Image cells: the engine classifies them (table-engine.js:144). Alignment and
   width stay per-domain; there is no type-derived fact to share beyond keeping
   the cell from collapsing, so this class carries no declarations here and is
   documented rather than silently absent. Per-domain sheets own it. */

/* Long free-text: one line, clipped with an ellipsis. Paired with a title
   tooltip by the surface that supplies one. */
.cell-truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Identifiers (GUIDs, hashes, keys). MOVED VERBATIM from
   Admin/modules/_components.css — it was already declared bare/unscoped there,
   i.e. it was always leaking solution-wide. Moving it REMOVES an admin-owned
   global rather than retrofitting admin. `word-break` and `font-size` are part
   of the rule; dropping either would be an unflagged admin regression. */
.cell-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
    word-break: break-all;
    font-size: 0.9rem;
}

/* Cells whose VALUE lives in BLOCK CHILDREN (`.hint` rows, stacked divs) rather
   than the cell's own line boxes. A RENDER fact read from the DOM by
   table-engine.js's structure sniffers — the same category as cell-actions /
   cell-image, never a declaration ("Structure is never declared away",
   table-engine.js:131-141). A block child's text overflows the CHILD, so
   `text-overflow` on the cell can never reach it: on a nowrap surface these clip
   with neither an ellipsis nor a tooltip — single-wrapper cells exactly as much
   as multi-block stacks.
   `overflow-wrap` is NOT optional and is not a duplicate of `.hint`'s: once
   nowrap is released, a long unbroken token in a NON-hint block child (GUID,
   URL) has nothing to break on. Same pairing admin's mobile-stack block uses.
   Overflow is deliberately left at the surface's own value — cells are
   auto-height, so `hidden` clips nothing once the text wraps, and keeping it
   preserves the last-resort guard.
   Declared LAST in this file on purpose: `.cell-truncate` (nowrap+ellipsis) is
   its exact opposite and both are bare (0,1,0), so source order is the arbiter
   on any surface without a specificity arm. The engine also refuses to emit
   `cell-truncate` for a stacked column — on admin that emission is th-only and
   out-specified by `.admin-table thead th` (0,1,2), so the refusal has no
   rendering effect there today; it keeps this published vocabulary and the
   --dump-table-classes record truthful for the declarative surfaces that will
   consume it. */
.cell-stack {
    white-space: normal;
    overflow-wrap: anywhere;
}
