/* ==========================================================================
   GoldenBearing Design System — Legacy class bridge (UX hardening pass)
   ==========================================================================
   WHY THIS FILE EXISTS

   AdminPortal grew two parallel visual vocabularies:

     1. `site.css` (Stage 4.9 → Recruitment Stage 1): `.button`, `.card`,
        `.tile`, `.data-table`, `.badge`, `.alert`, `.page-header`,
        `.form-field`, `.recruitment-*` — used by Home, Login, HR,
        Organization, Careers, Recruitment and the Workflow dashboard.
     2. `design-system/*.css` (GB-UI-01..05): `.gb-btn`, `.gb-card`,
        `.gb-table`, `.gb-badge`, `.gb-alert` — used by Identity, the
        Workflow Templates/Instances pages and Administration/Delete.

   Both are correct in isolation; together they make one ERP look like two
   products, and the legacy half had three concrete defects:

     * `site.css` hard-codes its own light-only `--color-*` palette, so
       every legacy page stayed light while the shell around it went dark
       via `[data-theme="dark"]`.
     * `.button--primary { width: 100% }` (authored for the login card)
       stretched EVERY primary action across its container.
     * `--color-success` was referenced but never declared.

   STRATEGY — remap, do not rewrite.

   §1 re-points site.css's own `--color-*` custom properties at the `--gb-*`
   tokens. Because `legacy-bridge.css` loads after `site.css`, these
   declarations win, and since custom-property references resolve at
   used-value time, every existing `site.css` rule (and every page-specific
   `.recruitment-*` rule) becomes token-driven and theme-aware with zero
   changes to those rules and zero changes to any page's markup.

   §2+ then align the handful of legacy components whose *shape* (not just
   color) diverged from the design system, so a `.button` and a `.gb-btn`
   sitting side by side on the same page read as the same control.

   SCOPE RULE: this file must never style a `.gb-*` class — the design
   system stays the single source of truth for those. It only touches
   legacy selectors. Pages migrating to `.gb-*` therefore lose nothing.
   ========================================================================== */


/* ==========================================================================
   §1  Palette remap — the whole point of this file
   ========================================================================== */

:root {
    --color-bg: var(--gb-background);
    --color-surface: var(--gb-surface);
    --color-surface-alt: var(--gb-surface-alt);
    --color-border: var(--gb-border);
    --color-text: var(--gb-text-primary);
    --color-muted: var(--gb-text-secondary);

    --color-primary: var(--gb-accent);
    --color-primary-hover: var(--gb-accent-hover);

    /* Referenced by site.css's `.recruitment-flow li.is-done::before` but
       never declared there — an invalid custom property made that tick mark
       inherit its color instead of reading as "done". */
    --color-success: var(--gb-success);

    --color-error-bg: var(--gb-danger-subtle);
    --color-error-border: var(--gb-danger-subtle-border);
    --color-error-text: var(--gb-text-danger);
    --color-info-bg: var(--gb-info-subtle);
    --color-info-border: var(--gb-info-subtle-border);
    --color-info-text: var(--gb-info);
    --color-warning-bg: var(--gb-warning-subtle);
    --color-warning-border: var(--gb-warning-subtle-border);
    /* --gb-warning is the colour of a warning MARK; on the warning tint it
       only reaches 4.45:1 as text. --gb-text-warning is the ink for that
       pairing — same split --color-error-text already makes for red. */
    --color-warning-text: var(--gb-text-warning);
}


/* ==========================================================================
   §2  Typography — Persian-first
   ==========================================================================
   site.css sets a Latin-first stack on <body>, so Persian copy on every
   legacy page fell back to Tahoma/Arial while the shell around it rendered
   in Vazirmatn. Same family everywhere, plus tabular figures so Jalali
   dates and counts line up in columns. */

body {
    font-family: var(--gb-font-family-base);
    font-feature-settings: "tnum" 1;
    -webkit-font-smoothing: antialiased;
}


/* ==========================================================================
   §3  Buttons — align `.button` with `.gb-btn`
   ========================================================================== */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--gb-space-2);
    padding: var(--gb-space-2) var(--gb-space-4);
    min-height: 2.5rem;
    border-radius: var(--gb-radius-md);
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-medium);
    line-height: var(--gb-line-height-tight);
    text-decoration: none;
    white-space: nowrap;
    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);
}

.button:focus-visible {
    outline: none;
    box-shadow: var(--gb-shadow-focus);
}

/* The single most damaging legacy rule: `width: 100%` was authored for the
   login card's submit button and then inherited by every primary action in
   the app, so "ایجاد فرصت شغلی" rendered as a full-width slab in page
   headers and toolbars. Width now comes from the context (see the login
   card's own opt-in below), not from the variant. */
.button--primary {
    width: auto;
    background: var(--gb-primary);
    color: var(--gb-on-primary);
    border-color: var(--gb-primary);
    font-weight: var(--gb-font-weight-semibold);
}

.button--primary:hover:not(:disabled) {
    background: var(--gb-primary-hover);
    border-color: var(--gb-primary-hover);
}

.button--primary:active:not(:disabled) {
    background: var(--gb-primary-active);
    border-color: var(--gb-primary-active);
}

.button--secondary {
    background: var(--gb-surface);
    border-color: var(--gb-border);
    color: var(--gb-text-primary);
}

.button--secondary:hover:not(:disabled) {
    background: var(--gb-surface-alt);
    border-color: var(--gb-border-strong);
}

/* Matches `.gb-btn--danger` exactly — destructive actions must read the
   same whichever class family a page happens to use. Protection against
   accidental activation is a confirmation step, not a quieter color. */
.button--danger {
    background: var(--gb-danger);
    border-color: var(--gb-danger);
    color: var(--gb-on-danger);
}

.button--danger:hover:not(:disabled) {
    background: var(--gb-danger-hover);
    border-color: var(--gb-danger-hover);
}

.button--link {
    min-height: auto;
    padding: var(--gb-space-1);
    color: var(--gb-text-link);
}

/* Low-emphasis text actions ("پاک کردن فیلتر", "ثبت نظر") still have to be
   hittable with a thumb — the visual weight stays low, only the target grows. */
@media (pointer: coarse) {
    .button--link {
        min-height: 2.75rem;
        padding-inline: var(--gb-space-2);
    }
}

.button:disabled,
.button[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    pointer-events: none;
}

/* The login card genuinely wants a full-width submit; it opts in rather
   than every primary button paying for it. */
.auth-form .button {
    width: 100%;
}


/* ==========================================================================
   §4  Surfaces — cards, tiles, sections
   ========================================================================== */

/* The portal has two card vocabularies. `.gb-card` is the design system's;
   `.card` / `.tile` / `.recruitment-card` predate it and are used MORE —
   about a thousand places against six hundred. Whatever the redesign does
   to `.gb-card` therefore reaches barely a third of the product unless the
   old names are given the same treatment here.

   So they get it in full: no outline, the surface radius, and the
   two-layer shadow that lets a sheet sit on warm paper. The border is
   overridden to `transparent` rather than removed because site.css sets a
   real one on `.card` and this file loads after it — and because High
   Contrast Mode drops shadows, which the media query below repaints. */
.card,
.tile,
.recruitment-card {
    border-color: transparent;
    border-radius: var(--gb-radius-xl);
    box-shadow: var(--gb-shadow-md);
}

@media (forced-colors: active) {
    .card,
    .tile,
    .recruitment-card {
        border-color: CanvasText;
    }
}

/* Hovering a card that is itself a link lifts it, the same step
   `.gb-card--link` takes. Scoped to anchors so a static card never moves. */
a.card:hover,
a.tile:hover,
a.recruitment-card:hover {
    border-color: var(--gb-primary);
    box-shadow: var(--gb-shadow-lg);
}

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

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

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

.tile__link {
    margin-top: auto;
    padding-top: var(--gb-space-2);
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-link);
}

/* `.gb-app` qualified so it outranks base.css's `.gb-app h2` (0,1,1) — a
   section title is a labelled component, not a generic heading. */
/* A card heading. It matches .gb-card__title exactly — 261 places use the
   legacy name, and a section that looks lighter than the identical section
   next to it is the clearest sign of two design systems in one product. */
.gb-app .section-title,
.gb-app .recruitment-card__head h2,
.gb-app .card > h2 {
    margin: 0 0 var(--gb-space-3);
    font-size: var(--gb-font-size-lg);
    font-weight: var(--gb-font-weight-bold);
    line-height: var(--gb-line-height-tight);
    color: var(--gb-text-primary);
}


/* ==========================================================================
   §5  Tables
   ==========================================================================
   Legacy `.data-table` defaulted to `text-align: left` and was only
   corrected inside `.rtl-page`. Every AdminPortal page now renders inside
   `<html dir="rtl">`, so alignment follows direction logically instead —
   which also stops a table from silently reverting to LTR alignment the
   moment a page forgets the `.rtl-page` wrapper. */

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

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

.data-table {
    border-radius: var(--gb-radius-lg);
}

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

.data-table a {
    color: var(--gb-text-link);
    font-weight: var(--gb-font-weight-medium);
}

/* Counts/dates read better end-aligned and never wrap mid-value. */
.data-table td .gb-numeric,
.data-table .table-numeric {
    font-feature-settings: "tnum" 1;
    white-space: nowrap;
}

/* A bare `.data-table` with more columns than the viewport used to push the
   whole page sideways. `.table-scroll` is the deliberate, opt-in responsive
   strategy: the table scrolls inside its own box, the page never does. */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
}

.table-scroll .data-table {
    margin: 0;
    border: 0;
    border-radius: 0;
}

/* Row action cells: keep the links on one line and visually grouped so the
   "what can I do with this row" column is scannable. The vertical padding is
   not cosmetic — a bare 22px-tall text link is not a usable touch target, and
   these are the links a user taps most often in the whole product. */
.data-table .row-actions {
    display: flex;
    align-items: center;
    gap: var(--gb-space-3);
    flex-wrap: wrap;
    white-space: nowrap;
}

.data-table .row-actions > a {
    display: inline-flex;
    align-items: center;
    min-height: 2rem;
    padding-block: var(--gb-space-1);
}

@media (pointer: coarse) {
    .data-table .row-actions > a {
        min-height: 2.75rem;
    }
}


/* ==========================================================================
   §6  Empty states
   ==========================================================================
   `.data-table__empty` was a bare grey line of text, which reads as a
   broken page rather than "nothing here yet". Given the same treatment as
   `.gb-empty-state` so both spellings look identical. */

.data-table__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--gb-space-2);
    padding: var(--gb-space-10) var(--gb-space-6);
    text-align: center;
    color: var(--gb-text-secondary);
    font-size: var(--gb-font-size-sm);
}

.data-table__empty strong {
    font-size: var(--gb-font-size-md);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-primary);
}

.data-table__empty .button {
    margin-top: var(--gb-space-2);
}


/* ==========================================================================
   §7  Badges — one status vocabulary across both class families
   ==========================================================================
   Legacy `.badge--active` / `.badge--inactive` / `.badge--workflow-*`
   hard-coded their own light-only hex values, so Recruitment and HR statuses
   drifted from `.gb-badge--*` and stayed light in dark mode. Remapped onto
   the same semantic tokens, and given the border + weight `.gb-badge` uses
   so status never depends on hue alone (the text label is always present in
   the markup). */

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--gb-space-1);
    padding: var(--gb-space-1) var(--gb-space-3);
    border: 1px solid transparent;
    border-radius: var(--gb-radius-full);
    font-size: var(--gb-font-size-xs);
    font-weight: var(--gb-font-weight-semibold);
    line-height: var(--gb-line-height-tight);
    white-space: nowrap;
}

/* A `.badge` with no modifier (e.g. the Job Opening detail header) used to
   render as invisible unstyled text. Neutral is the honest default. */
.badge,
.badge--inactive,
.badge--neutral {
    background: var(--gb-gray-200);
    color: var(--gb-text-secondary);
    border-color: var(--gb-border);
}

.badge--active,
.badge--success {
    background: var(--gb-success-subtle);
    color: var(--gb-success);
    border-color: var(--gb-success-subtle-border);
}

.badge--workflow-pending,
.badge--pending,
.badge--warning {
    background: var(--gb-warning-subtle);
    color: var(--gb-warning);
    border-color: var(--gb-warning-subtle-border);
}

.badge--workflow-rejected,
.badge--danger {
    background: var(--gb-danger-subtle);
    color: var(--gb-text-danger);
    border-color: var(--gb-danger-subtle-border);
}

.badge--info,
.badge--primary {
    background: var(--gb-info-subtle);
    color: var(--gb-info);
    border-color: var(--gb-info-subtle-border);
}

/* Dark surfaces need a lighter neutral chip than `--gb-gray-200`, but the
   `:not()` guard matters: `[data-theme="dark"] .badge` is (0,2,0) and would
   otherwise outrank every `.badge--active` / `--workflow-pending` /
   `--workflow-rejected` (0,1,0), flattening all status colors to grey in dark
   mode — the exact opposite of what a status badge is for. */
[data-theme="dark"] .badge:not([class*="badge--"]),
[data-theme="dark"] .badge--inactive,
[data-theme="dark"] .badge--neutral {
    background: var(--gb-surface-alt);
}


/* ==========================================================================
   §8  Alerts
   ========================================================================== */

.alert {
    display: flex;
    gap: var(--gb-space-3);
    padding: var(--gb-space-3) var(--gb-space-4);
    border-radius: var(--gb-radius-md);
    font-size: var(--gb-font-size-sm);
    line-height: var(--gb-line-height-normal);
}

.alert--success {
    background: var(--gb-success-subtle);
    border: 1px solid var(--gb-success-subtle-border);
    color: var(--gb-success);
}

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


/* ==========================================================================
   §9  Page headers, breadcrumbs, sections
   ==========================================================================
   `.page-header` predates the app shell, which now renders the page title
   and a `PageActions` slot itself. Pages that still use `.page-header` keep
   working; it is only re-spaced so a page never shows two competing title
   blocks with different type scales. */

.gb-app .page-header h1 {
    font-size: var(--gb-font-size-2xl);
    font-weight: var(--gb-font-weight-semibold);
    line-height: var(--gb-line-height-tight);
}

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

/* `.rtl-page .page-header { flex-direction: row-reverse }` (site.css) was
   written when the document itself was LTR. The document is RTL now, so
   row-reverse pushes the primary action to the *wrong* edge — back to
   normal flow, which already lays out correctly under `dir="rtl"`. */
.rtl-page .page-header {
    flex-direction: row;
}

.breadcrumb {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-secondary);
    margin-bottom: var(--gb-space-3);
}

.breadcrumb a {
    color: var(--gb-text-secondary);
    text-decoration: none;
}

.breadcrumb a:hover {
    color: var(--gb-text-link);
    text-decoration: underline;
}


/* ==========================================================================
   §10  Forms
   ========================================================================== */

.form-field label {
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-medium);
    color: var(--gb-text-primary);
}

.form-field input,
.form-field select,
.form-field textarea {
    min-height: 2.5rem;
    padding: var(--gb-space-2) var(--gb-space-3);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    color: var(--gb-text-primary);
    font-size: var(--gb-font-size-sm);
    transition: border-color var(--gb-duration-fast) var(--gb-ease-standard);
}

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

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
    outline: none;
    border-color: var(--gb-focus-ring-color);
    box-shadow: var(--gb-shadow-focus);
}

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

/* Marks a required field without relying on the developer remembering to
   type an asterisk into the label text. */
.form-field label .required-mark,
.required-mark {
    color: var(--gb-text-danger);
    margin-inline-start: var(--gb-space-1);
    font-weight: var(--gb-font-weight-bold);
}

.form-hint {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-tertiary);
    line-height: var(--gb-line-height-normal);
}

.field-error {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-danger);
}

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

.form-actions {
    flex-wrap: wrap;
    align-items: center;
}

/* Separates the commit/cancel row from the fields above it so "Save" is
   never mistaken for just another field. */
.form-actions--footer {
    margin-top: var(--gb-space-5);
    padding-top: var(--gb-space-4);
    border-top: 1px solid var(--gb-border-subtle);
}


/* ==========================================================================
   §11  Auth card (login)
   ========================================================================== */

.auth-card {
    border-radius: var(--gb-radius-lg);
    box-shadow: var(--gb-shadow-md);
    max-width: 24rem;
}

.auth-card__title {
    font-size: var(--gb-font-size-xl);
    font-weight: var(--gb-font-weight-semibold);
}

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


/* ==========================================================================
   §12  Timelines / pipeline board / org tree
   ========================================================================== */

.workflow-timeline__item,
.timeline__item {
    border-radius: var(--gb-radius-md);
}

.timeline__item {
    border-inline-start-width: 3px;
    border-inline-start-style: solid;
    border-inline-start-color: var(--gb-primary);
    border-block: 1px solid var(--gb-border-subtle);
    border-inline-end: 1px solid var(--gb-border-subtle);
}

.pipeline-board__list li {
    border-radius: var(--gb-radius-md);
}

/* `padding-left` on the org tree is physical: under RTL the indentation
   landed on the wrong side and every nesting level lost its visual step. */
.org-tree,
.org-tree ul {
    padding-left: 0;
    padding-inline-start: var(--gb-space-4);
}

.org-tree {
    padding-inline-start: 0;
}

.org-tree__node-button {
    text-align: start;
}


/* ==========================================================================
   §13  Pagination
   ========================================================================== */

.pagination {
    flex-wrap: wrap;
    gap: var(--gb-space-2);
    font-size: var(--gb-font-size-sm);
}

.pagination a,
.pagination__page {
    display: inline-flex;
    align-items: center;
    min-height: 2.25rem;
    padding: var(--gb-space-1) var(--gb-space-3);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    color: var(--gb-text-link);
}

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


/* ==========================================================================
   §14  Responsive — the 390px floor
   ==========================================================================
   Requirement: no accidental horizontal page overflow at 390px, and no
   "shrink the text until it fits". Layouts collapse to one column and
   wide data moves into its own scroll container instead. */

@media (max-width: 640px) {
    .page-header {
        flex-direction: column;
        align-items: stretch;
    }

    /* A page header's action is the primary action on that screen — give it
       the full width it now has to earn, rather than a cramped tap target. */
    .page-header > .button,
    .page-header > gb-permission > .button {
        width: 100%;
    }

    .tile-grid {
        grid-template-columns: 1fr;
    }

    .form-grid {
        max-width: none;
    }

    .form-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .form-actions .button {
        width: 100%;
    }

    /* Any table that hasn't been wrapped in `.table-scroll` yet still must
       not push the page sideways. */
    .data-table {
        display: block;
        overflow-x: auto;
    }

    .table-scroll .data-table {
        display: table;
    }

    .rtl-page dl {
        grid-template-columns: 1fr;
        gap: var(--gb-space-1) 0;
    }

    .rtl-page dd {
        margin-bottom: var(--gb-space-3);
    }
}


/* ==========================================================================
   §15  Public careers site (_PublicLayout.cshtml)
   ==========================================================================
   The outward-facing /jobs and /apply pages. Deliberately a small, contained
   block rather than a second shell: same tokens, same components, just a
   simple header/main/footer for people who are not ERP users. */

.gb-public {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* The public layout does not load shell/app-shell.css, which is where the «skip to main content» link is parked above the
   viewport until it is focused. Without these two rules (the same declarations, repeated here) the link sat at the top of
   every public page as a plain underlined line of text — the one page a customer reaches from a QR code included. */
.gb-shell__skip-link {
    position: fixed;
    inset-block-start: var(--gb-space-2);
    inset-inline-start: var(--gb-space-2);
    z-index: calc(var(--gb-z-toast) + 1);
    padding: var(--gb-space-2) var(--gb-space-4);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    color: var(--gb-text-link);
    box-shadow: var(--gb-shadow-focus), var(--gb-shadow-md);
    transform: translateY(-200%);
}

.gb-shell__skip-link:focus {
    transform: translateY(0);
}

.gb-public__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--gb-space-3);
    padding: var(--gb-space-4) var(--gb-space-6);
    background: var(--gb-surface);
    border-bottom: 1px solid var(--gb-border);
}

.gb-public__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--gb-space-3);
    text-decoration: none;
    color: var(--gb-text-primary);
}

/* Same change as `.gb-shell__logo-mark` in app-shell.css: the real logo
   image replaced a `GB` text tile, so the coloured ground and radius are
   gone and the mark keeps its own aspect ratio. */
.gb-public__brand-mark {
    display: block;
    width: auto;
    height: 2.25rem;
    flex-shrink: 0;
}

.gb-public__brand-text {
    display: flex;
    flex-direction: column;
    line-height: var(--gb-line-height-tight);
}

.gb-public__brand-text small {
    color: var(--gb-text-secondary);
    font-size: var(--gb-font-size-xs);
}

.gb-public__nav {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--gb-space-4);
    font-size: var(--gb-font-size-sm);
}

/* The authenticity page (/Verify/Product) is written in three languages and puts a language switch in this nav; the
   language it is currently in is marked with aria-current, so it needs no class of its own. */
.gb-public__nav a[aria-current="true"] {
    color: var(--gb-text-primary);
    font-weight: 700;
}

.gb-public__main {
    flex: 1;
    width: 100%;
    max-width: 68rem;
    margin-inline: auto;
    padding: var(--gb-space-8) var(--gb-space-6);
}

.gb-public__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--gb-space-2);
    padding: var(--gb-space-4) var(--gb-space-6);
    border-top: 1px solid var(--gb-border);
    background: var(--gb-surface);
    color: var(--gb-text-tertiary);
    font-size: var(--gb-font-size-xs);
}

@media (max-width: 640px) {
    .gb-public__header,
    .gb-public__main,
    .gb-public__footer {
        padding-inline: var(--gb-space-4);
    }

    .gb-public__main {
        padding-block: var(--gb-space-6);
    }
}


/* ==========================================================================
   §16  Public application form (/apply)
   ==========================================================================
   A two-column field grid that collapses to one column below the tablet
   breakpoint. Fields that hold free text (skills, resume, notes) span the
   full width because a half-width box misrepresents how much is expected. */

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

.apply-fields .form-field {
    min-width: 0;
}

.apply-fields__full {
    grid-column: 1 / -1;
}

@media (max-width: 640px) {
    .apply-fields {
        grid-template-columns: 1fr;
    }
}


/* ==========================================================================
   §17  Approval decision forms (/workflow/approvals)
   ==========================================================================
   A reason field plus its button. Previously these were `.form-grid` with
   four inline style overrides each; one named class replaces them and keeps
   the field and its action on the same line until there is no room. */

.approval-decision {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: var(--gb-space-3);
}

.approval-decision .form-field {
    flex: 1 1 18rem;
    min-width: 0;
}

@media (max-width: 640px) {
    .approval-decision {
        align-items: stretch;
    }

    .approval-decision .button {
        width: 100%;
    }
}


/* ==========================================================================
   §18  Inline list filters
   ==========================================================================
   Replaces the `class="form-grid" style="max-width:none; flex-direction:row;
   align-items:end; gap:1rem"` pattern that had been copy-pasted onto every
   list page's search form. Same layout, one name, and it now collapses
   properly instead of squeezing the input at 390px. */

/* These do the same job as .gb-listpage__filters and now look like it:
   a filter bar should read as one object on every list page in the portal,
   not as a bare row here and a panel there. Values copied from the pattern
   so the two cannot drift. */
.employee-filter,
.recruitment-filter {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: var(--gb-space-4);
    padding: var(--gb-space-4);
    border-radius: var(--gb-radius-xl);
    background: var(--gb-surface);
    box-shadow: var(--gb-shadow-sm);
}

/* ...except where the page already wrapped the form in a card. Five of the
   nine do. A panel inside a panel reads as a mistake, so inside a card the
   bar goes back to being a plain row. :where() keeps the specificity equal
   to the rule above, so source order decides and neither needs !important. */
:where(.card, .gb-card, .recruitment-card, .tile) .employee-filter,
:where(.card, .gb-card, .recruitment-card, .tile) .recruitment-filter {
    padding: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
}

.employee-filter .form-field {
    flex: 1 1 18rem;
    min-width: 0;
}

@media (max-width: 640px) {
    .employee-filter,
    .recruitment-filter {
        align-items: stretch;
    }

    .employee-filter .form-field,
    .recruitment-filter .form-field {
        flex: 1 1 100%;
    }
}


/* ==========================================================================
   §19  Inline "end employment" row form
   ==========================================================================
   A date input and its button inside a table cell. Replaces an inline
   `style="display:inline-flex;gap:.5rem;align-items:center"`; wraps instead
   of forcing the row wider on a narrow screen. */

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

.employment-end-form input[type="date"] {
    min-height: 2.25rem;
    padding: var(--gb-space-1) var(--gb-space-2);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    color: var(--gb-text-primary);
    font-size: var(--gb-font-size-sm);
}


/* ==========================================================================
   §20  Public application wizard (/apply)
   ==========================================================================
   Layout only — every colour, radius, spacing and font value below reads a
   design-system token, so the wizard inherits both themes with no extra
   work. The step indicator itself is .gb-trail (patterns.css §4), not a new
   component.

   min-width: 0 appears on every flex/grid child that can hold long text:
   without it a wide value (a file name, a long institution) forces a
   page-level horizontal scrollbar at 390px even though the element itself
   would wrap. */

.apply-wizard__header {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-5);
}

.apply-wizard__headline {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gb-space-4);
    min-width: 0;
}

.apply-wizard__headline > div {
    min-width: 0;
}

.apply-wizard__status {
    display: flex;
    align-items: center;
    gap: var(--gb-space-4);
    flex-wrap: wrap;
}

.apply-wizard__progress {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--gb-space-2) var(--gb-space-4);
    border: 1px solid var(--gb-primary-subtle-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-primary-subtle);
    color: var(--gb-text-primary);
    white-space: nowrap;
}

.apply-wizard__progress strong {
    font-size: var(--gb-font-size-lg);
    font-weight: var(--gb-font-weight-bold);
}

.apply-wizard__progress span {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-secondary);
}

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

.apply-wizard__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gb-space-3);
}

.apply-wizard__footnote {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--gb-space-3);
    margin-top: var(--gb-space-4);
}

/* One repeatable record (an education entry, a past job, a skill). */
.apply-row {
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    padding: var(--gb-space-4);
    margin: 0;
    min-width: 0;
}

.apply-row legend {
    padding: 0 var(--gb-space-2);
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-semibold);
    color: var(--gb-text-secondary);
}

/* "I have no work experience" / "no university education" / consent. */
.apply-optout,
.apply-inline-check {
    display: flex;
    align-items: flex-start;
    gap: var(--gb-space-2);
    cursor: pointer;
    min-width: 0;
}

.apply-optout input,
.apply-inline-check input {
    margin-top: 0.2rem;
    flex: none;
}

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

.apply-upload {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-2);
    border: 1px dashed var(--gb-border-strong);
    border-radius: var(--gb-radius-md);
    padding: var(--gb-space-4);
    background: var(--gb-surface-alt);
    min-width: 0;
}

.apply-upload__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gb-space-2);
    flex-wrap: wrap;
}

.apply-upload__file,
.apply-upload__control {
    display: flex;
    align-items: center;
    gap: var(--gb-space-2);
    flex-wrap: wrap;
    min-width: 0;
}

/* A long file name must wrap inside its card, never widen the page. */
.apply-upload__file > span {
    min-width: 0;
    overflow-wrap: anywhere;
}

.apply-upload input[type="file"] {
    min-width: 0;
    max-width: 100%;
    font-size: var(--gb-font-size-sm);
}

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

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

.apply-summary > div {
    min-width: 0;
}

.apply-summary dt {
    font-size: var(--gb-font-size-xs);
    color: var(--gb-text-secondary);
}

.apply-summary dd {
    margin: 0;
    font-size: var(--gb-font-size-sm);
    color: var(--gb-text-primary);
    overflow-wrap: anywhere;
}

.apply-review__list,
.apply-missing {
    margin: 0;
    padding-inline-start: var(--gb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-2);
    font-size: var(--gb-font-size-sm);
}

.apply-review-photo {
    display: flex;
    align-items: center;
    gap: var(--gb-space-4);
}

.apply-review-photo img {
    width: 7rem;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    border-radius: var(--gb-radius-md);
    border: 1px solid var(--gb-border);
    background: var(--gb-surface-alt);
}

.apply-review-photo > div,
.apply-document-preview__info {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gb-space-2);
    min-width: 0;
}

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

.apply-document-preview-panel {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-4);
    padding: var(--gb-space-4);
    border: 2px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface-alt);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gb-primary) 8%, transparent);
}

.apply-document-preview-panel__head {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-1);
    padding-bottom: var(--gb-space-3);
    border-bottom: 1px solid var(--gb-border);
}

.apply-document-preview {
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
    box-shadow: var(--gb-shadow-sm);
}

.apply-document-preview__media {
    position: relative;
    width: 100%;
    height: 18rem;
    overflow: hidden;
    background: #eef1f4;
    border-bottom: 1px solid var(--gb-border);
}

.apply-document-preview__media img,
.apply-document-preview__media object {
    display: block;
    position: absolute;
    inset: var(--gb-space-3);
    width: calc(100% - (2 * var(--gb-space-3)));
    height: calc(100% - (2 * var(--gb-space-3)));
    max-width: none;
    max-height: none;
    object-fit: contain;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-sm);
    background: #fff;
}

.apply-document-preview__media object {
    overflow: hidden;
}

/* Candidate workspace: resume context and recruitment actions are visually
   separate, while remaining on one operational page for HR. */
.candidate-hero {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    overflow: hidden;
    border: 0;
    /* This band was #fff on an amber gradient — about 2.1:1. Switching the
       ink to the charcoal --gb-on-primary fixed the light end (5.36:1) but
       not the dark one: the gradient ran to --gb-primary-active, where the
       same charcoal measures only 3.09:1. No single ink passes across that
       lightness range, so the gradient is what had to go.

       Flat --gb-primary now, which reads 5.36:1 everywhere on the band and
       matches how every other amber surface in the system is painted. */
    color: var(--gb-on-primary);
    background: var(--gb-primary);
    box-shadow: var(--gb-shadow-md);
}

.candidate-hero::after {
    content: "";
    position: absolute;
    inset-inline-end: -5rem;
    inset-block-start: -7rem;
    width: 16rem;
    height: 16rem;
    border-radius: 50%;
    background: rgb(255 255 255 / 8%);
    pointer-events: none;
}

.candidate-hero .gb-entity__main,
.candidate-hero__avatar,
.candidate-hero__summary {
    position: relative;
    z-index: 1;
}

/* White here measures 2.15:1 on the amber band -- the very failure the note
   on .candidate-hero above says was fixed. It WAS fixed, on the parent; these
   descendant rules exist because .gb-entity__name and .gb-text-secondary carry
   their own colour, and they quietly put the white back for the candidate's
   name, their facts and the secondary line. The band's ink is charcoal:
   --gb-on-primary, 7.56:1 on the same amber. */
.candidate-hero .gb-entity__name,
.candidate-hero .gb-entity__fact strong,
.candidate-hero .gb-text-secondary {
    color: var(--gb-on-primary);
}

/* Translucent white is worse than opaque, not better: at 78% over amber it
   lands near 1.9:1. Secondary rank comes from size and weight here, not from
   fading the ink past the point of being readable. */
.candidate-hero .gb-text-secondary,
.candidate-hero .gb-entity__facts {
    color: var(--gb-on-primary);
}

.candidate-hero__avatar {
    display: grid;
    place-items: center;
    width: 5rem;
    height: 5rem;
    border: 2px solid rgb(255 255 255 / 55%);
    border-radius: 50%;
    background: rgb(255 255 255 / 16%);
    font-size: var(--gb-font-size-xl);
    font-weight: var(--gb-font-weight-bold);
    overflow: hidden;
}

.candidate-hero__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.candidate-hero__summary {
    display: grid;
    grid-template-columns: repeat(3, minmax(6rem, 1fr));
    gap: 1px;
    overflow: hidden;
    border: 1px solid rgb(255 255 255 / 24%);
    border-radius: var(--gb-radius-md);
    background: rgb(255 255 255 / 20%);
}

.candidate-hero__summary > div {
    display: flex;
    flex-direction: column;
    gap: var(--gb-space-1);
    padding: var(--gb-space-3);
    background: rgb(0 0 0 / 12%);
    text-align: center;
}

.candidate-hero__summary span {
    color: var(--gb-on-primary);
    font-size: var(--gb-font-size-xs);
}

.candidate-hero__summary strong { color: var(--gb-on-primary); }

.candidate-workspace .recruitment-card {
    border-radius: var(--gb-radius-lg);
    box-shadow: var(--gb-shadow-sm);
}

.candidate-workspace .recruitment-card__head {
    padding-bottom: var(--gb-space-3);
    border-bottom: 1px solid var(--gb-border);
}

.candidate-profile-rail {
    padding: var(--gb-space-3);
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface-alt);
}

.candidate-profile-rail > .recruitment-card {
    box-shadow: none;
    background: var(--gb-surface);
}

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

.candidate-attachment {
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--gb-border);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface);
}

.candidate-attachment__preview {
    display: grid;
    place-items: center;
    height: 9rem;
    padding: var(--gb-space-2);
    overflow: hidden;
    border-bottom: 1px solid var(--gb-border);
    background: var(--gb-surface-alt);
    color: var(--gb-text-tertiary);
    font-weight: var(--gb-font-weight-bold);
}

.candidate-attachment__preview img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.candidate-attachment__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gb-space-2);
    padding: var(--gb-space-3);
}

.candidate-information-card {
    border-inline-start: 4px solid var(--gb-primary);
}

.candidate-information-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gb-space-3);
}

.candidate-information-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    padding: var(--gb-space-4);
    border-radius: var(--gb-radius-md);
    background: var(--gb-surface-alt);
}

.candidate-information-grid__wide { grid-column: span 2; }

.gb-trail__actor {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gb-space-1);
    margin-top: var(--gb-space-1);
    padding: var(--gb-space-2);
    border-radius: var(--gb-radius-sm);
    background: var(--gb-surface-alt);
    color: var(--gb-text-secondary);
    font-size: var(--gb-font-size-xs);
}

.gb-trail__actor strong { color: var(--gb-text-primary); }
.gb-trail__actor small { color: var(--gb-text-tertiary); }

.gb-persian-time-control {
    position: relative;
    display: block;
    width: 100%;
}

.gb-persian-time-control > .gb-input {
    width: 100%;
    padding-inline-end: 3rem;
}

.gb-persian-time-control__button {
    position: absolute;
    inset-inline-end: .35rem;
    inset-block: .35rem;
    display: grid;
    place-items: center;
    width: 2.15rem;
    padding: 0;
    border: 0;
    border-inline-start: 1px solid var(--gb-border);
    background: transparent;
    color: var(--gb-primary);
    font-size: 1.35rem;
    cursor: pointer;
}

.gb-persian-time-control__button:hover { background: var(--gb-surface-alt); }
.gb-persian-time-control__button:focus-visible { outline: 2px solid var(--gb-focus); }

.gb-persian-time-picker {
    position: absolute;
    z-index: 30;
    inset-inline-end: 0;
    inset-block-start: calc(100% + var(--gb-space-2));
    width: min(19rem, 92vw);
    padding: var(--gb-space-4);
    border: 1px solid var(--gb-border-strong);
    border-radius: var(--gb-radius-lg);
    background: var(--gb-surface);
    box-shadow: var(--gb-shadow-lg);
    direction: rtl;
}

.gb-persian-time-picker[hidden] { display: none; }

.gb-persian-time-picker__title {
    margin-bottom: var(--gb-space-3);
    color: var(--gb-text-primary);
    font-weight: var(--gb-font-weight-semibold);
}

/* The labels sit over the two selects, so they must be laid out exactly like
   them: same three columns (the ":" between hour and minute is a column of its
   own) and the same direction. The selects are forced LTR because a time reads
   left to right; without the same override here the labels inherited the page's
   RTL and swapped, so «ساعت» sat above the minutes and «دقیقه» above the hours
   — reported from the factory on the interview-time form. */
.gb-persian-time-picker__labels {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: var(--gb-space-2);
    margin-bottom: var(--gb-space-1);
    color: var(--gb-text-secondary);
    font-size: var(--gb-font-size-xs);
    text-align: center;
    direction: ltr;
}

.gb-persian-time-picker__selects {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--gb-space-2);
    direction: ltr;
}

.gb-persian-time-picker__selects .gb-select {
    text-align: center;
    font-size: var(--gb-font-size-lg);
}

.gb-persian-time-picker__actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--gb-space-2);
    margin-top: var(--gb-space-4);
    padding-top: var(--gb-space-3);
    border-top: 1px solid var(--gb-border);
}

@media (max-width: 70rem) {
    .candidate-information-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 40rem) {
    .candidate-information-grid { grid-template-columns: 1fr; }
    .candidate-information-grid__wide { grid-column: auto; }
}

@media (min-width: 62rem) {
    .candidate-workspace.gb-workspace--rail {
        grid-template-columns: minmax(0, 1fr) minmax(23rem, 29rem);
    }

    .candidate-workspace.gb-workspace--rail > .gb-workspace__rail {
        position: static;
    }
}

@media (max-width: 61.99rem) {
    .candidate-hero {
        grid-template-columns: auto minmax(0, 1fr);
    }

    .candidate-hero__summary {
        grid-column: 1 / -1;
        width: 100%;
    }
}

@media (max-width: 40rem) {
    .candidate-hero {
        grid-template-columns: 1fr;
        text-align: center;
    }

    .candidate-hero__avatar { margin-inline: auto; }
    .candidate-hero .gb-entity__identity,
    .candidate-hero .gb-entity__facts { justify-content: center; }
    .candidate-hero__summary { grid-template-columns: 1fr; }
}

.apply-document-preview__icon {
    font-weight: var(--gb-font-weight-bold);
    color: var(--gb-text-secondary);
}

.apply-document-preview__info {
    padding: var(--gb-space-3);
}

/* Honeypot. Positioned off-screen rather than display:none — some bots skip
   hidden fields, which would defeat the point of having one. Offset
   vertically, not horizontally: a horizontal offset lands off the RIGHT edge
   under RTL and can widen the page, which is exactly what the 390px
   no-horizontal-overflow rule forbids. */
.gb-honeypot {
    position: absolute;
    top: -9999px;
    inset-inline-start: 0;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media (max-width: 640px) {
    .apply-wizard__headline,
    .apply-wizard__footnote {
        flex-direction: column;
        align-items: stretch;
    }

    .apply-wizard__actions .gb-btn {
        flex: 1 1 100%;
    }

    .apply-uploads,
    .apply-summary {
        grid-template-columns: 1fr;
    }

    .apply-document-preview__media {
        height: 15rem;
    }
}

/* Numbered section heads. The wizard's steps already carry numbers in the
   trail; inside a step, these give the eye an anchor per group so a long
   form reads as four short ones rather than one continuous field dump. */

.apply-section__head {
    display: flex;
    align-items: flex-start;
    gap: var(--gb-space-3);
    min-width: 0;
}

.apply-section__head > div {
    min-width: 0;
}

.apply-section__index {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--gb-radius-full);
    background: var(--gb-primary-subtle);
    border: 1px solid var(--gb-primary-subtle-border);
    color: var(--gb-text-primary);
    font-size: var(--gb-font-size-sm);
    font-weight: var(--gb-font-weight-bold);
    line-height: 1;
}

/* The read-only opening summary sits inside an editable section, so it needs
   to read as reference material rather than as more fields to fill in. */
.apply-summary--inset {
    background: var(--gb-surface-alt);
    border: 1px solid var(--gb-border-subtle);
    border-radius: var(--gb-radius-md);
    padding: var(--gb-space-4);
}

/* `.button--sm` is written on 14 screens across PhysicalSecurity — row actions
   inside dense tables, where a 2.5rem button is too tall — and was never
   defined anywhere. Every one of them has been rendering at full height since
   the day it was written; nothing in the build can catch a class that simply
   does not exist. Matched to `.gb-btn--sm`, its counterpart in the current
   vocabulary, so the two families size identically. */
.button--sm {
    min-height: 36px;
    padding-block: 0;
    padding-inline: 14px;
    font-size: var(--gb-font-size-md);
}
