/* CWG HR dense-foundation module sheet (UX-L1, 2026-09-26).
 *
 * Everything in this file is ADDITIVE: new modifier classes and new
 * primitives only. Nothing here redeclares an existing bare selector
 * (`.property-editor-fields`, `.property-register-table`, the global
 * `[data-w="narrow"|"wide"|"num"|"fill"]` rules in gsp-structural.css), so
 * every non-HR surface that already uses those classes is byte-for-byte
 * unaffected by this file. See HR-UX-SPEC.md section 6 for the design
 * rationale and section 3.3 for the field-width mapping this feeds.
 *
 * Loaded after components.css/gsp-structural.css and before red-plate.css
 * (src/lib/designSystems.ts SKIN_AND_MODULE_CSS_FILES) so its modifier
 * rules win the cascade over the base rules they extend, without needing
 * extra selector specificity or !important anywhere in this file.
 */

/* ----------------------------------------------------------------------
 * 1. Dense form grid (spec 3.3 / 6.1)
 * `.property-editor-fields--dense` is an opt-in modifier applied ALONGSIDE
 * the existing `.property-editor-fields` class, never instead of it. Below
 * 641px it inherits the base class's own single-column mobile rule
 * untouched (components.css `@media (max-width:640px)`).
 *
 * UX-FIXFOUND (2026-09-26): the previous version of this rule picked a
 * FIXED column count (4 at >=960px viewport width, 6 at >=1280px) keyed to
 * the *browser viewport*. `.property-editor-fields--dense` is used inside
 * RowPopup modals (CompensationTab, DocumentsTab, PerformanceTab) whose own
 * rendered width is far narrower than the viewport -- e.g. the default
 * `.ds-modal--dialog` is `min(880px, 100vw-24)`, so at a 1440px-wide
 * viewport the grid still got 6 viewport-keyed columns squeezed into an
 * ~830px dialog body, giving ~128px tracks. A "wide" control sized to fill
 * one full track (360px, see below) then rendered 232px past its own
 * track's right edge with nothing clipping it -- the literal cause of the
 * "Personal email box runs over Work phone" / "Address line 1 overlaps
 * line 2" overlap Ben saw on preview.
 *
 * Fixed with `repeat(auto-fill, minmax(180px, 1fr))`: the browser sizes
 * columns from the GRID'S OWN rendered width (not the viewport), so a
 * narrow modal body correctly gets fewer, still-non-overlapping columns and
 * a full-width page tab gets more -- one column unit (180px) used
 * everywhere, no viewport breakpoint math to keep in sync with modal
 * widths. 180px is sized to the "medium" tier below (160/150px input/
 * select) plus a few px of headroom; "wide" fields explicitly span 2 of
 * these tracks (section 2 below) instead of assuming a fixed track count.
 * ------------------------------------------------------------------- */
@media (min-width: 641px) {
  .property-editor-fields--dense {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  }
}

/* New data-w tiers, mirroring the exact element-scoped shape of the
 * existing global rules in gsp-structural.css (separate .gsp-input/
 * .gsp-select rules, not a bare [data-w] selector). Scoped to the dense
 * container so the existing global `[data-w="wide"]` (200px input / 168px
 * select, used by non-HR modules) keeps its current meaning everywhere
 * outside a dense HR form. */
.property-editor-fields--dense .gsp-input[data-w="medium"] {
  flex: none;
  width: 160px;
}
.property-editor-fields--dense .gsp-select[data-w="medium"] {
  flex: none;
  width: 150px;
}
.property-editor-fields--dense .gsp-input[data-w="wide"] {
  flex: none;
  width: 360px;
}
.property-editor-fields--dense .gsp-select[data-w="wide"] {
  flex: none;
  width: 320px;
}

/* UX-FIXFOUND: a "wide" control (360/320px) is wider than a single 180px
 * track -- span 2 tracks explicitly instead of letting the fixed-width
 * control overflow its cell. `:has()` keys off the control's own data-w so
 * every existing consumer of the dense grid (CompensationTab, DocumentsTab,
 * PerformanceTab, CwgHrDocumentsWorkspace, CwgPerformanceListWorkspace,
 * CwgPayrollWorkspace, DenseFields) gets this for free -- no markup change
 * needed in any of those files. Unconditional: in the base 1-column mobile
 * grid a span of 2 simply clamps to the single existing track (harmless);
 * everywhere else it is exactly the extra room a wide field needs. The
 * country typeahead (CountrySelect, section 10) is included here too so it
 * gets the same two-track width instead of the country-only override
 * competing with the grid for space. */
.property-editor-fields--dense > .property-editor-field:has(> .gsp-input[data-w="wide"]),
.property-editor-fields--dense > .property-editor-field:has(> .gsp-select[data-w="wide"]),
.property-editor-fields--dense > .property-editor-field:has(> .gsp-country-select) {
  grid-column: span 2;
}

/* UX-FIXFOUND: the "narrow" tier (76px input / 96px select, gsp-structural.
 * css) was designed for short VALUES (dates, numbers, codes). A <select>'s
 * collapsed state always shows "Select <Label>" regardless of how short its
 * OPTION values are, so Title/Gender/Marital-status selects (short option
 * SETS, correctly mapped to "narrow" by DenseFields' fieldWidthFor) rendered
 * "Select Gen", "Select Mari" -- truncated with no visual cue. Widen the
 * SELECT half of the narrow tier only; narrow date/number/code *inputs* are
 * untouched (76px is correct for those). 172px comfortably fits every
 * current label's "Select <Label>" placeholder (longest: "Select Marital
 * status") and stays within one 180px track. */
.property-editor-fields--dense .gsp-select[data-w="narrow"] {
  flex: none;
  width: 172px;
}

/* Checkboxes render inline with their own label, left-aligned, never a
 * wide label row with the box floated underneath (spec 3.3, acceptance
 * check 11). A dedicated modifier on the existing `.property-editor-field`
 * block -- not scoped to the dense grid, since it only ever applies where a
 * caller adds it explicitly and changes nothing for any current markup. */
.property-editor-field--check {
  flex-direction: row-reverse;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}

/* ----------------------------------------------------------------------
 * 2. Dense register table (spec 3.2 / 6.1)
 * ------------------------------------------------------------------- */
.property-register-table--dense {
  font-size: 12px;
  line-height: 1.3;
  /* UX-FIXFOUND round 2: `table-layout: auto` (the base `.property-
   * register-table` rule, components.css) sizes a column to its content's
   * min-content width -- with `white-space:nowrap` below, that IS the
   * cell's full unbroken text width, so a table with a couple of long
   * nowrap cells (a legal-entity name, a job title) simply renders WIDER
   * than its own `width:100%` and overflows its container instead of
   * shrinking (Ben's preview look, round 1: "Status column clipped at the
   * right edge" on the Employees list at 1280px). `table-layout: fixed`
   * makes the table strictly respect its own width; ellipsis (still set
   * below) then engages for whichever cells don't fit their column's
   * share instead of pushing the table wider. */
  table-layout: fixed;
}
.property-register-table--dense th,
.property-register-table--dense td {
  padding: 4px 6px;
  /* Rows were also measuring taller than the ~28-32px this modifier
   * declares below, because a long cell wrapped onto a 2nd/3rd line before
   * table-layout:fixed above gave it anywhere to shrink to. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Fixed layout takes each column's width from the THEAD row's cells (CSS
 * table sizing algorithm) -- a page's `<th data-w="narrow">`/`<th
 * data-align="right">` marks the columns (a status/action chip, a numeric
 * amount) that should stay narrow while the rest of the row's `1fr`-like
 * remaining columns share whatever's left and ellipsis under it, per
 * "let Job title/Legal entity shrink with ellipsis; status column fixed
 * narrow". Reuses the SAME `data-w` vocabulary already governing every
 * other dense-grid control (section 1) rather than a new one-off
 * attribute; `data-align="right"` was already an existing convention
 * (CwgPerformanceListWorkspace.tsx's "Overall", CwgPayrollWorkspace.tsx's
 * money columns) that just had no width behind it yet. */
.property-register-table--dense th[data-w="narrow"],
.property-register-table--dense td[data-w="narrow"] {
  width: 90px;
}
.property-register-table--dense tbody tr {
  height: 28px;
}
/* UX-FIXFOUND: a cell whose value is genuinely absent renders as literally
 * empty (React drops a "" child, leaving no text node at all), which read
 * as a rendering glitch rather than "no data on file" -- inconsistent with
 * RecordBar's own facts strip, where callers already pass an explicit "—".
 * `:empty` needs no per-cell markup change in any page file: it matches
 * whenever a table cell (or a status chip that itself renders null for an
 * unset value) produces zero child nodes. */
.property-register-table--dense td:empty::after {
  content: "\2014";
  color: var(--ink-mute);
}
.property-register-table--dense thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--paper);
}
.property-register-table--dense td[data-align="right"],
.property-register-table--dense th[data-align="right"] {
  width: 100px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.property-register-table--dense .gsp-rowbtn {
  padding: 0 5px;
  font-size: 9px;
}

/* UX-FIXFOUND round 2: portal-core.css's bare `h1` rule is sized for a
 * marketing/landing headline (`clamp(26px, 2.6vw, 34px)`) -- CwgEmployees-
 * Workspace.tsx / CwgHrDocumentsWorkspace.tsx / CwgPerformanceListWorkspace.
 * tsx all deliberately render a bare `<h1>` for their list-page title (FE-
 * FIX F1, 2026-09-26 -- "same bare serif h1, no eyebrow"), which reads
 * oversized for a dense ERP working screen. `h1.gsp-list-title` -- element +
 * class beats the bare `h1` rule on specificity alone, no cascade-order
 * dependency -- restrains it to the same register as RecordBar's own title
 * (section 3 below) so a detail page and a list page read as one system. */
.gsp-list-title {
  font-size: 20px;
  line-height: 1.2;
  font-weight: 600;
  margin: 0 0 2px;
}

/* ----------------------------------------------------------------------
 * 3. Record header / action bar (spec 3.1)
 * ------------------------------------------------------------------- */
.gsp-record-bar {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 0 10px;
}
.gsp-record-bar__row1 {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: space-between;
  flex-wrap: wrap;
}
.gsp-record-bar__title {
  font-size: 20px;
  font-weight: 600;
  color: var(--ink);
  min-width: 0;
}
.gsp-record-bar__actions {
  display: flex;
  gap: 8px;
  flex: none;
  align-items: center;
}
.gsp-record-bar__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  align-items: baseline;
}
.gsp-record-bar__fact {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.gsp-record-bar__fact-l {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-mute);
  white-space: nowrap;
}
.gsp-record-bar__fact-v {
  font-size: 14px;
  color: var(--ink);
}
/* UX-FIXFOUND: same "—" placeholder as the dense table (section 2) for a
 * fact value the caller left empty rather than passing "—" itself. */
.gsp-record-bar__fact-v:empty::after {
  content: "\2014";
  color: var(--ink-mute);
}

/* ----------------------------------------------------------------------
 * 4. Dropzone (spec 4 / 6.2) -- light theme, warm/sand tones already in the
 * gsp-* palette (no new colour tokens introduced).
 * ------------------------------------------------------------------- */
.gsp-dropzone {
  border: 1px dashed var(--hairline-dark);
  background: var(--ds-c-yellow-06);
  border-radius: var(--ds-radius-sm);
  padding: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
}
.gsp-dropzone[data-active="true"] {
  border-color: var(--baobab);
  background: var(--ds-c-yellow-13);
}
.gsp-dropzone[data-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}
/* UX-FIXFOUND: the tall drag-and-drop box above is now opt-in only (New
 * employee step 1, the one place HR-UX-SPEC.md's ingestion-first flow pairs
 * it with IngestPicker's own 3-card chooser, which carries its own "From
 * email" slot). Every in-page ingestion point (Personal tab "fill from
 * document", Documents tab, Employment tab, each array tab's "add from
 * document") rendered as a ~150px dashed box for a single Browse button --
 * this is Dropzone's new DEFAULT (`compact` prop defaults to true in
 * Dropzone.tsx): a one-line strip with the label, an Upload button and a
 * disabled "From email" affordance, requiring no change to any of those
 * pages' own markup. Drag-and-drop still targets this whole strip (the
 * same onDragOver/onDrop handlers, just on a row instead of a column). */
.gsp-dropzone--compact {
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  padding: 6px 10px;
  gap: 10px;
  text-align: left;
  /* UX-FIXFOUND round 2: the dashed border is drag-target chrome that reads
   * right on the tall box (a big empty area inviting a drop) but wrong on a
   * one-line strip, where it looked like a second, competing "form field"
   * next to the real ones (Ben's preview look, round 1). A plain hairline
   * -- same weight every other dense control uses -- still frames the row
   * without implying it is a drop target only, and still turns baobab/
   * solid on an active drag via the data-active rule below (inherited from
   * the base .gsp-dropzone rule, just switched from dashed to solid here). */
  border-style: solid;
}
.gsp-dropzone--compact .gsp-dropzone__icon {
  display: none;
}
.gsp-dropzone--compact .gsp-dropzone__label {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gsp-dropzone--compact .gsp-dropzone__actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: 6px;
}
.gsp-dropzone--compact .gsp-dropzone__hint {
  flex-basis: 100%;
}
.gsp-dropzone--compact .gsp-dropzone__files {
  flex-basis: 100%;
  margin-top: 0;
}
.gsp-dropzone__icon {
  font-size: 20px;
  color: var(--ink-mute);
}
.gsp-dropzone__label {
  font-size: 12px;
  color: var(--ink);
  font-weight: 600;
}
.gsp-dropzone__hint {
  font-size: 10px;
  color: var(--ink-mute);
}
.gsp-dropzone__files {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  margin-top: 6px;
  text-align: left;
}
.gsp-dropzone__file {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  border: 1px solid var(--ds-c-neutral-06);
  background: var(--paper);
  padding: 3px 8px;
  border-radius: var(--ds-radius-sm);
}
.gsp-dropzone__file-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gsp-dropzone__file-progress {
  flex: none;
  font-size: 10px;
  color: var(--ink-mute);
}
.gsp-dropzone__file-remove {
  flex: none;
}

/* ----------------------------------------------------------------------
 * 5. Suggestion card (spec 4 / 6.2) -- formalizes the extraction-suggestion
 * markup so the confidence badge is a real, testable part.
 * ------------------------------------------------------------------- */
.gsp-suggestion-card {
  border: 1px solid var(--ds-c-neutral-06);
  background: var(--ds-c-white-01);
  border-radius: var(--ds-radius-sm);
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.gsp-suggestion-card__title {
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.gsp-suggestion-card__confidence {
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--ds-radius-sm);
}
.gsp-suggestion-card__confidence[data-tier="high"] {
  background: var(--ds-c-green-04);
  color: var(--ds-c-green-12);
  border: 1px solid var(--ds-c-green-09);
}
.gsp-suggestion-card__confidence[data-tier="medium"] {
  background: var(--ds-c-yellow-19);
  color: var(--ds-c-yellow-26);
  border: 1px solid var(--ds-c-amber-23);
}
.gsp-suggestion-card__confidence[data-tier="low"] {
  background: var(--ds-c-red-08);
  color: var(--ds-c-red-26);
  border: 1px solid var(--ds-c-red-17);
}
.gsp-suggestion-card__confidence[data-tier="manual"] {
  background: var(--ds-c-yellow-15);
  color: var(--ds-c-neutral-13);
  border: 1px solid var(--ds-c-neutral-06);
}
.gsp-suggestion-card__evidence {
  font-size: 10px;
  color: var(--ink-mute);
}
.gsp-suggestion-card__actions {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
}

/* ----------------------------------------------------------------------
 * 6. Ingest picker (spec 4.1-4.3 / 6.2) -- the "Upload documents / Enter
 * manually" two-choice landing.
 * ------------------------------------------------------------------- */
.gsp-ingest-picker {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.gsp-ingest-picker__options {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.gsp-ingest-picker__option {
  flex: 1 1 220px;
  border: 1px solid var(--hairline-dark);
  border-radius: var(--ds-radius-sm);
  background: var(--paper);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
}
.gsp-ingest-picker__option[aria-pressed="true"] {
  border-color: var(--baobab);
  background: var(--baobab-bg);
}
.gsp-ingest-picker__option:disabled,
.gsp-ingest-picker__option[data-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}
.gsp-ingest-picker__option-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
}
.gsp-ingest-picker__option-desc {
  font-size: 10px;
  color: var(--ink-mute);
}
.gsp-ingest-picker__option-reason {
  font-size: 10px;
  color: var(--ds-c-red-26);
}
.gsp-ingest-picker__fallback {
  font-size: 11px;
}

/* ----------------------------------------------------------------------
 * 7. Employee-file tab row overflow grouping (spec 3.4 / 6.2). The
 * outer flex row only -- the "Records" dropdown group inside it composes
 * the EXISTING .gsp-menu-drop / .gsp-menu-panel / .gsp-menu-item primitives
 * (gsp-structural.css) rather than duplicating their disclosure chrome.
 * ------------------------------------------------------------------- */
.gsp-tabgroup-overflow {
  /* flex: none keeps the tab row from collapsing to 0px height inside the
     shell's fixed-height iframe (overflow-x:auto forces overflow-y non-visible,
     which lets flexbox auto-min-size shrink it). Same guard as .property-register. */
  flex: none;
  display: flex;
  align-items: center;
  gap: 2px;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: visible;
  min-width: 0;
}

/* ----------------------------------------------------------------------
 * 8. View toggle (spec 2 / 5.1 / 6.2) -- "Full record | Contact lookup"
 * segmented control.
 * ------------------------------------------------------------------- */
.gsp-view-toggle {
  display: inline-flex;
  border: 1px solid var(--hairline-dark);
  border-radius: var(--ds-radius-sm);
  overflow: hidden;
  flex: none;
}
.gsp-view-toggle__option {
  border: 0;
  background: var(--paper);
  color: var(--ink-mute);
  font: inherit;
  font-size: 11px;
  padding: 5px 12px;
  cursor: pointer;
}
.gsp-view-toggle__option + .gsp-view-toggle__option {
  border-left: 1px solid var(--hairline-dark);
}
.gsp-view-toggle__option[aria-pressed="true"] {
  background: var(--baobab);
  color: var(--baobab-on);
  font-weight: 600;
}

/* ----------------------------------------------------------------------
 * 9. Error banner (spec 3.6 / 6.2) -- red variant of the existing neutral
 * `.notice`. Reuses `.notice`'s own child classes (`.l` / `.v` / `.btn`,
 * already allowlisted) rather than inventing parallel ones.
 * ------------------------------------------------------------------- */
.ds-banner-error {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  background: var(--ds-c-red-08);
  border-left: 3px solid var(--ds-c-red-17);
  margin-bottom: 20px;
  font-size: calc(13px * var(--fs-scale, 1));
  color: var(--ds-c-red-26);
}
.ds-banner-error .l {
  font-weight: 700;
}
.ds-banner-error .v {
  flex: 1;
}
.ds-banner-error .btn {
  flex: none;
}

/* ----------------------------------------------------------------------
 * 10. Country select (spec 4.2 / 6.2) -- searchable ISO2 typeahead.
 * The wrapper only; the dropdown list reuses .gsp-menu-panel/.gsp-menu-item
 * and the text field reuses .gsp-input with a data-w attribute, same as
 * every other text control in the DS.
 * ------------------------------------------------------------------- */
.gsp-country-select {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  min-width: 0;
}
/* UX-FIXFOUND: CountrySelect always renders its typeahead as a plain
 * `.gsp-input` with `data-w="narrow"` (fieldWidthFor("country") is always
 * "narrow" -- see DenseFields.tsx), which is the 76px tier meant for a date/
 * number/code value, not "Search country…" or a selected name like "United
 * Arab Emirates" -- hence "Search c" truncating with no ellipsis at all.
 * Section 1's `:has(> .gsp-country-select)` rule already gives the field's
 * grid cell a full 2-track span; size the input itself to use that room,
 * with graceful ellipsis (not a hard cut) for the handful of country names
 * still longer than this. */
.gsp-country-select .gsp-input {
  width: 100%;
  min-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gsp-country-select__empty {
  padding: 6px 8px;
  font-size: 11px;
  color: var(--ink-mute);
}
