/* ==========================================================================
   GoldenBearing — Product UX patterns
   ==========================================================================
   Composition patterns for the UX Product Redesign pass. These are NOT new
   primitives: every rule below consumes tokens.css's --gb-* variables and
   sits on top of components.css's existing .gb-card / .gb-btn / .gb-badge.
   Nothing here replaces or overrides a design-system component.

   Why a separate file: the redesign needed a small set of *layout*
   idioms — a work queue, an operational list row, a process trail, a
   summary strip — that recur across Home, Recruitment, HR and Workflow.
   Expressing them once here is what stops each module inventing its own
   one-off markup, which is exactly how the ERP came to feel like a pile of
   separate CRUD screens.

   Loaded directly by the layouts, after components.css, with
   asp-append-version="true" — see index.css's caching note for why the
   layouts link each file rather than relying on @import.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Section rhythm
   --------------------------------------------------------------------------
   A page is a short stack of labelled sections, not a wall of cards. The
   heading carries an optional trailing link ("مشاهده همه") so a section can
   summarise without becoming a dead end.
   -------------------------------------------------------------------------- */

.gb-section {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-3);
}

.gb-section + .gb-section {
    margin-top: var(--gb-space-6);
}

.gb-section__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--gb-space-3);
    flex-wrap: wrap;
}

/* One step ABOVE a card title (13.5px), because a section heading groups
   cards. It declared `md` (12.5px) — smaller than the cards underneath it —
   and got away with it only because the `.gb-app h2` ramp was silently
   overriding every component title; on the 22 headings that carry this class
   it rendered at 15px all along. Now that components win as the design system
   always intended, the value it was really using is stated here. */
.gb-section__title {
    margin: 0;
    font-size: var(--gb-font-size-xl);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
}

.gb-section__hint {
    margin: 0;
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-section__link {
    font-size: var(--gb-font-size-sm);
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   2. Work queue — "نیازمند اقدام شما"
   --------------------------------------------------------------------------
   The single most important pattern of this pass. One row = one thing the
   user can act on: what it is, why it is here, and the button that resolves
   it. Deliberately not a table — these are tasks, not records, and the row
   must read as a sentence on any width.
   -------------------------------------------------------------------------- */

.gb-worklist {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
    overflow: hidden;
}

.gb-worklist__item {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: var(--gb-space-4);
    padding: var(--gb-space-4);
}

.gb-worklist__item + .gb-worklist__item {
    border-top: 1px solid var(--gb-border-subtle);
}

.gb-worklist__item:hover {
    background: var(--gb-surface-alt);
}

/* A calm, meaningful accent — the only colour in the row, carrying urgency. */
.gb-worklist__marker {
    width: 0.25rem;
    align-self: stretch;
    min-height: 2.5rem;
    border-radius: 999px;
    background: var(--gb-border-strong);
}

.gb-worklist__item--action .gb-worklist__marker { background: var(--gb-primary); }
.gb-worklist__item--wait .gb-worklist__marker { background: var(--gb-info); }
.gb-worklist__item--overdue .gb-worklist__marker { background: var(--gb-danger); }

.gb-worklist__body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.gb-worklist__title {
    margin: 0;
    font-size: var(--gb-font-size-md);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
}

.gb-worklist__title a { color: inherit; }

/* The "why is this in front of me" line. This is the part that turns a
   record into a task. */
.gb-worklist__reason {
    margin: 0;
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-worklist__meta {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gb-space-2);
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
}

.gb-worklist__meta > * + *::before {
    content: "·";
    margin-inline-end: var(--gb-space-2);
    color: var(--gb-border-strong);
}

.gb-worklist__action {
    display: flex;
    align-items: center;
    gap: var(--gb-space-2);
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   3. Operational list row
   --------------------------------------------------------------------------
   For desktop tables that must communicate more than columns: a primary
   name with its reference underneath, a context line, and the row's own next
   action. Applied INSIDE an existing <table> so sorting/pagination and the
   established table semantics are untouched.
   -------------------------------------------------------------------------- */

.gb-oplist__primary {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

.gb-oplist__name {
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
    line-height: 1.4;
}

.gb-oplist__ref {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
    font-variant-numeric: tabular-nums;
}

.gb-oplist__context {
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

/* Status cell: badge on top, operational meaning underneath. */
.gb-oplist__status {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
}

.gb-oplist__status-note {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
    max-width: 22ch;
    line-height: 1.5;
}

/* --------------------------------------------------------------------------
   4. Process trail — "الان کجای فرایند هستیم؟"
   --------------------------------------------------------------------------
   Horizontal on desktop, vertical on narrow screens. Only ever rendered with
   stages the implementation actually supports.
   -------------------------------------------------------------------------- */

.gb-trail {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gb-space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.gb-trail__step {
    flex: 1 1 9rem;
    min-width: 8rem;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: var(--gb-space-3);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface-alt);
    border: 1px solid transparent;
}

.gb-trail__marker {
    display: inline-flex;
    align-items: center;
    gap: var(--gb-space-2);
    font-size: var(--gb-font-size-xs);
    /* --gb-text-tertiary is tuned for text on --gb-surface; the trail step sits
       on --gb-surface-alt, where it fell to 3.39:1 in light mode. */
    color: var(--gb-text-secondary);
}

.gb-trail__label {
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-medium);
    color: var(--gb-text-secondary);
}

.gb-trail__note {
    font-size: var(--gb-font-size-xs);
    /* Same reason as .gb-trail__marker — this text sits on --gb-surface-alt. */
    color: var(--gb-text-secondary);
    line-height: 1.5;
}

.gb-trail__step--done .gb-trail__label { color: var(--gb-text-primary); }
.gb-trail__step--done .gb-trail__marker { color: var(--gb-success); }

.gb-trail__step--current {
    background: var(--gb-primary-subtle);
    border-color: var(--gb-primary);
}

.gb-trail__step--current .gb-trail__label {
    color: var(--gb-text-primary);
    font-weight: var(--gb-font-weight-semibold);
}

/* The current step is the only one with a tinted background
   (--gb-primary-subtle). The secondary/link colours that clear AA on
   --gb-surface-alt do not clear it there, so this step states its own text
   colours rather than inheriting the trail defaults. */
.gb-trail__step--current .gb-trail__marker,
.gb-trail__step--current .gb-trail__note,
.gb-trail__step--current .gb-trail__label a {
    color: var(--gb-text-primary);
}

.gb-trail__step--todo { opacity: 0.72; }

/* --------------------------------------------------------------------------
   5. Summary strip
   --------------------------------------------------------------------------
   Counts that are entry points, never vanity metrics: every figure links to
   the filtered list it describes. Compact by design so it never becomes the
   focus of the page.
   -------------------------------------------------------------------------- */

.gb-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--gb-space-3);
}

.gb-summary__item {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: var(--gb-space-3) var(--gb-space-4);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    text-decoration: none;
    transition: border-color 120ms ease, background 120ms ease;
}

a.gb-summary__item:hover {
    border-color: var(--gb-primary);
    background: var(--gb-surface-alt);
}

.gb-summary__value {
    font-size: var(--gb-font-size-2xl);
    font-weight: var(--gb-font-weight-bold);
    line-height: 1.1;
    color: var(--gb-text-primary);
    font-variant-numeric: tabular-nums;
}

.gb-summary__label {
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-summary__item--attention .gb-summary__value { color: var(--gb-primary-active); }

/* --------------------------------------------------------------------------
   6. Entity header
   --------------------------------------------------------------------------
   The top of a detail page: name, status, and the two or three facts that
   identify the record — so the user never has to read the body to know what
   they are looking at.
   -------------------------------------------------------------------------- */

.gb-entity {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gb-space-4);
    padding: var(--gb-space-5);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
}

.gb-entity__main {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-2);
    min-width: 0;
}

.gb-entity__identity {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--gb-space-3);
}

.gb-entity__name {
    margin: 0;
    font-size: var(--gb-font-size-xl);
    font-weight: var(--gb-font-weight-bold);
    color: var(--gb-text-primary);
    line-height: 1.3;
}

.gb-entity__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gb-space-2) var(--gb-space-4);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-entity__fact strong {
    color: var(--gb-text-primary);
    font-weight: var(--gb-font-weight-medium);
}

.gb-entity__actions {
    display: flex;
    align-items: center;
    gap: var(--gb-space-2);
    flex-wrap: wrap;
}

/* --------------------------------------------------------------------------
   7. Field groups
   --------------------------------------------------------------------------
   Reduces cognitive load on detail pages: labelled groups of related facts
   rather than one long definition list of equal-weight rows.
   -------------------------------------------------------------------------- */

.gb-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: var(--gb-space-4);
}

.gb-fact {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.gb-fact__label {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
}

.gb-fact__value {
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-primary);
    overflow-wrap: anywhere;
}

.gb-fact__value--muted { color: var(--gb-text-tertiary); }

/* --------------------------------------------------------------------------
   8. Guided form sections
   --------------------------------------------------------------------------
   A long form reads as a sequence of questions, each with its own short
   heading, instead of one undifferentiated field wall.
   -------------------------------------------------------------------------- */

.gb-formstep {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-4);
    padding: var(--gb-space-5);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
}

.gb-formstep + .gb-formstep { margin-top: var(--gb-space-4); }

.gb-formstep__head {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.gb-formstep__title {
    margin: 0;
    font-size: var(--gb-font-size-md);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
}

.gb-formstep__hint {
    margin: 0;
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

/* Inherited context on a Create page: values carried from the parent record,
   visually distinct from the fields the user is being asked to fill in. */
.gb-inherited {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gb-space-2) var(--gb-space-5);
    padding: var(--gb-space-3) var(--gb-space-4);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface-alt);
    border: 1px dashed var(--gb-border-strong);
    font-size: var(--gb-font-size-sm);
}

/* --------------------------------------------------------------------------
   9. Desktop density
   --------------------------------------------------------------------------
   This is an office/factory desktop ERP: use the width. Content stays
   readable via a generous max, but forms and detail pages are no longer
   pinned to a narrow column inside a wide display.
   -------------------------------------------------------------------------- */

.gb-workspace {
    display: grid;
    gap: var(--gb-space-5);
}

@media (min-width: 62rem) {
    /* Main column + a context rail that carries status, process and history. */
    .gb-workspace--rail {
        grid-template-columns: minmax(0, 1fr) 20rem;
        align-items: start;
    }

    .gb-workspace--rail > .gb-workspace__rail {
        position: sticky;
        top: var(--gb-space-4);
    }
}

.gb-workspace__rail {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-4);
    min-width: 0;
}

.gb-workspace__main {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-4);
    min-width: 0;
}

/* --------------------------------------------------------------------------
   10. Narrow screens
   --------------------------------------------------------------------------
   Mobile stays fully usable without dictating the desktop composition.
   -------------------------------------------------------------------------- */

@media (max-width: 48rem) {
    .gb-worklist__item {
        grid-template-columns: auto 1fr;
        row-gap: var(--gb-space-3);
    }

    .gb-worklist__action {
        grid-column: 2;
        justify-content: flex-start;
    }

    .gb-entity {
        padding: var(--gb-space-4);
    }

    .gb-entity__actions {
        width: 100%;
    }

    .gb-trail__step {
        flex-basis: 100%;
    }
}

/* --------------------------------------------------------------------------
   11. Jalali date field
   --------------------------------------------------------------------------
   The Persian replacement for <input type="date">. See
   _GBJalaliDateField.cshtml for why the visible input is unnamed and the
   hidden one carries the contract.
   -------------------------------------------------------------------------- */

.gb-jalali-date {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--gb-space-2);
}

.gb-jalali-date__input {
    flex: 1 1 auto;
    min-width: 0;
    font-variant-numeric: tabular-nums;
}

.gb-jalali-date__trigger {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    color: var(--gb-text-secondary);
    cursor: pointer;
}

.gb-jalali-date__trigger:hover {
    border-color: var(--gb-primary);
    color: var(--gb-text-primary);
}

.gb-jalali-date__panel {
    position: absolute;
    top: calc(100% + var(--gb-space-2));
    inset-inline-end: 0;
    z-index: 40;
    width: 17.5rem;
    padding: var(--gb-space-3);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
    box-shadow: var(--gb-shadow-lg);
}

.gb-jalali-date__panel[hidden] { display: none; }

.gb-jalali-date__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gb-space-2);
    margin-bottom: var(--gb-space-3);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
}

/* Month/year selects sit between the step arrows so a distant year is one
   choice away rather than one click per month. */
.gb-jalali-date__period {
    display: inline-flex;
    align-items: center;
    gap: var(--gb-space-1);
    min-width: 0;
}

.gb-jalali-date__select {
    appearance: none;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-sm);
    background: var(--gb-surface);
    color: var(--gb-text-primary);
    font: inherit;
    font-size: var(--gb-font-size-sm);
    padding: var(--gb-space-1) var(--gb-space-2);
    max-width: 8rem;
    cursor: pointer;
}

.gb-jalali-date__select:focus-visible {
    outline: none;
    border-color: var(--gb-primary);
    box-shadow: var(--gb-shadow-focus);
}

.gb-jalali-date__nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid transparent;
    border-radius: var(--gb-radius-sm);
    background: transparent;
    color: var(--gb-text-secondary);
    cursor: pointer;
}

.gb-jalali-date__nav:hover {
    background: var(--gb-surface-alt);
    color: var(--gb-text-primary);
}

.gb-jalali-date__grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 0.15rem;
    text-align: center;
}

.gb-jalali-date__weekday {
    padding: 0.25rem 0;
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-secondary);
}

.gb-jalali-date__day {
    padding: 0.4rem 0;
    border: 1px solid transparent;
    border-radius: var(--gb-radius-sm);
    background: transparent;
    color: var(--gb-text-primary);
    font-size: var(--gb-font-size-sm);
    cursor: pointer;
}

.gb-jalali-date__day:hover { background: var(--gb-surface-alt); }

.gb-jalali-date__day--today { border-color: var(--gb-border-strong); }

.gb-jalali-date__day--selected {
    background: var(--gb-primary);
    color: var(--gb-on-primary);
    font-weight: var(--gb-font-weight-semibold);
}

.gb-jalali-date__footer {
    display: flex;
    justify-content: space-between;
    gap: var(--gb-space-2);
    margin-top: var(--gb-space-3);
    padding-top: var(--gb-space-3);
    border-top: 1px solid var(--gb-border-subtle);
}

/* --------------------------------------------------------------------------
   7. Commit bar
   --------------------------------------------------------------------------
   The save/cancel row for a long form, pinned to the bottom of the viewport
   while the form is on screen.

   The ERP has forms of twenty and thirty fields — the employee record, the
   letter register, the control plan. Their submit button sat below the last
   field or at the end of a side rail, so filling the form and then finding
   the way to save it were two separate journeys, and on a short screen the
   second one was a scroll into empty space.

   Proven first on the letter register as `.l-actionbar`; that module keeps
   its own copy because its rail geometry differs, and the two must not
   drift — change both.

   `position: sticky`, never `fixed`. Fixed would float over the footer and
   every page behind it, and would need a body offset so it did not cover
   the last field. Sticky stays inside the form and stops where it ends.

   It deliberately does NOT bleed to the window edges: the shell padding it
   would have to cancel changes at breakpoints this rule cannot see, and an
   earlier full-bleed version hung 8px past the content at narrow widths and
   gave the page a horizontal scrollbar.
   -------------------------------------------------------------------------- */

.gb-commitbar {
    position: sticky;
    inset-block-end: var(--gb-space-3);
    z-index: 5;
    display: flex;
    align-items: center;
    gap: var(--gb-space-3);
    flex-wrap: wrap;
    margin-block-start: var(--gb-space-5);
    padding: var(--gb-space-3) var(--gb-space-4);
    border: 1px solid var(--gb-border-subtle);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
    box-shadow: 0 6px 18px rgba(35, 32, 26, 0.10);
}

/* Pushes what follows to the far end — the note about what saving does
   belongs opposite the buttons, not beside them. */
.gb-commitbar__note {
    margin-inline-start: auto;
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
    line-height: var(--gb-line-height-relaxed);
}

@media (max-width: 720px) {
    /* The bar is the whole row here, so the note cannot sit opposite the
       buttons any more. It takes its own row instead of disappearing: the
       phone is where a person is least sure what "save" is about to do, so
       it is the last place to drop the sentence that says so. The bar
       already wraps, so this costs one line, not a layout. */
    .gb-commitbar__note {
        flex-basis: 100%;
        margin-inline-start: 0;
    }
}

/* --------------------------------------------------------------------------
   8. Record navigator
   --------------------------------------------------------------------------
   The sections of one record, as a rail beside the content rather than tabs
   above it.

   A tab strip stops working somewhere around six items. The employee file
   has nine: measured at 790px it wanted 1207px of strip, so three sections
   sat off-screen behind a native scrollbar — navigation nobody could see.
   Wrapping hid nothing but produced a two-row strip, which reads as two
   groups of tabs rather than one set of peers. A column holds all nine at
   full label length and has room for more.

   Pair it with the existing `[data-file-tab]`/`[data-file-panel]` toggling,
   or any equivalent: this pattern is layout only and owns no behaviour.

   Below 1100px it becomes a horizontal scroller — a 220px rail plus
   readable content does not fit, and section names are short enough to
   swipe. `contain: paint` is required there, not optional: without it an
   RTL scroll container lets the whole PAGE scroll sideways.
   -------------------------------------------------------------------------- */

/* The container always carries a layout class of its own -- .gb-workspace__main
   on the PhysicalSecurity pages, .gb-stack on the Identity/Workflow ones -- and
   both of those are flex columns at the same (0,1,0) specificity as this rule.
   Today this one wins only because it is later in the file. The second selector
   makes that explicit at (0,2,0): the runtime adds .gb-recordnav to an element
   that by definition has the data attribute, so it always matches, and the grid
   no longer depends on where anyone puts a stylesheet. */
.gb-recordnav,
[data-gb-recordnav].gb-recordnav {
    display: grid;
    grid-template-columns: 13.75rem minmax(0, 1fr);
    gap: var(--gb-space-4);
    align-items: start;
}

.gb-recordnav__rail {
    position: sticky;
    top: var(--gb-space-4);
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--gb-space-2);
    border: 1px solid var(--gb-border-subtle);
    border-radius: var(--gb-radius-xl);
    background: var(--gb-surface);
    box-shadow: var(--gb-shadow-sm);
}

.gb-recordnav__item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 0.65rem;
    border: 0;
    border-radius: var(--gb-radius-sm);
    background: transparent;
    color: var(--gb-text-secondary);
    font: inherit;
    font-size: var(--gb-font-size-md);
    font-weight: var(--gb-font-weight-medium);
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.gb-recordnav__item:hover {
    background: var(--gb-surface-alt);
    color: var(--gb-text-primary);
}

/* The same treatment the sidebar gives the current page: amber tint, dark
   ink, amber icon — so "where am I" reads identically everywhere. */
.gb-recordnav__item.is-active {
    background: var(--gb-primary-subtle);
    color: var(--gb-text-primary);
    font-weight: var(--gb-font-weight-bold);
}

.gb-recordnav__icon {
    display: inline-flex;
    flex: 0 0 auto;
    width: 1.05rem;
    height: 1.05rem;
    color: var(--gb-text-tertiary);
}

.gb-recordnav__icon svg { width: 100%; height: 100%; }

.gb-recordnav__item.is-active .gb-recordnav__icon { color: var(--gb-primary-active); }

.gb-recordnav__label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gb-recordnav__body { min-width: 0; }

/* An anchored section stops clear of the sticky header instead of sliding
   under it. `scroll-margin-block-start` is the property for exactly this;
   padding would change the card, and a JS offset would fight the browser. */
.gb-recordnav__body > .gb-card {
    scroll-margin-block-start: calc(var(--gb-shell-header-height, 4rem) + var(--gb-space-4));
}

/* Jumping the page with no motion makes it look like a reload. Honoured
   only where the reader has not asked for less movement. */
@media (prefers-reduced-motion: no-preference) {
    html:has(.gb-recordnav) { scroll-behavior: smooth; }
}

@media (max-width: 1100px) {
    .gb-recordnav { grid-template-columns: minmax(0, 1fr); }

    .gb-recordnav__rail {
        position: static;
        flex-direction: row;
        overflow-x: auto;
        contain: paint;
    }

    .gb-recordnav__item { flex: 0 0 auto; }
}

@media (max-width: 720px), (pointer: coarse) {
    /* 36px of hit area is fine under a mouse and under the 44px touch target
       every platform guideline asks for. Width alone is the wrong test — a
       768px tablet is a touch device too — so this asks about the POINTER as
       well, and catches the tablet the width query misses. Measured at 375px:
       36 -> 44. Padding, not height, so the label keeps centring itself. */
    .gb-recordnav__item {
        padding-block: 0.8rem;
    }
}


/* --------------------------------------------------------------------------
   9. List workspace
   --------------------------------------------------------------------------
   The shape 59 pages in this ERP share: filter, then result count, then the
   table, then paging. They each invented their own spacing for it, so the
   same screen in two modules looked like two products.

   The count line is not decoration. A filtered list that silently returns
   nothing looks identical to a broken one; stating "۱۲ of ۳۴۰" is what tells
   the user the filter worked and how hard it bit.
   -------------------------------------------------------------------------- */

.gb-listpage {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-4);
}

.gb-listpage__filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--gb-space-3);
    padding: var(--gb-space-4);
    border-radius: var(--gb-radius-xl);
    background: var(--gb-surface);
    box-shadow: var(--gb-shadow-sm);
}

/* A page that already wrapped its filters in a card gets a flat row instead:
   a panel inside a panel reads as a mistake. :where() keeps the specificity
   equal to the rule above, so source order decides. The legacy twins of this
   class (.employee-filter, .recruitment-filter) get the same treatment in
   legacy-bridge.css -- all three are one object with three names. */
:where(.card, .gb-card, .recruitment-card, .tile) .gb-listpage__filters {
    padding: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
}

/* Each filter keeps its label above its control and takes only the width it
   needs, so a row of three short filters does not stretch to fill the page. */
/* Counted across the 47 pages that use the filter bar: .gb-field appears 33
   times inside one, .gb-listpage__filter twice, .form-field twice. So the
   class this pattern documented is the outlier and .gb-field is the real
   convention -- the parallel-vocabulary problem, this time inside my own
   pattern. Rather than rewrite 45 pages, the pattern sizes what the portal
   actually writes. Scoped to children of the bar: .gb-field is a general form
   class and must not pick up filter sizing anywhere else. The margin reset
   matters -- .gb-field carries margin-bottom for stacked forms, which in a
   single-row filter bar is just a gap under the row. */
.gb-listpage__filter,
.gb-listpage__filters > .gb-field,
.gb-listpage__filters > .form-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 9rem;
    flex: 0 1 14rem;
    margin-bottom: 0;
}

.gb-listpage__filter--wide { flex: 1 1 20rem; }

.gb-listpage__actions {
    display: flex;
    align-items: center;
    gap: var(--gb-space-2);
    margin-inline-start: auto;
}

.gb-listpage__count {
    display: flex;
    align-items: baseline;
    gap: var(--gb-space-2);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-listpage__count strong {
    color: var(--gb-text-primary);
    font-weight: var(--gb-font-weight-bold);
    font-variant-numeric: tabular-nums;
}

/* The table sits on its own sheet with no padding of its own — the rows
   supply it — and clips so the first and last rows take the card corners. */
.gb-listpage__table {
    padding: 0;
    overflow: hidden;
}

/* A wide table scrolls inside its own box. `contain: paint` is what stops
   an RTL overflow container from scrolling the whole page sideways — the
   single most-repeated layout bug in this codebase. */
/* .gb-listpage__scroll used to live here as { overflow-x: auto; contain:
   paint; } -- which is .gb-table-wrapper with the border taken off, and that
   is on 120 pages while this was on none but the style guide's own example.
   Removed: a second name for the RTL overflow fix is how the portal grew two
   card vocabularies in the first place. A list page's table goes in a
   .gb-table-wrapper like every other table.

   .gb-listpage__pager went the same way -- zero uses, and .gb-pagination is
   the real component, with a summary and a page-size control this never had. */



@media (max-width: 720px) {
    .gb-listpage__filter,
    .gb-listpage__filters > .gb-field,
    .gb-listpage__filters > .form-field,
    .gb-listpage__filter--wide { flex: 1 1 100%; }

    .gb-listpage__actions { margin-inline-start: 0; width: 100%; }
}
