/*
 * Compact pill filter bar — the always-visible row of 30px round pills that
 * sits directly under a page's tab strip (ISH-895).
 *
 * ISH-638 built this on analytics.html: the stacked uppercase <label> above
 * each control is dropped, the trigger's resting text ("All regions") becomes
 * the label, and a selection shows as a red count. ISH-826 hand-copied it onto
 * uninvoiced-approved-tasks.html as `.uat-*` for native <select>s, and that
 * page's own comment named the reason — "`.filter-bar` is still per-page inline
 * across the app". This file is that reason removed. A page adopts the look
 * with a <link>; delete its inline copy in the same change rather than leaving
 * both, which is how the pre-ISH-353 stage palette drifted.
 *
 * Consumers today, all rendering `.multi-filter` pills: analytics.html (Sales
 * Report), uninvoiced-approved-tasks.html (Un-invoiced Approved Task Report) and
 * contractor-review.html (the cross-broker contractor queue, whose bar is built
 * by js/contractor-review-filters.js).
 *
 * ⚠️ This list said the second of those was React — `MultiFilter.tsx`, mounted
 * from `react-app/src/uninvoiced-approved-tasks/App.tsx`. **It has not been since
 * ISH-928 retired that island**; the page is vanilla modules and builds its bar
 * in js/uninvoiced-approved-tasks-view.js. The only surviving `MultiFilter.tsx`
 * is in the link-only `react-app/` sandbox (ISH-1068), whose bundle is gitignored
 * and which no user-facing page loads. Corrected here rather than left, because
 * the claim sent a reader looking for a build step this app does not have.
 *
 * ⚠️ THIS FILE IS OVERRIDES ONLY, AND LINKING IT ALONE STYLES NOTHING.
 *
 * `.filter-bar .mf-trigger` sets the pill's geometry AND its border (pinned by
 * ISH-921 — see the rule); the rest of the base it sits on — ground, hover, and
 * the whole `.mf-dropdown` panel — comes from css/filter-toolbar.css, or from
 * the page's own inline copy (analytics.html still carries one until ISH-444).
 * **A host page links both.**
 *
 * ⚠️ ISH-895 shipped a second arm here, a self-contained treatment for native
 * `<select>`s, because uninvoiced-approved-tasks.html rendered three of them.
 * ISH-906 moved that page onto the real `.multi-filter` control an hour later,
 * leaving the arm with zero consumers, so it was deleted rather than kept as a
 * variant nothing renders — and its note said to write it back deliberately if a
 * report ever did want plain selects, rather than assume it was dropped by
 * accident. **The Broker Platform Utilization report is that report**, and the arm is back under
 * "Native selects". Two differences from the deleted version, both deliberate:
 * it hangs off `.filter-group` rather than a parallel `.filter-field` container,
 * so a select reuses the pill row AND the visually-hidden-label rule instead of
 * needing copies of both; and it carries a `:focus-visible` the original lacked.
 *
 * ⚠️ `.filter-bar` was also the name of an unrelated boxed card container in
 * manage-templates.html. That block styled nothing — the class appeared in its
 * <style> and nowhere in its markup or js/manage-templates.js — so ISH-895
 * deleted it rather than renaming it. If you reintroduce a `.filter-bar` on any
 * page, it means this component.
 *
 * What one shared rule changes, measured against what each page rendered
 * before. Nothing else moved:
 *
 *   .filter-bar-label, .filter-clear-btn — resting colour is
 *       var(--text-secondary). analytics.html had var(--text-label) and the uat
 *       copy #aaaaaa. ⚠️ A shared rule cannot use --text-label here: it is
 *       #777777 on analytics.html but #94a3b8 on
 *       uninvoiced-approved-tasks.html, where it fails contrast at 2.43:1 —
 *       the trap that page already sidestepped for its own caption. This
 *       darkens both. See .docs/AGENT_GUIDE.md §CX.4c.
 *   .filter-clear-btn hover — var(--red), the uat copy's, not
 *       analytics.html's var(--text). Clearing every filter at once is the one
 *       destructive control in the bar, and red is how this app marks that.
 *   .filter-clear-btn height/size — 32px / 0.8rem, the uat copy's and
 *       css/filter-toolbar.css's, which already agreed; analytics.html's bar
 *       had 26px / 0.75rem. On a borderless button in an `align-items: center`
 *       row the height is invisible, and the larger value is the better target.
 *   border-radius — 50px throughout, css/filter-toolbar.css's value.
 *       analytics.html wrote 999px. Both fully round a 30px control, so this
 *       renders identically; it is written this way so the shared bar and the
 *       shared toolbar state one radius between them.
 *
 * Depends on the page's own :root tokens: --red, --border, --border-light,
 * --text, --text-secondary, --text-label, --radius. Every page declares them.
 *
 * The markup contract this styles:
 *
 *   .filter-bar
 *     .filter-bar-label            the one visible "Filters" caption
 *     .filter-bar-search           free-text input, sized to sit among the pills
 *     .filter-group                wrapper for a .multi-filter OR a native <select>
 *       label                      visually hidden — the accessible name
 *       .multi-filter > .mf-trigger[.has-value] > .mf-count
 *       select                     the native-select arm (see "Native selects")
 *     .filter-clear-btn            resets every filter at once
 *     .filter-bar-spacer           pushes what follows to the right end
 *     .filter-bar-divider          hairline between two groups of controls
 */

/* ── Container ───────────────────────────────────────────────────────────────
   No card and no rule. The pills are already the thing with edges, so a fill
   around them was a second container drawn on objects that were contained; and
   `.main-tabs` already draws a 2px rule directly above, so a bottom hairline
   put two lines around one short row. The margin below is the separator. */
.filter-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.55rem 0.1rem;
  margin-bottom: 1rem;
}

.filter-bar[hidden] {
  display: none;
}

.filter-bar-label {
  font-size: 0.625rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  /* --text-secondary, not --text-label: at 0.625rem this is small text, so the
     4.5:1 floor applies, and uninvoiced-approved-tasks.html's --text-label is
     #94a3b8 (2.43:1). */
  color: var(--text-secondary);
  flex-shrink: 0;
}

/* Pushes everything after it (a period control, a submarket count) to the right
   end, away from the facet pills. */
.filter-bar-spacer {
  margin-left: auto;
}

.filter-bar-divider {
  width: 1px;
  align-self: stretch;
  background: var(--border-light);
  margin: 0 0.35rem;
}

.filter-bar-empty {
  font-size: 0.75rem;
  color: var(--text-label);
  font-style: italic;
}

/* ── The accessible name ─────────────────────────────────────────────────────
   ⚠️ Visually hidden, NOT deleted, and never `display: none` — that would take
   it from screen readers too. The visible trigger text ("All regions") is the
   label now; an uppercase word beside it would be a second label saying the
   same thing. Dropping this rule is an accessibility regression you cannot
   see. */
.filter-bar .filter-group > label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ── Pill geometry ───────────────────────────────────────────────────────────
   `flex-wrap: nowrap` + `white-space: nowrap` + `width: auto` are what make a
   trigger a pill rather than a full-width field, and the 30px is a fixed
   `height`, not a `min-height`. The 50px radius is css/filter-toolbar.css's
   `.mf-trigger` value, so the two components stay one look; the border
   deliberately is NOT — see the rule below. */
.filter-bar .filter-group {
  flex-direction: row;
  align-items: center;
  flex: 0 0 auto;
  min-width: 0;
}

.filter-bar .filter-group[hidden] {
  display: none;
}

.filter-bar .mf-trigger {
  width: auto;
  min-height: 30px;
  height: 30px;
  padding: 0 0.55rem;
  /* ⚠️ PINNED HERE, not left to the base (ISH-921). This file used to set everything about a
     `.filter-bar .mf-trigger` except the border, on the reasoning that the base supplies it — but
     the bases disagree: css/filter-toolbar.css is 1.5px and analytics.html's own inline copy is
     1px, so one shared component rendered two weights depending on which stylesheet the host
     happened to carry, and analytics.html ended up overriding itself on one of its two bars.
     1px is the Sales Report Dashboard's value and the decision of 2026-09-11.

     This does NOT change css/filter-toolbar.css's `.mf-trigger` base — the collapsible panel on
     the Sales Pipeline pages is still 1.5px. Only the compact bar is pinned. */
  border: 1px solid var(--border);
  border-radius: 50px;
  font-size: 0.75rem;
  flex-wrap: nowrap;
  white-space: nowrap;
}

/* A set filter is called out so an active one is visible without reading every
   control. The search is in this list too: a typed query narrows the table exactly as a chosen
   dropdown value does, and leaving it out made the one control whose state you cannot infer from
   a glance at the row the one control that did not show it. The page toggles the class — there is
   no CSS state for "has text" that also survives a programmatic clear.

   ⚠️ The native-select arm that stood here until ISH-906 is back, but as its own rule under
   "Native selects" below rather than another selector on this one — a `<select>` cannot be given
   `font-weight: 700` on its closed value in every engine, so it states its own active look. */
.filter-bar .mf-trigger.has-value,
.filter-bar .filter-bar-search.has-value {
  border-color: var(--red);
  background: rgba(166, 38, 38, 0.06);
  color: var(--red);
  font-weight: 700;
}

/* ⚠️ Replaces the inline `.mf-trigger-chip` list when a trigger is inside the
   bar — five chips blow the pill's width out on one line. css/filter-toolbar.css
   renders the chips, so a page carrying both files needs this override. */
.filter-bar .mf-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 0.25rem;
  border-radius: 50px;
  background: var(--red);
  color: #ffffff;
  font-size: 0.625rem;
  font-weight: 800;
}

/* ── Native selects ──────────────────────────────────────────────────────────
   A plain `<select>` dressed as one of the row's 30px pills, for a bar whose
   facets are single-choice and short enough not to need the `.multi-filter`
   panel. The Broker Platform Utilization report's two (CSM, Partner type) are
   the renderer; see that page and my-brokers.html.

   ⚠️ Geometry is copied from `.filter-bar .mf-trigger` above rather than shared
   with it, and that is the honest shape: a `<select>` cannot be a `<button>`, so
   there is no common element to hang one rule on. If you retune the pill, retune
   BOTH — they sit in the same row and a 1px difference in height is visible.

   ⚠️ `appearance: none` plus a drawn caret, because a native select arrow inside
   a 50px-radius pill sits on the straight part of the border and reads as a
   second, squarer control pasted into a round one. The caret is a background
   SVG so it needs no extra element in the markup the page already emits. */
.filter-bar .filter-group select {
  appearance: none;
  -webkit-appearance: none;
  height: 30px;
  padding: 0 1.55rem 0 0.55rem;
  border: 1px solid var(--border);
  border-radius: 50px;
  background-color: #ffffff;
  /* A 10×6 chevron in --text-secondary (#4b5563), inlined: this file must not
     fetch an asset, and an <img> would need markup. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%234b5563' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.55rem center;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition:
    background-color 0.15s,
    border-color 0.15s;
}

.filter-bar .filter-group select:hover {
  border-color: var(--text-label);
}

.filter-bar .filter-group select:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 1px;
}

/* The chosen-value state, matching `.mf-trigger.has-value` above. ⚠️ Set by the
   page on the element (the renderer adds the class when the value is not its
   "all" option), NOT by a CSS selector — there is no way to ask a `<select>`
   whether its current option is the first one. The caret is redrawn in --red so
   the whole control changes together rather than keeping a grey arrow. */
.filter-bar .filter-group select.has-value {
  border-color: var(--red);
  background-color: rgba(166, 38, 38, 0.06);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a62626' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  color: var(--red);
  font-weight: 700;
}

/* ── Search ──────────────────────────────────────────────────────────────────
   `flex: 0 1` rather than growing to fill: it sits among the pills instead of
   dominating the row. */
.filter-bar-search {
  /* ⚠️ `appearance: none` is load-bearing, not a reset for tidiness. Both consumers render this
     as `<input type="search">`, and WebKit gives that a NATIVE searchfield appearance which
     overrides `border-radius` and the box metrics — so on Safari the control renders as a taller
     rounded rectangle beside three capsule pills, while Chromium honours the CSS and looks
     correct. That asymmetry is why it shipped: it is invisible in a Chromium-based browser and in
     any Chromium-driven check. Reported from Safari on the Sales Report 2026-09-11.
     Do not drop this, and do not "simplify" it by switching the markup to `type="text"` — that
     loses the input's search semantics to save one declaration. */
  appearance: none;
  -webkit-appearance: none;
  flex: 0 1 250px;
  min-width: 170px;
  height: 30px;
  padding: 0 0.75rem;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text);
  background: #ffffff;
  /* ⚠️ Must equal the pill's border above. Pinning the pills at 1px and leaving this at 1.5px just
     inverts the mismatch that analytics.html's `.unattributed-filter-bar` override existed to fix
     — a 1px pill beside a 1.5px input, visible side by side. Change the two together. */
  border: 1px solid var(--border);
  border-radius: 50px;
  transition: border-color 0.15s;
}

.filter-bar-search::placeholder {
  color: var(--text-secondary);
}

.filter-bar-search:hover {
  border-color: #999999;
}

/* ── Clear ───────────────────────────────────────────────────────────────────
   Plain text, no border: an escape hatch, not a filter. A bordered pill here
   reads as one more dropdown. Declared in full, so a page linking only this
   file still gets a styled button. */
.filter-bar .filter-clear-btn {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex-shrink: 0;
  height: 32px;
  padding: 0 0.5rem;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s;
}

.filter-bar .filter-clear-btn:hover {
  color: var(--red);
}

/* ⚠️ **`display: inline-flex` above BEATS the UA stylesheet's `[hidden] { display: none }`**, so a
   page that hides this button by setting `.hidden = true` gets a button that is still on screen.
   Both report bars do exactly that — the Un-invoiced report has since ISH-1082, and the Broker
   Utilization bar joined it in ISH-1235 when it stopped rebuilding itself on every render — so
   "Clear all" sat there permanently, offering to undo filters nobody had set.

   Invisible to jsdom, which is why it survived: `el.hidden` is true and the assertion passes, and
   only a real cascade shows the element still laid out. Caught in Chromium against the real page's
   stylesheets. analytics.html already carries this rule for its own `.unattributed-filter-bar`;
   the shared bar never got one. See `.docs/AGENT_GUIDE.md` §DI.3. */
.filter-bar .filter-clear-btn[hidden] {
  display: none;
}

/* ── Controls that ride along in the bar ─────────────────────────────────────
   analytics.html's period control and the Scorecard's static period badge,
   sized to match the facet pills so the bar reads as one row. */
.filter-bar .submarkets-toggle {
  height: 30px;
  border-radius: 50px;
  font-size: 0.75rem;
}

.filter-bar .mtd-badge {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 0.6rem;
  border-radius: 50px;
  font-size: 0.6875rem;
}

/* ── The `+ Add filter` control and the pills it adds (ISH-1235) ─────────────
   Built by js/filter-bar-add-control.js; the class names below are that file's
   contract, so the two move together.

   ⚠️ **Moved here from analytics.html's inline <style> (ISH-1123), which is now
   deleted rather than left in place.** Three pages render this control and all
   three link this file; a page carrying both a shared stylesheet AND its own
   copy of the component is the drift this file's header exists to undo. The
   inline block anticipated the move — its own comment said it travels with the
   `.mf-trigger` base when ISH-444 lifts that out.

   ⚠️ Every measurement is INHERITED from `.filter-bar .mf-trigger` above — the
   30px height, the 1px border ISH-921 pinned, the radius, the font. Only what
   makes this read as an ACTION rather than a facet is declared here: a dashed
   edge, no resting value, and the accent on hover. */
.filter-bar .filter-add-trigger {
  border-style: dashed;
  color: var(--text-secondary);
  gap: 0.3rem;
}

.filter-bar .filter-add-trigger:hover,
.filter-bar .filter-add-trigger[aria-expanded="true"] {
  border-style: solid;
  border-color: var(--red);
  color: var(--red);
}

.filter-add-icon {
  flex-shrink: 0;
}

/* Hidden when every facet is already in the bar — an "Add filter" that opens an
   empty panel is a dead control. The control sets this. */
.filter-add[hidden] {
  display: none;
}

/* A menu row. `.mf-option` draws a checkbox slot for its `.mf-check` span; these
   rows have no span, so without this they sit 24px in from an empty gutter.
   Picking one is an action, not a selection that persists in the list. */
.filter-bar .filter-add .mf-option-single {
  padding-left: 0.75rem;
}

/* ── An added facet's group ──────────────────────────────────────────────────
   The pill and its remove button read as ONE control: they sit in a flex row
   with no gap, and the × is square-ended rather than round so the pair still
   reads as a single pill with an affordance on its end.

   ⚠️ The × is a SIBLING of `.multi-filter`, never a child of `.mf-trigger`.
   createMultiFilter() rewrites `trigger.innerHTML` wholesale on every selection
   change, so a button placed inside it is silently destroyed the first time
   anyone picks a value.

   ⚠️ Scoped under `.filter-bar`, not written bare. analytics.html declares its
   own `.filter-group { display: flex; flex-direction: column; gap: 0.25rem }`
   inline, which loads AFTER this file — so a bare `.filter-group-added` ties on
   specificity and loses on source order, which rendered the × 3px adrift of its
   pill with the group still in column flow. Scoped, it wins on specificity
   regardless of order. Measured in Chromium against the real cascade, per
   `.docs/AGENT_GUIDE.md` §DI.3. */
.filter-bar .filter-group-added {
  display: flex;
  align-items: center;
  gap: 0;
}

.filter-bar .filter-remove-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 30px;
  margin-left: -1px;
  padding: 0;
  background: none;
  border: 1px solid var(--border);
  border-left: none;
  border-radius: 0 50px 50px 0;
  color: var(--text-label);
  cursor: pointer;
  flex-shrink: 0;
  transition:
    color 0.1s,
    background 0.1s;
}

/* The pill's own right edge would draw a line through the middle of the pair. */
.filter-bar .filter-group-added .mf-trigger,
.filter-bar .filter-group-added select {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: none;
}

/* ⚠️ The × has to turn red WITH its pill, or a selected facet renders as a
   half-red capsule — red trigger, grey button — which reads as a broken control
   rather than a filtered one. Caught in a browser render; jsdom cannot see it.
   Same reasoning this file gives for redrawing the native select's caret in
   --red: the whole control changes together.

   `:has()` because the × is a SIBLING of `.multi-filter` and `.has-value` lands
   on the `.mf-trigger` inside it, so there is no descendant or sibling path from
   one to the other. Already this repo's way across that boundary —
   css/portal-rail.css does the same for `.rail-account.is-open`. Values copied
   from `.filter-bar .mf-trigger.has-value`; if that rule changes, this changes
   with it. */
.filter-bar .filter-group-added:has(.mf-trigger.has-value) .filter-remove-btn,
.filter-bar .filter-group-added:has(select.has-value) .filter-remove-btn {
  border-color: var(--red);
  background: rgba(166, 38, 38, 0.06);
  color: var(--red);
}

.filter-bar .filter-remove-btn:hover,
.filter-bar .filter-group-added:has(.mf-trigger.has-value) .filter-remove-btn:hover {
  background: rgba(166, 38, 38, 0.08);
  color: var(--red);
}

.filter-bar .filter-remove-btn:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 1px;
}

/* ══ ISH-1365: the Group by switch ═══════════════════════════════════════════════════════
 *
 * Two toggles over one setting, at the end of the Contractor Submission Review bar. It is a
 * GROUPING, not a filter — it narrows nothing — so it is set apart from the pills rather than
 * dressed as one more of them: a label, then two small segmented buttons.
 *
 * ⚠️ Deliberately NOT `.mf-trigger`'s treatment. A pill in this bar means "this narrows the
 * list", and four of them already do; a fifth that reorders instead would be the same shape
 * making a different promise.
 *
 * ⚠️ `margin-left: auto` puts it at the bar's far end, past Clear all's slot. On a narrow bar
 * the flex wrap drops it to its own line, which is right — it is the least urgent control here.
 */
.filter-bar .filter-groupby {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: auto;
  white-space: nowrap;
}

.filter-bar .filter-groupby-label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-label, #9b9b9b);
}

.filter-bar .filter-groupby-btn {
  appearance: none;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 999px;
  background: #ffffff;
  color: var(--text, #1a1a1a);
  cursor: pointer;
}

.filter-bar .filter-groupby-btn:hover[aria-pressed="false"] {
  border-color: #cccccc;
  background: var(--page-bg, #f8f9fa);
}

/* ⚠️ Keyed on `aria-pressed` rather than on a class, so the thing a screen reader reads and the
 * thing the eye reads cannot drift apart — there is only one source for both. */
.filter-bar .filter-groupby-btn[aria-pressed="true"] {
  background: var(--red, #a62626);
  border-color: var(--red, #a62626);
  color: #ffffff;
}

.filter-bar .filter-groupby-btn:focus-visible {
  outline: 2px solid var(--red, #a62626);
  outline-offset: 1px;
}
