/* DPT App Kit v5 — desktop components (AMENDMENT 46).
   Loads AFTER dpt.v5.css and reads only its tokens. First built for the testing app's desktop
   rebuild, then lifted here so Ops, Club Hub, Health Hub, Testing, Programs and DPT Hub
   share one experience. Every class is dp5- prefixed; an app keeps its own names for its own
   things and adds these beside them.

   Contents:  1 content contract   2 hues   3 card + rail   4 stat row   5 rows, dots, who-chips
              6 toolbar + filter chips   7 table + checkbox   8 bulk bar   9 detail panel
             10 split (list | detail)   11 progress track   12 entry card

   Rules that hold everywhere in this file: classic min/max media queries only (iPadOS 15 on the
   gym floor cannot parse range syntax); 44px targets under a coarse pointer; no lift, no glow,
   no outer focus ring; the six hues carry MEANING (a wave, a team, a club, a coach, a test family)
   and a card that specifies nothing takes ONE shared rail colour, never a hue per card.
   AMENDMENT 50 (look C): tokens only, no charcoal. A card is a tile (raised), so fills inside it
   step one rung up (raised-hover, raised-press); SELECTED is the white slab (--dp5-primary), never green.
   AMENDMENT 50.1: the four places the apps still had to override are fixed here. The open panel
   tab is the white slab (no green underline); the open or checked table row is a raised-press fill (no 3px
   green bar); an unpicked filter chip is plain text (no outline).
   AMENDMENT 50.2: td.is-empty and td.is-zero take the off ink. */

/* ============================================================ 1 CONTENT CONTRACT
   Content fills the window from 1280 up (a 2560px window): the 1180px --dp5-content-max cap
   is history. The app applies .dp5-fill to its scrolling content column. */
.dp5-fill { width: 100%; max-width: none; box-sizing: border-box; }
@media (min-width: 1280px) {
  .dp5-fill { padding-inline: 32px; }
}
.dp5-stack { display: flex; flex-direction: column; gap: 20px; }
.dp5-g2 { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
@media (min-width: 1280px) {
  .dp5-g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ============================================================ 2 HUES
   The Ops six-hue set. Never the accent green as a hue: green already means
   active, positive and money. */
:root {
  --dp5-hue-0: #F97316;
  --dp5-hue-1: #5B9DFF;
  --dp5-hue-2: #C4B5FD;
  --dp5-hue-3: #FFB224;
  --dp5-hue-4: #F472B6;
  --dp5-hue-5: #2DD4BF;
  --dp5-panel-w: 480px;
}
[data-hue="0"] { --hue: var(--dp5-hue-0); }
[data-hue="1"] { --hue: var(--dp5-hue-1); }
[data-hue="2"] { --hue: var(--dp5-hue-2); }
[data-hue="3"] { --hue: var(--dp5-hue-3); }
[data-hue="4"] { --hue: var(--dp5-hue-4); }
[data-hue="5"] { --hue: var(--dp5-hue-5); }

/* ============================================================ 3 CARD + RAIL
   .dp5-card is in dpt.v5.css. The rail is the hue: 3px down the left, or across the top of a
   stat card. overflow: clip (after hidden) so a sticky child can still reach the viewport. */
.dp5-card { position: relative; overflow: hidden; overflow: clip; }
.dp5-card--rail { border-left: 3px solid var(--hue, var(--dp5-line-strong)); }
.dp5-card--rail-top { border-top: 3px solid var(--hue, var(--dp5-line-strong)); }
.dp5-card__head { display: flex; align-items: center; gap: 12px; padding: 16px 20px 0; }
.dp5-card__head h2, .dp5-card__title { margin: 0; font-size: 16px; font-weight: 600; }
.dp5-card__meta { margin-left: auto; display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--dp5-text-2); }
.dp5-card__label { display: block; padding: 16px 20px 4px; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--dp5-text-2); }

/* ============================================================ 4 STAT ROW
   Four cards at 1280+, two beside an open panel and under 1280, one under 700. */
.dp5-stat-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 700px) {
  .dp5-stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1280px) {
  .dp5-stat-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  body.dp5-panel-open .dp5-stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.dp5-stat { position: relative; padding: 18px 20px 16px; }
/* dpt.v5.css already uses .dp5-stat as the stat NUMBER's type (28/600/1.1). Here it is the card
   block, so undo that inheritance on the block: only __v is the number. */
.dp5-card.dp5-stat, .dp5-stat-row .dp5-stat { font-size: inherit; font-weight: inherit; letter-spacing: normal; line-height: inherit; font-variant-numeric: normal; }
.dp5-stat__k { display: block; font-size: 13px; color: var(--dp5-text-2); }
.dp5-stat__v { display: block; margin-top: 4px; font-size: 32px; font-weight: 600; line-height: 40px; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.dp5-stat__s { display: flex; align-items: center; gap: 8px; margin-top: 2px; font-size: 13px; color: var(--dp5-text-2); }
.dp5-stat__s b { font-weight: 500; color: var(--dp5-green); }
.dp5-stat__act { position: absolute; top: 16px; right: 16px; }
.dp5-stat--has-act { padding-right: 88px; }   /* the number never sits under the action (iPad) */

/* ============================================================ 5 ROWS, DOTS, WHO-CHIPS */
.dp5-row--desk { min-height: 48px; gap: 14px; padding: 0 20px; }
.dp5-row--desk .dp5-row__t { font-size: 15px; font-weight: 500; }
.dp5-row--desk .dp5-row__m { display: flex; align-items: center; gap: 10px; margin-left: auto; font-size: 13px; color: var(--dp5-text-2); white-space: nowrap; }
.dp5-dot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--hue, var(--dp5-text-3)); margin-right: 8px; vertical-align: 1px; }
/* A person chip: hue circle with an INK initial (white fails on every hue), name in text-2. */
.dp5-who { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 8px 0 4px; border-radius: var(--dp5-r-chip); background: var(--dp5-raised-hover); font-size: 12px; color: var(--dp5-text-2); white-space: nowrap; }
.dp5-who__i { display: grid; place-items: center; flex: none; width: 16px; height: 16px; border-radius: 50%; background: var(--hue, var(--dp5-raised-hover)); font: 600 9px/1 var(--dp5-font); font-style: normal; color: var(--dp5-ink); }

/* ============================================================ 6 TOOLBAR + FILTER CHIPS
   A pressed filter is SELECTED, so it is the white slab (A50, as Ops and Hub ship it; the A46 green tint is
   retired: selected things are never green). A50.1: at rest it is plain text, #D5DCE6 (text-2) turning white
   on hover, with no outline and no fill; the 1px border stays, transparent, so the box keeps its size. */
.dp5-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--dp5-line); }
.dp5-toolbar > .dp5-field { width: 320px; max-width: 100%; }
.dp5-toolbar__count { margin-left: auto; font-size: 13px; color: var(--dp5-text-2); white-space: nowrap; }
.dp5-toolbar__count b { font-weight: 600; color: var(--dp5-text); }
.dp5-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.dp5-fchip { display: inline-flex; align-items: center; gap: 6px; height: 32px; min-height: 32px; padding: 0 12px; border: 1px solid transparent; border-radius: var(--dp5-r-ctl); background: transparent; box-shadow: none; font: 500 13px var(--dp5-font); color: var(--dp5-text-2); white-space: nowrap; cursor: pointer; }
.dp5-fchip.is-on, .dp5-fchip[aria-pressed="true"] { border-color: transparent; background: var(--dp5-primary); color: var(--dp5-primary-ink); font-weight: 600; }
.dpt-v5.dpt-v5.dpt-v5 .dp5-fchip:is(.is-on, [aria-pressed="true"]):focus-visible { box-shadow: inset 0 0 0 1.5px var(--dp5-primary-ink); }
.dp5-fchip__x { opacity: .7; }
.dp5-fchip:focus-visible { outline: 0; box-shadow: var(--dp5-focus); }
@media (pointer: coarse) {
  .dp5-fchip { min-height: 44px; }
}

/* ============================================================ 7 TABLE + CHECKBOX
   A table sits in a tile, so its fills step up the navy ladder: hover raised-hover, and a SELECTED row
   (checked, or open beside the panel) raised-press. A50.1: that fill is the whole mark. The 3px green
   bar on the open row is gone (Hub and the testing app removed it by hand); green means a wave, a
   board or a PR. Inset marks only: an outer ring on a row paints over the row above. */
.dp5-tbl { width: 100%; border-collapse: collapse; }
.dp5-tbl th { height: 44px; padding: 0 16px; text-align: left; white-space: nowrap; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--dp5-text-2); background: rgba(255, 255, 255, .03); border-bottom: 1px solid var(--dp5-line); }
.dp5-tbl td { height: 48px; padding: 0 16px; white-space: nowrap; font-size: 15px; border-bottom: 1px solid var(--dp5-line); }
.dp5-tbl tr:last-child td { border-bottom: 0; }
.dp5-tbl :is(th, td).is-num { text-align: right; font-variant-numeric: tabular-nums; }
.dp5-tbl td.is-num { font-weight: 500; }
.dp5-tbl td.is-zero { font-weight: 400; color: var(--dp5-text-missing); }
/* AMENDMENT 50.2: a cell whose value is missing says so in words (Not set, No team, Never)
   and steps down to the missing ink (--dp5-text-missing, 5.4:1), so a table of mostly-empty rows lets the real values stand out.
   Apps put is-empty on the td; a zero count is the same case. */
.dp5-tbl td.is-empty { color: var(--dp5-text-missing); }
.dp5-tbl td.is-mu { font-size: 14px; color: var(--dp5-text-2); }
.dp5-tbl .is-name { font-weight: 500; color: var(--dp5-text); }
.dp5-tbl .dp5-tbl__check { width: 52px; padding-right: 0; }
.dp5-tbl .dp5-tbl__act { width: 72px; text-align: right; }
.dp5-tbl tbody tr.is-checked td, .dp5-tbl tbody tr.is-open td { background: var(--dp5-raised-press); }
.dp5-tbl tbody tr:focus-visible { outline: 0; }
.dp5-tbl tbody tr:focus-visible td:first-child { box-shadow: inset 2px 0 0 var(--dp5-text); }
@media (hover: hover) {
  .dp5-tbl tbody tr:not(.is-checked):not(.is-open):hover td { background: var(--dp5-raised-hover); }   /* a selected row keeps its fill under the pointer */
}
/* The checkbox: an 18px box, never a pill; the tick is ink on the accent; mixed is a white bar. */
.dp5-check { display: inline-grid; place-items: center; flex: none; width: 18px; height: 18px; min-height: 0; padding: 0; border: 1.5px solid var(--dp5-line-strong); border-radius: 3px; background: transparent; box-shadow: none; }
.dp5-check.is-on { border-color: var(--dp5-green); background: var(--dp5-green); }
.dp5-check.is-on::after { content: ''; width: 5px; height: 9px; border: solid var(--dp5-ink); border-width: 0 2px 2px 0; transform: translateY(-1px) rotate(45deg); }
.dp5-check.is-mixed { border-color: var(--dp5-text); }
.dp5-check.is-mixed::after { content: ''; width: 8px; height: 2px; background: var(--dp5-text); }
/* The 18px box never moves; the hit target around it is 36px with a mouse, 44px under a finger. */
.dp5-check-hit { display: inline-grid; place-items: center; width: 36px; height: 36px; min-height: 0; padding: 0; border: 0; background: transparent; box-shadow: none; cursor: pointer; }
.dp5-check-hit:focus-visible { outline: 0; box-shadow: var(--dp5-focus); }
.dp5-tbl .dp5-tbl__more td { height: 44px; text-align: center; }
@media (pointer: coarse) {
  .dp5-tbl td { height: 44px; }
  .dp5-check-hit { width: 44px; height: 44px; min-height: 44px; }
}
/* Beside an open panel the wide columns hide; an app marks them .dp5-tbl__wide. */
@media (min-width: 1280px) {
  body.dp5-panel-open .dp5-tbl .dp5-tbl__wide { display: none; }
}

/* ============================================================ 8 BULK BAR
   Only ever on screen with a selection. Sticks to the bottom of the scrolling view (the card
   above it is overflow: clip for exactly this). */
.dp5-bulk { position: sticky; bottom: 0; z-index: 2; display: flex; align-items: center; gap: 8px; height: 48px; padding: 0 12px 0 20px; background: var(--dp5-raised-hover); border-top: 1px solid var(--dp5-line-strong); font-size: 14px; }
.dp5-bulk b { margin-right: 6px; font-weight: 600; }
.dp5-bulk__sp { flex: 1; }
@media (pointer: coarse) {
  .dp5-bulk { height: auto; min-height: 56px; flex-wrap: wrap; padding: 6px 12px; }
}

/* ============================================================ 9 DETAIL PANEL
   State, not a route. Full screen under 1280; a 480px column beside the content from 1280, where
   body.dp5-panel-open reserves the width on the app's content column (.dp5-panel-reserve) so the
   page never jumps. dp5-components.js owns the markup and the keys. */
.dp5-panel { position: fixed; inset: 0; z-index: 40; display: flex; flex-direction: column; background: var(--dp5-surface); border-left: 1px solid var(--dp5-line-card); }
.dp5-panel[hidden] { display: none; }
.dp5-panel__head { flex: none; padding: 20px 24px 0; border-bottom: 1px solid var(--dp5-line); }
.dp5-panel__top { display: flex; align-items: center; gap: 8px; }
.dp5-panel__top .dp5-panel__close { margin-left: auto; }
.dp5-panel__top button { width: 32px; min-width: 32px; height: 32px; min-height: 32px; padding: 0; justify-content: center; border-color: transparent; }
.dp5-panel__title { margin: 10px 0 2px; font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
.dp5-panel__sub { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 13px; color: var(--dp5-text-2); }
.dp5-panel__meta { font-size: 13px; color: var(--dp5-text-3); }
.dp5-panel__tabs { display: flex; gap: 0; margin-top: 16px; }
.dp5-panel__tabs button { height: 38px; min-height: 38px; padding: 0 14px; border: 0; border-bottom: 2px solid transparent; border-radius: var(--dp5-r-ctl); margin-bottom: -1px; background: transparent; font: 500 14px var(--dp5-font); color: var(--dp5-text-2); cursor: pointer; }
/* A50.1: the open tab is SELECTED, so it is the white slab with navy ink (dpt.v5.css rule 2), never a green
   underline; its focus line takes the slab's ink. An unopened tab is a word, white on hover. */
.dp5-panel__tabs button[aria-selected="true"] { background: var(--dp5-primary); color: var(--dp5-primary-ink); --dp5-focus: var(--dp5-focus-ink); }
.dp5-panel__tabs button:focus-visible { outline: 0; box-shadow: var(--dp5-focus); }
.dp5-panel__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px 24px; }
.dp5-panel__foot { flex: none; display: flex; align-items: center; gap: 12px; padding: 16px 24px; border-top: 1px solid var(--dp5-line); background: var(--dp5-surface); }
.dp5-panel__foot .dp5-panel__hint { flex: 1; font-size: 12px; color: var(--dp5-text-3); }
.dp5-kbd { font: 500 11px/16px var(--dp5-font); color: var(--dp5-text-3); border: 1px solid var(--dp5-line-strong); border-radius: 3px; padding: 0 4px; }
@media (pointer: coarse) {
  .dp5-panel__top button, .dp5-panel__tabs button { min-height: 44px; }
  .dp5-panel__top button { width: 44px; min-width: 44px; height: 44px; }
}
@media (max-width: 1279.98px) {
  .dp5-panel { padding-bottom: env(safe-area-inset-bottom, 0px); }
}
@media (min-width: 1280px) {
  .dp5-panel { position: absolute; inset: 0 0 0 auto; width: var(--dp5-panel-w); box-shadow: var(--dp5-shadow-sheet); }
  body.dp5-panel-open { position: relative; }
  body.dp5-panel-open .dp5-panel-reserve { padding-right: var(--dp5-panel-w); }
}
@media (prefers-reduced-motion: no-preference) {
  .dp5-panel { animation: dp5-panel-in var(--dp5-t-base) var(--dp5-ease); }
}
@keyframes dp5-panel-in {
  from { transform: translateX(16px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
/* Labelled field rows inside the panel: title + caption left, an 88x36 value well right, the unit
   locked inside the well, a flag (PR) outside it. */
.dp5-fieldrow { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: start; min-height: 52px; padding: 8px 0; border-bottom: 1px solid var(--dp5-line); }
.dp5-fieldrow__n { font-size: 15px; font-weight: 500; }
.dp5-fieldrow__b { font-size: 12px; color: var(--dp5-text-3); margin-top: 2px; }
.dp5-fieldrow__b b { color: var(--dp5-text-2); font-weight: 500; }
.dp5-well { position: relative; width: 88px; height: 36px; }
.dp5-well .dp5-field { width: 88px; height: 36px; min-height: 36px; padding: 0 30px 0 8px; background: var(--dp5-surface); border: 1px solid var(--dp5-line-strong); border-radius: var(--dp5-r-ctl); color: var(--dp5-text); font: 600 15px var(--dp5-font); font-variant-numeric: tabular-nums; text-align: right; }
.dp5-well .dp5-field:focus { outline: 0; border-color: var(--dp5-text); box-shadow: none; }
.dp5-well__u { position: absolute; right: 8px; top: 0; line-height: 36px; font-size: 11px; font-weight: 500; color: var(--dp5-text-2); pointer-events: none; }
.dp5-well__flag { position: absolute; left: calc(100% + 8px); top: 0; line-height: 36px; font-size: 10px; font-weight: 600; color: var(--dp5-green); }
.dp5-fam { display: flex; align-items: center; padding: 18px 0 4px; font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--dp5-text-2); }
.dp5-fam:first-child { padding-top: 0; }

/* ============================================================ 10 SPLIT (list | detail)
   A 280px list beside the detail from 1280; stacked under, where the list collapses to a
   field-shaped picker row (.dp5-split__pick) that opens the same list as a sheet. */
.dp5-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
.dp5-split__pick { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: 44px; padding: 0 12px; background: var(--dp5-raised); border: 1px solid var(--dp5-line-strong); border-radius: var(--dp5-r-ctl); color: var(--dp5-text); font: 500 14px var(--dp5-font); text-align: left; cursor: pointer; }
.dp5-split__pick:focus-visible { outline: 0; box-shadow: var(--dp5-focus); }
@media (max-width: 1279.98px) {
  .dp5-split__list { display: none; }
}
@media (min-width: 1280px) {
  .dp5-split { grid-template-columns: 280px minmax(0, 1fr); }
  .dp5-split__pick { display: none; }   /* declared after the base rule: the hide must win the cascade */
  body.dp5-panel-open .dp5-split { grid-template-columns: minmax(0, 1fr); }
  body.dp5-panel-open .dp5-split__list { display: none; }
  body.dp5-panel-open .dp5-split__pick { display: flex; }
}
.dp5-split__item { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 12px; border-radius: var(--dp5-r-ctl); color: var(--dp5-text); cursor: pointer; }
.dp5-split__item.is-on { background: var(--dp5-raised-press); color: var(--dp5-text); }   /* A50: selected is a fill, never green */

/* ============================================================ 11 PROGRESS TRACK
   An empty track must still read on the card: --dp5-line is 1.4:1 there, line-strong is 3.2:1. */
.dp5-prog { flex: 1; min-width: 80px; height: 4px; overflow: hidden; border-radius: 2px; background: var(--dp5-line-strong); }
.dp5-prog > i, .dp5-prog__fill { display: block; height: 100%; background: var(--hue, var(--dp5-green)); }

/* ============================================================ 12 ENTRY CARD
   The card IS the button: no control inside it competing with the screen's one primary. */
.dp5-enter { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 700px) {
  .dp5-enter { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.dp5-enter .dp5-card { display: flex; align-items: center; gap: 16px; height: auto; min-height: 0; padding: 20px; cursor: pointer; text-align: left; white-space: normal; font-size: 13px; font-weight: 400; color: var(--dp5-text); }
.dp5-enter .dp5-card:focus-visible { outline: 0; box-shadow: var(--dp5-focus); }
.dp5-enter__ico { display: grid; place-items: center; flex: none; width: 44px; height: 44px; border-radius: var(--dp5-r-card); background: var(--dp5-raised-press); }
.dp5-enter__ico svg { width: 22px; height: 22px; stroke: var(--dp5-text); fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.dp5-enter h3, .dp5-enter__t { margin: 0; font-size: 16px; font-weight: 600; }
.dp5-enter p, .dp5-enter__s { margin: 2px 0 0; font-size: 13px; color: var(--dp5-text-2); }
.dp5-enter__chev { margin-left: auto; font-size: 18px; color: var(--dp5-text-2); }
@media (hover: hover) {
  .dp5-enter .dp5-card:hover { background: var(--dp5-raised-hover); }
  .dp5-split__item:not(.is-on):hover { background: var(--dp5-raised-hover); }
  .dp5-fchip:not(.is-on):not([aria-pressed="true"]):hover { background: transparent; color: var(--dp5-text); }   /* A50.1: a word turning white, no fill */
  .dp5-panel__tabs button:not([aria-selected="true"]):hover { color: var(--dp5-text); }
}
