/**
 * ERPAL Tidy — the density layer (handoffs/TIDY_STANDARD_v1.md).
 *
 * Loads AFTER erpal_record/record.css (library weight 20) and re-expresses that
 * stylesheet's hardcoded Lucky Duck literals as TOKENS with the literal kept
 * only as a var() fallback. record.css hardcodes rgb(33,57,47)/#fff/#e2e2da with
 * no Night variant, which is exactly why every tenant needs a skin to restate
 * them; this layer is the first record CSS that is correct in Night unskinned.
 *
 * Nothing here edits the shared satis packages (erpal_record, erpal_crm_ui).
 */

/* ---------- §2 the density scale — one scale, no ad-hoc values ---------- */
:root {
  --tidy-gap-xs: .2rem;
  --tidy-gap-sm: .35rem;
  --tidy-gap-md: .55rem;
  --tidy-gap-lg: .8rem;
  --tidy-radius: 9px;
  --tidy-fs-row: .84rem;
  --tidy-fs-title: .78rem;
  --tidy-fs-meta: .75rem;
  --tidy-lh: 1.35;
  --tidy-label-w: 42%;
}

/* ---------- §3 Tidy Card — tokenized surfaces ---------- */
.rec-card,
.rec-stagebar,
details.rec-addpanel {
  background: var(--erpal-surface, #fff);
  border-color: var(--erpal-border, #e2e2da);
  border-radius: var(--tidy-radius);
  box-shadow: var(--erpal-shadow, 0 1px 3px rgba(20, 30, 25, .05));
}
.rec-card__body {
  color: var(--erpal-text, #3c423a);
  padding: var(--tidy-gap-sm) var(--tidy-gap-lg) calc(var(--tidy-gap-sm) + .15rem);
}
.rec-card__title,
details.rec-addpanel > summary {
  background: var(--erpal-thead-bg, #f7f7f2);
  border-bottom-color: var(--erpal-divider, #ececE2);
  font-size: var(--tidy-fs-title);
}
/* §3.1 — the title stays typographic (uppercase + tracking), NEVER
   colour-only. d-2026-08-04-024: a skin repaints this with the accent token
   that links also use, so a colour-only heading became a link that did
   nothing. Restated here because this layer sets the colour. */
.rec-card__title {
  color: var(--erpal-text, rgb(33, 57, 47));
  text-transform: uppercase;
  letter-spacing: .5px;
}
.rec-row {
  border-bottom-color: var(--erpal-divider, #efefe6);
  font-size: var(--tidy-fs-row);
  line-height: var(--tidy-lh);
  padding: var(--tidy-gap-xs) 0;
}
.rec-row__l {
  color: var(--erpal-muted, #6b7069);
  flex: 0 0 var(--tidy-label-w);
}
/* §3.2 — links underlined; colour alone cannot signal link-ness (WCAG 1.4.1). */
.rec-row__v a {
  color: var(--erpal-accent, #205c48);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.rec-empty {
  color: var(--erpal-muted, #8a8f86);
}

/* §3.3 — a card title sticks while its body scrolls, so a long list never
   loses the label of what you are looking at. */
details.rec-card > summary.rec-card__title {
  position: sticky;
  top: 0;
  z-index: 2;
}

/* ---------- §4 Tidy Views — rel_* lists as nested, counted cards ----------
   Scoped by BLOCK ID, not by region. record.css dressed these only under
   .layout__region--third, so the same view looked different in a different
   region; placement must not change appearance. */
/* A rel list arrives either as a placed block wrapping .views-element-container
   or as a Layout Builder component that IS .views-element-container, so dress
   both shapes. .tidy-rel is applied by tidy.js to whichever node matched. */
.tidy-rel.views-element-container,
.tidy-rel .views-element-container {
  background: var(--erpal-surface, #fff);
  border: 1px solid var(--erpal-border, #e2e2da);
  border-radius: var(--tidy-radius);
  box-shadow: var(--erpal-shadow, 0 1px 3px rgba(20, 30, 25, .05));
  margin-bottom: var(--tidy-gap-md);
  overflow-x: hidden;
  padding: .15rem var(--tidy-gap-lg) calc(var(--tidy-gap-md) - .1rem);
}
/* Never double-frame: when the placed-block wrapper matched, the inner
   container must not draw its own box inside it. */
.tidy-rel:not(.views-element-container) .views-element-container {
  border: 0;
  box-shadow: none;
  margin-bottom: 0;
  padding-left: 0;
  padding-right: 0;
}
.tidy-rel h2 {
  align-items: center;
  color: var(--erpal-text, rgb(33, 57, 47));
  cursor: pointer;
  display: flex;
  font-size: var(--tidy-fs-title);
  gap: .45rem;
  letter-spacing: .5px;
  margin: var(--tidy-gap-sm) 0 var(--tidy-gap-xs);
  text-transform: uppercase;
  user-select: none;
}
.tidy-rel h2:focus-visible {
  outline: 2px solid var(--erpal-accent, #205c48);
  outline-offset: 2px;
}
/* §3.6 — the count is WHY a user opens or skips a shut card. Rendered from a
   data-attribute so h2.textContent stays clean for erpal-relrail.js. */
.tidy-rel h2[data-tidy-count]::after {
  background: var(--erpal-accent-soft, #eef0ea);
  border-radius: 999px;
  color: var(--erpal-accent, #205c48);
  content: attr(data-tidy-count);
  font-size: var(--tidy-fs-meta);
  font-weight: 700;
  letter-spacing: 0;
  padding: .05rem .45rem;
}
.tidy-rel h2::before {
  content: '▾';
  color: var(--erpal-muted, #9aa093);
  font-size: .7rem;
  transition: transform .15s;
}
.tidy-rel.is-collapsed h2::before {
  transform: rotate(-90deg);
}
/* Collapse hides everything the block holds except its own heading, which works
   for both shapes without knowing where .view sits in the tree. */
.tidy-rel.is-collapsed > *:not(h2),
.tidy-rel.is-collapsed .views-element-container > *:not(h2) {
  display: none;
}
.tidy-rel--empty h2[data-tidy-count]::after {
  background: transparent;
  color: var(--erpal-muted, #9aa093);
}
/* §3.6 — where the rendered rows stop short of the counted total, the card says
   so at the foot of the list. Quiet by design: it is a footnote to the pill,
   not a second heading. */
.tidy-rel__more {
  color: var(--erpal-muted, #8a8f86);
  font-size: var(--tidy-fs-meta);
  font-style: italic;
  margin: var(--tidy-gap-xs) 0 0;
}

/* §4.3/§4.4 — rows are teasers: clamped, fixed-layout, and an unbreakable URL
   wraps rather than widening the cockpit. */
.tidy-rel table {
  font-size: var(--tidy-fs-row);
  table-layout: fixed;
  width: 100%;
}
.tidy-rel td {
  overflow-wrap: anywhere;
  padding: var(--tidy-gap-xs) .3rem;
}
.tidy-rel tbody td {
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  display: -webkit-box;
  overflow: hidden;
}
.tidy-rel thead th {
  font-size: var(--tidy-fs-meta);
  padding: var(--tidy-gap-xs) .3rem;
}

/* ---------- narrow rails stack, they do not squeeze ----------
   MEASURED on the hub 2026-08-06: the Contacts list in the 24% right rail put
   EMAIL/PHONE/TITLE columns in ~90px each, so "steve.meng@kfallsymca.org" broke
   one or two characters per line and the card became unreadable. A fixed-layout
   table cannot narrow gracefully, so below a usable width the row stops being a
   table row and becomes a stacked entry: name first, supporting fields under it.

   Driven by a CONTAINER query, not the viewport and not the region, so the same
   list behaves the same wherever it is placed (§4.2 — placement must not change
   appearance). The container is declared unconditionally; only the stacking is
   conditional. */
.tidy-rel {
  container-type: inline-size;
}

@container (max-width: 420px) {
  .tidy-rel thead {
    /* Column headers mean nothing once the row is stacked, but they must stay
       reachable to a screen reader — clip, do not display:none. */
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    width: 1px;
  }
  .tidy-rel table,
  .tidy-rel tbody,
  .tidy-rel tr,
  .tidy-rel td {
    display: block;
    width: auto;
  }
  .tidy-rel tbody tr {
    border-bottom: 1px dotted var(--erpal-divider, #efefe6);
    padding: var(--tidy-gap-sm) 0;
  }
  .tidy-rel tbody tr:last-child {
    border-bottom: 0;
  }
  .tidy-rel tbody td {
    -webkit-line-clamp: 2;
    padding: 0;
  }
  /* The first cell is the record's name — it leads the entry. */
  .tidy-rel tbody td:first-child {
    -webkit-line-clamp: 2;
    font-weight: 600;
  }
  /* Everything after it is supporting detail, set quieter and smaller. */
  .tidy-rel tbody td:not(:first-child) {
    color: var(--erpal-muted, #6b7069);
    font-size: var(--tidy-fs-meta);
  }
  /* An empty supporting cell would otherwise leave a blank line. */
  .tidy-rel tbody td:empty {
    display: none;
  }
}

/* ---------- §5 the peek affordance ---------- */
.tidy-peek-btn {
  border-radius: 5px;
  color: var(--erpal-muted, #6b7069);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: .8rem;
  line-height: 1;
  margin-left: .3rem;
  /* §8.6 — 32px minimum touch target. */
  min-width: 32px;
  min-height: 32px;
  text-decoration: none;
  vertical-align: middle;
}
.tidy-peek-btn:hover,
.tidy-peek-btn:focus-visible {
  background: var(--erpal-hover, #eef0ea);
  color: var(--erpal-accent, #205c48);
}
@media (pointer: fine) {
  /* On a mouse, the button is quiet until the row is hovered — the rail is
     dense and 20 always-on glyphs read as noise. It stays keyboard-reachable
     because :focus-within reveals it. */
  .tidy-rel tbody tr .tidy-peek-btn { opacity: 0; transition: opacity .12s; }
  .tidy-rel tbody tr:hover .tidy-peek-btn,
  .tidy-rel tbody tr:focus-within .tidy-peek-btn { opacity: 1; }
}

/* ---------- §3.8 two-column rows on a wide desktop ----------
   The single biggest density win on a 1080p screen: short label/value pairs in
   the wide centre column stop wasting half the row. Scoped to the 50% region so
   the narrow rails are untouched, and `break-inside` keeps a row whole. */
@media (min-width: 1200px) {
  .layout__region--second .rec-card__body > .rec-row {
    break-inside: avoid;
  }
  .layout__region--second .rec-card--tidy-2col .rec-card__body {
    column-count: 2;
    column-gap: calc(var(--tidy-gap-lg) * 1.5);
  }
}

/* ---------- the chrome band above the record ----------
   This is ERPAL_BRAND_COMPACT_STANDARD_2026-08-03 §6, which until now shipped
   ONLY in the tenant brand-skin skeleton (distribution/brand_skin/skel). The
   rules are brand-INDEPENDENT, so a tenant skin was the wrong home for them:
   Lucky Duck's own hub has no skin and therefore never got them, which is why
   the account record still printed its name twice with ~380px of dead chrome
   above the header card (measured 1920x1080, 2026-08-06).

   erpal_tidy is the right home -- a shared, brand-independent platform module
   -- and it lands here rather than in erpal_record/erpal_crm_ui because those
   are satis-shipped packages whose edits belong to the ruled re-bake batch
   d-2026-08-03-003. Nothing shared is touched.

   Every rule is scoped by a :has() test for record furniture, so entity EDIT
   and DELETE forms — which carry neither — keep their page title and normal
   spacing. TWO different tests, deliberately:
     :has(.rec-header) → only the rule that HIDES THE PAGE TITLE. A duplicate
       name is only a duplicate when a header card is printing the name too.
     :has(.rec-card)   → the spacing and tab-pill rules, which every record with
       Tidy Cards wants. This is what carries the compaction onto CMS record
       types (publication, site, site page, submissions): they have Tidy Cards
       and no header card, so they get the tight chrome AND keep their title. */

/* §6.1 — the record's name appears ONCE. The header card already carries name,
   avatar, chips, stats and actions, so the page-title block is the duplicate. */
.erpal-content__inner:has(.rec-header) .block-page-title-block {
  display: none;
}

/* §6.4 — the band gives back its slack. Olivero's grid row-gap plus per-block
   margins put ~126px between each of breadcrumb, title, tabs and the card.
   Keyed on .rec-card, NOT .rec-header, so it reaches CMS records too: a CMS
   record type (publication, site, site page, submissions) has Tidy Cards but no
   header card — the CRM header cards are contact/org/lead/deal-shaped and would
   report another entity's stats on a content record — so it keeps its page
   title as the single print of its name (gate 2) while still getting the
   compacted chrome (gate 7: identical density). The title suppression above
   stays keyed on .rec-header for exactly that reason. */
.erpal-content__inner:has(.rec-card) .region--content {
  row-gap: 0;
}
.erpal-content__inner:has(.rec-card) .block-local-tasks-block,
.erpal-content__inner:has(.rec-card) .block-page-title-block {
  margin-block-end: 0;
  margin-block-start: 0;
}
.erpal-content__inner:has(.rec-card) .tabs-wrapper {
  margin: 0 0 var(--tidy-gap-md);
}

/* The NAV-5 chip rail is INSERTED BY JS as a sibling of the local-tasks block,
   so it lands as a direct child of the Olivero content grid with no column of
   its own -- record.css grants `grid-column: 1 / -1` to .block-system only.
   It therefore rendered on incidental auto-placement, and tightening the row
   gaps above was enough to lose it (measured: visible before the chrome pass,
   gone after). Give it the same explicit full-width column as the record body
   so its position is decided rather than inherited. */
.erpal-content__inner:has(.rec-card) .region--content > .erpal-relrail {
  grid-column: 1 / -1;
}

/* §6.2 — tabs are a compact pill row, never a slab. Olivero pins
   .tabs__link { height: var(--tabs-height) } = 54px; the FIXED HEIGHT, not the
   padding, is what makes the slab, so height must be reset explicitly. */
.erpal-content__inner:has(.rec-card) ul.tabs--primary {
  border: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: .3rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.erpal-content__inner:has(.rec-card) .tabs__tab {
  border: 0;
  margin: 0;
}
.erpal-content__inner:has(.rec-card) .tabs__link {
  background: var(--erpal-surface, #fff);
  border: 1px solid var(--erpal-border, #e2e2da);
  border-radius: 999px;
  color: var(--erpal-text, #3c423a);
  font-size: var(--tidy-fs-title);
  height: auto;
  line-height: 1.2;
  min-height: 0;
  padding: .3rem .8rem;
  text-decoration: none;
}
.erpal-content__inner:has(.rec-card) .tabs__link:hover,
.erpal-content__inner:has(.rec-card) .tabs__link.is-active {
  background: var(--erpal-accent-soft, #eef0ea);
  border-color: var(--erpal-accent, #205c48);
  color: var(--erpal-accent, #205c48);
}
/* Olivero draws the active state with a thick ::before bar sized to the slab. */
.erpal-content__inner:has(.rec-card) .tabs__link::before,
.erpal-content__inner:has(.rec-card) .tabs__link::after {
  display: none;
}

/* §6.3 — EVERY TAB STAYS REACHABLE ON A PHONE. Olivero hides non-active tabs
   below 700px and re-reveals them through .tabs__trigger; a compact row that
   drops the trigger would strand Edit and Delete on mobile. Caught by rendering
   at 390px, never by reading CSS. */
.erpal-content__inner:has(.rec-card) .tabs__trigger {
  display: none;
}
.erpal-content__inner:has(.rec-card) .tabs__tab {
  display: inline-block;
}

/* ---------- §6/§7 phone ---------- */
@media (max-width: 800px) {
  .tidy-rel h2 { font-size: var(--tidy-fs-row); }
  /* Touch has no hover, so the peek button is always visible there. */
  .tidy-rel tbody tr .tidy-peek-btn { opacity: 1; }
}


/* ---------- §5 expand-in-place: the inline peek panel ----------
   The fragment is inserted as a row directly under the record it summarises, so
   the parent record never leaves the screen. Styles live HERE rather than in a
   separate dialog-only library because the fragment is injected into a page
   that has already loaded its CSS -- a library attached to the fragment would
   arrive too late to style it. */
/* The expansion is NOT a teaser, so it must escape the 4-line clamp and the
   -webkit-box display that every other cell in these lists carries -- otherwise
   the panel renders two lines tall and clipped. Specificity is deliberate: it
   has to outrank `.tidy-rel tbody td` and the container-query stack rules. */
.tidy-rel tbody tr.tidy-peek-row > td,
.tidy-peek-row > td {
  -webkit-line-clamp: unset;
  background: var(--erpal-hover-soft, #f7f7f2);
  border-left: 3px solid var(--erpal-accent, #205c48);
  display: block;
  overflow: visible;
  padding: var(--tidy-gap-sm) var(--tidy-gap-lg);
}
.tidy-peek__loading,
.tidy-peek__error {
  font-size: var(--tidy-fs-meta);
  margin: 0;
}
.tidy-peek__loading { color: var(--erpal-muted, #8a8f86); font-style: italic; }
/* An access refusal is a real answer and is shown as one, not swallowed. */
.tidy-peek__error { color: var(--erpal-danger, #8a4a3b); font-weight: 600; }
.tidy-peek-btn[aria-expanded="true"] {
  background: var(--erpal-accent-soft, #eef0ea);
  color: var(--erpal-accent, #205c48);
  opacity: 1;
}

.tidy-peek {
  font-size: var(--tidy-fs-row, .84rem);
  line-height: var(--tidy-lh, 1.35);
}

.tidy-peek__head {
  align-items: baseline;
  border-bottom: 1px solid var(--erpal-divider, #ececE2);
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: var(--tidy-gap-md, .55rem);
  padding-bottom: var(--tidy-gap-sm, .35rem);
}
.tidy-peek__type {
  background: var(--erpal-accent-soft, #eef0ea);
  border-radius: 999px;
  color: var(--erpal-accent, #205c48);
  font-size: var(--tidy-fs-meta, .75rem);
  font-weight: 700;
  letter-spacing: .4px;
  padding: .1rem .5rem;
  text-transform: uppercase;
}
.tidy-peek__name {
  color: var(--erpal-text, #3c423a);
  font-size: 1.05rem;
  font-weight: 700;
}

.tidy-peek__rows { margin: 0; }
.tidy-peek__row {
  display: flex;
  gap: .7rem;
  border-bottom: 1px dotted var(--erpal-divider, #efefe6);
  padding: var(--tidy-gap-xs, .2rem) 0;
}
.tidy-peek__row:last-child { border-bottom: 0; }
.tidy-peek__row dt {
  color: var(--erpal-muted, #6b7069);
  flex: 0 0 var(--tidy-label-w, 42%);
  font-weight: 400;
}
.tidy-peek__row dd {
  flex: 1;
  margin: 0;
  overflow-wrap: anywhere;
}
.tidy-peek__row dd a {
  color: var(--erpal-accent, #205c48);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* §5.8 — the way out. A modal with no exit to the real record is a dead end. */
.tidy-peek__foot {
  border-top: 1px solid var(--erpal-divider, #ececE2);
  margin-top: var(--tidy-gap-md, .55rem);
  padding-top: var(--tidy-gap-sm, .35rem);
}
/* §5.8 / §8.1 — THE WAY OUT MUST BE READABLE.
   MEASURED on the hub 2026-08-06: this button rendered its label in
   rgb(91,155,255) on a background of rgb(91,155,255) — the same colour, a 1:1
   contrast ratio, an invisible label on a visible blue slab. The exit from the
   expansion was, in effect, unlabelled.
   Cause is specificity, not the token: the peek fragment is injected INSIDE a
   related-list cell, so the ancestor-qualified link rules that dress those
   cells (`… td a { color: var(--erpal-accent) }`) outrank a single-class
   `.tidy-peek__open` and repaint the label with the accent the background is
   already painted with. Answered with specificity rather than !important, so a
   brand skin can still re-point it. */
.tidy-peek .tidy-peek__foot a.tidy-peek__open {
  background: var(--erpal-accent, #205c48);
  border-radius: 6px;
  color: var(--erpal-on-accent, #fff);
  display: inline-block;
  font-size: var(--tidy-fs-row, .84rem);
  font-weight: 600;
  padding: .35rem .8rem;
  text-decoration: none;
}
.tidy-peek .tidy-peek__foot a.tidy-peek__open:hover,
.tidy-peek .tidy-peek__foot a.tidy-peek__open:focus-visible {
  background: var(--erpal-accent-dark, #14402f);
  color: var(--erpal-on-accent, #fff);
}
