/* ============================================================================
   easyjob design system — the canonical tokens and primitives
   ----------------------------------------------------------------------------
   Phase 1 of the UI/UX overhaul. This file is ADDITIVE: every class here is
   `ej-` prefixed so it cannot collide with the existing .btn / .card / .chip /
   .nav / .container rules that seven page stylesheets still own. Nothing on any
   page consumes it yet — pages migrate one per commit in later phases, each
   deleting its own forked rules as its markup moves over.

   It replaces, when that migration is done:
     · 7 separate :root blocks (style, jobs, profile, apply,
       employer-dashboard, company-profile, admin) whose --bg, --radius,
       --surface-2, --primary-soft and --shadow values disagree
     · 29 distinct border-radius values, 32 box-shadow, 89 font-size,
       47 max-width
     · .btn redefined in 8 files, .brand in 6, .nav in 4, .container in 4

   Load order, once pages start using it: easyjob.css FIRST, then the page's
   own stylesheet, so a page can still override during migration.
   ========================================================================== */

/* ── The one global reset ─────────────────────────────────────────────────────
   Four pages — apply, job, jobs, profile — reached Phase 9 with NO global
   box-sizing rule at all, because the reset lived in each page's own
   stylesheet: style.css, admin.css, employer-dashboard.css and
   company-profile.css each declare their own, and easyjob.css (the one file
   every page loads) declared none. apply.css says what that costs, in its own
   words: ".ej-container is width:100% plus padding-inline, and the site has no
   global box-sizing: border-box, so below its max-width the padding is added ON
   TOP of a full-width box and the container overflows its parent. Every page
   that uses it gets away with this only by zeroing the padding, which also
   removes the gutter — on a phone the cards then touch both edges."

   It belongs here, where all nineteen pages see it, and it is loaded FIRST so a
   page stylesheet can still override. A census of all 19 pages at 1440/1280/
   900/768/390/360 measured no change and no regression from adding it.
   Deliberately NOT copied from admin.css, which also zeroes every margin and
   padding globally — that is a far more aggressive reset and propagating it
   would restyle the whole site. */
/* ── Tokens ───────────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
}


:root {
  /* surface */
  --ej-bg: #f7fbff;
  --ej-surface: #ffffff;
  --ej-surface-2: #eef4fb;
  --ej-surface-3: #e6eef8;

  /* text */
  --ej-text: #0f172a;
  --ej-text-2: #334155;
  --ej-muted: #64748b;

  /* brand */
  --ej-primary: #2563eb;
  --ej-primary-2: #1d4ed8;
  --ej-primary-soft: #e8f1ff;
  --ej-primary-dark: #1e40af;

  /* ── Brand ────────────────────────────────────────────────────────────────
     NOT new colours. These are the values the "Start hiring free" button on
     /employers has always computed to, lifted verbatim from style.css's own
     :root (--primary / --primary-2) and from .btn--primary's two shadows.
     Browser-measured on #openEmployerAuthBtnHero before this block existed:

       background-image   linear-gradient(90deg, rgb(29,78,216), rgb(14,165,233))
       color              rgb(255,255,255)
       border             0px none
       box-shadow         rgba(29,78,216,.18) 0px 10px 24px
       box-shadow :hover  rgba(29,78,216,.22) 0px 14px 28px

     style.css, employer-dashboard.css, company-profile.css and job-checker.css
     each carried their own identical copy of that rule. This is the one
     definition all of them, and the design system, now point at.

     --ej-brand-from is the same blue as --ej-primary-2 below; it is named
     separately because its job is "the gradient starts here", not "primary,
     pressed". Nothing else in this file changes value. */
  --ej-brand-from: #1d4ed8;
  --ej-brand-to: #0ea5e9;
  --ej-brand-grad: linear-gradient(90deg, var(--ej-brand-from), var(--ej-brand-to));
  /* The 135deg variant is the lockup treatment company-profile.css already uses
     for .avatar-btn — the same two stops, turned for a square. */
  --ej-brand-grad-mark: linear-gradient(135deg, var(--ej-brand-from), var(--ej-brand-to));
  --ej-brand-shadow: 0 10px 24px rgba(29, 78, 216, .18);
  --ej-brand-shadow-hover: 0 14px 28px rgba(29, 78, 216, .22);

  /* semantic */
  --ej-success: #059669;
  --ej-success-soft: #d1fae5;
  --ej-warning: #d97706;
  --ej-warning-soft: #fef3c7;
  --ej-danger: #dc2626;
  --ej-danger-soft: #fee2e2;
  --ej-info: #0284c7;
  --ej-info-soft: #e0f2fe;

  /* borders */
  --ej-line: #e2e8f0;
  --ej-line-strong: #cbd5e1;

  /* radius */
  --ej-r-sm: 8px;
  --ej-r-md: 12px;
  --ej-r-lg: 18px;
  --ej-r-pill: 999px;

  /* elevation */
  --ej-e-1: 0 1px 2px rgba(15, 23, 42, .06);
  --ej-e-2: 0 8px 24px rgba(15, 23, 42, .08);
  --ej-e-3: 0 16px 40px rgba(15, 23, 42, .10);

  /* typography */
  --ej-fs-xs: 12px;
  --ej-fs-sm: 13px;
  --ej-fs-base: 15px;
  --ej-fs-md: 17px;
  --ej-fs-lg: 20px;
  --ej-fs-xl: 26px;
  --ej-fs-2xl: 34px;
  --ej-fs-3xl: 44px;

  --ej-lh-tight: 1.25;
  --ej-lh-base: 1.55;

  --ej-fw-normal: 400;
  --ej-fw-med: 550;
  --ej-fw-bold: 700;

  /* spacing */
  --ej-s-1: 4px;
  --ej-s-2: 8px;
  --ej-s-3: 12px;
  --ej-s-4: 16px;
  --ej-s-5: 24px;
  --ej-s-6: 32px;
  --ej-s-7: 48px;
  --ej-s-8: 64px;

  /* widths */
  --ej-max: 1160px;
  --ej-max-narrow: 760px;
  --ej-max-form: 620px;

  /* Type. The homepage stack, verbatim, promoted to a token.
     It was only ever declared in style.css, which jobs / job / profile /
     apply do not load, so those four pages rendered in the user agent's
     serif default. Measured, not assumed: computed font-family on body,
     headings, nav, buttons, inputs, selects, textareas and labels was
     "Times New Roman" on all four and this stack on the homepage. */
  --ej-font: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* The shared header's own height, so the space it will occupy can be
     reserved before chrome.js mounts it. Browser-measured on the mounted
     header: 69px at >=900, 61px below. */
  --ej-header-h: 69px;

  /* The apply page's sticky stage bar, measured and published at runtime by
     apply.js (it is one line at 1440 and wraps to two on a phone, so a fixed
     number would be wrong at one width or the other). Declared here, with a
     zero default, so that every page can use it in a scroll offset and nothing
     moves on the pages that never show the bar. */
  --ej-applybar-h: 0px;

  /* focus */
  --ej-ring: 0 0 0 3px rgba(37, 99, 235, .35);

  /* Layering. Added in Phase 2 for the sticky shared header. */
  --ej-z-header: 50;
}

/* Breakpoints — the three this system standardises on. Custom properties
   cannot be used in a media query, so these are documented here and written
   literally below; every new @media in this file uses one of them:
     640px   phone
     900px   tablet / nav collapse
     1200px  wide
   Existing page breakpoints (760, 768, 700, 680, 980, 920) are NOT rewritten
   in Phase 1 — each page maps onto this scale when its phase arrives. */

/* ── Base typography ──────────────────────────────────────────────────────────

   ONE global declaration, and only one: the font family.

   Phase 1 deliberately made no global element rules, because at that point
   nothing consumed this file and a `body { font-size }` here would have
   reflowed all 18 pages. That reasoning still holds for SIZE. It stopped
   holding for FAMILY the moment Phases 2-5 gave jobs, job, profile and apply
   a stylesheet that is easyjob.css plus their own — neither of which declared
   a font — while style.css, which does, was no longer loaded there. Those
   four pages have been rendering in Times New Roman.

   This rule cannot reflow anything. On every page that still loads style.css
   the value is byte-identical to the one style.css sets on body, and
   style.css loads after this file, so the homepage's own declaration remains
   the one in effect. Nothing about size, weight, line-height or hierarchy is
   touched here; those stay where each page already put them.

   Everything else in this section is still opt-in via .ej-type. */

body {
  font-family: var(--ej-font);
}

/* Form controls do not inherit the document font by default. `font-family`
   alone, NOT the `font` shorthand: the shorthand would also reset size,
   weight and line-height, and several pages set those on their controls on
   purpose. The defect is the family. */
button,
input,
select,
textarea,
optgroup {
  font-family: inherit;
}

.ej-type {
  font-size: var(--ej-fs-base);
  line-height: var(--ej-lh-base);
  color: var(--ej-text);
}
.ej-type h1, .ej-h1 { font-size: var(--ej-fs-2xl); line-height: var(--ej-lh-tight); font-weight: var(--ej-fw-bold); }
.ej-type h2, .ej-h2 { font-size: var(--ej-fs-xl); line-height: var(--ej-lh-tight); font-weight: var(--ej-fw-bold); }
.ej-type h3, .ej-h3 { font-size: var(--ej-fs-lg); line-height: var(--ej-lh-tight); font-weight: var(--ej-fw-med); }
.ej-lead   { font-size: var(--ej-fs-md); line-height: var(--ej-lh-base); color: var(--ej-text-2); }
.ej-small  { font-size: var(--ej-fs-sm); color: var(--ej-muted); }
.ej-micro  { font-size: var(--ej-fs-xs); color: var(--ej-muted); }

/* ── Layout ──────────────────────────────────────────────────────────────── */

.ej-container {
  width: 100%;
  max-width: var(--ej-max);
  margin-inline: auto;
  padding-inline: var(--ej-s-4);
}
.ej-container--narrow { max-width: var(--ej-max-narrow); }
.ej-container--form   { max-width: var(--ej-max-form); }

.ej-stack { display: flex; flex-direction: column; gap: var(--ej-s-4); }
.ej-stack--tight { gap: var(--ej-s-2); }
.ej-stack--loose { gap: var(--ej-s-6); }

.ej-row { display: flex; align-items: center; gap: var(--ej-s-3); flex-wrap: wrap; }
.ej-row--between { justify-content: space-between; }
.ej-row--end { justify-content: flex-end; }
.ej-row--nowrap { flex-wrap: nowrap; }

.ej-grid { display: grid; gap: var(--ej-s-4); grid-template-columns: repeat(12, minmax(0, 1fr)); }
.ej-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ej-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ej-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 900px) {
  .ej-grid--3, .ej-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .ej-grid, .ej-grid--2, .ej-grid--3, .ej-grid--4 { grid-template-columns: minmax(0, 1fr); }
  .ej-container { padding-inline: var(--ej-s-3); }
}

/* ── Brand lockup ────────────────────────────────────────────────────────────
   The wordmark is ALWAYS lowercase: easyjob. Only the legal entity keeps its
   capital — Easyjob Technologies Private Limited — and that belongs in footer
   legal copy, never in this lockup.

   The tagline is fixed copy: "Apply smarter. Get shortlisted faster."
   Two sentences, two full stops, sentence case. It is not re-worded, not
   title-cased, and not shortened.

   Variants:
     .ej-brand              mark + name inline (the default)
     .ej-brand--stacked     mark + name, tagline beneath  (footer, hero, auth)
     .ej-brand--compact     mark + name only, smaller     (mobile header)
   A compact lockup never shows the tagline, even if the markup includes it. */

.ej-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--ej-s-2);
  text-decoration: none;
  color: var(--ej-text);
}

.ej-brand__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: var(--ej-r-sm);
  /* The flat --ej-primary is not one of the two stops the rest of the brand is
     built from. The mark takes the same pair, in the same 135deg treatment
     company-profile.css gives its own square lockup. */
  background: var(--ej-brand-grad-mark);
  color: #fff;
  font-size: var(--ej-fs-md);
  line-height: 1;
  font-weight: var(--ej-fw-bold);
}

.ej-brand__name {
  font-size: var(--ej-fs-lg);
  font-weight: var(--ej-fw-bold);
  letter-spacing: -0.01em;
  line-height: var(--ej-lh-tight);
  text-transform: lowercase; /* the brand cannot be shouted, even by a parent */
  color: var(--ej-text);
}

.ej-brand__tagline {
  display: block;
  margin-top: var(--ej-s-1);
  font-size: var(--ej-fs-sm);
  font-weight: var(--ej-fw-normal);
  line-height: var(--ej-lh-base);
  color: var(--ej-muted);
  text-transform: none;
  letter-spacing: 0;
}

/* Stacked: the name and tagline form a block beside the mark. */
.ej-brand--stacked {
  align-items: flex-start;
  gap: var(--ej-s-3);
}
.ej-brand--stacked .ej-brand__mark { margin-top: 2px; }
.ej-brand--stacked .ej-brand__body { display: flex; flex-direction: column; }

/* Compact: header-sized, tagline suppressed. */
.ej-brand--compact { gap: var(--ej-s-2); }
.ej-brand--compact .ej-brand__mark { width: 26px; height: 26px; flex-basis: 26px; font-size: var(--ej-fs-base); }
.ej-brand--compact .ej-brand__name { font-size: var(--ej-fs-md); }
.ej-brand--compact .ej-brand__tagline { display: none; }

/* On a phone the tagline is noise in any inline lockup. */
@media (max-width: 640px) {
  .ej-brand:not(.ej-brand--stacked) .ej-brand__tagline { display: none; }
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */

.ej-btn {
  --_ej-btn-bg: var(--ej-surface);
  --_ej-btn-fg: var(--ej-text);
  --_ej-btn-bd: var(--ej-line-strong);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ej-s-2);
  min-height: 42px;
  padding: 0 var(--ej-s-4);
  border: 1px solid var(--_ej-btn-bd);
  border-radius: var(--ej-r-md);
  background: var(--_ej-btn-bg);
  color: var(--_ej-btn-fg);
  font: inherit;
  font-size: var(--ej-fs-base);
  font-weight: var(--ej-fw-med);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, transform .15s ease;
}
/* Each variant names its own hover fill. This used to be a flat
   `background: var(--ej-surface-2)`, which out-specifies .ej-btn's own
   `background: var(--_ej-btn-bg)` — so a variant that changed only the custom
   property did not change on hover, it turned the default light grey-blue.
   Browser-measured: hovering Find jobs, the homepage's final CTA and the
   header's Sign up gave rgb(238,244,251) under rgb(255,255,255) text. */
.ej-btn:hover { background: var(--_ej-btn-bg-hover, var(--ej-surface-2)); }
.ej-btn:active { transform: translateY(1px); }

/* The brand treatment, identical to the one /employers has always shown on
   "Start hiring free": the 90deg gradient, white text, no visible border and
   the lifted shadow. The border stays in the box at 1px transparent so no
   button changes size, and --_ej-btn-bg stays a solid colour underneath as the
   fallback if the gradient ever fails to paint. */
.ej-btn--primary {
  --_ej-btn-bg: var(--ej-brand-from);
  --_ej-btn-bg-hover: var(--ej-brand-from);
  --_ej-btn-fg: #fff;
  --_ej-btn-bd: transparent;
  background-image: var(--ej-brand-grad);
  /* THE 1px BORDER IS WHY THIS LINE EXISTS.
     .ej-btn's `background` shorthand leaves background-origin at padding-box
     while background-clip stays border-box, so the gradient is SIZED to a box
     2px narrower than the one it is PAINTED into, and the default
     background-repeat tiles it to fill the difference. The 1px strips then show
     the tile wrapping: the gradient's end colour down the left edge and its
     start colour — the dark blue — down the right. Browser-measured on Find
     jobs at 1280: column 135 was rgb(14,165,233) and column 136, the last one,
     was rgb(29,78,216).
     /employers never had it because .btn--primary has no border at all, so its
     two boxes are the same box. Removing the border here would match that, but
     it would also make every one of these buttons 2px smaller. Sizing the
     gradient to the border box fixes the cause and changes nothing else. */
  background-origin: border-box;
  box-shadow: var(--ej-brand-shadow);
}
/* The gradient does not change on hover — the lift does, exactly as it does on
   /employers. background-image is re-declared because .ej-btn:hover sets the
   `background` shorthand, which would otherwise drop it. */
.ej-btn--primary:hover {
  background-image: var(--ej-brand-grad);
  /* Re-declared for the same reason the image is: .ej-btn:hover's `background`
     shorthand resets the origin as well. */
  background-origin: border-box;
  box-shadow: var(--ej-brand-shadow-hover);
}

.ej-btn--ghost {
  --_ej-btn-bg: transparent;
  --_ej-btn-bd: var(--ej-line);
}
.ej-btn--ghost { --_ej-btn-bg-hover: var(--ej-primary-soft); }
.ej-btn--ghost:hover { --_ej-btn-bd: var(--ej-primary-soft); }

.ej-btn--danger {
  --_ej-btn-bg: var(--ej-danger);
  --_ej-btn-bg-hover: #b91c1c;
  --_ej-btn-fg: #fff;
  --_ej-btn-bd: var(--ej-danger);
}
.ej-btn--danger:hover { --_ej-btn-bd: #b91c1c; }

.ej-btn--sm { min-height: 34px; padding: 0 var(--ej-s-3); font-size: var(--ej-fs-sm); }
.ej-btn--lg { min-height: 50px; padding: 0 var(--ej-s-5); font-size: var(--ej-fs-md); }
.ej-btn--full { width: 100%; }

.ej-btn:disabled,
.ej-btn[disabled],
.ej-btn[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
  transform: none;
}

/* Loading: the label stays (so the button does not resize) and a spinner
   leads it. aria-busy is the accessible half; the class is the visual half. */
.ej-btn--loading { pointer-events: none; }
.ej-btn--loading::before {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  animation: ej-spin .7s linear infinite;
}
@keyframes ej-spin { to { transform: rotate(360deg); } }

/* ── Cards ───────────────────────────────────────────────────────────────── */

.ej-card {
  background: var(--ej-surface);
  border: 1px solid var(--ej-line);
  border-radius: var(--ej-r-lg);
  box-shadow: var(--ej-e-2);
  padding: var(--ej-s-5);
}
.ej-card--flat { box-shadow: none; }
.ej-card--pad-sm { padding: var(--ej-s-4); }
.ej-card--interactive {
  cursor: pointer;
  transition: box-shadow .15s ease, border-color .15s ease, transform .15s ease;
}
.ej-card--interactive:hover {
  box-shadow: var(--ej-e-3);
  border-color: var(--ej-line-strong);
  transform: translateY(-1px);
}
.ej-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ej-s-3); margin-bottom: var(--ej-s-4); }
.ej-card__title { font-size: var(--ej-fs-md); font-weight: var(--ej-fw-med); line-height: var(--ej-lh-tight); }

/* ── Forms ───────────────────────────────────────────────────────────────── */

.ej-field { display: flex; flex-direction: column; gap: var(--ej-s-2); }

.ej-label {
  font-size: var(--ej-fs-sm);
  font-weight: var(--ej-fw-med);
  color: var(--ej-text-2);
}
.ej-label__req { color: var(--ej-danger); margin-left: 2px; }

.ej-input,
.ej-select,
.ej-textarea {
  /* Load-bearing, and scoped on purpose rather than a global reset.
     `width: 100%` on a content-box control adds its 12px of horizontal
     padding and 1px border on top of the column: measured at 1280, the
     Expected salary input rendered 271px inside a 245px grid cell and its
     right edge landed 10px PAST the start of the Notice period field, with
     the 3px focus ring on top of that. The gap was never missing — the
     control was wider than the cell it sits in. */
  box-sizing: border-box;
  width: 100%;
  min-height: 42px;
  padding: var(--ej-s-2) var(--ej-s-3);
  border: 1px solid var(--ej-line-strong);
  border-radius: var(--ej-r-md);
  background: var(--ej-surface);
  color: var(--ej-text);
  font: inherit;
  font-size: var(--ej-fs-base);
  line-height: var(--ej-lh-base);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.ej-textarea { min-height: 110px; resize: vertical; }
.ej-select { appearance: none; padding-right: var(--ej-s-6); background-image: linear-gradient(45deg, transparent 50%, var(--ej-muted) 50%), linear-gradient(135deg, var(--ej-muted) 50%, transparent 50%); background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; }

.ej-input::placeholder,
.ej-textarea::placeholder { color: var(--ej-muted); }

.ej-input:disabled,
.ej-select:disabled,
.ej-textarea:disabled { background: var(--ej-surface-2); opacity: .7; cursor: not-allowed; }

.ej-help { font-size: var(--ej-fs-sm); color: var(--ej-muted); }
.ej-error { font-size: var(--ej-fs-sm); color: var(--ej-danger); font-weight: var(--ej-fw-med); }

.ej-field--invalid .ej-input,
.ej-field--invalid .ej-select,
.ej-field--invalid .ej-textarea { border-color: var(--ej-danger); }

/* ── Chips ───────────────────────────────────────────────────────────────── */

.ej-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ej-s-2);
  min-height: 30px;
  padding: 0 var(--ej-s-3);
  border: 1px solid var(--ej-line);
  border-radius: var(--ej-r-pill);
  background: var(--ej-surface-2);
  color: var(--ej-text-2);
  font-size: var(--ej-fs-sm);
  line-height: 1;
  white-space: nowrap;
}
button.ej-chip { cursor: pointer; font: inherit; font-size: var(--ej-fs-sm); }

.ej-chip--selected {
  background: var(--ej-primary-soft);
  border-color: var(--ej-primary);
  color: var(--ej-primary-dark);
  font-weight: var(--ej-fw-med);
}
.ej-chip--removable { padding-right: var(--ej-s-2); }
.ej-chip__x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 0;
  border-radius: var(--ej-r-pill);
  background: transparent;
  color: inherit;
  font-size: var(--ej-fs-sm);
  line-height: 1;
  cursor: pointer;
}
.ej-chip__x:hover { background: rgba(15, 23, 42, .08); }

/* Match semantics: a skill the job asked for and the candidate has, versus
   one the job asked for and the candidate does not. */
.ej-chip--match   { background: var(--ej-success-soft); border-color: var(--ej-success); color: #065f46; }
.ej-chip--missing { background: var(--ej-danger-soft);  border-color: var(--ej-danger);  color: #991b1b; }

/* ── Badges ──────────────────────────────────────────────────────────────── */

.ej-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--ej-s-1);
  padding: 2px var(--ej-s-2);
  border-radius: var(--ej-r-sm);
  font-size: var(--ej-fs-xs);
  font-weight: var(--ej-fw-med);
  line-height: 1.5;
  white-space: nowrap;
}
.ej-badge--neutral { background: var(--ej-surface-2);    color: var(--ej-text-2); }
.ej-badge--success { background: var(--ej-success-soft); color: #065f46; }
.ej-badge--warning { background: var(--ej-warning-soft); color: #92400e; }
.ej-badge--danger  { background: var(--ej-danger-soft);  color: #991b1b; }
.ej-badge--info    { background: var(--ej-info-soft);    color: #075985; }

/* ── Screen-reader-only text ──────────────────────────────────────────────────
   Phase 8 put this in admin.css because that was the only page that needed it.
   The application tracker needs it too, so it moves to the shared system
   rather than being copied a second time; admin.css's identical copy is
   removed in the same commit. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── Status pills (application lifecycle) ────────────────────────────────── */

.ej-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--ej-s-2);
  min-height: 26px;
  padding: 0 var(--ej-s-3);
  border-radius: var(--ej-r-pill);
  background: var(--ej-surface-2);
  color: var(--ej-text-2);
  font-size: var(--ej-fs-xs);
  font-weight: var(--ej-fw-med);
  line-height: 1;
  white-space: nowrap;
}
.ej-pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 6px;
}
.ej-pill--applied     { background: var(--ej-info-soft);    color: #075985; }
.ej-pill--shortlisted { background: var(--ej-success-soft); color: #065f46; }
.ej-pill--rejected    { background: var(--ej-danger-soft);  color: #991b1b; }
.ej-pill--pending     { background: var(--ej-warning-soft); color: #92400e; }

/* ── Alerts ──────────────────────────────────────────────────────────────── */

.ej-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--ej-s-3);
  padding: var(--ej-s-4);
  border: 1px solid var(--ej-line);
  border-left-width: 3px;
  border-radius: var(--ej-r-md);
  background: var(--ej-surface-2);
  color: var(--ej-text-2);
  font-size: var(--ej-fs-base);
  line-height: var(--ej-lh-base);
}
.ej-alert__title { font-weight: var(--ej-fw-med); color: var(--ej-text); margin-bottom: var(--ej-s-1); }
.ej-alert--info    { background: var(--ej-info-soft);    border-color: var(--ej-info);    border-left-color: var(--ej-info); }
.ej-alert--success { background: var(--ej-success-soft); border-color: var(--ej-success); border-left-color: var(--ej-success); }
.ej-alert--warning { background: var(--ej-warning-soft); border-color: var(--ej-warning); border-left-color: var(--ej-warning); }
.ej-alert--error   { background: var(--ej-danger-soft);  border-color: var(--ej-danger);  border-left-color: var(--ej-danger); }

/* ── Empty state ─────────────────────────────────────────────────────────── */

.ej-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ej-s-3);
  padding: var(--ej-s-7) var(--ej-s-5);
  border: 1px dashed var(--ej-line-strong);
  border-radius: var(--ej-r-lg);
  background: var(--ej-surface);
  text-align: center;
}
.ej-empty__icon  { font-size: var(--ej-fs-2xl); line-height: 1; color: var(--ej-muted); }
.ej-empty__title { font-size: var(--ej-fs-md); font-weight: var(--ej-fw-med); color: var(--ej-text); }
.ej-empty__body  { font-size: var(--ej-fs-base); color: var(--ej-muted); max-width: 46ch; }

/* ── Meter (scores: easyjob Match 0–100, Application Score, CV score) ─────── */

.ej-meter { display: flex; flex-direction: column; gap: var(--ej-s-1); min-width: 140px; }
.ej-meter__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--ej-s-2); }
.ej-meter__value { font-size: var(--ej-fs-md); font-weight: var(--ej-fw-bold); color: var(--ej-text); }
.ej-meter__label { font-size: var(--ej-fs-xs); color: var(--ej-muted); }
.ej-meter__track {
  height: 8px;
  border-radius: var(--ej-r-pill);
  background: var(--ej-surface-2);
  overflow: hidden;
}
.ej-meter__fill {
  display: block;
  height: 100%;
  border-radius: var(--ej-r-pill);
  background: var(--ej-primary);
  transition: width .3s ease;
}
.ej-meter--strong .ej-meter__fill { background: var(--ej-success); }
.ej-meter--mid    .ej-meter__fill { background: var(--ej-warning); }
.ej-meter--low    .ej-meter__fill { background: var(--ej-danger); }
/* A score that does not exist is not a zero — render the track empty and say so
   in the value slot ("—"), never a 0% fill that reads as a real result. */
.ej-meter--none .ej-meter__fill { width: 0; }

/* ── Focus, one treatment for everything interactive ─────────────────────── */

.ej-btn:focus-visible,
.ej-chip:focus-visible,
.ej-chip__x:focus-visible,
.ej-card--interactive:focus-visible,
.ej-input:focus-visible,
.ej-select:focus-visible,
.ej-textarea:focus-visible,
a:focus-visible {
  outline: 2px solid transparent;   /* keeps a visible ring in forced-colors */
  outline-offset: 2px;
  box-shadow: var(--ej-ring);
  border-color: var(--ej-primary);
}

/* Inputs also ring on plain :focus, because a click into a field should show
   where the caret went. */
.ej-input:focus,
.ej-select:focus,
.ej-textarea:focus {
  outline: none;
  border-color: var(--ej-primary);
  box-shadow: var(--ej-ring);
}

.ej-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── Reduced motion ──────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .ej-btn,
  .ej-card--interactive,
  .ej-input, .ej-select, .ej-textarea,
  .ej-meter__fill {
    transition: none;
  }
  .ej-btn:active,
  .ej-card--interactive:hover { transform: none; }
  .ej-btn--loading::before { animation: none; }
}

/* ═════════════════════════════════════════════════════════════════════════════
   SHARED CHROME — the site header and the site footer
   ─────────────────────────────────────────────────────────────────────────────
   Added in Phase 2, consumed by public/js/lib/chrome.js. These rules replace
   the per-page .site-header / .nav / .nav__inner / .brand / .site-footer blocks
   that were duplicated (and drifting) across style.css, jobs.css, profile.css
   and apply.css.

   Breakpoint note: the nav collapses to the burger at 980px, which is the width
   every page except Jobs already used. Jobs collapsed at 720px and so had no
   menu at all between 721px and 980px. Keeping 980 means no page shifts at a
   width where it did not shift before; the design system's 640/900/1200 scale
   still governs everything else here.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ── [hidden] must actually hide ─────────────────────────────────────────────
   The UA stylesheet's rule is `[hidden] { display: none }` at specificity
   (0,1,0). A component class — .ej-btn, .ej-nav__link — is also (0,1,0) and
   comes later, so it WINS: an action the auth state hid stayed painted, and a
   signed-out visitor saw Log in, Sign up, Log out and the neutral chip stacked
   on top of one another, with every role-gated destination visible. Browser
   verification caught it; nothing at the attribute level could, because the
   attribute was set correctly the whole time.

   Scoped to the shared chrome rather than declared globally, so no page's own
   display handling changes. */

.ej-header [hidden],
.ej-footer [hidden],
.ej-header[hidden],
.ej-footer[hidden] {
  display: none !important;
}

/* ── Header shell ────────────────────────────────────────────────────────── */

/* ── Reserving the chrome's space ──────────────────────────────────────────────
   #ejHeader ships as an empty <div> and chrome.js fills it after first paint.
   Nothing reserved its height, so the whole page jumped down the moment the
   header arrived. Measured with a layout-shift observer at 1280x900 before this
   change: /jobs scored CLS 0.338 ("poor" by Core Web Vitals), /apply 0.333 on a
   third of loads, /profile 0.052 — and on every one of them the shift's own
   recorded source was the element the header had pushed down.

   The reservation is the header's real height, carried in a token the header
   itself uses, so the two cannot drift. Not an arbitrary number, and not a
   fixed height on the header: min-height only, so a wrapping header still
   grows. The footer needs no such treatment — it varies from 300px to 798px as
   its columns stack, and it was only ever moving because the header above it
   moved. */
#ejHeader {
  min-height: var(--ej-header-h);
}

.ej-header {
  min-height: var(--ej-header-h);
  position: sticky;
  top: 0;
  z-index: var(--ej-z-header, 50);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(140%) blur(8px);
  -webkit-backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--ej-line);
}

.ej-header__inner {
  width: min(100% - 32px, var(--ej-max));
  margin-inline: auto;
  min-height: calc(var(--ej-header-h) - 1px);   /* the 1px is .ej-header's border-bottom */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ej-s-3);
}

/* The brand-only header used by the app-shell and admin pages. */
.ej-header--brand { position: static; background: none; backdrop-filter: none; border-bottom: 0; }
.ej-header__inner--brand { min-height: 0; justify-content: flex-start; width: 100%; }

/* ── Primary nav ─────────────────────────────────────────────────────────── */

.ej-nav { min-width: 0; }

.ej-nav__list {
  display: flex;
  align-items: center;
  gap: var(--ej-s-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ej-nav__link {
  display: inline-block;
  padding: 6px 2px;
  font-size: var(--ej-fs-sm);
  font-weight: var(--ej-fw-med);
  line-height: var(--ej-lh-tight);
  color: var(--ej-text-2);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.ej-nav__link:hover { color: var(--ej-text); }

.ej-nav__link--active {
  color: var(--ej-primary);
  border-bottom-color: var(--ej-primary);
}

/* Between the collapse point and the wide breakpoint an employer carries two
   extra destinations, so the row tightens rather than wrapping or clipping. */
@media (min-width: 980px) and (max-width: 1200px) {
  .ej-nav__list { gap: var(--ej-s-3); }
  .ej-nav__link { font-size: var(--ej-fs-xs); }
}

/* ── Auth actions ────────────────────────────────────────────────────────── */

.ej-nav__actions {
  display: flex;
  align-items: center;
  gap: var(--ej-s-2);
}

/* The neutral account state: shown when the session or the role is unconfirmed.
   It is deliberately not a button — there is nothing honest to click yet. */
.ej-nav__account {
  display: inline-block;
  padding: 4px 10px;
  border: 1px solid var(--ej-line);
  border-radius: var(--ej-r-pill);
  background: var(--ej-surface-2);
  color: var(--ej-muted);
  font-size: var(--ej-fs-xs);
  font-weight: var(--ej-fw-med);
  line-height: var(--ej-lh-tight);
  white-space: nowrap;
}

/* ── Burger ──────────────────────────────────────────────────────────────── */

.ej-nav__burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 42px;
  height: 42px;
  padding: 0 10px;
  border: 1px solid var(--ej-line);
  border-radius: var(--ej-r-sm);
  background: var(--ej-surface);
  cursor: pointer;
}
.ej-nav__burger-bar {
  display: block;
  height: 2px;
  width: 100%;
  border-radius: 2px;
  background: var(--ej-text);
}

/* ── Mobile sheet ────────────────────────────────────────────────────────── */

.ej-nav__mobile {
  width: min(100% - 32px, var(--ej-max));
  margin-inline: auto;
  padding: var(--ej-s-3) 0 var(--ej-s-5);
  border-top: 1px solid var(--ej-line);
}
.ej-nav__mobile[hidden] { display: none; }

.ej-nav__list--mobile {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
}
.ej-nav__list--mobile .ej-nav__link {
  display: block;
  padding: var(--ej-s-3) 2px;
  font-size: var(--ej-fs-base);
  border-bottom: 1px solid var(--ej-line);
}
.ej-nav__list--mobile .ej-nav__link--active { border-bottom-color: var(--ej-primary); }

.ej-nav__actions--mobile {
  flex-direction: column;
  align-items: stretch;
  gap: var(--ej-s-2);
  margin-top: var(--ej-s-4);
}
.ej-nav__actions--mobile .ej-btn { width: 100%; }
.ej-nav__actions--mobile .ej-nav__account { text-align: center; }

/* Below the collapse point the row becomes brand + burger, nothing else. */
@media (max-width: 979px) {
  /* One number, not two: the inner follows the token and #ejHeader's
     reservation follows it too. */
  :root { --ej-header-h: 61px; }
  .ej-nav,
  .ej-header__inner > .ej-nav__actions { display: none; }
  .ej-nav__burger { display: flex; }
}

/* Above it the sheet can never be showing, whatever a stale [hidden] says. */
@media (min-width: 980px) {
  .ej-nav__mobile { display: none; }
}

/* ── Footer ──────────────────────────────────────────────────────────────── */

.ej-footer {
  margin-top: var(--ej-s-8);
  padding: var(--ej-s-7) 0 var(--ej-s-5);
  background: var(--ej-surface-2);
  border-top: 1px solid var(--ej-line);
  color: var(--ej-text-2);
  font-size: var(--ej-fs-sm);
}

.ej-footer__top {
  width: min(100% - 32px, var(--ej-max));
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(260px, 1fr) 2fr;
  gap: var(--ej-s-7);
  align-items: start;
}

.ej-footer__brand-block { display: grid; gap: var(--ej-s-2); }
.ej-footer__legal-name { margin: var(--ej-s-2) 0 0; font-weight: var(--ej-fw-med); color: var(--ej-text); }
.ej-footer__recognition { margin: 0; color: var(--ej-muted); font-size: var(--ej-fs-xs); }
.ej-footer__social { margin: var(--ej-s-1) 0 0; }
.ej-footer__social a { color: var(--ej-primary); text-decoration: none; font-weight: var(--ej-fw-med); }
.ej-footer__social a:hover { text-decoration: underline; }

.ej-footer__links {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--ej-s-5);
}
/* No text-transform here. One of these headings IS the product brand, and the
   brand is lowercase everywhere — an uppercase eyebrow style would render it
   "EASYJOB", which is precisely the drift Phase 1 removed from the page copy.
   The weight, size and tracking carry the eyebrow look without shouting. */
.ej-footer__column-title {
  margin: 0 0 var(--ej-s-2);
  font-size: var(--ej-fs-xs);
  font-weight: var(--ej-fw-bold);
  letter-spacing: 0.08em;
  color: var(--ej-muted);
}
.ej-footer__column-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--ej-s-2); }
.ej-footer__column-list a { color: var(--ej-text-2); text-decoration: none; }
.ej-footer__column-list a:hover { color: var(--ej-primary); }

.ej-footer__bottom {
  width: min(100% - 32px, var(--ej-max));
  margin-inline: auto;
  margin-top: var(--ej-s-6);
  padding-top: var(--ej-s-4);
  border-top: 1px solid var(--ej-line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ej-s-3);
  font-size: var(--ej-fs-xs);
  color: var(--ej-muted);
}
.ej-footer__copyright { margin: 0; }
.ej-footer__bottom-links { display: flex; flex-wrap: wrap; gap: var(--ej-s-4); margin: 0; padding: 0; list-style: none; }
.ej-footer__bottom-links a { color: var(--ej-muted); text-decoration: none; }
.ej-footer__bottom-links a:hover { color: var(--ej-primary); }

/* The simplified footer: brand, legal entity, DPIIT recognition. Nothing else. */
.ej-footer--minimal { margin-top: var(--ej-s-6); padding: var(--ej-s-5) 0; }
.ej-footer__bottom--minimal { margin-top: 0; padding-top: 0; border-top: 0; align-items: flex-start; }
.ej-footer__brand-block--minimal { gap: var(--ej-s-1); }

@media (max-width: 900px) {
  .ej-footer__top { grid-template-columns: 1fr; gap: var(--ej-s-6); }
}
@media (max-width: 640px) {
  .ej-footer__links { grid-template-columns: 1fr; gap: var(--ej-s-5); }
  .ej-footer__bottom { flex-direction: column; align-items: flex-start; }
}

/* ── Focus, on the chrome's own interactive parts ────────────────────────── */

.ej-nav__link:focus-visible,
.ej-nav__burger:focus-visible,
.ej-footer__column-list a:focus-visible,
.ej-footer__bottom-links a:focus-visible,
.ej-footer__social a:focus-visible {
  outline: none;
  border-radius: var(--ej-r-sm);
  box-shadow: var(--ej-ring);
}

@media (prefers-reduced-motion: reduce) {
  .ej-header { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* A smaller mark, for a lockup inside a dialog or a dense panel. Replaces the
   legacy .brand__mark--sm that the employer auth modal used. */
.ej-brand__mark--sm {
  width: 22px;
  height: 22px;
  flex-basis: 22px;
  border-radius: 6px;
  font-size: var(--ej-fs-xs);
}
