/* Global site styles — shared across pages/components. Component-specific layout
   lives in each component's own .razor.css (CSS isolation). Tokens: tokens.css. */

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    font-family: var(--font-body);
    color: var(--color-text);
    background: var(--color-bg);
}

/* The off-canvas drawers (.filter-rail, .candidate-filter-rail, .admin-sidebar,
   .dash-sidebar mobile) sit at position:fixed + transform:translateX(-100%) when closed.
   Chrome still counts that off-screen box toward the document's scrollable width, so
   without this the whole page gets a few hundred px of phantom horizontal scroll on
   every load — the drawer never has to open for it to happen. */
html {
    overflow-x: hidden;
}

/* Lock page scroll behind the admin mobile nav drawer while it's open (native :has(),
   no JS) — #admin-nav-toggle lives inside AdminLayout, so this can't be a scoped rule
   in AdminLayout.razor.css (the isolation attribute never lands on <body>). */
body:has(#admin-nav-toggle:checked) {
    overflow: hidden;
}

/* Same idea for the /jobs mobile filter drawer (#filter-drawer-toggle lives in Jobs.razor) —
   lock page scroll behind it while it's open. */
body:has(#filter-drawer-toggle:checked) {
    overflow: hidden;
}

/* Restore the sidebar's collapsed width on page load, before admin.js gets a chance to
   re-check the collapse checkbox — avoids a flash of the expanded sidebar on every
   full-page navigation (static SSR, so this runs fresh per request). Each layout's own
   inline <script> sets this class on <html> as early as possible from localStorage.
   Shared by AdminLayout, JobSeekerLayout and RecruiterLayout — only one of .admin-sidebar
   / .dash-sidebar is ever on the page at once, so one html class covers all three. This
   has to live here rather than in AdminLayout.razor.css: Blazor CSS isolation only
   supports ::deep, not a :global() escape hatch, and <html> is outside that component's
   scope attribute anyway. */
@media (min-width: 960px) {
    html.sidebar-pref-collapsed .admin-sidebar {
        width: 64px;
    }

    html.sidebar-pref-collapsed .admin-sidebar .admin-nav-link__label,
    html.sidebar-pref-collapsed .admin-sidebar .admin-sidebar__profile-text,
    html.sidebar-pref-collapsed .admin-sidebar .admin-nav-link--sub,
    html.sidebar-pref-collapsed .admin-sidebar .admin-nav-link--parent .icon:last-child {
        display: none;
    }

    html.sidebar-pref-collapsed .admin-sidebar .admin-sidebar__group-label {
        height: var(--space-3);
        margin: var(--space-2) 0 0;
        padding: 0;
        overflow: hidden;
    }

    html.sidebar-pref-collapsed .admin-sidebar .admin-nav-link,
    html.sidebar-pref-collapsed .admin-sidebar .admin-sidebar__brand,
    html.sidebar-pref-collapsed .admin-sidebar .admin-sidebar__collapse-btn {
        justify-content: center;
    }

    html.sidebar-pref-collapsed .admin-sidebar__collapse-btn .icon {
        transform: rotate(-90deg);
    }

    html.sidebar-pref-collapsed .dash-sidebar {
        width: 64px;
    }

    html.sidebar-pref-collapsed .dash-sidebar .dash-nav-link span,
    html.sidebar-pref-collapsed .dash-sidebar .dash-sidebar__profile-text,
    html.sidebar-pref-collapsed .dash-sidebar .dash-sidebar__collapse-btn span {
        display: none;
    }

    html.sidebar-pref-collapsed .dash-sidebar .dash-nav-link,
    html.sidebar-pref-collapsed .dash-sidebar .dash-sidebar__brand,
    html.sidebar-pref-collapsed .dash-sidebar .dash-sidebar__collapse-btn {
        justify-content: center;
    }

    html.sidebar-pref-collapsed .dash-sidebar__collapse-btn .icon {
        transform: rotate(-90deg);
    }
}

/* Hide the scrollbar on mobile widths — scrolling still works, just no visible
   track/thumb. Desktop keeps its native scrollbar. */
@media (max-width: 767px) {
    html {
        scrollbar-width: none;       /* Firefox */
        -ms-overflow-style: none;    /* legacy Edge/IE */
    }

    html::-webkit-scrollbar {        /* Chrome/Safari/new Edge */
        display: none;
    }
}

h1, h2, h3, h4 {
    font-family: var(--font-display);
    line-height: 1.2;
    margin: 0 0 var(--space-3);
}

p {
    margin: 0 0 var(--space-3);
    color: var(--color-text-muted);
}

a {
    color: var(--color-interactive);
}

:focus-visible {
    outline: 3px solid var(--color-accent);
    outline-offset: 2px;
}

/* Blazor's <FocusOnNavigate Selector="h1"> focuses the page heading after each navigation (for screen
   readers); a heading isn't interactive, so it shouldn't draw the keyboard focus ring. */
h1:focus-visible {
    outline: none;
}

.container {
    max-width: var(--content-max-width);
    margin: 0 auto;
    padding: 0 var(--space-5);
}

/* Accessible hide — used for <label for>-only text and the view-toggle's radio
   inputs. Was missing (labels were rendering visibly); adding it since the new
   card-size toggle depends on it working correctly. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Buttons */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--fs-sm);
    text-decoration: none;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, transform 80ms ease;
}

.btn:active {
    transform: translateY(1px);
}

.btn--primary {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
}

.btn--primary:hover {
    background: var(--color-primary-dark);
}

.btn--accent {
    background: var(--color-accent);
    color: #22200f;
}

.btn--accent:hover {
    background: var(--color-accent-dark);
}

:root[data-theme="light"] .btn--accent {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
}

:root[data-theme="light"] .btn--accent:hover {
    background: var(--color-primary-dark);
}

.btn--outline {
    background: transparent;
    border-color: var(--color-border);
    color: var(--color-text);
}

.btn--outline:hover {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

/* Chips & badges — job cards use these (docs/01 §7) */
.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--color-chip-bg);
    color: var(--color-chip-text);
    font-size: var(--fs-xs);
    font-weight: 600;
    white-space: nowrap;
}

/* Small icon-style badge for the source platform (CareerJunction/Indeed/PNet) —
   first letter only, full name in the title tooltip + aria-label. */
.badge-source {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--color-badge-source);
    color: var(--color-badge-source-text);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
}

/* Job card */
.job-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 120ms ease, transform 120ms ease, border-color 120ms ease;
}

.job-card:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--color-interactive);
    transform: translateY(-2px);
}

.job-card__cta {
    font-weight: 600;
    color: var(--color-interactive);
}

.job-card__top {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
}

.job-card__heading {
    flex: 1;
    min-width: 0;
}

/* Company logo — an <img> when Job.LogoUrl is set, otherwise a coloured
   initials fallback (CompanyAvatar.cs) rendered as a same-sized <span>. */
.job-card__logo {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    object-fit: cover;
}

.job-card__logo--fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-weight: 700;
    font-size: var(--fs-sm);
}

.job-card__title {
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    font-weight: 600;
    margin: 0 0 var(--space-1);
}

.job-card__company {
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
    margin: 0;
}

.job-card__country-flag {
    border-radius: 2px;
    vertical-align: middle;
    margin-right: var(--space-1);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
}

.job-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: var(--space-3) 0;
}

/* Job.Salary is free text straight from the source feed, no length cap — a long one
   (seen: "£13.53 per hour. Generous Company Benefits, Training & Development") blew
   its chip, and with it the whole card, past the container's right edge since .chip
   is white-space: nowrap by design elsewhere. Truncate with an ellipsis here instead
   of loosening nowrap globally. */
.job-card__meta .chip {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.job-card__footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: auto;
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
}

.job-card--featured {
    background: var(--color-featured-bg);
    border-color: var(--color-featured-border);
    color: var(--color-featured-text);
}

.job-card--featured .job-card__company {
    color: var(--color-featured-text);
    opacity: 0.75;
}

.job-card__featured-badge {
    display: inline-flex;
    padding: var(--space-1) var(--space-2);
    margin-bottom: var(--space-2);
    border-radius: var(--radius-sm);
    background: var(--color-accent);
    color: #2b1608;
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Job detail page */
.breadcrumbs {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-5);
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
    overflow-x: auto;
    white-space: nowrap;
    scrollbar-width: none;
}

.breadcrumbs::-webkit-scrollbar {
    display: none;
}

.breadcrumbs a {
    color: var(--color-text-muted);
    text-decoration: none;
    flex-shrink: 0;
}

.breadcrumbs a:hover {
    color: var(--color-interactive);
}

/* The current page (last crumb) is the one most likely to be a long job title —
   let it ellipsis instead of forcing the whole bar to wrap onto a second line. */
.breadcrumbs [aria-current] {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 45vw;
}

/* No max-width here (there was one — 760px, left over from the old single-column
   design) — .job-layout now owns the page's real width and needs the full
   .container to lay out its two columns; .job-description keeps its own
   narrower measure for the prose text specifically. */
.job-detail__main {
    width: 100%;
}

/* A scraped/pasted job description can contain a long unbroken token (a raw URL, an email
   address, a run-on word with no spaces) that a normal line-break won't wrap — on a narrow phone
   that pushes the whole page wider than the viewport (owner report: content spilling out of its
   box, a right-side gap visible once zoomed out). overflow-wrap is inherited, so setting it once
   here covers every text descendant (title, company name, description body, details card) rather
   than chasing each one individually. */
.job-detail {
    overflow-wrap: anywhere;
}

.job-detail__header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}

/* Public company page banner — was uploaded/stored via the recruiter profile's cover-image
   form but never actually rendered anywhere; this is the first real display of it. */
.company-cover {
    display: block;
    width: 100%;
    max-height: 280px;
    object-fit: cover;
    border-radius: var(--radius-md);
    margin-bottom: var(--space-4);
}

.job-detail__logo {
    width: 56px;
    height: 56px;
    font-size: var(--fs-lg);
}

.job-detail__header h1 {
    margin-bottom: var(--space-1);
}

.job-detail__subtitle {
    color: var(--color-text-muted);
    margin: 0 0 var(--space-3);
}

/* Company website link — a small circular icon button (globe), same size/shape convention as
   .social-links in the footer, just recoloured for this page's light background instead of the
   footer's dark navy one. */
.company-social-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.company-website-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-pill);
    background: var(--color-bg-subtle);
    color: var(--color-interactive);
}

.company-website-link:hover {
    background: var(--color-primary-light);
}

.job-detail__posted {
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
    margin: 0;
}

.job-detail__description {
    margin: var(--space-6) 0;
}

/* CompanyDetail.razor's About text renders as one plain <p> — a multi-paragraph About (blank-line
   separated) would otherwise collapse to a single run-on line, since HTML ignores literal
   newlines by default. pre-line keeps the paragraph breaks without needing a server-side split
   into multiple <p> tags. */
.job-detail__description p {
    white-space: pre-line;
}

.job-detail__apply {
    margin-top: var(--space-5);
}

.job-detail__save {
    margin: var(--space-3) 0;
}

.job-detail__apply-section {
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid var(--color-border);
}

.job-detail__apply-section .auth-form {
    max-width: 480px;
    margin: var(--space-4) 0 0;
}

/* Sticky mobile "Apply" bar — docs/01 §7. Desktop already shows the Apply button in
   job-hero__actions/job-apply-card, so this only needs to exist below 768px. */
.job-detail__mobile-bar {
    display: none;
}

@media (max-width: 767px) {
    .job-detail__mobile-bar {
        display: block;
        position: fixed;
        inset-inline: 0;
        bottom: 0;
        padding: var(--space-3) var(--space-4);
        padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
        background: var(--color-surface);
        border-top: 1px solid var(--color-border);
        box-shadow: var(--shadow-md);
        z-index: 10;
    }

    .job-detail__mobile-bar .btn {
        width: 100%;
    }

    /* room so the sticky bar never covers the inline apply button/content */
    .job-detail__main {
        padding-bottom: var(--space-8);
    }
}

/* Job hero banner — the recruiter's own company cover image (RecruiterAccount.CoverR2Key,
   already used as-is on /company/{slug} via .company-cover) reused here as the job detail
   page's own cover. Same breakpoint-scaled height as .hero (Jobs.razor.css) rather than
   aspect-ratio — matches this codebase's existing responsive-banner convention. */
.job-detail-cover {
    display: block;
    width: 100%;
    height: 160px;
    object-fit: cover;
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-5);
}

@media (min-width: 640px) {
    .job-detail-cover {
        height: 220px;
    }
}

@media (min-width: 1024px) {
    .job-detail-cover {
        height: 300px;
    }
}

/* Job hero — title/company/meta grouped into one card-free header block, logo reuses
   .job-card__logo's own sizing/fallback rules, just bigger. Same column widths as
   .job-layout below it so job-hero__aside's ad sits flush above the sidebar cards. */
.job-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--space-6);
    align-items: start;
}

.job-hero__top {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    flex-wrap: wrap;
}

.job-hero__logo {
    width: 64px;
    height: 64px;
    font-size: var(--fs-xl);
}

.job-hero__title {
    margin: 0 0 var(--space-1);
    overflow-wrap: anywhere;
}

.job-hero__company {
    margin: 0 0 var(--space-3);
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--color-text);
}

.job-hero__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
}

.job-hero__meta li {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.job-hero__meta .icon {
    color: var(--color-interactive);
    flex-shrink: 0;
}

.job-hero__meta a {
    color: var(--color-text-muted);
    text-decoration: none;
}

.job-hero__meta a:hover {
    color: var(--color-interactive);
    text-decoration: underline;
}

.job-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-5);
}

@media (max-width: 600px) {
    .job-hero__actions .btn {
        flex: 1 1 auto;
        justify-content: center;
    }
}

/* Two-column layout: description/apply-form/similar-jobs on the left, a sticky
   quick-facts + apply card on the right. Collapses to one column ≤960px — the
   sidebar cards fall in as normal content, right after the Apply actions. */
.job-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--space-6);
    align-items: start;
    margin-top: var(--space-6);
}

.job-layout__aside {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    position: sticky;
    top: calc(var(--header-height) + var(--space-4));
}

.job-hero__aside {
    display: none;
}

@media (min-width: 961px) {
    .job-hero__aside {
        display: block;
    }
}

@media (max-width: 960px) {
    .job-layout {
        grid-template-columns: 1fr;
    }

    .job-layout__aside {
        position: static;
    }

    .job-hero {
        grid-template-columns: 1fr;
    }
}

.job-details-card,
.job-apply-card {
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.job-details-card h2,
.job-apply-card h2 {
    margin: 0 0 var(--space-4);
    font-size: var(--fs-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.job-details-card dl {
    margin: 0;
}

.job-details-card__row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border);
    font-size: var(--fs-sm);
}

.job-details-card__row:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.job-details-card__row dt {
    color: var(--color-text-muted);
}

.job-details-card__row dd {
    margin: 0;
    font-weight: 600;
    text-align: right;
}

.job-details-card__row dd a {
    color: var(--color-interactive);
    text-decoration: none;
}

.job-details-card__row dd a:hover {
    text-decoration: underline;
}

.job-detail__similar {
    margin-top: var(--space-8);
}

.job-apply-card p {
    margin: 0 0 var(--space-4);
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
}

.job-apply-card .btn {
    width: 100%;
    justify-content: center;
}

.job-apply-card .btn + .btn,
.job-apply-card .btn + form {
    margin-top: var(--space-2);
}

.job-apply-card form .btn {
    margin: 0;
}

/* Job description — sanitized HTML from Job.DescriptionHtml (JobDescriptionSanitizer),
   given editorial spacing/measure rather than the site's default paragraph rhythm. */
.job-description {
    max-width: 720px;
}

.job-description__body {
    font-size: var(--fs-base);
    line-height: 1.75;
    color: var(--color-text);
}

.job-description__body p {
    margin: 0 0 var(--space-4);
}

.job-description__body ul,
.job-description__body ol {
    margin: 0 0 var(--space-4);
    padding-left: 1.3em;
}

.job-description__body li {
    margin-bottom: var(--space-2);
}

.job-description__body h3,
.job-description__body h4 {
    margin: var(--space-5) 0 var(--space-2);
    font-family: var(--font-display);
}

.job-description__body a {
    color: var(--color-interactive);
}

/* Similar jobs — dedicated cards (SimilarJobCard.razor), not JobCard (shared with the
   /jobs listing) so this redesign can't affect that unrelated page. */
.similar-jobs-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-4);
}

@media (max-width: 960px) {
    .similar-jobs-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

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

.similar-job-card {
    display: flex;
    gap: var(--space-3);
    padding: var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 120ms ease, transform 120ms ease, border-color 120ms ease;
}

.similar-job-card:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--color-interactive);
    transform: translateY(-2px);
}

.similar-job-card:focus-visible {
    outline: 2px solid var(--color-interactive);
    outline-offset: 2px;
}

.similar-job-card__logo {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    object-fit: cover;
}

.similar-job-card__logo--fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    font-size: var(--fs-sm);
}

.similar-job-card__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

.similar-job-card__title {
    margin: 0 0 2px;
    font-size: var(--fs-base);
    font-weight: 600;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.similar-job-card__company {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
}

.similar-job-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-3);
    margin-bottom: var(--space-3);
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
}

.similar-job-card__meta span {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.similar-job-card__footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: auto;
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border);
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
}

.similar-job-card__cta {
    font-weight: 600;
    color: var(--color-interactive);
}

/* Quick filter buttons (Job Type / Location / Employer Type) */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.filter-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--fs-sm);
    font-weight: 600;
    text-decoration: none;
    transition: border-color 120ms ease, color 120ms ease;
}

.filter-btn:hover {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

.filter-btn__chevron {
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
}

/* Ad slots — named placements, docs/01 §7. Placeholder until AdSense is wired
   (needs a live domain + approved account — see docs/03 "Blocked"). Full width,
   auto height so it behaves like a real responsive AdSense unit once swapped in. */
.ad-slot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 90px;
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg-subtle);
}

.ad-slot--leaderboard {
    min-height: 100px;
}

.ad-slot--in-feed {
    min-height: 120px;
}

.ad-slot--panel-top {
    margin-bottom: var(--space-5);
}

/* Slot placed as the last child of a page's <section class="section container"> (Browse*, About,
   Contact, Register, Forgot/Set password, Company) — own top gap, since those sections only
   pad their outer edges. */
.section > .ad-slot {
    margin-top: var(--space-6);
}

/* Job detail: right-column card (300x250 "medium rectangle" shape) and the paragraph-break
   units. The in-text ones need their own vertical air — .job-description__body only spaces
   its own paragraphs — and the same 720px measure as the prose, so an ad never runs wider
   than the text it interrupts. */
.ad-slot--sidebar-sticky {
    min-height: 250px;
}

.job-hero__aside .ad-slot--sidebar-sticky {
    min-height: 200px;
}

.ad-slot--detail-mid {
    min-height: 120px;
    max-width: 720px;
    margin-block: var(--space-6);
}

/* Skyscraper-shaped side rails on /login — desktop only, same collapse-on-mobile technique
   job-hero__aside already uses (a stacked side-by-side ad next to a centered 480px form
   doesn't fit a phone screen, so it's not rendered there at all, not just squeezed). */
.ad-slot--login-side {
    display: none;
    min-height: 250px;
}

@media (min-width: 1100px) {
    .ad-slot--login-side {
        display: flex;
    }
}

.ad-slot__label {
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Employer / "post a job" feature section */
.employer-feature {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
    border-radius: var(--radius-lg);
    padding: var(--space-7) var(--space-6);
    display: grid;
    gap: var(--space-6);
}

.employer-feature h2 {
    color: var(--color-text-on-primary);
    font-size: var(--fs-2xl);
}

.employer-feature p {
    color: color-mix(in srgb, var(--color-text-on-primary) 90%, transparent);
}

.employer-feature__benefits {
    list-style: none;
    margin: var(--space-4) 0;
    padding: 0;
    display: grid;
    gap: var(--space-2);
}

.employer-feature__benefits li {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
}

.employer-feature__benefits li::before {
    content: "✓";
    color: color-mix(in srgb, var(--color-text-on-primary) 88%, var(--color-accent) 12%);
    font-weight: 700;
}

.employer-feature__stat {
    text-align: center;
    padding: var(--space-6);
    border: 1px dashed rgba(255, 255, 255, 0.3);
    border-radius: var(--radius-md);
}

.employer-feature__stat strong {
    display: block;
    font-family: var(--font-display);
    font-size: var(--fs-3xl);
    color: var(--color-text-on-primary);
}

.employer-feature__stat span {
    color: color-mix(in srgb, var(--color-text-on-primary) 90%, transparent);
    font-size: var(--fs-sm);
}

@media (min-width: 768px) {
    .employer-feature {
        grid-template-columns: 1.3fr 1fr;
        align-items: center;
    }
}

/* Rich text editor toolbar — used on the job-posting form */
.rte {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.rte__toolbar {
    display: flex;
    gap: var(--space-1);
    padding: var(--space-2);
    background: var(--color-bg-subtle);
    border-bottom: 1px solid var(--color-border);
}

.rte__toolbar button {
    width: 32px;
    height: 32px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text);
    font-weight: 700;
    cursor: pointer;
}

.rte__toolbar button:hover {
    background: var(--color-chip-bg);
}

.rte__surface {
    min-height: 180px;
    padding: var(--space-4);
    font-size: var(--fs-base);
    line-height: 1.5;
}

.rte__surface:focus {
    outline: none;
}

.rte__surface:empty::before {
    content: attr(data-placeholder);
    color: var(--color-text-muted);
}

/* Form grid system — shared by every Create/Edit form via .admin-form (admin panel
   and recruiter-facing pages like /post-job alike). A bare .form-field outside any .form-row already
   spans the full container width, so "full width" needs no class of its own —
   only fields meant to share a row get wrapped in .form-row/.form-row--3.
   minmax(0, 1fr), not a bare 1fr: without it a long value (a URL, a long option
   label) can force its grid column wider than its share, overflowing the row —
   the classic CSS Grid form gotcha. */
.form-row {
    display: grid;
    gap: var(--space-5);
    /* Without this, grid's default align-items:stretch forces every .form-field
       in the row to match the tallest sibling's height — so a field with a
       .form-hint under it (extra line) stretches its plain neighbor's input
       box taller too, misaligning two inputs that should sit flush under
       their labels. align-items:start makes each field size to its own
       content instead. */
    align-items: start;
}

@media (min-width: 640px) {
    .form-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Tablet: a 3-up row reads as 2 columns, not 3 — three narrow columns on a
       tablet-width screen is the "squeezed" look this system exists to avoid.
       True 3-column only once there's room for it (900px+, below). */
    .form-row--3 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 900px) {
    .form-row--3 {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.form-field {
    display: grid;
    /* Explicit minmax(0, 1fr) track, not the implicit `auto` one: an auto track never shrinks
       below its child's min-content, so a JS-built .pp-select trigger (nowrap text, e.g.
       "Assistant Hotel Manager") pushed the whole field wider than its card and the dropdown
       poked out of the right edge. */
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2);
    min-width: 0; /* lets the field shrink inside a grid column instead of overflowing it */
}

/* A subtle section break inside a multi-section form (docs: "Basic Information",
   "SEO", etc.) — a label plus a hairline, not a card-within-a-card. First one in
   a form skips the divider so it doesn't float a line above nothing. */
.admin-form__section-title {
    margin: 0;
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-text-muted);
}

.admin-form__section-title:first-child {
    padding-top: 0;
    border-top: none;
}

/* Generic <dialog>-based popup shell (data-js-dialog in admin.js) — first use is the "Add
   team member" flow on RecruiterTeam.razor, for a form that doesn't warrant its own page.
   Renders server-side with the `open` attribute (see admin.js) so it degrades to plain
   inline content with JS disabled, rather than being unreachable. */
dialog.admin-dialog {
    width: min(480px, calc(100vw - var(--space-5) * 2));
    padding: var(--space-5);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    background: var(--color-surface);
    color: var(--color-text);
}

/* Closed by default. The dialog is server-rendered with `open` (so it still works with JS off),
   and admin.js used to close it on load — but that script doesn't re-run on a Blazor enhanced
   navigation (e.g. clicking "Team" in the sidebar), so the popup showed already open. :modal
   only matches once showModal() has run, so anything else stays hidden regardless of script
   timing. App.razor's <noscript> block puts the inline form back for JS-off visitors. */
dialog.admin-dialog[data-js-dialog]:not(:modal) {
    display: none;
}

dialog.admin-dialog::backdrop {
    background: rgba(15, 23, 42, 0.55);
}

/* The form inside is .admin-form (its own bordered, padded card) — in a dialog that was a card
   inside a card. The dialog is the container; strip the form's chrome. */
dialog.admin-dialog > .admin-form {
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    max-width: none;
    gap: var(--space-4);
}

.admin-dialog__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.admin-dialog__header h2 {
    margin: 0;
    font-size: var(--fs-lg);
}

.admin-dialog__close {
    display: inline-flex;
    padding: var(--space-1);
    border: none;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--color-text-muted);
    cursor: pointer;
}

.admin-dialog__close:hover {
    color: var(--color-text);
    background: var(--color-bg-subtle);
}

/* Wraps the submit button (and a Cancel link, where a form has one) so the
   action row lays out the same way everywhere instead of a bare button sitting
   as its own full-width grid row. */
.admin-form__actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-top: var(--space-2);
}

.form-field label {
    font-size: var(--fs-sm);
    font-weight: 600;
}

.form-field input,
.form-field select,
.form-field textarea {
    width: 100%;
    min-width: 0;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: var(--fs-base);
    font-family: var(--font-body);
    color: var(--color-text);
    /* --color-bg (darker than .admin-form's --color-surface card) so fields read as
       insets, not the same-shade-on-same-shade blend .admin-filter-bar hit before. */
    background: var(--color-bg);
}

.form-field textarea {
    resize: vertical;
    min-height: 4.5em;
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
    border-color: var(--color-interactive);
}

/* Category card */
.category-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    text-decoration: none;
    color: var(--color-text);
    transition: border-color 120ms ease, transform 120ms ease;
}

.category-card:hover {
    border-color: var(--color-interactive);
    transform: translateY(-2px);
}

.category-card__icon {
    font-size: var(--fs-xl);
    color: var(--color-interactive);
}

.category-card__count {
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
}

/* Sections */
.section {
    /* padding-block only (not the padding shorthand) — a shorthand here would
       zero out .container's left/right padding whenever both classes are on
       the same element, since .section is later in the cascade. That bug is
       exactly why headings were flush against the edge. */
    padding-block: var(--space-8);
}

/* Job detail / company pages: the breadcrumb is now the first thing inside .section (moved there
   fixing a different, bigger gap on /company — see .job-detail's own comment earlier in this
   file), so .section's full --space-8 top padding reads as a lot of dead air above it — owner
   flagged this on both pages (same class, same gap, confirmed by measuring — not new). Trims just
   the top; .section's own padding-bottom below the content is untouched, and no other .section
   page is affected since this is scoped to .job-detail specifically. Must come after .section's
   own rule above — padding-top and padding-block's mapped padding-block-start tie on specificity,
   so source order decides the winner. */
.job-detail {
    padding-top: var(--space-5);
}

.section__header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-3);
    padding: 0 0 var(--space-4);
    margin-bottom: var(--space-5);
    border-bottom: 1px solid var(--color-border);
}

.section__header h1,
.section__header h2 {
    margin-bottom: 0;
    font-size: var(--fs-2xl);
}

.section__header a {
    font-size: var(--fs-sm);
    font-weight: 600;
    text-decoration: none;
}

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

.grid--jobs {
    /* minmax(0, 1fr), not a plain 1fr track — a job card's non-wrapping content (badges,
       title) otherwise forces the track past its container on narrow screens (see
       .listing-layout above for the full explanation of this grid min-size bug). */
    grid-template-columns: minmax(0, 1fr);
}

/* In-feed ad slots are direct children of .grid--jobs (Jobs.razor) — span the full row. */
.grid--jobs > .ad-slot {
    grid-column: 1 / -1;
}

/* Card-size toggle — pure CSS (checked-radio + sibling selector), no JS required
   so the page still works with JS disabled (docs/02 rule 1). */
.view-toggle {
    display: flex;
    width: fit-content;
    gap: var(--space-1);
    padding: var(--space-1);
    margin-bottom: var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.view-toggle--hidden {
    display: none;
}

/* Sort dropdown (docs/08-backlog.md item 12) shares a row with the (currently hidden)
   view-toggle — wraps on narrow screens instead of squeezing both onto one line. */
.listing-results__toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: flex-end;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.form-field--inline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.form-field--inline label {
    font-size: var(--fs-sm);
    font-weight: 600;
}

.form-field--inline select {
    width: auto;
}

/* The pp-select enhancement's hidden native <select> (site.js) needs to win this fight — otherwise it
   sits at its natural ~200px content width, invisible but still occupying layout space, which pushed
   /jobs' sort control past the viewport edge on mobile (2026-09-22 mobile check). */
.form-field--inline .pp-select__native {
    width: 1px;
}

.btn--sm {
    padding: var(--space-2) var(--space-3);
    font-size: var(--fs-xs);
}

.view-toggle__btn {
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--color-text-muted);
    cursor: pointer;
    user-select: none;
}

.view-toggle__input:checked + .view-toggle__btn {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
}

.view-toggle__input:focus-visible + .view-toggle__btn {
    outline: 3px solid var(--color-accent);
    outline-offset: 2px;
}

/* /jobs listing only (scoped via .listing-results, doesn't touch Home.razor's
   grid--jobs sections): "Cards" is always one per row, full width; "Compact" is
   always two per row. Both fixed — not responsive column counts — per request. */
.listing-results .grid--jobs {
    grid-template-columns: minmax(0, 1fr);
}

/* #view-compact is nested inside .view-toggle, not a direct sibling of
   .grid--jobs, so a plain `~` combinator never matches — scope through :has()
   on their shared ancestor (.listing-results) instead. */
.listing-results:has(#view-compact:checked) .grid--jobs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
}

.listing-results:has(#view-compact:checked) .grid--jobs .job-card {
    padding: var(--space-3);
}

.listing-results:has(#view-compact:checked) .grid--jobs .job-card__title {
    font-size: var(--fs-base);
}

.listing-results:has(#view-compact:checked) .grid--jobs .job-card__footer {
    display: none;
}

@media (max-width: 639px) {
    /* even compact stays one-per-row on phones — two cramps too much below 640px */
    .listing-results:has(#view-compact:checked) .grid--jobs {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Pager links jump to #jobs-results; keep the heading clear of the sticky header. */
#jobs-results {
    scroll-margin-top: var(--header-height);
}

.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    margin-top: var(--space-6);
}

.pagination__status {
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

.grid--categories {
    grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 768px) {
    .grid--jobs {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .grid--categories {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 1024px) {
    .grid--jobs {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .grid--categories {
        grid-template-columns: repeat(6, 1fr);
    }
}

/* /jobs listing page: hero search bar (sits inside the hero in Jobs.razor.css,
   same rounded-card look as the homepage's .search-form) + filter rail / results / ad rail */
.jobs-search-bar {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    background: var(--color-surface);
    padding: var(--space-3);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.jobs-search-bar input,
.jobs-search-bar select {
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: var(--fs-base);
    font-family: var(--font-body);
    color: var(--color-text);
    background: var(--color-bg);
}

.jobs-search-bar .pp-select {
    width: 100%;
}

@media (min-width: 640px) {
    .jobs-search-bar {
        flex-direction: row;
        flex-wrap: wrap;
    }

    .jobs-search-bar input,
    .jobs-search-bar select,
    .jobs-search-bar .pp-select {
        flex: 1;
        min-width: 0;
    }

    /* Filters (hidden at 1024px+ anyway) would otherwise squeeze onto the same row as the input
       and Search Jobs — force it onto its own full-width line instead of a cramped third column. */
    .filter-drawer-trigger {
        flex-basis: 100%;
    }
}

/* Home.razor's hero .search-form is Blazor CSS-isolated (scoped selectors get a
   b-xxxx attribute rewritten onto them at build time) — the .pp-select wrapper below
   is created by plain JS at runtime and never gets that attribute, so its layout rules
   have to live here in the global stylesheet, not in Home.razor.css, or they silently
   never match. */
.search-form .pp-select {
    width: 100%;
}

@media (min-width: 640px) {
    .search-form .pp-select {
        flex: 1;
        min-width: 0;
    }
}

/* Custom-styled select ("pp-select") — progressive enhancement over a real <select>,
   wired up by site.js for any select[data-pp-select]. The real <select> stays in the DOM
   (visually hidden, not disabled) so the form still submits correctly with JS off; this
   only changes how the field looks/is operated when JS is on — a rounded panel with a
   highlighted selected row instead of the browser's unstyled native list. */
.pp-select {
    position: relative;
}

.pp-select__native {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.pp-select__trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: var(--fs-base);
    font-family: var(--font-body);
    color: var(--color-text);
    background: var(--color-bg);
    cursor: pointer;
    text-align: left;
}

.pp-select__trigger:focus-visible {
    outline: 3px solid var(--color-accent);
    outline-offset: 1px;
}

.pp-select--open .pp-select__trigger {
    border-color: var(--color-interactive);
}

.pp-select__trigger--placeholder {
    color: var(--color-text-muted);
}

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

.pp-select__chevron {
    flex: none;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--color-text-muted);
    border-bottom: 2px solid var(--color-text-muted);
    transform: rotate(45deg);
    margin-top: -4px;
    transition: transform 120ms ease;
}

.pp-select--open .pp-select__chevron {
    transform: rotate(-135deg);
    margin-top: 3px;
}

.pp-select__panel {
    position: absolute;
    z-index: 40;
    top: calc(100% + var(--space-2));
    left: 0;
    right: 0;
    max-height: 280px;
    overflow-y: auto;
    margin: 0;
    padding: var(--space-2);
    list-style: none;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}

.pp-select__panel[hidden] {
    display: none;
}

.pp-select__search {
    display: block;
    width: 100%;
    margin-bottom: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg);
    color: var(--color-text);
    font-size: var(--fs-sm);
}

.pp-select__search:focus {
    outline: 2px solid var(--color-interactive);
    outline-offset: -1px;
}

.pp-select__empty {
    padding: var(--space-2) var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

.pp-select__option {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    font-size: var(--fs-base);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pp-select__option:hover,
.pp-select__option--active {
    background: var(--color-bg);
}

.pp-select__option[aria-selected="true"] {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
    font-weight: 600;
}

.listing-layout {
    display: grid;
    gap: var(--space-6);
    /* minmax(0, 1fr), not a plain 1fr track: a grid track's implicit minimum is auto
       (content-based), so .listing-results — whose Sort by dropdown resists shrinking —
       was blowing the column past the container's right edge on mobile, eating the right
       padding (same bug/fix as .form-field above). */
    grid-template-columns: minmax(0, 1fr);
}

/* Below 1024px .filter-rail is an off-canvas left drawer, not the inline block it was — owner
   request: filters were eating the top of the screen on mobile before you ever saw a job. Pure
   CSS (a hidden checkbox + <label> triggers, #filter-drawer-toggle in Jobs.razor — same mechanism
   the header hamburger/admin sidebar already use), so it still works with JavaScript disabled
   (rule 1). Reset back to the plain static sidebar at 1024px, in the media query below. */
.filter-rail {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    position: fixed;
    inset-block: 0;
    left: 0;
    z-index: 40;
    width: min(85vw, 320px);
    overflow-y: auto;
    background: var(--color-surface);
    padding: var(--space-5);
    box-shadow: var(--shadow-md);
    transform: translateX(-100%);
    transition: transform 200ms ease;
    /* Same treatment as .breadcrumbs' own horizontal scroll — the drawer's content scrolls fine
       without a visible track/thumb; a raw system scrollbar down the right edge of an otherwise
       clean panel reads as unfinished (owner screenshot: "yeh scroll visible hoga kya"). */
    scrollbar-width: none;
}

.filter-rail::-webkit-scrollbar {
    display: none;
}

#filter-drawer-toggle:checked ~ .listing-layout .filter-rail {
    transform: translateX(0);
}

/* Mobile-only, merged into .jobs-search-bar right under the hero's Search Jobs button (Jobs.razor)
   — btn--outline (not a solid fill) so it reads as the secondary action next to that button rather
   than a visually-identical twin. Full width and on its own line even once .jobs-search-bar
   switches to a row layout at 640px+ (its own rule below). */
.filter-drawer-trigger {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    background: var(--color-accent);
    color: #22200f;
    border-color: transparent;
}

.filter-drawer-trigger:hover {
    background: var(--color-accent-dark);
}

.filter-drawer-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 39;
    background: rgba(0, 0, 0, 0.5);
}

#filter-drawer-toggle:checked ~ .listing-layout .filter-drawer-overlay {
    display: block;
}

.filter-drawer-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: var(--radius-sm, 6px);
    color: var(--color-text-muted);
    cursor: pointer;
}

.filter-drawer-close:hover {
    background: var(--color-bg-subtle);
}

.filter-rail__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.filter-rail__title {
    margin: 0;
    font-size: var(--fs-base);
}

.filter-group {
    /* Same card treatment as .job-card (background + border, no shadow — the filter groups sit
       stacked in a narrow column, not spaced out in a grid, so a shadow read as visual noise there;
       owner request after the .filter-rail panel-background fix — keep individual groups as their
       own white cards, not the whole rail). */
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
}

.filter-group summary {
    font-weight: 600;
    cursor: pointer;
    padding: var(--space-2) 0;
}

.filter-group label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) 0;
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
    /* Long role names with no spaces ("Media/Communications/PROMOTION") must wrap inside the box
       instead of pushing the count out of it. */
    min-width: 0;
    overflow-wrap: anywhere;
}

.filter-group label input[type="checkbox"],
.filter-group__count {
    flex-shrink: 0;
}

.filter-group__count {
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
}

.filter-group__more {
    display: inline-block;
    margin-top: var(--space-2);
    font-size: var(--fs-sm);
    font-weight: 600;
}

/* /browse and its drill-down pages (BrowseRegion, BrowseIndustry) — headings
   followed by a grid of icon boxes, no underlined link lists. */
.browse-page h2 {
    margin: var(--space-6) 0 var(--space-3);
    font-size: var(--fs-lg);
}

.browse-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-3);
}

.browse-card {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    color: var(--color-text);
    font-weight: 600;
    font-size: var(--fs-sm);
    text-decoration: none;
    transition: border-color 120ms ease, background-color 120ms ease, transform 120ms ease;
}

.browse-card .icon {
    flex-shrink: 0;
    color: var(--color-interactive);
}

.browse-card:hover {
    border-color: var(--color-interactive);
    background: var(--color-primary-light);
    transform: translateY(-2px);
}

.browse-page__crumbs {
    margin-top: var(--space-7);
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-border);
    font-size: var(--fs-sm);
}

.filter-group__row {
    display: flex;
    gap: var(--space-3);
    padding-top: var(--space-2);
}

.filter-group__row input {
    width: 0;
    flex: 1;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

.filter-rail__apply {
    flex-shrink: 0;
}

/* Vertical ad under the filter groups (AdSlotSize.FilterRail) — desktop only, where the rail is a
   real 240px sidebar; stacked above the results on smaller screens it would only push them down. */
.ad-slot--filter-rail {
    display: none;
    min-height: 400px;
}

@media (min-width: 1024px) {
    .listing-layout {
        grid-template-columns: 240px minmax(0, 1fr);
        align-items: start;
    }

    .ad-slot--filter-rail {
        display: flex;
    }

    /* Back to the plain always-visible sidebar this was before the drawer existed — same
       breakpoint .listing-layout switches to its two-column grid at. */
    .filter-rail {
        position: static;
        inset-block: auto;
        width: auto;
        overflow-y: visible;
        padding: 0;
        /* The drawer needs an opaque surface (it covers page content when open on mobile) — that
           background never got reset back to none here, so at desktop it left a faint white box
           (--color-surface, #fff) behind the whole rail against the page's own off-white
           --color-bg (#f7f9ff), visible in an owner screenshot as a leftover panel behind the
           filters. Individual .filter-group cards still have their own real background/border. */
        background: none;
        box-shadow: none;
        transform: none;
        transition: none;
        /* CSS Grid quirk, not covered by resetting position above: a grid item's z-index applies
           "as if position were relative" even when position is genuinely static (spec: z-index on
           a grid/flex item is never a no-op the way it is on a normal static block). Left at the
           drawer's z-index:40 here, .filter-rail was painting above the sticky site header
           (z-index:20) at desktop width — owner screenshot caught it. */
        z-index: auto;
    }

    .filter-drawer-trigger,
    .filter-drawer-close,
    .filter-drawer-overlay {
        display: none !important;
    }
}

/* Sign-in style pages (login / register / forgot / set password / finish sign-up / contact) share
   AuthPageFrame.razor, whose layout and size are Bootstrap classes (row / col-* / card). Only what
   Bootstrap can't know is here: the site's theme colours on the card (light + dark) and the
   heading inside it. */
.auth-frame__card {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text);
}

.auth-frame__card h1 {
    margin: 0 0 var(--space-3);
    font-size: var(--fs-xl);
    text-align: center;
}

.auth-frame__card .card-body > p:not(.auth-switch):not(.form-error):not(.form-success) {
    margin-bottom: var(--space-3);
}

.auth-frame__card .form-field label {
    margin-bottom: var(--space-1);
}

/* Bootstrap's .btn-primary hard-codes its colours; point them at the site navy. */
.auth-frame__card .btn-primary {
    --bs-btn-bg: var(--color-primary);
    --bs-btn-border-color: var(--color-primary);
    --bs-btn-hover-bg: var(--color-primary-dark);
    --bs-btn-hover-border-color: var(--color-primary-dark);
    --bs-btn-active-bg: var(--color-primary-dark);
    --bs-btn-active-border-color: var(--color-primary-dark);
    --bs-btn-disabled-bg: var(--color-primary);
    --bs-btn-disabled-border-color: var(--color-primary);
}

.auth-frame__card .btn-outline-primary {
    --bs-btn-color: var(--color-interactive);
    --bs-btn-border-color: var(--color-border);
    --bs-btn-hover-bg: var(--color-primary-light);
    --bs-btn-hover-color: var(--color-interactive);
    --bs-btn-hover-border-color: var(--color-interactive);
}

.auth-form {
    display: grid;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.auth-form input {
    padding-block: var(--space-3);
}

.auth-role-switch {
    margin-bottom: var(--space-3);
}

.filter-btn--active {
    border-color: var(--color-interactive);
    background: var(--color-primary-light);
    color: var(--color-interactive);
}

.form-error {
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-5);
    border-radius: var(--radius-md);
    background: #fdeceb;
    color: #a3271b;
    font-size: var(--fs-sm);
}

:root[data-theme="dark"] .form-error {
    background: #3a1f1c;
    color: #ff9a8a;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .form-error {
        background: #3a1f1c;
        color: #ff9a8a;
    }
}

.form-success {
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-5);
    border-radius: var(--radius-md);
    background: #e7f6ec;
    color: #1e6b3a;
    font-size: var(--fs-sm);
}

:root[data-theme="dark"] .form-success {
    background: #1c3a26;
    color: #8fe0ab;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .form-success {
        background: #1c3a26;
        color: #8fe0ab;
    }
}

.form-hint {
    margin-top: calc(var(--space-4) * -1);
    font-size: var(--fs-xs);
}

.form-hint-list {
    margin: var(--space-2) 0;
    padding-left: var(--space-5);
}

.form-hint-list li {
    margin-bottom: var(--space-1);
}

.auth-switch {
    font-size: var(--fs-sm);
}

.auth-divider {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: var(--space-3) 0;
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
}

.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--color-border);
}

.social-login-buttons {
    display: grid;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.btn--social {
    width: 100%;
    justify-content: center;
}

/* Role panels — /dashboard, /recruiter, /admin */
.panel-grid {
    display: grid;
    gap: var(--space-5);
    grid-template-columns: 1fr;
}

@media (min-width: 768px) {
    .panel-grid {
        /* minmax(0, 1fr), not bare 1fr — same overflow gotcha .form-row already
           guards against: an unbreakable long value in one card (a long job
           title in .panel-list, an untruncated email) could otherwise force
           this track wider than its share. */
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .panel-card--wide {
        grid-column: 1 / -1;
    }
}

.panel-card {
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
}

/* Candidate Search (docs/08-backlog.md item 15) — filters on the left, results on the right,
   same "stack on mobile, sidebar on desktop" shape the public /jobs listing-layout already
   uses, kept as its own class rather than reusing .listing-layout/.filter-rail directly since
   this page's filters are plain form-fields, not <details>+checkbox groups. */
.candidate-search-layout {
    display: grid;
    gap: var(--space-6);
    grid-template-columns: 1fr;
    align-items: start;
}

.candidate-filter-rail {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.candidate-filter-rail h2 {
    font-size: var(--fs-lg);
}

/* No .panel-card--wide on the results card: that class is `grid-column: 1 / -1` (built for
   .panel-grid), which here pushed the results below the filter rail and left the whole right
   side of the page empty. min-width:0 lets the table scroll inside the card instead of
   stretching the 1fr track. */
.candidate-search-results {
    min-width: 0;
}

@media (min-width: 900px) {
    .candidate-search-layout {
        grid-template-columns: 300px minmax(0, 1fr);
    }

    .candidate-filter-rail {
        position: sticky;
        top: calc(var(--header-height) + var(--space-4));
    }
}

.panel-card h2 {
    font-size: var(--fs-lg);
    margin-bottom: var(--space-4);
}

.panel-card form {
    margin-top: var(--space-4);
}

.panel-empty {
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

.panel-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-3);
}

.panel-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

/* Skeleton placeholder — docs/01 §7: "never a full-page spinner" */
.skeleton {
    background: linear-gradient(90deg, var(--color-chip-bg) 25%, var(--color-border) 37%, var(--color-chip-bg) 63%);
    background-size: 400% 100%;
    animation: skeleton-shine 1.4s ease infinite;
    border-radius: var(--radius-sm);
}

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

.blazor-error-boundary {
    background: #b32121;
    padding: var(--space-4) var(--space-4) var(--space-4) 3.7rem;
    color: white;
    border-radius: var(--radius-md);
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* Admin dashboard chrome — shared across every /admin/* page (was Admin.razor.css,
   moved here since CSS isolation only scopes to elements written in the component
   that owns the .razor.css file; new admin pages need these classes too). */
.admin-page {
    padding-top: var(--space-6);
    padding-bottom: var(--space-8);
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.admin-page__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.admin-page__header-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.admin-import-form {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
}

.admin-import-form label {
    margin: 0;
    cursor: pointer;
}

.admin-page__header h1 {
    margin-bottom: 2px;
    font-size: var(--fs-2xl);
}

.admin-page__header p {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

/* KPI cards. auto-fit instead of fixed breakpoint counts (repeat(6,...) etc.) —
   pages with fewer cards than the max column count (recruiter has 4, admin has 8)
   used to leave empty trailing columns instead of stretching to fill the row. */
.stat-grid {
    display: grid;
    gap: var(--space-3);
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* Phones: two compact cards per row instead of one tall card per row (13 cards on the
   admin dashboard otherwise means a very long scroll). Card internals: StatCard.razor.css. */
@media (max-width: 559px) {
    .stat-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--space-2);
    }
}

.recruiter-my-jobs-card {
    margin-top: var(--space-3);
}

/* Section cards */
.admin-card {
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

/* Account & Security: card on the left, ad on the right, same row — stacks on narrow screens.
   The ad stretches to the card's height; its panel-top bottom margin is only for the stacked layout. */
.account-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-5);
    align-items: stretch;
}

.account-row > .ad-slot {
    margin-bottom: 0;
}

@media (min-width: 900px) {
    .account-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Saved Jobs: compact two-per-row cards (same look as the compact /jobs listing); in-feed ads span the row. */
.saved-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-3);
}

.saved-grid > .ad-slot {
    grid-column: 1 / -1;
}

@media (min-width: 900px) {
    .saved-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* One card per saved job: the wrapper owns the border/shadow, the job summary and the
   status + remove bar are sections inside it. (They used to be two separate things, so the
   Live badge and delete button floated loose under the card.) */
.saved-job {
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}

.saved-job:hover {
    border-color: var(--color-interactive);
    box-shadow: var(--shadow-md);
}

.saved-job .job-card {
    flex: 1;
    padding: var(--space-3);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    transform: none;
}

.saved-job .job-card__title {
    font-size: var(--fs-base);
}

.saved-job .job-card__footer {
    display: none;
}

.saved-job__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-2) var(--space-3);
    border-top: 1px solid var(--color-border);
    background: var(--color-bg-subtle);
}

/* Expired/closed bookmark: shown for reference, not a link to a dead page. */
.saved-job--inactive .job-card {
    opacity: 0.6;
    pointer-events: none;
}

.admin-card h2 {
    font-size: var(--fs-lg);
    margin: 0 0 var(--space-4);
}

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

.admin-card__header h2 {
    margin: 0;
}

/* Collapsible integration/credential cards on /admin/system-status — native <details>,
   no JS needed. Closed by default; a card opens itself when it's unconfigured (nudges
   first-time setup) or right after its own save/test action, so a result message is
   never hidden inside a collapsed card. */
.admin-integration-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.admin-integration-card__summary {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    cursor: pointer;
    list-style: none;
}

.admin-integration-card__summary::-webkit-details-marker {
    display: none;
}

.admin-integration-card__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    font-size: var(--fs-lg);
    font-weight: 600;
}

.admin-integration-card__desc {
    flex: 1 1 auto;
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
    min-width: 200px;
}

.admin-integration-card__summary svg {
    flex-shrink: 0;
    color: var(--color-text-muted);
    transition: transform 0.15s ease;
}

.admin-integration-card[open] > .admin-integration-card__summary svg {
    transform: rotate(180deg);
}

.admin-integration-card__body {
    padding: 0 var(--space-5) var(--space-5);
    border-top: 1px solid var(--color-border);
    margin-top: var(--space-1);
    padding-top: var(--space-4);
}

.admin-integration-card__actions {
    margin-bottom: var(--space-4);
}

/* Readability of the Integrations page: intro as a short bullet list, hints at a legible size. */
.admin-intro-list {
    margin: var(--space-2) 0 0;
    padding-left: var(--space-5);
    display: grid;
    gap: var(--space-1);
    font-size: var(--fs-sm);
    line-height: 1.55;
    color: var(--color-text-muted);
}

.admin-integration-card .form-hint {
    font-size: var(--fs-sm);
    line-height: 1.5;
}

.admin-integration-card .admin-form__section-title {
    margin: var(--space-2) 0 0;
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-border);
    font-size: var(--fs-base);
}

/* The settings <form class="admin-form"> inside the body is itself a bordered, padded card, so
   each integration read as a box inside a box with double padding. The integration card is
   already the container — strip the form's own chrome here. */
.admin-integration-card__body > .admin-form {
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    max-width: none;
}

@media (max-width: 640px) {
    .admin-integration-card__summary {
        flex-wrap: wrap;
        gap: var(--space-2) var(--space-3);
        padding: var(--space-3) var(--space-4);
    }

    /* Title (+ status badge, which may wrap under the name) takes the row's free space so the
       chevron stays on the right of the same row instead of dropping onto its own line. */
    .admin-integration-card__title {
        flex: 1 1 0;
        min-width: 0;
        flex-wrap: wrap;
        font-size: var(--fs-base);
    }

    .admin-integration-card__desc {
        order: 3;
        flex-basis: 100%;
        min-width: 0;
    }

    .admin-integration-card__body {
        padding: var(--space-4);
    }

    /* Collapsed cards: 2-line teaser instead of a 4-line paragraph each (open ones show all). */
    .admin-integration-card:not([open]) .admin-integration-card__desc {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    .admin-integration-card__desc {
        line-height: 1.5;
    }

    /* 16px inputs: smaller text makes iOS zoom the page on focus and is hard to read. */
    .admin-integration-card input,
    .admin-integration-card select {
        font-size: 16px;
    }

    .admin-integration-card .admin-form__actions .btn,
    .admin-integration-card__actions .btn {
        width: 100%;
    }
}

/* A single <form> that submits one atomic action (e.g. Post a Job) but reads better
   split across several visual .admin-card sections instead of one long scroll — same
   gap/stacking .admin-page already uses for its own direct children. */
.admin-form-cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.admin-grid-2 {
    display: grid;
    gap: var(--space-5);
    grid-template-columns: 1fr;
}

@media (min-width: 768px) {
    .admin-grid-2 {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Post a Job / Admin Post a Job — classification dropdowns in a narrow left rail (Bootstrap's
   "col-3" ratio), the actual content (title, salary, how to apply, description) in the wide
   right column ("col-9") — owner's explicit split. Stacks to one column below 900px, same
   breakpoint .candidate-search-layout above already uses for its own sidebar+content split. */
.post-job-layout {
    display: grid;
    gap: var(--space-5);
    grid-template-columns: 1fr;
    align-items: start;
}

.post-job-sidebar,
.post-job-main {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    min-width: 0;
}

@media (min-width: 900px) {
    .post-job-layout {
        grid-template-columns: minmax(240px, 3fr) minmax(0, 9fr);
    }
}

/* .admin-card is a plain block, so consecutive .form-field children (and a .form-row after a
   .form-field) had zero space between them — a field's input sat flush against the next
   field's label. Card becomes a grid so every child gets the same vertical rhythm; the
   header's own margin-bottom is dropped so it isn't double-counted with the gap. */
.admin-form-cards .admin-card,
.admin-card--fields {
    display: grid;
    gap: var(--space-5);
}

.admin-form-cards .admin-card__header,
.admin-card--fields .admin-card__header {
    margin-bottom: 0;
}

/* The `hidden` attribute is only a UA-stylesheet display:none, so any author rule that sets
   `display` (.form-field is grid, .apply-email-row is flex) silently wins and the "hidden"
   element stays visible — the Application URL / email rows showed even with the default
   "Through JobPingo" apply mode selected. */
.form-field[hidden],
.apply-email-row[hidden] {
    display: none;
}

/* Multiple "apply by email" addresses on a job (docs/08-backlog.md) — JobPostingOptions.
   MaxApplyEmails rows render server-side; all but the first start hidden and are revealed one
   at a time via "+ Add another email" (site.js), so JS-off still submits the first address
   fine and never shows empty extra rows. */
.apply-email-row {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    margin-bottom: var(--space-2);
}

.apply-email-row input {
    flex: 1 1 auto;
}

.apply-email-remove {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--fs-base);
    line-height: 1;
    cursor: pointer;
}

.apply-email-remove:hover {
    color: var(--color-text);
    border-color: var(--color-interactive);
}

.admin-stat-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
}

.admin-stat-list > div {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border);
    font-size: var(--fs-sm);
}

.admin-stat-list > div:last-child {
    border-bottom: none;
}

.admin-stat-list dt {
    color: var(--color-text-muted);
}

.admin-stat-list dd {
    margin: 0;
    font-weight: 600;
}

/* Table */
.admin-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-sm);
}

.admin-table th {
    text-align: left;
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-subtle);
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.admin-table td {
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--color-border);
    vertical-align: middle;
}

.admin-table tbody tr:hover {
    background: var(--color-bg-subtle);
}

/* Table/card view switch — toolbar + the --cards/--table modifier classes are added by
   admin.js (wwwroot/js/admin.js, also loaded on JobSeekerLayout/RecruiterLayout). data-label
   on every <td> (set in each page's markup) supplies the card's field name. */
.admin-table-wrap__toolbar {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}

.admin-table-wrap__toolbar-btn {
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
    cursor: pointer;
}

.admin-table-wrap__toolbar-btn[aria-pressed="true"] {
    color: var(--color-text);
    border-color: var(--color-interactive);
}

.admin-table-wrap--cards table.admin-table,
.admin-table-wrap--cards table.admin-table tbody,
.admin-table-wrap--cards table.admin-table tr,
.admin-table-wrap--cards table.admin-table th,
.admin-table-wrap--cards table.admin-table td {
    display: block;
    width: 100%;
}

.admin-table-wrap--cards table.admin-table thead {
    display: none;
}

.admin-table-wrap--cards table.admin-table tr {
    margin-bottom: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 0 var(--space-4);
}

.admin-table-wrap--cards table.admin-table td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-top: 1px solid var(--color-border);
    text-align: right;
    white-space: normal;
}

.admin-table-wrap--cards table.admin-table tr > td:first-child {
    border-top: none;
}

.admin-table-wrap--cards table.admin-table td::before {
    content: attr(data-label);
    font-weight: 600;
    color: var(--color-text-muted);
    text-align: left;
}

/* Same collapse, applied automatically under 640px unless the toolbar above forced Table
   view — this is what keeps every table usable with JavaScript disabled (CLAUDE.md rule 1). */
@media (max-width: 640px) {
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table,
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tbody,
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr,
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table th,
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table td {
        display: block;
        width: 100%;
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table thead {
        display: none;
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr {
        margin-bottom: var(--space-3);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-sm);
        padding: 0 var(--space-4);
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table td {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: var(--space-3);
        padding: var(--space-2) 0;
        border-top: 1px solid var(--color-border);
        text-align: right;
        white-space: normal;
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr > td:first-child {
        border-top: none;
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table td::before {
        content: attr(data-label);
        font-weight: 600;
        color: var(--color-text-muted);
        text-align: left;
    }
}

/* Card-view rows sit inside an .admin-card of the same --color-surface fill with only a faint
   border, so every row blended into the container and the list read as one big box. Give each
   row its own inset look (darker fill, firmer border, soft shadow, a little breathing room). */
.admin-table-wrap--cards table.admin-table tr {
    background: var(--color-bg);
    border-color: color-mix(in srgb, var(--color-text) 16%, var(--color-border));
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: var(--space-1) var(--space-4);
}

.admin-table-wrap--cards table.admin-table tr:last-child {
    margin-bottom: 0;
}

@media (max-width: 640px) {
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr {
        background: var(--color-bg);
        border-color: color-mix(in srgb, var(--color-text) 16%, var(--color-border));
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-sm);
        padding: var(--space-1) var(--space-4);
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr:last-child {
        margin-bottom: 0;
    }

    /* The row's hover tint (desktop table) would otherwise repaint the card fill on tap. */
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tbody tr:hover {
        background: var(--color-bg);
    }
}

/* Grouped tables (Categories: one tbody per industry) put a section label row in the same <tr>
   the card view turns into a bordered card, so the label rendered as a card inside a card.
   In card layout the group row is just a heading: no card chrome, labelled strip only. */
.admin-table-wrap--cards table.admin-table tr.admin-table__group-row {
    background: transparent;
    border: 0;
    box-shadow: none;
    padding: 0;
    margin: var(--space-2) 0;
}

.admin-table-wrap--cards table.admin-table tr.admin-table__group-row th {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
}

@media (max-width: 640px) {
    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr.admin-table__group-row {
        background: transparent;
        border: 0;
        box-shadow: none;
        padding: 0;
        margin: var(--space-2) 0;
    }

    .admin-table-wrap:not(.admin-table-wrap--table) table.admin-table tr.admin-table__group-row th {
        display: block;
        width: 100%;
        padding: var(--space-2) var(--space-3);
        border-radius: var(--radius-sm);
    }
}

/* Phones: header action buttons share one row (equal width) and a search box sits on the same
   row as its Filter button, instead of each button wrapping onto a line of its own. The 240px
   flex-basis on the search input is what forced the wrap; selects/dates still wrap below. */
@media (max-width: 559px) {
    /* Wrap (not nowrap): 2 buttons share a row, 3+ (e.g. Export / Import / New on Categories)
       flow onto a second row instead of overflowing off-screen. */
    .admin-page__header-actions {
        width: 100%;
        flex-wrap: wrap;
        gap: var(--space-2);
    }

    .admin-page__header-actions > .btn,
    .admin-page__header-actions > form {
        flex: 1 1 auto;
        min-width: 0;
        justify-content: center;
        white-space: nowrap;
    }

    .admin-page__header-actions > form > .btn {
        flex: 1 1 auto;
        justify-content: center;
    }

    .admin-filter-bar.admin-filter-bar {
        gap: var(--space-2);
        padding: var(--space-3);
    }

    .admin-filter-bar.admin-filter-bar input[type="text"],
    .admin-filter-bar.admin-filter-bar input[type="search"] {
        flex: 1 1 0;
        min-width: 0;
    }

    .admin-filter-bar.admin-filter-bar > .btn {
        flex: none;
    }

    /* Bars with more than a search box (recruiter combobox, status select, date range): a
       2-column grid. Search/recruiter/status take a full row, the two dates share one, and
       Filter spans the bottom. Plain search + Filter bars keep the single row above. */
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > input[type="text"],
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > input[type="search"],
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > .js-combobox,
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > select,
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > .btn,
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > .date-range {
        grid-column: 1 / -1;
    }

    /* "Applied between" pair (recruiter Applications): the whole range takes a full row, its two
       dates split it evenly, instead of being squeezed into one half-width cell. */
    .admin-filter-bar.admin-filter-bar > .date-range {
        flex: none;
        width: 100%;
        min-width: 0;
    }

    .admin-filter-bar.admin-filter-bar > .date-range input[type="date"] {
        flex: 1 1 0;
        min-width: 0;
    }

    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > input,
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > select,
    .admin-filter-bar.admin-filter-bar:has(select, input[type="date"], .js-combobox) > .btn {
        width: 100%;
        min-width: 0;
    }
}

/* Filter submit: .btn--outline is transparent with a faint border, which vanished into the bar's
   tinted background so it didn't read as a button. Solid fill + interactive border/text. */
.admin-filter-bar > .btn[type="submit"] {
    background: var(--color-surface);
    border-color: var(--color-interactive);
    color: var(--color-interactive);
    box-shadow: var(--shadow-sm);
}

.admin-filter-bar > .btn[type="submit"]:hover {
    background: var(--color-interactive);
    color: var(--color-surface);
}

/* Admin forms/filters/actions (category management etc.) */
.admin-filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: center;
    padding: var(--space-4);
    margin-bottom: var(--space-4);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

/* --color-surface (the input's old fill) is the same color as the .admin-card
   these sit inside, so the field had only a 1px border to read as a field at
   all. --color-bg is darker than both the card and the bar above, giving the
   inputs a real inset look instead of blending into the card. */
.admin-filter-bar input[type="text"],
.admin-filter-bar input[type="search"],
.admin-filter-bar input[type="date"],
.admin-filter-bar select {
    padding: var(--space-3) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg);
    color: var(--color-text);
    font-size: var(--fs-sm);
}

.admin-filter-bar input[type="text"],
.admin-filter-bar input[type="search"] {
    flex: 1 1 240px;
}

/* Async searchable dropdown (.js-combobox in admin.js) — the text input above already picks
   up the shared field look from the rule above; this is just the floating suggestion list. */
.js-combobox {
    position: relative;
    flex: 1 1 240px;
}

/* Nested inside .js-combobox now, not a direct .admin-filter-bar child, so the flex-basis
   from the shared input[type="text"] rule above no longer sizes it — needs its own width. */
.js-combobox-input {
    width: 100%;
}

.js-combobox-list {
    position: absolute;
    top: calc(100% + var(--space-1));
    left: 0;
    right: 0;
    z-index: 20;
    margin: 0;
    padding: var(--space-1) 0;
    list-style: none;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    max-height: 260px;
    overflow-y: auto;
}

.js-combobox-option {
    padding: var(--space-2) var(--space-3);
    font-size: var(--fs-sm);
    cursor: pointer;
}

.js-combobox-option:hover {
    background: var(--color-bg-subtle);
    color: var(--color-interactive);
}

/* Bare <input type="date"> otherwise renders with the browser's own default chrome for the
   native calendar icon and date segments — they live in the browser's internal
   (non-CSS-reachable) date-picker widget, unreachable by the color/background set above.
   color-scheme tells the browser which built-in palette to draw that internal UI in, so it
   actually matches the input around it instead of looking like a different, unstyled control.
   Applies to every date input site-wide, not just the admin filter bar, on the same reasoning. */
input[type="date"] {
    color-scheme: light;
    position: relative; /* anchors the stretched picker-indicator below */
}

:root[data-theme="dark"] input[type="date"] {
    color-scheme: dark;
}

/* Native date inputs only open the calendar when you hit the small icon — everywhere else in
   the box just edits digits. Stretching the (invisible) icon over the whole field makes the
   entire box clickable to open the picker, which is what people expect. Chromium/WebKit only
   (::-webkit-calendar-picker-indicator isn't a real Firefox target) — Firefox keeps the
   default icon-only behavior, not broken, just not the enhanced click area. The onclick
   showPicker() call next to every date input in markup is the same idea for browsers where
   this pseudo-element trick doesn't apply but the modern picker API still does. */
input[type="date"]::-webkit-calendar-picker-indicator {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    cursor: pointer;
}

/* Stays a real table-cell (not display:flex): a flex <td> stops being a table-cell, so the
   row's `vertical-align: middle` no longer applied and the icons sat at the top of a tall row
   (e.g. next to a job title wrapped onto several lines). Children are lined up inline and
   centred on the cell instead; forms get margin:0 because `.panel-card form` gives every form
   inside a card a top margin, which pushed the button icons lower than the plain <a> icon. */
.admin-table__actions {
    white-space: nowrap;
}

.admin-table__actions > * {
    vertical-align: middle;
}

.admin-table__actions form {
    display: inline-block;
    margin: 0;
}

.admin-table__actions > * + * {
    margin-left: var(--space-2);
}

/* One shared look for every action-column icon, whether it's an <a> (edit) or a <button>
   (toggle/delete forms) — a bare <button> otherwise keeps the browser's own default chrome
   (background/border/padding), which made it look nothing like the plain, colorless <a>
   next to it. Reset + a real fixed-size hit target fixes both the mismatch and the "can
   barely see it" complaint in one place, for all admin tables site-wide. */
.admin-table__icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-chip-bg);
    color: var(--color-interactive);
    font: inherit;
    line-height: 1;
    cursor: pointer;
    text-decoration: none;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.admin-table__icon-btn--danger:hover {
    color: #a3271b;
    border-color: #a3271b;
}

:root[data-theme="dark"] .admin-table__icon-btn--danger:hover {
    color: #ff9a8a;
    border-color: #ff9a8a;
}

/* Red flag next to a job title in the admin list — description looks like it names a phone
   number or email (ContactInfoDetector), a policy-review hint, not a verdict. */
.admin-table__id {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
    user-select: all; /* one click-drag or triple-click grabs the whole id to copy */
}

.contact-flag {
    color: #ff6b6b;
    font-weight: 800;
    margin-right: var(--space-1);
    cursor: help;
}

.seo-status--ok {
    color: #6fd89a;
}

.seo-status--missing {
    color: #f0b160;
}

/* Status pills — moved here from StatusBadge.razor.css (deleted): CSS isolation only scopes
   to elements written by the component that owns a .razor.css file, so raw
   <span class="status-badge status-badge--live"> markup elsewhere (AdminCategories,
   AdminSourceVendors, Recruiter's job list, etc.) was never actually receiving these rules —
   same lesson .admin-page/.admin-card already document further up this file. The
   <StatusBadge> component still works the same, it just isn't the only thing styled by this
   now. */
.status-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 3px var(--space-3);
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 600;
    white-space: nowrap;
    border: 1px solid transparent;
}

.status-badge--pending {
    background: #fdf1e2;
    color: #a3620c;
    border-color: #f3d9ae;
}

.status-badge--live {
    background: #e5f6ec;
    color: #1c7a44;
    border-color: #bfe6cd;
}

.status-badge--rejected {
    background: #fdeceb;
    color: #a3271b;
    border-color: #f5c9c3;
}

.status-badge--blocked {
    background: #fbe2e3;
    color: #8f1d24;
    border-color: #f0c2c4;
}

.status-badge--expired,
.status-badge--draft {
    background: var(--color-chip-bg);
    color: var(--color-text-muted);
    border-color: var(--color-border);
}

/* Dark-theme variants for status badges. */
:root[data-theme="dark"] .status-badge--pending {
    background: #2a2013;
    color: #f0b160;
    border-color: #4a3218;
}

:root[data-theme="dark"] .status-badge--live {
    background: #123420;
    color: #6fd89a;
    border-color: #1c4a2e;
}

:root[data-theme="dark"] .status-badge--rejected {
    background: #3a1f1c;
    color: #ff9a8a;
    border-color: #4a2622;
}

:root[data-theme="dark"] .status-badge--blocked {
    background: #3a1013;
    color: #ff6b6b;
    border-color: #5c1a1f;
}

/* 960px, not the old 920px: three real columns (.form-row--3) plus its two
   gutters need the extra room to stay comfortable, not cramped, at the widest
   breakpoint — the shared .form-row/.form-row--3 rules above do the actual
   column-count work now, this is just the form's overall reading width. */
.admin-form {
    display: grid;
    gap: var(--space-6);
    max-width: 960px;
    /* Card wrapper — was a bare stack of fields directly on the page background,
       which read as one continuous strip (e.g. Parent category and Display order
       looked merged). --space-6 padding is already fluid via clamp(), so this
       needs no extra breakpoint to stay comfortable on narrow phones. */
    padding: var(--space-6);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
}

/* A hint that lives inside its .form-field (right under the input, sharing the
   field's own grid gap) instead of as a sibling after it — no negative margin
   needed, and it stays correctly spaced under a multi-line textarea too. */
.form-field .form-hint {
    margin-top: 0;
}

/* Recruiter profile's social-links section — SocialLinks.MaxCount fixed rows (platform select +
   URL input), not a JS-driven add/remove list, so this still works with JavaScript disabled. */
.social-link-row {
    display: flex;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}

.social-link-row select {
    flex: 0 0 auto;
    width: auto;
}

.social-link-row input {
    flex: 1;
    min-width: 0;
}

.icon-class-input {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.icon-class-input__preview {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.75rem;
    height: 2.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg-subtle);
    font-size: 1.1rem;
    color: var(--color-interactive);
}

.icon-class-input input {
    flex: 1;
}

.admin-form__code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--fs-sm);
}

.admin-form__checkbox-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 500;
}

.admin-table__group-row th {
    background: var(--color-bg-subtle);
    color: var(--color-accent);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    text-align: left;
}

.admin-table__group-count {
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
}

/* Vertical column dividers — opt-in modifier (`admin-table--bordered`), currently the recruiter
   "My jobs" table only. Off in card layout (each <td> is a block there, so a left border would
   draw a stray line down every card). */
.admin-table-wrap:not(.admin-table-wrap--cards) .admin-table--bordered th + th,
.admin-table-wrap:not(.admin-table-wrap--cards) .admin-table--bordered td + td {
    border-left: 1px solid var(--color-border);
}

@media (max-width: 640px) {
    .admin-table-wrap:not(.admin-table-wrap--table) .admin-table--bordered th + th,
    .admin-table-wrap:not(.admin-table-wrap--table) .admin-table--bordered td + td {
        border-left: none;
    }
}

/* Count cell that links somewhere (My jobs → Applications count → that job's applications). */
.admin-table__count-link {
    display: inline-block;
    min-width: 2rem;
    font-weight: 600;
    color: var(--color-interactive);
    text-decoration: none;
}

.admin-table__count-link:hover {
    text-decoration: underline;
}

/* Job summary card at the top of the recruiter's per-job Applications view. */
.job-summary {
    display: grid;
    gap: var(--space-4);
}

.job-summary__head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
}

.job-summary__title {
    margin: 0;
    font-size: var(--fs-xl, 1.35rem);
}

.job-summary__meta {
    margin: var(--space-1) 0 0;
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

.job-summary__badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.job-summary__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--space-3);
    margin: 0;
}

.job-summary__stats > div {
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.job-summary__stats dt {
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.job-summary__stats dd {
    margin: 0;
    font-size: var(--fs-xl, 1.35rem);
    font-weight: 700;
}

.job-summary__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* Full cover note on the application detail page — keeps the applicant's own line breaks. */
.application-cover-note {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* Removable active-filter tag inside a filter bar (e.g. "Job: Head Chef ×"). */
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-3);
    border-radius: 999px;
    background: var(--color-chip-bg);
    color: var(--color-text);
    font-size: var(--fs-sm);
}

.filter-chip a {
    color: var(--color-text-muted);
    font-size: 1.1rem;
    line-height: 1;
    text-decoration: none;
}

.filter-chip a:hover {
    color: var(--color-text);
}

/* Wide tables that still scroll sideways when they must (touch swipe, trackpad, shift+wheel,
   keyboard) but without the visible scrollbar strip under them. */
.admin-table-wrap--no-scrollbar {
    scrollbar-width: none;        /* Firefox */
    -ms-overflow-style: none;     /* legacy Edge */
}

.admin-table-wrap--no-scrollbar::-webkit-scrollbar {
    display: none;                /* Chrome / Safari */
}

/* Tighter cell padding so a many-column table (recruiter My jobs) overflows less. */
.admin-table--compact th,
.admin-table--compact td {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
}

/* Collapsible filter panel (native <details>) — same title + chevron pattern as
   .admin-integration-card, lighter (no card background: the filter bar inside has its own). */
.admin-filter-details {
    margin-bottom: var(--space-4);
}

.admin-filter-details__summary {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg-subtle);
    font-weight: 600;
    font-size: var(--fs-sm);
    cursor: pointer;
    list-style: none;
}

.admin-filter-details__summary::-webkit-details-marker {
    display: none;
}

.admin-filter-details__chevron {
    margin-left: auto;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--color-text-muted);
    border-bottom: 2px solid var(--color-text-muted);
    transform: rotate(45deg);
    transition: transform 150ms ease;
}

.admin-filter-details[open] > .admin-filter-details__summary .admin-filter-details__chevron {
    transform: rotate(-135deg);
}

.admin-filter-details[open] > .admin-filter-details__summary {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    border-bottom-color: transparent;
}

.admin-filter-details > .admin-filter-bar {
    margin-bottom: 0;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

/* Date range picker (site.js wires [data-date-range] up to flatpickr, loaded on demand). Without
   JS the two native date inputs show as-is; with JS they're hidden and one text input replaces
   them. `[hidden]` rules are explicit because these elements have their own `display`. */
.date-range {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex: 1 1 260px;
}

.date-range input[type="date"] {
    flex: 1 1 0;
    min-width: 0;
}

.date-range input.date-range__text {
    flex: 1 1 auto;
    min-width: 0;
    padding-right: 2rem;
    cursor: pointer;
}

.date-range--js input[type="date"],
.date-range__text[hidden],
.date-range__clear[hidden] {
    display: none;
}

.date-range__clear {
    position: absolute;
    right: var(--space-2);
    top: 50%;
    transform: translateY(-50%);
    padding: 0 var(--space-2);
    border: none;
    background: none;
    color: var(--color-text-muted);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
}

.date-range__clear:hover {
    color: var(--color-text);
}

/* flatpickr theming — its stock stylesheet is light-only; map the parts you actually see onto
   the design tokens so the popup follows light/dark like the rest of the panel. */
.flatpickr-calendar {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    box-shadow: var(--shadow-md);
    color: var(--color-text);
    font-family: var(--font-body);
}

.flatpickr-months .flatpickr-month,
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year,
span.flatpickr-weekday,
.flatpickr-day {
    color: var(--color-text);
    fill: var(--color-text);
}

.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
    fill: var(--color-text-muted);
}

.flatpickr-current-month .flatpickr-monthDropdown-months {
    background: var(--color-surface);
}

.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay,
.flatpickr-day.flatpickr-disabled {
    color: var(--color-text-muted);
}

.flatpickr-day:hover {
    background: var(--color-chip-bg);
    border-color: var(--color-chip-bg);
}

.flatpickr-day.today {
    border-color: var(--color-interactive);
}

.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-text-on-primary);
}

.flatpickr-day.inRange,
.flatpickr-day.inRange:hover {
    background: var(--color-chip-bg);
    border-color: var(--color-chip-bg);
    box-shadow: -5px 0 0 var(--color-chip-bg), 5px 0 0 var(--color-chip-bg);
}

.flatpickr-calendar.arrowTop::before,
.flatpickr-calendar.arrowTop::after {
    display: none;
}

/* Job title column on the recruiter "My jobs" table. With ten columns the browser's auto table
   layout squeezed this one to a few characters wide ("Multi / Email / Test / Chef" on four
   lines) while the numeric columns kept plenty of room. A min-width keeps titles readable
   (the wrap scrolls sideways instead, as it already did); above 640px only, since below that
   the table collapses to stacked cards where a min-width isn't wanted. */
@media (min-width: 641px) {
    .admin-table__job-cell {
        min-width: 15rem;
    }
}

.admin-table__job-cell a,
.admin-table__job-cell {
    font-weight: 600;
}

.admin-table__name-cell i {
    margin-right: var(--space-2);
    color: var(--color-interactive);
    width: 1.1em;
    text-align: center;
}

.admin-pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-border);
}

.admin-pagination__summary {
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

.admin-pagination__controls {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.admin-pagination__page {
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
    white-space: nowrap;
}

.btn--disabled {
    pointer-events: none;
    opacity: 0.4;
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 34px;
    width: 34px;
    padding: 0;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    background: var(--color-chip-bg);
    color: var(--color-primary);
    line-height: 1;
    cursor: pointer;
    transition: border-color 150ms ease, color 150ms ease, background-color 150ms ease;
}

.theme-toggle:hover {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

.theme-toggle .icon {
    stroke-width: 2;
}

.theme-toggle__sun,
.theme-toggle__moon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.theme-toggle__moon {
    display: none;
}

.theme-toggle[data-theme="light"] .theme-toggle__sun {
    display: inline-flex;
}

.theme-toggle[data-theme="light"] .theme-toggle__moon {
    display: none;
}

.theme-toggle[data-theme="dark"] .theme-toggle__sun {
    display: none;
}

.theme-toggle[data-theme="dark"] .theme-toggle__moon {
    display: inline-flex;
}

.theme-toggle[data-theme="dark"] {
    background: var(--color-chip-bg);
    color: var(--color-accent);
}

/* ---------- Dashboard shell (job seeker + recruiter panels) ----------
   global classes (not component-scoped) since two layouts need it —
   JobSeekerLayout.razor and RecruiterLayout.razor both render these classes.
   Same lesson StatusBadge.razor.css already taught this codebase: isolated
   one component uses belongs here instead. */

.dash-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
}

.dash-nav-toggle-input {
    position: absolute;
}

.dash-topbar {
    height: var(--header-height);
    flex: none;
    padding: 0 var(--space-5);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    position: sticky;
    top: 0;
    z-index: 20;
}

.dash-topbar__menu-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    color: var(--color-text);
    cursor: pointer;
}

.dash-topbar__menu-btn:hover {
    background: var(--color-chip-bg);
}

.dash-topbar__brand {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    text-decoration: none;
    color: var(--color-text);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: var(--fs-sm);
}

.dash-topbar__spacer {
    flex: 1;
}

.dash-topbar__account {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
}

.dash-topbar__role {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 var(--space-3);
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--color-accent) 52%, transparent);
    background: color-mix(in srgb, var(--color-accent) 18%, transparent);
    color: color-mix(in srgb, var(--color-accent) 88%, white);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.02em;
}

.dash-topbar__link {
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: var(--fs-sm);
    font-weight: 600;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--color-chip-bg);
}

.dash-topbar__link:hover {
    color: var(--color-text);
}

.dash-body {
    flex: 1;
    display: flex;
    align-items: stretch;
    min-height: 0;
}

.dash-scrim {
    display: none;
}

.dash-sidebar {
    width: 240px;
    flex: none;
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border-right: 1px solid var(--color-border);
}

/* Reused as the user-info block at the very top of the sidebar (see .dash-sidebar__profile
   below) — same spot AdminLayout's .admin-sidebar__brand occupies, and shown at every
   viewport width (not desktop-only) since it's the only place these panels show who's
   signed in, unlike the topbar's brand logo which is decorative. */
.dash-sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-4);
    border-bottom: 1px solid var(--color-border);
}

.dash-sidebar__nav {
    /* Sized to its links, not `flex: 1`: stretching it to fill the sidebar pinned the
       "Collapse" button to the very bottom, far from the menu. Still shrinks (and scrolls)
       when there are more links than fit, so the button never gets pushed off-screen. */
    flex: 0 1 auto;
    overflow-y: auto;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
    padding: var(--space-4) var(--space-3);
}

.dash-sidebar__nav::-webkit-scrollbar {
    width: 0;
    height: 0;
}

.dash-nav-link {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: var(--fs-sm);
    font-weight: 500;
    transition: background-color 150ms ease, color 150ms ease;
}

.dash-nav-link:hover {
    background: var(--color-chip-bg);
    color: var(--color-text);
}

.dash-nav-link--active {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
}

.dash-nav-link--active:hover {
    background: var(--color-primary);
    color: var(--color-text-on-primary);
}

.dash-nav-link .icon {
    flex: none;
    opacity: 0.9;
}

.dash-sidebar__profile {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-3);
}

.dash-sidebar__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex: none;
    border-radius: 50%;
    background: var(--color-chip-bg);
    color: var(--color-text-muted);
}

.dash-sidebar__profile-text {
    min-width: 0;
}

.dash-sidebar__profile-name {
    margin: 0;
    font-size: var(--fs-xs);
    font-weight: 500;
    color: var(--color-text-muted);
    line-height: 1.3;
    /* One line with an ellipsis ("test.recruiter@jobpingo.te…") instead of breaking an email
       mid-word onto a second line; the full address is in the element's title tooltip. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Desktop icon-rail collapse toggle, bottom of the sidebar — same pattern as
   AdminLayout's .admin-sidebar__collapse-btn (AdminLayout.razor.css). */
.dash-sidebar__collapse-btn {
    display: none;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-3);
    border-top: 1px solid var(--color-border);
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
    font-weight: 500;
    cursor: pointer;
}

.dash-sidebar__collapse-btn:hover {
    color: var(--color-text);
}

.dash-sidebar__collapse-btn .icon {
    flex: none;
    transform: rotate(90deg);
    transition: transform 200ms ease;
}

.dash-topbar__home-link,
.dash-topbar__logout-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex: none;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    background: var(--color-chip-bg);
    color: var(--color-interactive);
    cursor: pointer;
    transition: border-color 150ms ease, color 150ms ease;
}

.dash-topbar__home-link {
    text-decoration: none;
}

.dash-topbar__home-link:hover,
.dash-topbar__logout-btn:hover {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

.dash-logout-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text-muted);
    font-family: var(--font-body);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
    transition: border-color 150ms ease, color 150ms ease;
}

.dash-logout-btn:hover {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

.dash-main {
    flex: 1;
    min-width: 0;
}

@media (max-width: 959px) {
    .dash-body {
        position: relative;
        overflow-x: clip;
    }

    .dash-sidebar {
        position: fixed;
        top: var(--header-height);
        bottom: 0;
        left: 0;
        z-index: 30;
        transform: translateX(-100%);
        transition: transform 200ms ease;
        box-shadow: var(--shadow-md);
    }

    .dash-nav-toggle-input:checked ~ .dash-body .dash-sidebar {
        transform: translateX(0);
    }

    .dash-scrim {
        display: block;
        position: fixed;
        inset: var(--header-height) 0 0 0;
        background: rgba(0, 0, 0, 0.4);
        z-index: 25;
        opacity: 0;
        pointer-events: none;
        transition: opacity 200ms ease;
    }

    .dash-nav-toggle-input:checked ~ .dash-body .dash-scrim {
        opacity: 1;
        pointer-events: auto;
    }
}

/* Phones: the single-row topbar overflows, which pushed the role badge half off-screen and
   the logout button out of view. Drop the role badge (the sidebar already shows who you are),
   tighten spacing, and keep the account/logout cluster from ever shrinking away. */
@media (max-width: 559px) {
    .dash-topbar {
        padding: 0 var(--space-3);
        gap: var(--space-2);
    }

    .dash-topbar__role {
        display: none;
    }

    .dash-topbar__account {
        flex: none;
    }

    .dash-topbar__brand {
        min-width: 0;
    }

    .dash-topbar__link {
        white-space: nowrap;
        padding: var(--space-1) var(--space-2);
    }
}

@media (min-width: 960px) {
    .dash-topbar__menu-btn {
        display: none;
    }

    .dash-sidebar__collapse-btn {
        display: flex;
    }

    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar {
        width: 64px;
    }

    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar .dash-nav-link span,
    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar .dash-sidebar__profile-text,
    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar .dash-sidebar__collapse-btn span {
        display: none;
    }

    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar .dash-nav-link,
    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar .dash-sidebar__brand,
    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar .dash-sidebar__collapse-btn {
        justify-content: center;
    }

    .dash-sidebar-collapse-input:checked ~ .dash-body .dash-sidebar__collapse-btn .icon {
        transform: rotate(-90deg);
    }
}

/* PWA install popup — hidden by default (see wwwroot/site.js) */
.pwa-install {
    position: fixed;
    left: var(--space-4);
    right: var(--space-4);
    bottom: var(--space-4);
    z-index: 30;
    display: flex;
    align-items: center;
    gap: var(--space-4);
    max-width: 420px;
    margin: 0 auto;
    padding: var(--space-4) var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}

.pwa-install[hidden] {
    display: none;
}

.pwa-install__text {
    flex: 1;
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--color-text);
}

.pwa-install__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.pwa-install__dismiss {
    background: none;
    border: none;
    cursor: pointer;
    font-size: var(--fs-lg);
    line-height: 1;
    color: var(--color-text-muted);
    padding: var(--space-1);
}

/* /about — plain reading page. */
.about-page {
    max-width: 48rem;
}

.about-page h2 {
    margin: var(--space-6) 0 var(--space-2);
    font-size: var(--fs-lg);
}

.about-page .btn {
    margin: var(--space-2) var(--space-2) 0 0;
}

/* Type-ahead under the keyword / location boxes (site.js, input[data-suggest]). The box stays a plain
   input without JS; this wrapper only positions the dropdown. Global (not Home/Jobs scoped CSS) because
   the list is created by script at runtime and never gets a Blazor scope attribute. */
.suggest {
    position: relative;
    flex: 1;
    min-width: 0;
}

.suggest input {
    width: 100%;
}

.suggest__list {
    position: absolute;
    z-index: 40;
    top: calc(100% + var(--space-1));
    left: 0;
    right: 0;
    margin: 0;
    padding: var(--space-1) 0;
    list-style: none;
    text-align: left;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}

.suggest__list[hidden] {
    display: none;
}

.suggest__item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    color: var(--color-text);
    font-size: var(--fs-sm);
    cursor: pointer;
    text-decoration: none;
}

.suggest__item--active,
.suggest__item:hover {
    background: var(--color-bg-subtle);
}

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

.suggest__hint {
    flex-shrink: 0;
    color: var(--color-text-muted);
    font-size: var(--fs-xs);
}

/* An ad row holding two units side by side (Home: a pair on one row, a single on the other).
   Stacks on phones, where two ads next to each other would each be too narrow to be useful. */
.ad-row--pair {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-4);
}

@media (min-width: 640px) {
    .ad-row--pair {
        grid-template-columns: 1fr 1fr;
    }
}

.auth-forgot {
    margin: var(--space-2) 0 0;
    text-align: right;
    font-size: var(--fs-sm);
}

/* Links under a sign-in card's form ("Register", "Back to sign in") sit centred. */
.auth-frame__card .auth-switch {
    margin: 0;
    text-align: center;
}

.auth-frame__card .social-login-buttons {
    margin-bottom: var(--space-3);
}

/* Eye (show/hide) button inside a sign-in password box — added by site.js. */
.password-field {
    position: relative;
}

.password-field input {
    padding-right: 3rem;
}

.password-field__toggle {
    position: absolute;
    top: 50%;
    right: var(--space-2);
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
}

.password-field__toggle:hover {
    color: var(--color-interactive);
}

/* "Want your jobs listed?" panel (ListYourJobs.razor) — job portals / employers: contact the admin team, and the
   ways we can take their jobs in (RSS, REST API, custom). Cards use surface tokens so dark mode follows. */
.list-jobs {
    display: grid;
    gap: var(--space-5);
    padding: var(--space-6);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.list-jobs__intro h2 {
    margin: 0 0 var(--space-2);
}

.list-jobs__intro p {
    margin: 0;
    max-width: 68ch;
}

.list-jobs__grid {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: minmax(0, 1fr);
}

.list-jobs__card {
    padding: var(--space-4);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.list-jobs__card h3 {
    margin: var(--space-3) 0 var(--space-2);
    font-size: var(--fs-lg);
}

.list-jobs__card p {
    margin: 0;
    font-size: var(--fs-sm);
}

.list-jobs__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--color-primary-light);
    color: var(--color-interactive);
}

.list-jobs__steps {
    display: grid;
    gap: var(--space-2);
    margin: 0;
    padding-left: var(--space-5);
    font-size: var(--fs-sm);
}

.list-jobs > .btn {
    justify-self: start;
}

@media (min-width: 768px) {
    .list-jobs__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.post-a-job__lead {
    max-width: 68ch;
    font-size: var(--fs-lg);
}

.post-a-job .list-jobs {
    margin-block: var(--space-6);
}

/* Terms & Conditions (Terms.razor): readable column, jump links between the three term sets. */
.legal-page {
    max-width: 820px;
}

.legal-page__updated {
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
}

.legal-page__toc {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin: var(--space-4) 0 var(--space-5);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--color-border);
}

.legal-page h2 {
    margin-top: var(--space-6);
    scroll-margin-top: var(--header-height);
}

.legal-page__list {
    display: grid;
    gap: var(--space-3);
    padding-left: var(--space-5);
}

.legal-page__contact {
    margin-top: var(--space-6);
}

/* Source credit on a feed job ("Source: Himalayas") — required by the source's terms, so it stays visible but quiet. */
.job-hero__source-row {
    margin: 0 0 var(--space-3);
}

.job-hero__source {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: 999px;
    background: var(--color-badge-source);
    color: var(--color-badge-source-text);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-decoration: none;
}

.job-hero__source:hover {
    text-decoration: underline;
}

.job-hero__source-label {
    font-weight: 500;
    opacity: 0.75;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Phone: keep the logo beside the title instead of stacking it above (the title block is wider
   than the space left next to a 64px logo, so flex-wrap pushed it onto its own line). */
@media (max-width: 600px) {
    .job-hero__top {
        flex-wrap: nowrap;
        gap: var(--space-3);
    }

    .job-hero__top > div {
        flex: 1;
        min-width: 0;
    }

    .job-hero__logo {
        width: 48px;
        height: 48px;
        font-size: var(--fs-md, 1rem);
        flex-shrink: 0;
    }

    .job-hero__title {
        font-size: var(--fs-xl);
    }
}

/* Top progress bar while a page loads (started/stopped by site.js — see "Feedback while a page loads"). */
html.is-navigating {
    cursor: progress;
}

html.is-navigating::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    z-index: 9999;
    background: var(--color-accent, #ea580c);
    transform-origin: left;
    animation: nav-progress 20s cubic-bezier(0.1, 0.6, 0.2, 1) forwards;
}

@keyframes nav-progress {
    from { transform: scaleX(0.05); }
    to { transform: scaleX(0.95); }
}

@media (prefers-reduced-motion: reduce) {
    html.is-navigating::before {
        animation: none;
        transform: scaleX(0.6);
    }
}

.site-footer__version {
    margin-left: var(--space-2);
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
}

/* Short-term / contract jobs (ADR-0041): duration and start-date chips stand out from the plain type chips. */
.chip--short-term {
    background: var(--color-badge-source);
    color: var(--color-badge-source-text);
    font-weight: 600;
}

/* Public Talent directory and profile pages (ADR-0042). */
.talent-page__lead {
    max-width: 48rem;
    color: var(--color-text-muted);
}

.talent-filters {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) minmax(0, 1fr) auto auto;
    align-items: end;
    gap: var(--space-3) var(--space-4);
    margin: var(--space-5) 0;
    padding: var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
}

.talent-filters__check {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding-bottom: var(--space-3);
    font-size: var(--fs-sm);
    white-space: nowrap;
}

@media (max-width: 900px) {
    .talent-filters {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }

    .talent-filters .form-field:first-child,
    .talent-filters .btn {
        grid-column: 1 / -1;
    }
}

@media (max-width: 560px) {
    .talent-filters {
        grid-template-columns: minmax(0, 1fr);
    }
}

.talent-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.talent-card {
    display: flex;
    gap: var(--space-4);
    height: 100%;
    padding: var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    color: inherit;
    text-decoration: none;
}

.talent-card:hover {
    border-color: var(--color-interactive);
}

.talent-card__body {
    min-width: 0;
}

.talent-card__name {
    margin: 0;
    font-size: var(--fs-lg);
}

.talent-card__headline {
    margin: var(--space-1) 0;
    color: var(--color-text);
    overflow-wrap: anywhere;
}

.talent-card__meta {
    margin: 0 0 var(--space-2);
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
}

.talent-avatar {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    object-fit: cover;
}

.talent-avatar--large {
    width: 96px;
    height: 96px;
}

.talent-avatar--initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--color-badge-source);
    color: var(--color-badge-source-text);
    font-weight: 700;
    font-size: var(--fs-lg);
}

.talent-avatar--large.talent-avatar--initials {
    font-size: var(--fs-xl);
}

.talent-pager,
.talent-empty {
    margin-top: var(--space-5);
}

.talent-pager {
    display: flex;
    gap: var(--space-3);
}

.talent-profile__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-5);
    margin: var(--space-4) 0 var(--space-5);
}

.talent-profile__head h1 {
    margin: 0;
}

.talent-profile__headline {
    margin: var(--space-1) 0;
    font-size: var(--fs-lg);
}

.talent-profile__section {
    margin-bottom: var(--space-6);
}

.talent-profile__bio {
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.talent-connect {
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
}

.talent-profile__removal {
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
}

/* Radio/checkbox option cards (profile visibility + public consent). Declared after the
   generic `.form-field input` rule's specificity by using .choice input, so the 100%-wide,
   padded text-input styling doesn't stretch the control onto its own line. */
.choice-list {
    display: grid;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.choice,
.form-field label.choice {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-bg);
    cursor: pointer;
    font-size: var(--fs-sm);
    font-weight: 400;
    line-height: 1.5;
}

.choice:has(input:checked) {
    border-color: var(--color-interactive);
}

.form-field .choice input,
.choice input {
    flex: none;
    width: 18px;
    height: 18px;
    min-width: 18px;
    margin: 2px 0 0;
    padding: 0;
    accent-color: var(--color-interactive);
}

.choice__text {
    display: grid;
    gap: 2px;
    min-width: 0;
    overflow-wrap: anywhere;
}

.choice__text strong {
    font-size: var(--fs-base);
    font-weight: 600;
}

.choice__text > span {
    color: var(--color-text-muted);
}

.talent-consent .choice__text > span {
    color: var(--color-text);
}

/* Job seeker "My Profile": tighter than the shared admin form rhythm (24px card padding, 24px
   gaps, 32px nested-form padding and 1rem inputs made the page mostly whitespace). Scoped to
   .profile-page so other admin/recruiter forms keep the shared spacing. */
.profile-page .admin-grid-2,
.profile-page .admin-form-cards {
    gap: var(--space-4);
}

.profile-page .admin-card {
    display: grid;
    gap: var(--space-3);
    align-content: start;
    padding: var(--space-4);
}

.profile-page .admin-card__header {
    margin-bottom: 0;
}

.profile-page .admin-card h2 {
    font-size: var(--fs-base);
}

.profile-page .admin-card > p {
    margin: 0;
}

/* The upload forms are .admin-form (a bordered, padded card of their own) inside the card. */
.profile-page .admin-card > .admin-form {
    gap: var(--space-3);
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    max-width: none;
}

.profile-page .form-row {
    gap: var(--space-3);
}

.profile-page .form-field {
    gap: var(--space-1);
}

.profile-page .form-field label {
    font-size: var(--fs-sm);
}

.profile-page .form-field input:not([type="checkbox"]),
.profile-page .form-field select,
.profile-page .form-field textarea {
    padding: var(--space-2) var(--space-3);
    font-size: var(--fs-sm);
}

/* Plain checkbox inside a .form-field label (open to short-term work) — the generic
   `.form-field input` rule would otherwise make it a full-width padded box. */
.profile-page .form-field input[type="checkbox"] {
    width: auto;
    min-width: 0;
    padding: 0;
    margin-right: var(--space-2);
    accent-color: var(--color-interactive);
}

.profile-page .form-hint {
    margin: 0;
    font-size: var(--fs-xs);
    line-height: 1.45;
}

.profile-page .admin-grid-2 > .profile-span-all {
    grid-column: 1 / -1;
}

@media (max-width: 559px) {
    /* 16px keeps iOS from zooming the page when a field is focused. */
    .profile-page .form-field input:not([type="checkbox"]),
    .profile-page .form-field select,
    .profile-page .form-field textarea {
        font-size: 16px;
    }
}

/* Visibility dropdown + the note for whichever option is selected. */
.vis-picker__note {
    margin: 0;
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-subtle);
    border-left: 3px solid var(--color-interactive);
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
    line-height: 1.5;
}

.vis-picker__consent > * + * {
    margin-top: var(--space-2);
}

.vis-picker__consent .choice {
    font-size: var(--fs-xs);
    padding: var(--space-2) var(--space-3);
}

@supports selector(:has(*)) {
    .vis-picker [data-vis] {
        display: none;
    }

    .vis-picker:has(#visibility option[value="Private"]:checked) [data-vis="Private"],
    .vis-picker:has(#visibility option[value="RecruitersOnly"]:checked) [data-vis="RecruitersOnly"],
    .vis-picker:has(#visibility option[value="Public"]:checked) [data-vis="Public"] {
        display: block;
    }
}

/* "Post your jobs" panel: two paths (post yourself / connect a feed). */
@media (min-width: 768px) {
    .list-jobs__grid.list-jobs__grid--two {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.list-jobs__card--featured {
    position: relative;
    background: var(--color-surface);
    border-color: var(--color-interactive);
    box-shadow: var(--shadow-sm);
}

.list-jobs__badge {
    position: absolute;
    top: var(--space-4);
    right: var(--space-4);
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    background: var(--color-accent);
    color: #22200f;
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.list-jobs__points {
    margin: var(--space-3) 0 0;
    padding-left: var(--space-5);
    font-size: var(--fs-sm);
}

.list-jobs__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    /* Pushed to the bottom of its card (cards are flex columns, below) so the buttons of side-by-side cards share one line. */
    margin-top: auto !important;
    padding-top: var(--space-4);
}

/* Columns in the two-path panel stretch to equal height; the card content stacks so the action row can sit at the bottom. */
.list-jobs__grid--two .list-jobs__card {
    display: flex;
    flex-direction: column;
}

/* The icon box stays its own size instead of stretching in the column. */
.list-jobs__grid--two .list-jobs__icon {
    align-self: flex-start;
}

/* Small "Free" pill on the header's Post a Job link. */
.site-nav__pill {
    display: inline-block;
    margin-left: var(--space-1);
    padding: 1px 8px;
    border-radius: var(--radius-pill);
    background: var(--color-accent);
    color: #22200f;
    font-size: var(--fs-xs);
    font-weight: 700;
    vertical-align: middle;
}

/* Colour highlights for the two-path "Post your jobs" panel (owner request, 2026-10-07). --color-interactive, not
   --color-primary: in dark mode primary is a dark navy that vanishes on the dark card, while interactive turns coral. */
.list-jobs__card--featured {
    background: linear-gradient(180deg, var(--color-primary-light) 0%, var(--color-surface) 70%);
    border-width: 2px;
    border-top: 4px solid var(--color-accent);
}

.list-jobs__card--featured h3 {
    color: var(--color-interactive);
}

.list-jobs__card--featured .list-jobs__icon {
    background: var(--color-interactive);
    color: var(--color-text-on-primary);
}

.list-jobs__card--featured .list-jobs__points li::marker {
    color: var(--color-accent-dark);
}

.list-jobs__card--featured .btn--outline {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

.list-jobs__card--featured .btn--outline:hover {
    background: var(--color-interactive);
    color: var(--color-text-on-primary);
}

.list-jobs__grid--two .list-jobs__card:not(.list-jobs__card--featured) .btn--outline {
    border-color: var(--color-interactive);
    color: var(--color-interactive);
}

.list-jobs__grid--two .list-jobs__card:not(.list-jobs__card--featured) .btn--outline:hover {
    background: var(--color-interactive);
    color: var(--color-text-on-primary);
}

/* One level of boxes only: the outer panel was a white card around two more cards ("double box"). The panel is now
   plain, so just the two coloured cards read as boxes. Both are tinted; the first stays the stronger, "Free" one. */
.list-jobs {
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
    border-radius: 0;
}

.list-jobs__grid--two .list-jobs__card:not(.list-jobs__card--featured) {
    background: linear-gradient(180deg, var(--color-badge-source) 0%, var(--color-surface) 70%);
    border: 2px solid var(--color-border);
    border-top: 4px solid var(--color-interactive);
}

.list-jobs__grid--two .list-jobs__card:not(.list-jobs__card--featured) h3 {
    color: var(--color-interactive);
}

.list-jobs__grid--two .list-jobs__card:not(.list-jobs__card--featured) .list-jobs__icon {
    background: var(--color-interactive);
    color: var(--color-text-on-primary);
}

/* Job detail on very narrow / older phones (320-375px wide, e.g. iPhone 5/SE): nothing may be wider than the screen.
   The cause was chips and the source pill being `nowrap` (a long salary line or "Source: Hospitality Jobs Africa" ran off
   the right edge, hidden by body overflow-x) and the grid/flex items refusing to shrink below their content. */
@media (max-width: 960px) {
    .job-hero,
    .job-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .job-hero__main,
    .job-hero__top > div {
        min-width: 0;
    }
}

@media (max-width: 600px) {
    .job-hero__meta {
        gap: var(--space-2);
    }

    .job-hero__meta li {
        min-width: 0;
        max-width: 100%;
    }

    /* Long chips (salary text, category) wrap onto a second line instead of running off-screen. */
    .job-hero__meta .chip,
    .job-hero__source {
        max-width: 100%;
        white-space: normal;
        overflow-wrap: anywhere;
        border-radius: var(--radius-md);
    }

    .job-hero__source {
        flex-wrap: wrap;
    }

    .job-hero__title,
    .job-hero__company {
        overflow-wrap: anywhere;
    }
}

/* Save / Share: an icon plus a text label on desktop; on phones the label hides and they become round icon buttons. */
.job-hero__icon-btn {
    gap: var(--space-2);
}

.job-hero__icon-btn-label {
    display: inline;
}

/* Job detail, phone layout (<= 600px) — modelled on the compact "title + logo on the right, one fact per line, a big
   primary button with round icon buttons beside it" job pages phone users already know (owner's PNet reference).
   Replaces desktop sizes squeezed into a narrow column. */
@media (max-width: 600px) {
    /* Title on the left, company logo on the right. */
    .job-hero__top {
        flex-direction: row-reverse;
        align-items: flex-start;
        justify-content: space-between;
        gap: var(--space-3);
    }

    .job-hero__top > div {
        flex: 1;
        min-width: 0;
    }

    .job-hero__logo {
        width: 48px;
        height: 48px;
        font-size: var(--fs-base);
        border-radius: var(--radius-md);
    }

    .job-hero__title {
        margin: 0 0 var(--space-1);
        font-size: 1.15rem;
        line-height: 1.3;
    }

    .job-hero__company {
        margin-bottom: var(--space-2);
        font-size: var(--fs-sm);
        font-weight: 600;
    }

    .job-hero__source-row {
        margin-bottom: var(--space-3);
    }

    /* "via Hospitality Jobs Africa ↗" — one quiet line rather than a labelled badge. */
    .job-hero__source {
        padding: 1px 8px;
        font-size: 0.72rem;
    }

    .job-hero__source-label {
        display: none;
    }

    .job-hero__source::before {
        content: "via";
        opacity: 0.7;
    }

    /* One fact per line with its icon (location, posted, category, type, salary) — easy to scan, no pill clutter. */
    .job-hero__meta {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
        font-size: 0.86rem;
        color: var(--color-text);
    }

    .job-hero__meta li {
        gap: 10px;
    }

    .job-hero__meta .chip {
        padding: 0;
        background: none;
        border-radius: 0;
        font-size: 0.86rem;
        font-weight: 500;
        color: var(--color-text);
    }

    .job-hero__meta .chip.chip--short-term {
        padding: 2px 10px;
        background: var(--color-badge-source);
        border-radius: var(--radius-md);
        color: var(--color-badge-source-text);
        font-weight: 600;
    }

    .job-hero__meta svg {
        width: 16px;
        height: 16px;
    }

    /* Apply takes the row; Save and Share are round icon buttons beside it. */
    .job-hero__actions {
        flex-wrap: nowrap;
        align-items: center;
        gap: var(--space-2);
        margin-top: var(--space-4);
    }

    .job-hero__actions > a.btn,
    .job-hero__actions > .btn--disabled {
        flex: 1 1 auto;
        justify-content: center;
        min-width: 0;
        padding: 12px 14px;
        font-size: var(--fs-sm);
        white-space: normal;
    }

    .job-hero__actions > form {
        flex: 0 0 44px;
    }

    .job-hero__actions .job-hero__icon-btn {
        flex: 0 0 44px;
        width: 44px;
        height: 44px;
        padding: 0;
        justify-content: center;
        border-radius: 50%;
    }

    .job-hero__icon-btn-label {
        display: none;
    }

    .job-description h2,
    .job-details-card h2,
    .job-apply-card h2,
    .job-detail__apply-section h2,
    .job-detail__similar h2 {
        font-size: 1.05rem;
    }

    .job-description__body {
        font-size: var(--fs-sm);
        line-height: 1.6;
    }

    .breadcrumbs {
        font-size: 0.75rem;
    }
}
