/* ==========================================================================
   GoldenBearing Design System — Component Library (GB-UI-01)
   ==========================================================================
   Rules for every component in this file:
     1. Every color, space, radius, shadow, and duration is a var(--gb-*)
        token from tokens.css — NEVER a literal value. This is what makes
        the [data-theme="dark"] override in tokens.css re-skin every
        component automatically.
     2. Layout uses CSS logical properties (margin-inline-start, not
        margin-left) so every component is correct in both `dir="ltr"` and
        `dir="rtl"` with zero direction-specific overrides needed here —
        see rtl.css for the few exceptions that genuinely need one.
     3. Class names are all `.gb-*` — a distinct namespace from the existing
        unprefixed classes in site.css (.button, .card, .badge, ...), so
        this file is safe to load on every existing page without changing
        how any current page looks.
   ========================================================================== */


/* ==========================================================================
   1. Buttons
   ========================================================================== */

/* GB-QMS-FRONTEND-001: the reference design's button. A fixed height rather
   than symmetric padding, because the reference lines buttons up against
   40px inputs and 38px header controls, and padding alone cannot hold a row
   of mixed-length Persian labels to one baseline. */
.gb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--gb-space-2);
    font-family: inherit;
    /* Measured off the design canvas, 2026-09-06: 40px tall, 8px/16px of
       padding, 11.5px at medium. It was 42px / 0 / 18px at "13px" semibold —
       and 13px is not a step on this system's own type ramp (10.5 · 11.5 ·
       12.5 · 13.5 · 15), so it was drift rather than a decision. min-height
       rather than height, as the canvas has it, so a button that wraps or
       carries a two-line label grows instead of clipping. */
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-medium);
    line-height: var(--gb-line-height-tight);
    min-height: 40px;
    padding-block: 8px;
    padding-inline: 16px;
    border-radius: var(--gb-radius-md);
    border: 1px solid transparent;
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: background-color var(--gb-duration-fast) var(--gb-ease-standard),
                border-color var(--gb-duration-fast) var(--gb-ease-standard),
                color var(--gb-duration-fast) var(--gb-ease-standard),
                box-shadow var(--gb-duration-fast) var(--gb-ease-standard);
}

.gb-btn:disabled,
.gb-btn[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: 0.55;
}

/* The canvas's two smaller buttons, measured: 36px at 6px/10px and 32px at
   6px/12px, both 10.5px semibold — a small button carries MORE weight than the
   default one, not less, because it has less area to be read from. */
.gb-btn--sm {
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-semibold);
    min-height: 36px;
    height: auto;
    padding-block: 6px;
    padding-inline: 10px;
    border-radius: var(--gb-radius-md);
}

/* The reference's smallest control — a row action inside a table cell. */
.gb-btn--xs {
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-semibold);
    min-height: 32px;
    height: auto;
    padding-block: 6px;
    padding-inline: 12px;
    border-radius: 8px;
}

/* `--lg` has no counterpart on any artboard, so it keeps its own metrics —
   restated as min-height so every button in the family grows the same way. */
.gb-btn--lg {
    font-size: var(--gb-font-size-lg);
    min-height: 48px;
    height: auto;
    padding-block: 10px;
    padding-inline: 20px;
    border-radius: var(--gb-radius-lg);
}

/* The reference draws its primary action at weight 700, one step above the
   rest of the row, so the one thing to press is legible at a glance from
   arm's length. */
.gb-btn--primary,
.gb-btn--danger {
    font-weight: var(--gb-font-weight-bold);
}

/* An action the backend cannot carry out yet. The reference gives it a flat
   grey rather than a faded primary: a dimmed gold still reads as the thing
   to press, and on a quality screen that is the wrong invitation. */
.gb-btn:disabled,
.gb-btn[aria-disabled="true"] {
    background: var(--gb-surface-sunken);
    border-color: var(--gb-surface-sunken);
    color: var(--gb-text-tertiary);
    opacity: 1;
}

.gb-btn--block {
    display: flex;
    width: 100%;
}

.gb-btn--icon {
    width: 40px;
    padding-inline: 0;
}

.gb-btn--sm.gb-btn--icon { width: 36px; }
.gb-btn--xs.gb-btn--icon { width: 32px; }
.gb-btn--lg.gb-btn--icon { width: 48px; }

/* Primary — the golden-orange call-to-action. */
.gb-btn--primary {
    background: var(--gb-primary);
    border-color: var(--gb-primary);
    color: var(--gb-on-primary);
}

.gb-btn--primary:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-primary-hover);
    border-color: var(--gb-primary-hover);
}

.gb-btn--primary:active:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-primary-active);
    border-color: var(--gb-primary-active);
}

/* Secondary — steel-gray, for the second-priority action next to a primary. */
/* The canvas draws the secondary button with the ordinary border, not the
   strong one: it sits beside a solid amber primary, and a near-black outline
   next to that reads as a second call to action rather than the quieter of
   the two. */
.gb-btn--secondary {
    background: var(--gb-surface);
    border-color: var(--gb-border);
    color: var(--gb-text-primary);
}

.gb-btn--secondary:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-surface-alt);
    border-color: var(--gb-secondary);
}

.gb-btn--secondary:active:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-surface-sunken);
}

/* Danger — destructive actions (delete, revoke, deactivate). */
.gb-btn--danger {
    background: var(--gb-danger);
    border-color: var(--gb-danger);
    color: var(--gb-on-danger);
}

.gb-btn--danger:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-danger-hover);
    border-color: var(--gb-danger-hover);
}

/* Outline — lowest-emphasis action; transparent until hovered. */
.gb-btn--outline {
    background: transparent;
    border-color: var(--gb-border-strong);
    color: var(--gb-text-primary);
}

.gb-btn--outline:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-surface-alt);
    border-color: var(--gb-primary);
    color: var(--gb-primary);
}

/* Link-styled button — parity with legacy .button--link. */
/* The quiet button: no fill and no border, used for a secondary action that
   sits beside a primary one (cancel, close the camera, remove a photo). The
   base .gb-btn is already transparent, so what this actually adds is the
   hover feedback those buttons had none of — every other variant defines its
   own hover and this one had no rule at all. */
.gb-btn--ghost {
    background: transparent;
    border-color: transparent;
    color: var(--gb-text-primary);
}

.gb-btn--ghost:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--gb-surface-alt);
    border-color: var(--gb-border);
}

.gb-btn--link {
    background: transparent;
    border-color: transparent;
    color: var(--gb-text-link);
    padding-inline: var(--gb-space-1);
    text-decoration: underline;
}

.gb-btn--link:hover:not(:disabled):not([aria-disabled="true"]) {
    color: var(--gb-text-link-hover);
    background: transparent;
}


/* ==========================================================================
   2. Cards
   ========================================================================== */

/* GB-QMS-FRONTEND-001. The border was --gb-border-strong (#6C757D): a mid
   grey, which outlines a card rather than edging it, and is most of why the
   screens read heavier than the design. The reference edges every card with
   the same hairline and lets the shadow do the lifting. */
/* UX redesign: a card is a sheet lifted off warm paper, not a boxed
   region. The 1px border did the separating work before; the two-layer
   shadow does it now, and the radius moved to the surface family. */
.gb-card {
    background: var(--gb-surface);
    border: 1px solid transparent;
    border-radius: var(--gb-radius-xl);
    padding: 18px;
    box-shadow: var(--gb-shadow-md);
}

/* That border is `transparent` rather than `none` on purpose: Windows
   High Contrast Mode drops box-shadow entirely, so without it a card
   would lose its edge completely there. This re-paints the same 1px as
   a system colour instead. */
@media (forced-colors: active) {
    .gb-card {
        border-color: CanvasText;
    }
}

.gb-card__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gb-space-3);
    margin-bottom: var(--gb-space-3);
}

/* Bold, not semibold: a card title has to separate itself from the body
   text right under it at only one step up in size. Kept in step with the
   legacy .section-title in legacy-bridge.css — the two must not drift. */
.gb-card__title {
    margin: 0;
    font-size: var(--gb-font-size-lg);
    font-weight: var(--gb-font-weight-bold);
    color: var(--gb-text-primary);
}

.gb-card__subtitle {
    margin-top: var(--gb-space-1);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-card__body {
    color: var(--gb-text-primary);
}

.gb-card__footer {
    margin-top: var(--gb-space-4);
    padding-top: var(--gb-space-4);
    border-top: 1px solid var(--gb-border-subtle);
    display: flex;
    gap: var(--gb-space-3);
}

/* ---- Dashboard card — the big KPI tile (replaces legacy .tile). --------- */

.gb-card--dashboard {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-2);
}

.gb-card--dashboard .gb-card__icon {
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--gb-radius-md);
    background: var(--gb-primary-subtle);
    color: var(--gb-primary);
    margin-bottom: var(--gb-space-2);
}

.gb-card__metric {
    font-size: var(--gb-font-size-3xl);
    font-weight: var(--gb-font-weight-bold);
    color: var(--gb-text-primary);
    line-height: var(--gb-line-height-tight);
}

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

.gb-card__trend {
    display: inline-flex;
    align-items: center;
    gap: var(--gb-space-1);
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-semibold);
}

.gb-card__trend--up { color: var(--gb-success); }
.gb-card__trend--down { color: var(--gb-text-danger); }

/* ---- Information card — icon/title/description, no metric. -------------- */

.gb-card--info {
    display: flex;
    gap: var(--gb-space-4);
    align-items: flex-start;
}

.gb-card--info .gb-card__icon {
    flex-shrink: 0;
    width: 2.75rem;
    height: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--gb-radius-md);
    background: var(--gb-accent-subtle);
    color: var(--gb-accent);
}

/* ---- Status card — an inline-start colored bar communicating state. ----- */

.gb-card--status {
    border-inline-start: 4px solid var(--gb-border-strong);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gb-space-3);
}

.gb-card--status-success { border-inline-start-color: var(--gb-success); }
.gb-card--status-warning { border-inline-start-color: var(--gb-warning); }
.gb-card--status-danger  { border-inline-start-color: var(--gb-danger); }
.gb-card--status-info    { border-inline-start-color: var(--gb-info); }

/* ---- Link card — a whole card that IS the navigation target. -------------
   Used by the Home module grid and module landing pages. Authored as an
   <a class="gb-card gb-card--link"> so the entire tile is one large, keyboard-
   reachable hit area with a real accessible name, rather than a decorative
   box containing a small "view" link (which forces precise aiming and reads
   as two separate things to a screen reader). */

.gb-card--link {
    text-decoration: none;
    color: inherit;
    transition: border-color var(--gb-duration-fast) var(--gb-ease-standard),
                box-shadow var(--gb-duration-fast) var(--gb-ease-standard),
                transform var(--gb-duration-fast) var(--gb-ease-standard);
}

/* The resting card now carries --gb-shadow-md (see .gb-card), so hovering
   to the same value produced no lift at all — this has to step past it. */
.gb-card--link:hover {
    border-color: var(--gb-primary);
    box-shadow: var(--gb-shadow-lg);
    color: inherit;
}

.gb-card--link:hover .gb-card__title {
    color: var(--gb-primary-active);
}

/* ---- Definition list — the standard "entity metadata" block. -------------
   Detail pages across Recruitment/HR/Workflow all need the same label/value
   pairs; this replaces the ad-hoc `.rtl-page dl` rule in site.css (which
   only worked inside that one wrapper) with a token-driven, responsive
   version any page can use. */

.gb-detail-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: var(--gb-space-4);
    margin: 0;
}

.gb-detail-list__item {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-1);
    min-width: 0;
}

.gb-detail-list__label {
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-medium);
    color: var(--gb-text-secondary);
}

.gb-detail-list__value {
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-medium);
    color: var(--gb-text-primary);
    overflow-wrap: anywhere;
}

/* ---- Action bar — the explicit primary/secondary/destructive hierarchy. --
   `.gb-action-bar__end` pushes the lowest-priority (usually destructive)
   actions away from the primary one, so "تأیید" and "حذف" are never
   adjacent look-alikes a tired user can hit by accident. */

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

/* An element carrying the native `hidden` attribute must never render,
   full stop — without this, `[hidden] { display: none }` (UA stylesheet,
   lowest-priority origin) always loses to this class's own `display: flex`
   (author origin), so any caller that toggles `.hidden` on a `.gb-action-bar`
   (e.g. the Internal Mailbox referral "انجام شد" trigger) silently keeps it
   visible regardless. Sitewide, correctness-only fix — an already-hidden
   bar staying hidden can never be a regression for an existing caller. */
.gb-action-bar[hidden] {
    display: none;
}

.gb-action-bar__end {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--gb-space-3);
}

/* Explains why an action is unavailable instead of leaving the user to guess
   at a greyed-out button (see the Requisition detail page's "ایجاد فرصت
   شغلی"). Pairs with `aria-disabled` + a `title` on the control itself. */
.gb-action-hint {
    display: block;
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
    line-height: var(--gb-line-height-normal);
}

@media (max-width: 640px) {
    .gb-action-bar,
    .gb-action-bar__end {
        width: 100%;
    }

    .gb-action-bar__end {
        margin-inline-start: 0;
    }

    .gb-action-bar .gb-btn,
    .gb-action-bar__end .gb-btn {
        flex: 1 1 auto;
    }
}


/* ==========================================================================
   3. Badges (small supporting primitive used by cards/tables)
   ========================================================================== */

.gb-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--gb-space-1);
    /* Measured off the design canvas, 2026-09-06: a 6px-radius rectangle at
       2.4px/8px and 10.5px, not a pill. The canvas keeps the fully-rounded
       shape for something else — the filter and tab chips a person clicks —
       so making a status badge a pill too erased the difference between "this
       is what the record IS" and "this is a control you can press". */
    padding-block: 2.4px;
    padding-inline: 8px;
    border-radius: var(--gb-radius-sm);
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-semibold);
    border: 1px solid transparent;
    white-space: nowrap;
}

.gb-badge--neutral { background: var(--gb-gray-200); color: var(--gb-text-secondary); }
.gb-badge--primary { background: var(--gb-primary-subtle); color: var(--gb-primary-active); border-color: var(--gb-primary-subtle-border); }
.gb-badge--success { background: var(--gb-success-subtle); color: var(--gb-success); border-color: var(--gb-success-subtle-border); }
.gb-badge--warning { background: var(--gb-warning-subtle); color: var(--gb-text-warning); border-color: var(--gb-warning-subtle-border); }
.gb-badge--danger  { background: var(--gb-danger-subtle); color: var(--gb-text-danger); border-color: var(--gb-danger-subtle-border); }
.gb-badge--info    { background: var(--gb-info-subtle); color: var(--gb-info); border-color: var(--gb-info-subtle-border); }


/* ==========================================================================
   4. Forms
   ========================================================================== */

/* Same class of bug as `.gb-validation-message[hidden]` further down, and the
   third time this codebase has hit it: the author `display: flex` below beats
   the user-agent's `[hidden] { display: none }`, so a field a form conditionally
   hides with the `hidden` attribute stays fully visible. Fixed here once, for
   every field. */
.gb-field[hidden] { display: none; }

.gb-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: var(--gb-space-4);
}

/* The reference's field label: quieter than its field, and 6px above it.
   A label heavier than the value it introduces makes a form read as a list
   of demands rather than of things you are filling in. */
.gb-label {
    font-size: var(--gb-font-size-md);
    font-weight: var(--gb-font-weight-medium);
    color: var(--gb-text-secondary);
}

.gb-label__optional {
    font-weight: var(--gb-font-weight-regular);
    color: var(--gb-text-tertiary);
}

/* Two label sizes the design canvas uses and this sheet had no word for,
   both read off the artboards rather than chosen: `--sm` (11.5px) is the
   label of a field nested inside a tinted group, where the group's own
   heading is already carrying the 12.5px; `--strong` (12.5px, semibold, in
   the primary colour) is the heading of a field group — it introduces a
   block, not a single value, which is why it is allowed to be the loudest
   thing in it. */
.gb-label--sm {
    font-size: var(--gb-font-size-sm);
}

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

/* GB-QMS-FRONTEND-001: the reference's field. 40px tall on the alternate
   surface rather than white — the reference's forms sit on white cards, and
   a white field on a white card has only its border to say it is a field. */
/* Every form control in the portal — about 1500 of them. The size and the
   radius were literal (13px / 9px) and therefore drifted from the type ramp
   and the radius family the redesign set; they are tokens now, so a control
   and the text beside it are the same size and a control and a card are
   demonstrably from the same system. */
.gb-input,
.gb-select,
.gb-textarea {
    font: inherit;
    font-size: var(--gb-font-size-lg);
    color: var(--gb-text-primary);
    background: var(--gb-surface-alt);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    padding-block: 0;
    padding-inline: 11px;
    height: 40px;
    width: 100%;
    transition: border-color var(--gb-duration-fast) var(--gb-ease-standard),
                background-color var(--gb-duration-fast) var(--gb-ease-standard);
}

/* The one control on a screen that the whole screen is waiting for — the
   gate's plate or badge scan, the key board's barcode. The canvas draws it
   44px tall at 15px, a step above every other field, because a guard reaches
   for it without reading the form. Only ever one per screen; a form where two
   fields are both the loudest has no loudest field. */
.gb-input--lg,
.gb-select--lg {
    height: 44px;
    padding-inline: 12px;
    font-size: var(--gb-font-size-xl);
}

/* Resting controls sit on the sunken surface so a form reads as a set of
   slots; the one being typed into lifts to the card surface, which is what
   makes "where is my cursor" answerable at a glance on a 25-field form. */
.gb-input:focus,
.gb-select:focus,
.gb-textarea:focus {
    background: var(--gb-surface);
    border-color: var(--gb-accent);
}

.gb-input::placeholder,
.gb-textarea::placeholder {
    color: var(--gb-text-tertiary);
}

.gb-input:hover,
.gb-select:hover,
.gb-textarea:hover {
    border-color: var(--gb-border-strong);
}

.gb-input:disabled,
.gb-select:disabled,
.gb-textarea:disabled {
    background: var(--gb-surface-alt);
    color: var(--gb-text-disabled);
    cursor: not-allowed;
}

/* A select in a filter bar rather than in a form — same step down that
   .gb-btn--sm makes, so the two line up when they sit in one row. */
.gb-select--sm {
    height: 36px;
    padding-inline: 9px;
    border-radius: var(--gb-radius-md);
}

.gb-textarea {
    resize: vertical;
    height: auto;
    min-height: 5.5rem;
    padding-block: var(--gb-space-2);
    line-height: var(--gb-line-height-normal);
}

/* A checkbox and its label on one row, sized so the whole row is a
   comfortable tap target. Lived in administration/administration.css, which
   is linked only for /Administration and /Messaging — /Traceability/Workstations
   uses it too and was getting an unaligned checkbox with no gap. */
.gb-checkbox-row {
    display: flex;
    align-items: flex-start;
    gap: var(--gb-space-2);
    min-height: 2.75rem;
    padding-block: .7rem;
}

/* Count fields are entered with a scanner-adjacent keypad and read back at a
   glance, so they are sized for that rather than for a form. Written for the
   shop floor and previously kept in traceability/shopfloor.css, which is
   linked only on /Traceability — the HR import wizard and the dealer order
   form both write `gb-input gb-count-input` and were silently getting only
   the first half. It is a plain .gb-input modifier, so it belongs here. */
.gb-count-input {
    font-size: var(--gb-font-size-2xl);
    font-variant-numeric: tabular-nums;
    text-align: center;
    padding: var(--gb-space-2) var(--gb-space-3);
}

/* A number typed and checked at a glance rather than read in a column. Near
   twin of .gb-count-input above — kept separate because Traceability screens
   use both and they differ in weight and padding. Moved out of
   traceability/shopfloor.css for the supplier assessment form, which is at
   /Equipment and so never loaded that sheet. */
.gb-input--num {
    font-size: var(--gb-font-size-2xl);
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* Custom select chevron — a single inline SVG, mirrored automatically since
   background-position uses a logical `insert-inline-end` via the shorthand
   trick below (background-position keywords are direction-aware). */
.gb-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%238A8F98' stroke-width='1.6'%3E%3Cpath d='M5 7.5l5 5 5-5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--gb-space-3) center;
    padding-inline-end: var(--gb-space-8);
}

.gb-app[dir="rtl"] .gb-select,
.rtl-page .gb-select {
    background-position: left var(--gb-space-3) center;
}

/* Field states */
.gb-field--error .gb-input,
.gb-field--error .gb-select,
.gb-field--error .gb-textarea {
    border-color: var(--gb-danger);
}

.gb-field--success .gb-input,
.gb-field--success .gb-select,
.gb-field--success .gb-textarea {
    border-color: var(--gb-success);
}

.gb-validation-message {
    font-size: var(--gb-font-size-xs);
    display: flex;
    align-items: center;
    gap: var(--gb-space-1);
}

/* The author `display: flex` above beats the user-agent's own
   `[hidden] { display: none }`, so a message a script toggles with the `hidden`
   attribute would stay on screen with nothing to show for it. The mailbox hit
   this same class of bug twice; fixed here once, for every message. */
.gb-validation-message[hidden] { display: none; }

.gb-validation-message--error { color: var(--gb-text-danger); }
.gb-validation-message--success { color: var(--gb-success); }
.gb-validation-message--hint { color: var(--gb-text-tertiary); }

/* ---- Date picker (Jalali-aware — see design-system.js for the widget) --- */

.gb-date-picker {
    position: relative;
    display: flex;
}

.gb-date-picker .gb-input {
    padding-inline-end: var(--gb-space-8);
}

.gb-date-picker__trigger {
    position: absolute;
    inset-inline-end: var(--gb-space-1);
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border: none;
    background: transparent;
    color: var(--gb-text-secondary);
    border-radius: var(--gb-radius-sm);
    cursor: pointer;
}

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

.gb-date-picker__panel {
    position: absolute;
    z-index: var(--gb-z-dropdown);
    top: calc(100% + var(--gb-space-2));
    inset-inline-start: 0;
    background: var(--gb-surface);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    box-shadow: var(--gb-shadow-lg);
    padding: var(--gb-space-3);
    width: 18rem;
    display: none;
}

.gb-date-picker__panel[data-open="true"] {
    display: block;
}

.gb-date-picker__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--gb-space-2);
    font-weight: var(--gb-font-weight-semibold);
}

.gb-date-picker__nav {
    border: none;
    background: transparent;
    color: var(--gb-text-secondary);
    cursor: pointer;
    padding: var(--gb-space-1);
    border-radius: var(--gb-radius-sm);
}

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

.gb-date-picker__grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    text-align: center;
    font-feature-settings: "tnum" 1;
}

.gb-date-picker__weekday {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
    padding-block: var(--gb-space-1);
}

.gb-date-picker__day {
    border: none;
    background: transparent;
    border-radius: var(--gb-radius-sm);
    padding-block: var(--gb-space-1);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-primary);
    cursor: pointer;
}

.gb-date-picker__day:hover {
    background: var(--gb-primary-subtle);
}

.gb-date-picker__day--muted {
    color: var(--gb-text-disabled);
}

.gb-date-picker__day--today {
    box-shadow: inset 0 0 0 1px var(--gb-accent);
}

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

/* ---- Filter bar (used above data tables) --------------------------------- */

.gb-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--gb-space-3);
    padding: var(--gb-space-4);
    background: var(--gb-surface-alt);
    border: 1px solid var(--gb-border-subtle);
    border-radius: var(--gb-radius-lg);
    margin-bottom: var(--gb-space-4);
}

.gb-filter-bar .gb-field {
    margin-bottom: 0;
    min-width: 10rem;
}

/* The bar itself is already tinted, so a tinted control on it has only its
   border left to say it is a control. The canvas turns filter controls white
   for exactly this reason — the same inversion it uses for a field inside a
   tinted group. */
.gb-filter-bar :is(.gb-input, .gb-select, .gb-textarea) {
    background: var(--gb-surface);
}

.gb-filter-bar__actions {
    display: flex;
    gap: var(--gb-space-2);
    margin-inline-start: auto;
}


/* ==========================================================================
   5. Tables
   ========================================================================== */

.gb-table-wrapper {
    overflow-x: auto;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    /* Flex items default to min-width:auto, which lets a wide table's
       intrinsic content width leak past this wrapper's own overflow-x:auto
       and expand ancestor flex containers (e.g. .gb-stack) instead of
       scrolling in place — narrow viewports then get a page-level
       horizontal scrollbar even though the table itself visibly scrolls
       correctly inside the wrapper. */
    min-width: 0;
    /* min-width:0 alone does NOT finish the job in RTL, which is every page
       in this ERP. The comment here used to call it "the standard fix"; it
       is half of one. Three module sheets — training.css,
       identity-consistency.css and physicalsecurity.css — had each
       independently discovered that and added `contain: paint` to their own
       wrappers, which is the same bug being patched three times because the
       base rule was incomplete. It belongs here, once, for all 203 wrappers.

       `overflow-x: clip` on an ancestor does not substitute for it — that
       was tried and does not suppress the page-level scroll either. */
    contain: paint;
}

.gb-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--gb-surface);
    font-size: var(--gb-font-size-sm);
    /* Jalali dates, personnel numbers, quantities and prices fill these
       tables. Proportional digits make a column of them ragged and make two
       rows of the same length look different; tabular figures line them up
       so the eye can compare down a column without reading. */
    font-variant-numeric: tabular-nums;
}

.gb-table th,
.gb-table td {
    text-align: start;
    padding-block: var(--gb-space-3);
    padding-inline: var(--gb-space-4);
    border-bottom: 1px solid var(--gb-border-subtle);
}

/* The header stays put while a long list scrolls. Without it, scrolling a
   200-row shift roster means losing the column names on the second screen
   and scrolling back to find out which column you are reading.

   `background` is required, not cosmetic: a sticky element with no ground
   lets rows show through it as they pass underneath. */
.gb-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--gb-surface-alt);
    color: var(--gb-text-secondary);
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-bold);
    white-space: nowrap;
}

/* Pointing at a row in a wide table and losing track of which one you are
   on is the classic wide-table error. A tint costs nothing and fixes it. */
.gb-table tbody tr:hover td {
    background: var(--gb-surface-alt);
}

/* Opt-in: put it on a cell that holds a quantity or an amount, so the
   digits end on the same edge down the column and magnitudes compare at a
   glance. Not automatic — a personnel number is digits but reads as a name,
   and right-aligning it would be wrong. */
.gb-table .gb-table__num {
    text-align: end;
    font-variant-numeric: tabular-nums;
}

/* ---- Sortable columns (gb-table-sort.js) -------------------------------
   The arrow is drawn with a pseudo-element rather than an icon so it costs
   no markup on 437 tables, and it reserves its own width at rest — without
   that, the heading shifts sideways the moment a column becomes sorted. */
.gb-table__sortable {
    cursor: pointer;
    user-select: none;
}

.gb-table__sortable::after {
    content: "";
    display: inline-block;
    width: 0.55em;
    height: 0.55em;
    margin-inline-start: 0.4em;
    border-inline-start: 1.5px solid currentColor;
    border-block-end: 1.5px solid currentColor;
    /* Rotated square = a chevron. Transparent at rest: the space is held,
       the mark is not shown, so nothing moves when a column is chosen. */
    transform: rotate(-45deg) translateY(-0.15em);
    opacity: 0;
    transition: opacity var(--gb-duration-fast) var(--gb-ease-standard);
}

/* A hint on hover that the column can be sorted at all — half-lit, so it
   never competes with the column that actually is sorted. */
.gb-table__sortable:hover {
    color: var(--gb-text-primary);
}

.gb-table__sortable:hover::after {
    opacity: 0.4;
}

.gb-table__sortable.is-sorted-asc,
.gb-table__sortable.is-sorted-desc {
    color: var(--gb-text-primary);
}

.gb-table__sortable.is-sorted-asc::after,
.gb-table__sortable.is-sorted-desc::after {
    opacity: 1;
    color: var(--gb-primary-active);
}

.gb-table__sortable.is-sorted-desc::after {
    transform: rotate(135deg) translateY(-0.15em);
}

.gb-table__sortable:focus-visible {
    outline: 2px solid var(--gb-focus-ring-color);
    outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
    .gb-table__sortable::after { transition: none; }
}

.gb-table th {
    background: var(--gb-surface-alt);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-secondary);
    white-space: nowrap;
}

.gb-table th[aria-sort] {
    cursor: pointer;
}

.gb-table tbody tr:last-child td {
    border-bottom: none;
}

.gb-table tbody tr:hover {
    background: var(--gb-surface-alt);
}

.gb-table__empty,
.gb-table__loading {
    padding: var(--gb-space-8);
    text-align: center;
    color: var(--gb-text-secondary);
}

.gb-pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gb-space-3);
    margin-top: var(--gb-space-4);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-secondary);
}

.gb-pagination__pages {
    display: flex;
    align-items: center;
    gap: var(--gb-space-1);
}

.gb-pagination__page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    height: 2rem;
    border-radius: var(--gb-radius-md);
    border: 1px solid transparent;
    background: transparent;
    color: var(--gb-text-secondary);
    cursor: pointer;
    text-decoration: none;
    font-feature-settings: "tnum" 1;
}

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

.gb-pagination__page[aria-current="page"] {
    background: var(--gb-primary);
    color: var(--gb-on-primary);
    font-weight: var(--gb-font-weight-semibold);
}

.gb-pagination__page:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}


/* ==========================================================================
   6. Feedback — Alert, Toast, Modal, Empty state, Loading state
   ========================================================================== */

/* ---- Alert ------------------------------------------------------------- */

.gb-alert {
    display: flex;
    gap: var(--gb-space-3);
    align-items: flex-start;
    padding: var(--gb-space-3) var(--gb-space-4);
    border-radius: var(--gb-radius-md);
    border: 1px solid transparent;
    font-size: var(--gb-font-size-sm);
}

.gb-alert__icon {
    flex-shrink: 0;
    margin-top: 0.1rem;
}

.gb-alert__title {
    font-weight: var(--gb-font-weight-semibold);
    margin-bottom: var(--gb-space-1);
}

/* .gb-alert is a flex row of icon | body | dismiss. The body was the one part
   never given a rule, so a long message could push the dismiss button out of
   the box instead of wrapping: min-width:0 lets it shrink below its content. */
.gb-alert__body {
    flex: 1;
    min-width: 0;
}

.gb-alert--info    { background: var(--gb-info-subtle);    border-color: var(--gb-info-subtle-border);    color: var(--gb-info); }
.gb-alert--success { background: var(--gb-success-subtle); border-color: var(--gb-success-subtle-border); color: var(--gb-success); }
.gb-alert--warning { background: var(--gb-warning-subtle); border-color: var(--gb-warning-subtle-border); color: var(--gb-text-warning); }
.gb-alert--danger  { background: var(--gb-danger-subtle);  border-color: var(--gb-danger-subtle-border);  color: var(--gb-text-danger); }

/* ---- Toast --------------------------------------------------------------- */

/* Self-contained font/line-height (not just color): design-system.js appends
   this region under the nearest `.gb-app` when one exists, but falls back to
   `<body>` on pages that render it before any `.gb-app` is in the DOM, so it
   cannot rely on inheriting typography from a `.gb-app` ancestor. */
.gb-toast-region {
    position: fixed;
    z-index: var(--gb-z-toast);
    inset-block-end: var(--gb-space-5);
    inset-inline-end: var(--gb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-2);
    width: 22rem;
    max-width: calc(100vw - var(--gb-space-8));
    font-family: var(--gb-font-family-base);
}

.gb-toast {
    display: flex;
    align-items: flex-start;
    gap: var(--gb-space-3);
    padding: var(--gb-space-3) var(--gb-space-4);
    background: var(--gb-surface);
    border: 1px solid var(--gb-border);
    border-inline-start: 3px solid var(--gb-secondary);
    border-radius: var(--gb-radius-md);
    box-shadow: var(--gb-shadow-lg);
    font-size: var(--gb-font-size-sm);
    line-height: var(--gb-line-height-normal);
    color: var(--gb-text-primary);
    animation: gb-toast-in var(--gb-duration-slow) var(--gb-ease-decelerate);
}

.gb-toast--success { border-inline-start-color: var(--gb-success); }
.gb-toast--warning  { border-inline-start-color: var(--gb-warning); }
.gb-toast--danger   { border-inline-start-color: var(--gb-danger); }
.gb-toast--info     { border-inline-start-color: var(--gb-info); }

.gb-toast__close {
    margin-inline-start: auto;
    border: none;
    background: transparent;
    color: var(--gb-text-tertiary);
    cursor: pointer;
    line-height: 1;
}

.gb-toast.gb-toast--leaving {
    animation: gb-toast-out var(--gb-duration-base) var(--gb-ease-accelerate) forwards;
}

@keyframes gb-toast-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes gb-toast-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(8px); }
}

/* ---- Modal ----------------------------------------------------------------- */

.gb-modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--gb-z-modal-backdrop);
    background: var(--gb-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--gb-space-4);
    font-family: var(--gb-font-family-base);
    animation: gb-fade-in var(--gb-duration-base) var(--gb-ease-standard);
}

.gb-modal-backdrop[hidden] {
    display: none;
}

.gb-modal {
    position: relative;
    z-index: var(--gb-z-modal);
    width: 100%;
    max-width: 32rem;
    max-height: calc(100vh - var(--gb-space-8));
    overflow-y: auto;
    background: var(--gb-surface);
    border-radius: var(--gb-radius-lg);
    box-shadow: var(--gb-shadow-xl);
    padding: var(--gb-space-6);
    font-size: var(--gb-font-size-md);
    line-height: var(--gb-line-height-normal);
    color: var(--gb-text-primary);
    animation: gb-modal-in var(--gb-duration-base) var(--gb-ease-decelerate);
}

.gb-modal__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gb-space-3);
    margin-bottom: var(--gb-space-4);
}

.gb-modal__title {
    margin: 0;
    font-size: var(--gb-font-size-xl);
    font-weight: var(--gb-font-weight-semibold);
}

.gb-modal__close {
    border: none;
    background: transparent;
    color: var(--gb-text-tertiary);
    cursor: pointer;
    font-size: var(--gb-font-size-lg);
    line-height: 1;
}

.gb-modal__close:hover {
    color: var(--gb-text-primary);
}

.gb-modal__footer {
    margin-top: var(--gb-space-5);
    display: flex;
    justify-content: flex-end;
    gap: var(--gb-space-3);
}

.gb-app[dir="rtl"] .gb-modal__footer,
.rtl-page .gb-modal__footer {
    justify-content: flex-start;
}

@keyframes gb-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes gb-modal-in {
    from { opacity: 0; transform: scale(0.96) translateY(8px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---- Empty state ------------------------------------------------------------ */

.gb-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--gb-space-2);
    padding: var(--gb-space-12) var(--gb-space-6);
    color: var(--gb-text-secondary);
}

/* ---- Empty note ---------------------------------------------------------
   The lighter half of .gb-empty-state, for the 41 places that render "there
   is nothing here" as one plain sentence. Those pages already had the right
   words; what they lacked was a shape, so an empty list looked identical to a
   page that had failed to load.

   No icon and no title/description split on purpose: adding either would mean
   inventing copy for forty-one screens nobody asked to have reworded. This
   takes the sentence exactly as written and gives it a region. */
.gb-empty-note {
    margin: 0;
    padding: var(--gb-space-6) var(--gb-space-4);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface-alt);
    color: var(--gb-text-secondary);
    text-align: center;
    text-wrap: pretty;
}

.gb-empty-state__icon {
    width: 3rem;
    height: 3rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--gb-radius-full);
    background: var(--gb-surface-alt);
    color: var(--gb-text-tertiary);
    margin-bottom: var(--gb-space-2);
}

.gb-empty-state__title {
    font-size: var(--gb-font-size-md);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
}

.gb-empty-state__actions {
    margin-top: var(--gb-space-3);
}

/* ---- Loading state / spinner / skeleton -------------------------------------- */

.gb-spinner {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--gb-radius-full);
    border: 2px solid var(--gb-border);
    border-top-color: var(--gb-primary);
    animation: gb-spin 0.7s linear infinite;
}

.gb-spinner--lg {
    width: 2.5rem;
    height: 2.5rem;
    border-width: 3px;
}

@keyframes gb-spin {
    to { transform: rotate(360deg); }
}

.gb-loading-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--gb-space-3);
    padding: var(--gb-space-12);
    color: var(--gb-text-secondary);
    font-size: var(--gb-font-size-sm);
}

.gb-skeleton {
    background: linear-gradient(90deg, var(--gb-surface-sunken) 25%, var(--gb-border-subtle) 37%, var(--gb-surface-sunken) 63%);
    background-size: 400% 100%;
    animation: gb-skeleton-shimmer 1.4s ease infinite;
    border-radius: var(--gb-radius-sm);
}

.gb-skeleton--text {
    height: 0.85em;
    margin-bottom: var(--gb-space-2);
}

.gb-skeleton--title {
    height: 1.5rem;
    width: 40%;
    margin-bottom: var(--gb-space-3);
}

@keyframes gb-skeleton-shimmer {
    0%   { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}


/* ==========================================================================
   7. Layout helpers (used by the showcase / future module pages)
   ========================================================================== */

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

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

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

@media (max-width: 640px) {
    .gb-filter-bar__actions {
        margin-inline-start: 0;
        width: 100%;
    }

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


/* ==========================================================================
   8. Dropdown / menu (added for GB-UI-02 — the application shell's header
   needs a user-profile menu and a notification panel, and both are the same
   generic pattern: a trigger button that reveals a floating panel anchored
   to it. Kept here rather than in the shell's own stylesheet because it is
   a generic content-level primitive any future module can reuse (e.g. a
   table row's "..." actions menu) — not something specific to page chrome.
   Behavior lives in design-system.js's GB.dropdown.
   ========================================================================== */

.gb-dropdown {
    position: relative;
    display: inline-flex;
}

.gb-dropdown__panel {
    position: absolute;
    z-index: var(--gb-z-dropdown);
    top: calc(100% + var(--gb-space-2));
    inset-inline-end: 0;
    min-width: 14rem;
    /* A hard cap, not just min-width: without it, a flex-row descendant
       that forgets its own min-width:0 (the usual cause — a flex item's
       default min-width:auto refuses to shrink below its unwrapped content
       width, which silently defeats any text-overflow:ellipsis inside it)
       balloons this panel to the width of its longest unwrapped line
       instead of truncating, which on a long notification title pushed the
       panel wide enough to run off the viewport edge. */
    max-width: min(24rem, calc(100vw - 2 * var(--gb-space-4)));
    background: var(--gb-surface);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    box-shadow: var(--gb-shadow-lg);
    padding: var(--gb-space-2);
    font-family: var(--gb-font-family-base);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-primary);
    display: none;
}

.gb-dropdown__panel[data-open="true"] {
    display: block;
    animation: gb-fade-in var(--gb-duration-fast) var(--gb-ease-standard);
}

.gb-dropdown__panel--start {
    inset-inline-end: auto;
    inset-inline-start: 0;
}

.gb-dropdown__panel--wide {
    min-width: 20rem;
}

.gb-dropdown__header {
    padding: var(--gb-space-2) var(--gb-space-3);
    font-weight: var(--gb-font-weight-semibold);
    border-bottom: 1px solid var(--gb-border-subtle);
    margin-bottom: var(--gb-space-1);
}

.gb-dropdown__item {
    display: flex;
    align-items: center;
    gap: var(--gb-space-2);
    width: 100%;
    padding: var(--gb-space-2) var(--gb-space-3);
    border: none;
    background: transparent;
    color: var(--gb-text-primary);
    font: inherit;
    text-align: start;
    text-decoration: none;
    border-radius: var(--gb-radius-md);
    cursor: pointer;
}

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

.gb-dropdown__item--danger {
    color: var(--gb-text-danger);
}

.gb-dropdown__divider {
    height: 1px;
    background: var(--gb-border-subtle);
    margin: var(--gb-space-1) 0;
    border: none;
}


/* ==========================================================================
   Avatar photo (GBPeopleInitials.RenderForEmployee/RenderForUser)
   ========================================================================== */

/* Sized to fill whatever circle/shape the caller's own existing avatar
   wrapper (.gb-shell__avatar, .gb-mailbox3__row-avatar, ...) already
   defines — border-radius: inherit means this needs no per-page CSS of its
   own, matching the "no page has its own avatar logic" rule the plain
   initials/icon fallback already follows. */
.gb-avatar-photo {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}

/* ==========================================================================
   Print
   ==========================================================================
   The redesign made a card a sheet lifted off warm paper: no outline, a
   two-layer shadow doing the separating. That is right on screen and wrong
   on paper — browsers drop box-shadow when printing, and they drop
   background colours too unless the user ticks "background graphics", which
   nobody does. A printed page of cards would therefore be a page of
   unseparated text, and this ERP prints a great deal: guard handovers,
   conduct forms, equipment reports, the organisation chart, barcode sheets.

   So on paper the border comes back and the shadow goes. This is not a
   different design; it is the same separation expressed in the one property
   that survives the printer.

   Five module sheets already carry their own `@media print` blocks for
   their own layouts. This one is about the shared components only, and it
   loads BEFORE those module sheets — so where the two overlap the MODULE
   rule wins, not this one. That is the right way round: a module that has
   thought about its own printed layout should not be overridden by a
   general baseline that has not.
   ========================================================================== */

@media print {
    .gb-card,
    .card,
    .tile,
    .recruitment-card,
    .gb-table-wrapper,
    .gb-listpage__filters,
    .gb-recordnav__rail {
        border: 1px solid #767676;
        box-shadow: none;
    }

    /* A sticky bar prints wherever it happened to be floating — usually
       across the middle of the first page, over the content. Neither of
       these is part of the record. */
    .gb-commitbar,
    .gb-pagination {
        display: none;
    }

    /* The rail is a navigation aid for a screen; on paper every section is
       already there, in order, so an index of them is noise. */
    .gb-recordnav__rail {
        display: none;
    }

    .gb-recordnav {
        display: block;
    }

    /* Paper has no tabs. A tabbed record prints as whichever panel happened
       to be open — one ninth of an employee file, one third of a user's
       identity record — and the reader has no way to tell anything is
       missing. On paper the whole record shows. */
    [role="tabpanel"][hidden] {
        display: block !important;
    }

    [role="tablist"] {
        display: none !important;
    }

    /* A table header repeated at the top of each printed page — the whole
       point of a sticky header, in the medium that has real pages. */
    .gb-table thead {
        display: table-header-group;
    }

    .gb-table thead th {
        position: static;
        border-bottom: 1.5px solid #767676;
    }

    /* A row split across a page break is unreadable on both halves. */
    .gb-table tr,
    .gb-card {
        break-inside: avoid;
    }

    /* Status is carried by a tinted pill on screen; tints do not print, so
       the outline is what keeps a badge legible as a badge. */
    .gb-badge,
    .badge {
        border: 1px solid #767676;
        color: #000;
    }

    /* Nothing on paper can be clicked. */
    .gb-btn,
    .button,
    .gb-shell__sidebar,
    .gb-shell__header {
        display: none;
    }
}
