/* ── Shared primitives: Command HQ, Detailer HQ and The Driveway ───────────
   One source for the marks every app draws. Command HQ inlines this file at
   build (css/src/ops-dashboard.css imports it where 67-status.css used to
   sit); detailer-day.html and portal.html load it after css/tokens.css and
   their own stylesheet, so it wins at equal specificity. Phase 6H (EAS-745)
   moved it here so the crew's and the customer's screens stop drawing their
   own copies; the field followed (EAS-746). Tokens only: no page may give it a colour of its own. */

/* ── Controls take the page's font (Phase 6H, EAS-748) ──────────────────────
   A button, field or dropdown does not inherit font-family: the browser gives
   it its own. Every Detailer HQ button.dd-btn was drawn in Arial beside an
   a.dd-btn in Barlow, and the Driveway's vehicle rows (buttons) set the car's
   name in Arial. :where() keeps this at zero specificity, so any rule that
   names a family still wins. */
:where(button, input, select, textarea) { font-family: inherit; }

/* ── One status pill (Phase 6G, EAS-743) ────────────────────────────────────────────
   Every record status draws one shape: --pill-font, --pill-track, --pill-pad,
   fully round, one line, 22px tall. Its colour is its MEANING, read from one
   of five tones in css/tokens.css. The fill and the line are mixed from the
   tone, so a status cannot be green text on a differently-green fill again.

   Measured before (app-tour.js marks, desktop): customer statuses 24 and 26px
   tall, supply 22 and 28px at 10 and 11px, payroll 10.5px with 5px corners,
   the Automations trust badge 700 weight at 20px, Archived 600 weight at
   10px corners. Tint's badge is left alone: it is filled solid by its caller
   and the feature is off. One deliberate exception: equipment condition in a
   supply row is a BUTTON (tap cycles it) standing among 28px action buttons,
   and css/supply-rules.css keeps it at their height. Tokens only. */

:is(.cust-status-badge, .settings-status-chip, .cal-agenda-status, .supply-status-badge, .billing-badge, .pr-badge, .jf-statuschip, .assistant-trust-badge, .svc-inactive-badge, .ops-request-queue-count, .detailer-status, .pt-pill, .dd-pill, .dd-invcat-stat) {
  --tone: var(--tone-neutral);
  display: inline-flex;
  align-items: center;
  align-self: center;
  gap: 4px;
  box-sizing: border-box;
  height: 22px;
  padding: var(--pill-pad);
  font: var(--pill-font);
  letter-spacing: var(--pill-track);
  text-transform: uppercase;
  white-space: nowrap;
  flex-shrink: 0;
  border-radius: var(--r-pill);
}
/* The colour, from the tone and nothing else. [class] lifts this to the
   specificity of a variant rule (.pt-pill.paid, .supply-status-badge.ok),
   and this file loads after every app's own stylesheet, so it wins: without
   it each app's variant kept painting its own green. */
:is(.cust-status-badge, .settings-status-chip, .cal-agenda-status, .supply-status-badge, .billing-badge, .pr-badge, .jf-statuschip, .assistant-trust-badge, .svc-inactive-badge, .ops-request-queue-count, .detailer-status, .pt-pill, .dd-pill, .dd-invcat-stat)[class] {
  color: var(--tone);
  /* A browser without color-mix() (iOS before 16.2) keeps a quiet fill. */
  background: var(--surface-soft);
  background: color-mix(in srgb, var(--tone) 13%, transparent);
  border: 1px solid var(--surface-line);
  border: 1px solid color-mix(in srgb, var(--tone) 28%, transparent);
}

/* What each status means. */
:is(.supply-status-badge.ok, .billing-badge.paid, .pr-badge.is-paid, .jf-statuschip.paid, .cust-status-badge.repeat, .settings-status-chip.ok, .detailer-status.on, .pt-pill.paid, .dd-pill.done, .dd-pill.is-good, .dd-invcat-stat.ok) { --tone: var(--tone-good); }
:is(.supply-status-badge.low, .billing-badge.invoiced, .billing-badge.partial, .jf-statuschip.invoiced, .jf-statuschip.disc, .cust-status-badge.needs-followup, .settings-status-chip.warn, .assistant-trust-badge, .ops-request-queue-count, .pt-pill.up, .pt-pill.live, .dd-pill.live, .dd-pill.is-warn, .dd-invcat-stat.low) { --tone: var(--tone-warn); }
:is(.supply-status-badge.critical, .billing-badge.overdue, .pr-badge.is-void, .cust-status-badge.needs-review, .pt-pill.due, .dd-invcat-stat.crit) { --tone: var(--tone-bad); }
:is(.billing-badge.sent, .pr-badge.is-approved, .cust-status-badge.new) { --tone: var(--tone-info); }

/* A voided invoice is struck through, whatever its tone. */
.billing-badge.void { text-decoration: line-through; }
/* The job card's money chips are amounts, not statuses: sentence case. */
.jf-statuschip:is(.disc, .net) { text-transform: none; letter-spacing: 0; }

/* ── One count badge (Phase 6G, EAS-743) ────────────────────────────────────────────
   A number waiting for you: the rail and the phone bar, the bell, the Comms
   rail's doors. It was 9px/900 at 16px on the rail, 10px/900 at 15px on the
   phone, 10px/800 at 17px with 9px corners on the bell, and 11px/400 at 12px
   on the Comms rail. And the red "risk" badge was white on --danger, about 2:1.
   Now one shape, and dark numerals on every fill. Where it sits is still
   each context's business (position rules in 13-mobile-nav, 58-nav-tablet,
   59-phone-bar, 23-alerts). */
:is(.ops-tab-badge, .ops-bell-badge, .inbox-filter-count, .billing-view-badge) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: var(--count-size);
  height: var(--count-size);
  padding: 0 5px;
  font: var(--count-font);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  border-radius: var(--r-pill);
  background: var(--tone-warn);
  color: var(--canvas);
}
:is(.ops-tab-badge.warn) { background: var(--warning); }
:is(.ops-tab-badge.risk, .ops-bell-badge.is-failure) { background: var(--tone-bad); color: var(--canvas); }
/* A badge with no number is not a badge. It used to collapse to 0px tall;
   with a fixed height it would be a blank gold pill. */
:is(.ops-tab-badge, .ops-bell-badge, .inbox-filter-count, .billing-view-badge):empty { display: none; }

/* ── One text field, one dropdown (Phase 6G, EAS-744; shared in 6H, EAS-746) ───────────────────────────────
   .ops-control-input / .ops-control-select are the house control (36px, 13px,
   7px 10px, one fill, one line, a gold focus ring; the caret and the disabled
   and invalid states live in 15-shared-ui.css). Measured before, the fields
   that never adopted it (app-tour.js fields, desktop):
     Billing's search and period      47px, on --dark2 with a --dark3 line
     Expenses' search / month         31 / 36px at 12px
     Comms' search / Who lens          33 / 30px, a third fill
     Settings › Automations' inputs    31px, 4px 8px, a fourth line
   A plain selector list, not :is(), so each keeps its own specificity and the
   shared focus, caret and invalid rules still reach them. Tokens only. */

.ops-control-input,
.ops-control-select,
.billing-search,
.billing-period-select,
.exp-search,
.exp-month-select,
.inbox-search,
.inbox-who,
.assistant-auto-group .settings-notify-row input[type="number"],
.assistant-auto-group .settings-notify-row input[type="url"] {
  box-sizing: border-box;
  height: var(--field-h);
  padding: var(--field-pad);
  font-family: var(--font-body);
  font-size: var(--field-size);
  line-height: 1.3;
  color: var(--white);
  background-color: var(--field-bg);
  border: 1px solid var(--field-line);
  border-radius: var(--r-sm);
}

/* The written-reply box is a field too: same fill, line and corners. It keeps
   its 14px, because it is where a message is composed. */
.rep-box {
  background-color: var(--field-bg);
  border: 1px solid var(--field-line);
  border-radius: var(--r-sm);
}

/* Focus: the house border and glow for any focus, and a keyboard ring on
   top. The ring matters: several of these fields said `outline: none` on
   :focus, which also outranked global.css's input:focus-visible, so a
   keyboard user tabbing into Billing's search saw only a border tint. */
.ops-control-input:focus,
.ops-control-select:focus,
.billing-search:focus,
.billing-period-select:focus,
.exp-search:focus,
.exp-month-select:focus,
.inbox-search:focus,
.inbox-who:focus,
.rep-box:focus,
.pt-input:focus,
.dd-linkform-input:focus,
.dd-msg-input:focus,
.dd-sheet-note:focus,
.assistant-auto-group .settings-notify-row input[type="number"]:focus,
.assistant-auto-group .settings-notify-row input[type="url"]:focus {
  border-color: color-mix(in srgb, var(--gold) 65%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold) 10%, transparent);
}
.ops-control-input:focus-visible,
.ops-control-select:focus-visible,
.billing-search:focus-visible,
.billing-period-select:focus-visible,
.exp-search:focus-visible,
.exp-month-select:focus-visible,
.inbox-search:focus-visible,
.inbox-who:focus-visible,
.rep-box:focus-visible,
.pt-input:focus-visible,
.dd-linkform-input:focus-visible,
.dd-msg-input:focus-visible,
.dd-sheet-note:focus-visible,
.assistant-auto-group .settings-notify-row input[type="number"]:focus-visible,
.assistant-auto-group .settings-notify-row input[type="url"]:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* Disabled: one look for every field, the house one. */
.billing-search:disabled,
.billing-period-select:disabled,
.exp-search:disabled,
.exp-month-select:disabled,
.inbox-search:disabled,
.inbox-who:disabled,
.rep-box:disabled,
.pt-input:disabled,
.dd-linkform-input:disabled,
.dd-msg-input:disabled,
.assistant-auto-group .settings-notify-row input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* The dropdowns that were not .ops-control-select get its caret. */
.billing-period-select,
.inbox-who {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 30px;
  cursor: pointer;
  background-image: var(--caret);
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 11px 7px;
}
.billing-period-select:focus,
.inbox-who:focus { background-image: var(--caret-focus); }

/* The touch density (6H, EAS-746): the Driveway's and Detailer HQ's fields.
   Same fill, line, corners and states as Command HQ's, sized for a thumb.
   Measured before: the Driveway's .pt-input was 15px on --dark3 with 6px
   corners and a 12% white line; Detailer HQ's inputs #0e0e0e with #333 and
   10px corners. Both turned the outline off on focus, so a keyboard user
   (or a switch control) saw only a border tint. */
.pt-input,
.dd-linkform-input,
.dd-msg-input,
.dd-sheet-note {
  box-sizing: border-box;
  padding: var(--field-pad-touch);
  font-family: var(--font-body);
  font-size: var(--field-size-touch);
  line-height: 1.3;
  color: var(--white);
  background-color: var(--field-bg);
  border: 1px solid var(--field-line);
  border-radius: var(--r-sm);
}
.pt-input,
.dd-linkform-input { min-height: var(--field-h-touch); }

/* Invalid outranks focus: a field that is wrong stays red while it is being
   fixed. It came before the focus rules, so a focused invalid field went
   gold and hid the error. */
.ops-control-input:user-invalid,
.ops-control-select:user-invalid,
.pt-input:user-invalid,
[aria-invalid="true"].ops-control-input,
[aria-invalid="true"].ops-control-select,
[aria-invalid="true"].pt-input {
  border-color: var(--danger);
}
