/* ============================================================
   BsSharedHeader — Brand & Store dashboard header.
   Hybrid layout, standardized on the canonical SOCOM classes:
     • Title block (.page-header / __title / __subtitle) — scrolls away.
     • Sticky rounded panel: a tab line (view tabs left + Currency/Number Format
       toggles right) + one .filter-bar row of .filter-item* data filters.
   Only the sticky shell, tab styling, and a couple of right-aligns are local.
   ============================================================ */

/* display:contents so the sticky panel's parent is the tall page container
   (not this short header wrapper) — otherwise it can't stick past the title. */
.bs-page-header { display: contents; }

/* Title block — scrolls away (canonical SOCOM .page-header). Line 1 = title +
   display toggles (right); the subtitle drops to a full-width line 2 so the
   long freshness/FX caption never collides with the toggles. */
.bs-hdr__titleblock {
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
}
.bs-hdr__titleblock .page-header__subtitle { flex: 1 0 100%; margin-top: 0; }
/* Subtitle = two stacked lines: "Data updated to <strong>{datetime}</strong>
   ({relative})" then "FX: 1 USD = {rate} ₫". Datetime is bolded/darkened. */
.bs-hdr__dt { font-weight: 700; color: var(--text-primary); }
.bs-hdr__subline { margin: 0; }
/* Opt-in monthly-grain caveat (SKU Performance). Muted, inline (i) icon. */
.bs-hdr__period-note {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-tertiary);
  font-size: var(--font-size-xs, 0.75rem);
}
.bs-hdr__period-note-icon { flex: 0 0 auto; opacity: 0.85; }

/* Sticky region: view tabs + filter bar, as a rounded panel (card). */
.bs-hdr__stack {
  position: sticky;
  top: 0;
  z-index: 100;
  /* No margin-bottom — the page wrapper's flex gap owns inter-card spacing, so
     the header-to-content gap matches the content-to-content gap (user 2026-05-30). */
  margin-bottom: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  overflow: hidden;                 /* clip tabs/filter rows to the rounded corners */
}

/* Tab line — view tabs only (Currency/Number Format now live on the title line). */
.bs-hdr__tabs {
  display: flex;
  align-items: stretch;
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

/* Inside the rounded panel the SOCOM .filter-bar drops its own bottom border
   (the card border owns it) and uses panel-appropriate horizontal padding. */
.bs-hdr__stack .filter-bar {
  padding: var(--space-5) var(--space-5);   /* roomy, equal top/bottom */
  border-bottom: none;
  background: transparent;
}

.bs-tabs {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.bs-tab {
  padding: var(--space-3) var(--space-1);
  margin-bottom: -1px;
  font-size: var(--font-body, 0.875rem);
  font-weight: 600;
  color: var(--text-tertiary);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.bs-tab:hover { color: var(--text-primary); }
.bs-tab.active { color: var(--color-action); border-bottom-color: var(--color-action); }

/* Display toggles (Currency, Number Format) — on the title line (right side,
   outside the panel) via .page-header__actions. */
.bs-hdr__display {
  display: flex;
  align-items: center;
  gap: var(--space-3) var(--space-4);
  flex-wrap: wrap;
}

/* Filter bar now hosts 3 stacked rows (date / dims / platform+store). The
   inner .filter-bar__filters becomes a column so each .bs-hdr__row sits on
   its own line; the Clear-filters link drops to its own flow position below. */
.bs-hdr__stack .filter-bar { justify-content: center; }
.bs-hdr__stack .filter-bar .filter-bar__filters {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-5, 20px);   /* between stacked rows / before Clear = top/bottom padding */
}

/* Shared row primitive — grid; every column equal width. Each
   .filter-item itself is a 2-column subgrid (label LEFT of control,
   inline) so labels of varying length share the same fixed slot and
   every control starts at the same X within its track → all boxes
   end up the same width across the row. User spec 2026-05-29:
   inline label-left, same-width boxes. */
.bs-hdr__row {
  display: grid;
  align-items: center;
  gap: var(--space-4, 16px);   /* uniform 16px vertical wrap-gap + horizontal col-gap */
}
.bs-hdr__row .filter-item {
  display: grid;
  /* Fixed label column wide enough for the longest uppercase label
     (GROUP BRAND) at 11px tracked-out; the box gets the remainder.
     Same fixed width → labels left-align across the row, boxes share
     the same start X within their column → equal-width boxes. */
  grid-template-columns: 104px minmax(0, 1fr);
  align-items: center;
  gap: var(--space-2, 8px);
  width: 100%;
  min-width: 0;
}
.bs-hdr__row .filter-item__label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  white-space: nowrap;
  text-align: left;
}
.bs-hdr__row .searchable-select__wrap { width: 100%; min-width: 0; display: block; }
/* Defensive: searchable-select global rules in styles.css set
   trigger min-width: 180px (or 280px with the --wide modifier) which
   forces boxes wider than their grid track, causing them to overflow
   into adjacent columns. Inside the new 3-row header, columns own
   the widths, so neutralise those min-widths here. */
.bs-hdr__row .searchable-select__trigger { min-width: 0; }
.bs-hdr__row .searchable-select.searchable-select--wide { width: auto; min-width: 0; max-width: none; }
.bs-hdr__row .searchable-select--wide .searchable-select__trigger { min-width: 0; }

/* Popover sizing — global rule pins min-width 320px / max-width 480px
   regardless of trigger. For wide triggers (Platform / Store on the
   2-col row) the popover used to sit under only the left half of the
   trigger. Make it match the trigger width when the trigger is wider
   than 320px; keep the 320 minimum for narrow CD/GBM-style boxes so
   long values stay legible. */
.bs-hdr__row .searchable-select__popover {
  width: 100%;
  min-width: 320px;
  max-width: none;
}

/* Popover anchoring — the global popover rule sets left:0 + min-width 320px,
   which overflows the viewport when the trigger sits in the right-half columns.
   In the combined 4-col --filters grid the right half is columns 3 & 4 of each
   wrapped row → DOM positions 3,4,7,8,11,12… = nth-child(4n+3)/(4n+4). Right-
   anchor those so dropdowns open INTO the page. (--dims/--platstore kept for
   older markup.) */
.bs-hdr__row--filters > .filter-item:nth-child(4n+3) .searchable-select__popover,
.bs-hdr__row--filters > .filter-item:nth-child(4n+4) .searchable-select__popover,
.bs-hdr__row--dims > .filter-item:nth-child(n+3) .searchable-select__popover,
.bs-hdr__row--platstore > .filter-item:nth-child(n+2) .searchable-select__popover {
  left: auto;
  right: 0;
}
.bs-hdr__row .filter-item__select,
.bs-hdr__row .searchable-select__trigger {
  width: 100%;
  height: 36px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
}
/* Active (value-selected) filter — tint background; header-scoped so it wins the
   specificity battle vs the base trigger rule above. */
.bs-hdr__row .searchable-select__trigger--active {
  background: rgba(37, 99, 235, 0.12);
  border-color: var(--color-action);
  color: var(--color-action);
}

/* Row 1 — Period preset toggle. Label LEFT of the pill group same as
   every other filter. The pill cluster sits at its natural width;
   when Custom is active, From/To inputs join the same row. */
.bs-hdr__row--date {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3, 12px);
}
.bs-hdr__row--date .filter-item { width: auto; grid-template-columns: 104px auto; }
.bs-hdr__row--date .bs-hdr__date-range .filter-item__select { width: 180px; }
.bs-hdr__row--date .pnl-compare-toggle { width: auto; }

/* Rows 2-4 — dims (CD/GBM/Group Brand/Brand) · platform+store · page-local
   filters. ALL share one 4-column track so every filter box is the SAME width
   regardless of how many filters a page declares: a row with 3 dims (no GBM),
   or only Platform, or 2 page-local filters, still sizes each box to one 1/4
   track instead of stretching to fill the row. Partial rows leave trailing
   empty columns (intentional) so boxes never grow wider than the canonical
   #overall-performance box. User spec 2026-05-29: "all filter box same width". */
/* ECOM/SOCOM SEPARATION (user 2026-05-29): the filter grid is scoped to the
   Brand & Store portal only (body[data-portal="brand-store"]). SOCOM #pnl borrows
   the header CHROME classes (stack/titleblock/dt/subline/display) but has its OWN
   filter UI and uses NONE of these row classes — defensive scope so ecom filter
   changes can never leak into SOCOM.

   COMBINED FILTER GRID (user 2026-05-29 "combine the filter to save space"):
   ALL dim filters (CD/GBM/Group Brand/Brand/Platform/Store) + the page-local
   #filters slot atoms flow into ONE 4-column grid that wraps densely — so a lone
   Platform or Grain no longer strands on its own row with 3 empty columns. Every
   box is still one 1/4 track = uniform width. The Period preset row stays its own
   flex row above (it's a pill group). `--dims`/`--platstore`/`--page` kept as
   aliases for any older markup. */
body[data-portal="brand-store"] .bs-hdr__row--filters,
body[data-portal="brand-store"] .bs-hdr__row--dims,
body[data-portal="brand-store"] .bs-hdr__row--platstore,
body[data-portal="brand-store"] .bs-hdr__row--page {
  display: grid;
  align-items: center;
  gap: var(--space-3, 12px) var(--space-4, 16px);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Responsive collapse — keep the grid uniform at every breakpoint. */
@media (max-width: 1280px) {
  body[data-portal="brand-store"] .bs-hdr__row .filter-item { grid-template-columns: 100px minmax(0, 1fr); }
}
@media (max-width: 1024px) {
  body[data-portal="brand-store"] .bs-hdr__row--filters,
  body[data-portal="brand-store"] .bs-hdr__row--dims,
  body[data-portal="brand-store"] .bs-hdr__row--platstore,
  body[data-portal="brand-store"] .bs-hdr__row--page { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  body[data-portal="brand-store"] .bs-hdr__row--filters,
  body[data-portal="brand-store"] .bs-hdr__row--dims,
  body[data-portal="brand-store"] .bs-hdr__row--platstore,
  body[data-portal="brand-store"] .bs-hdr__row--page { grid-template-columns: minmax(0, 1fr); }
  body[data-portal="brand-store"] .bs-hdr__row .filter-item { grid-template-columns: minmax(0, 1fr); }
  body[data-portal="brand-store"] .bs-hdr__row .filter-item__label { margin-bottom: 4px; }
}

.bs-hdr__clear {
  font-size: var(--font-small, 0.75rem);
  color: var(--color-action);
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 8px;
  align-self: center;
  text-decoration: underline;
}
.bs-hdr__clear:hover { opacity: 0.8; }

/* Brand select is disabled until a Group Brand is chosen — SOCOM's
   .filter-item__select has no disabled state, so add one here. */
.bs-hdr__stack .filter-item__select:disabled { opacity: 0.5; cursor: default; }

/* Phase 1 (filter consolidation): Date Range — a paired native date input
   that lives inline with the other filter-items. Inputs render as a
   .filter-item__select-style pill so they match the rest of the row. */
.bs-hdr__date-range {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: nowrap;
}
.bs-hdr__date-range .filter-item__label {
  margin: 0;
  white-space: nowrap;
  font-size: var(--font-small, 0.75rem);
  color: var(--text-secondary);
}
.bs-hdr__date-input {
  appearance: none;
  padding: 4px 8px;
  height: 28px;
  font-family: inherit;
  font-size: var(--font-small, 0.75rem);
  color: var(--text-primary);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  cursor: pointer;
  min-width: 130px;
}
.bs-hdr__date-input:hover { border-color: var(--border-strong); }
.bs-hdr__date-input:focus { outline: 2px solid var(--color-action-muted); outline-offset: 0; border-color: var(--color-action); }
[data-theme="dark"] .bs-hdr__date-input::-webkit-calendar-picker-indicator {
  filter: invert(1);
  opacity: 0.7;
}

/* ====================================================================
   BsDateField — themed calendar popover (feedback 2026-06-08 #6)
   Replaces the native <input type="date"> (OS calendar rendered in the
   browser locale — French jj/mm/aaaa). Tokens only → correct in both
   themes. Used by the shared-header Custom From/To + page custom pickers.
   ==================================================================== */
.bs-datefield { position: relative; display: inline-block; }
.bs-datefield__trigger {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 10px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--font-small, 0.75rem); font-variant-numeric: tabular-nums;
  color: var(--text-primary); background: var(--bg-surface);
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  cursor: pointer; min-width: 134px; white-space: nowrap;
  transition: border-color var(--transition-fast, 0.15s), box-shadow var(--transition-fast, 0.15s);
}
.bs-datefield__trigger:hover { border-color: var(--border-strong); }
.bs-datefield--open .bs-datefield__trigger { border-color: var(--color-action); box-shadow: 0 0 0 3px var(--color-action-muted); }
.bs-datefield__ico { color: var(--text-tertiary); flex-shrink: 0; }
.bs-datefield__val { overflow: hidden; text-overflow: ellipsis; }
.bs-datefield__trigger--empty .bs-datefield__val { color: var(--text-tertiary); }

.bs-datefield__popover {
  position: absolute; top: calc(100% + 6px); z-index: 1200;
  width: 256px; padding: 10px;
  background: var(--bg-elevated, var(--bg-surface)); color: var(--text-primary);
  border: 1px solid var(--border-default); border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow-lg);
}
.bs-datefield__popover--left { left: 0; }
.bs-datefield__popover--right { right: 0; }
.bs-datefield__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.bs-datefield__title { font-size: var(--font-small, 12px); font-weight: 700; color: var(--text-primary); letter-spacing: 0.01em; }
.bs-datefield__nav {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: none; color: var(--text-secondary); cursor: pointer;
  transition: background var(--transition-fast, 0.12s), color var(--transition-fast, 0.12s);
}
.bs-datefield__nav:hover { background: var(--bg-hover); color: var(--text-primary); }
.bs-datefield__wd { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 4px; }
.bs-datefield__wd span { text-align: center; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-tertiary); }
.bs-datefield__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.bs-datefield__day {
  height: 30px; border: none; border-radius: var(--radius-sm, 6px); cursor: pointer;
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; font-variant-numeric: tabular-nums;
  color: var(--text-primary); background: none;
  transition: background var(--transition-fast, 0.12s), color var(--transition-fast, 0.12s);
}
.bs-datefield__day:hover:not(.is-disabled):not(.is-sel) { background: var(--bg-hover); }
.bs-datefield__day.is-out { color: var(--text-tertiary); opacity: 0.55; }
.bs-datefield__day.is-today:not(.is-sel) { box-shadow: inset 0 0 0 1px var(--color-action); color: var(--color-action); font-weight: 700; }
.bs-datefield__day.is-sel { background: var(--color-action); color: #fff; font-weight: 700; }
.bs-datefield__day.is-disabled { color: var(--text-tertiary); opacity: 0.3; cursor: default; }
.bs-datefield__foot { display: flex; align-items: center; justify-content: space-between; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border-subtle); }
.bs-datefield__act { background: none; border: none; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--color-action); padding: 2px 8px; border-radius: var(--radius-sm); }
.bs-datefield__act:hover { background: var(--color-action-muted); }

/* ====================================================================
   Sticky-header enabler — HOISTED PORTAL-WIDE (2026-05-31)
   The router outlet .page-content is overflow-y:auto, which scopes the
   sticky filter header to a container that never scrolls internally →
   it won't pin. Drop to visible for ALL brand-store routes in one rule
   (SOCOM is data-portal="socom" → unaffected). This supersedes the
   per-route overrides in aging.css/bs-atp.css (harmless duplicates) and
   fixes the filter-sticky on the 8 ecom pages that lacked it (doi, cs,
   fulfillment, media, sku, shopper, store-traffic, affiliate).
   content-area min-width:0 lets wide tables scroll in their own wrap
   instead of widening the page. See design-guideline "Wide detail tables"
   + memory project_ecom_sticky_page_content. ==================== */
body[data-portal="brand-store"] .page-content { overflow: visible; }
body[data-portal="brand-store"] .content-area { min-width: 0; }

/* Wide-table self-contained scroll, hoisted portal-wide (2026-05-31): every ecom
   page using the shared .data-table-wrap (DataTable) needs a height cap so the
   wrap owns vertical scroll and the sticky <thead> pins (the ATP recipe). Short
   tables are unaffected (overflow:auto shows no scrollbar when content fits).
   Bespoke frozen-column tables use their OWN wrap classes (.bs-*-scroll/-wrap),
   so they're untouched here and fixed in their page CSS. */
body[data-portal="brand-store"] .data-table-wrap { max-height: calc(100vh - 240px); overflow: auto; }
