/* ═══════════════════════════════════════════════════════════════════════
   CAREERSTUDIOMAX — TYPOGRAPHY DESIGN SYSTEM v1.0
   ═══════════════════════════════════════════════════════════════════════
   A complete, standalone type system: Inter-first, fluid clamp() scale,
   WCAG-conformant, dark-mode aware, mobile-first. Built to sit alongside
   the existing app.css design-token layer (--fh/--fm/--fb/--text-*) without
   colliding with it — every token here is namespaced under --ts-* (type
   system) so it can be adopted page-by-page instead of forcing a rewrite.

   NOTE — read before wiring this in: the live app currently uses a
   different, intentionally distinctive brand type system (Clash Display /
   JetBrains Mono / Instrument Serif, see public/css/app.css :root). This
   file does not touch or override that. It's additive: link it on new
   pages/surfaces that should use the clean Inter-based SaaS system this
   spec describes, or use it as the target system for a deliberate,
   separately-scoped rebrand pass. It won't silently change how any
   existing page looks.

   TABLE OF CONTENTS
   1.  Font loading (@font-face, performance)
   2.  Core tokens (families, weights, tracking, line-height)
   3.  Fluid type scale (clamp-based responsive sizes)
   4.  Base element styles (mobile-first)
   5.  Text-color tokens + dark mode
   6.  Utility classes
   7.  Forms
   8.  Buttons
   9.  Dashboard / data-table typography (shared by ATS, Analytics,
       Employer Portal, Candidate Portal — see section comments)
   10. Marketing-page typography
   11. Authentication-page typography
   12. Accessibility guarantees
   13. Responsive breakpoint reference
   ═══════════════════════════════════════════════════════════════════════ */


/* ───────────────────────────────────────────────────────────────────────
   1. FONT LOADING — performance-first
   ───────────────────────────────────────────────────────────────────────
   Self-host Inter and Plus Jakarta Sans as variable fonts (one file covers
   the full 100–900 weight range instead of shipping 5–6 static-weight
   files). Variable-font WOFF2 for Inter is ~110KB — smaller than three
   static weights combined. `font-display: swap` avoids invisible text
   (FOIT); the system-ui fallback stack means there's readable text on
   screen even before the swap happens.

   Pair with these two tags in <head>, as early as possible:
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link rel="preload" href="/fonts/InterVariable.woff2" as="font"
           type="font/woff2" crossorigin>
   If self-hosting (recommended over Google Fonts CDN for both performance
   and privacy — no third-party request on every page load), drop the
   preconnect tag and just preload the local file. Only preload the exact
   weight range actually used above the fold to avoid wasting bandwidth.
   ─────────────────────────────────────────────────────────────────────── */

@font-face {
  font-family: 'Inter';
  src: url('/fonts/InterVariable.woff2') format('woff2-variations'),
       url('/fonts/InterVariable.woff2') format('woff2');
  font-weight: 100 900;   /* variable font — one file, every weight */
  font-style: normal;
  font-display: swap;
  font-named-instance: 'Regular';
}

@font-face {
  font-family: 'Inter';
  src: url('/fonts/InterVariable-Italic.woff2') format('woff2-variations'),
       url('/fonts/InterVariable-Italic.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
  font-named-instance: 'Italic';
}

@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('/fonts/PlusJakartaSans-Variable.woff2') format('woff2-variations'),
       url('/fonts/PlusJakartaSans-Variable.woff2') format('woff2');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* Static-weight fallback for browsers/build pipelines that can't use the
   variable font (rare in 2026, but keep this as a documented escape hatch —
   uncomment and point at static files if variable-font loading is ever
   disabled):
   @font-face { font-family:'Inter'; font-weight:400; src:url('/fonts/Inter-Regular.woff2') format('woff2'); font-display:swap; }
   @font-face { font-family:'Inter'; font-weight:600; src:url('/fonts/Inter-SemiBold.woff2') format('woff2'); font-display:swap; }
   @font-face { font-family:'Inter'; font-weight:700; src:url('/fonts/Inter-Bold.woff2') format('woff2'); font-display:swap; }
   @font-face { font-family:'Inter'; font-weight:800; src:url('/fonts/Inter-ExtraBold.woff2') format('woff2'); font-display:swap; }
*/


/* ───────────────────────────────────────────────────────────────────────
   2. CORE TOKENS
   ─────────────────────────────────────────────────────────────────────── */
:root {
  /* Font families — primary stack per spec, alt + mono for data/code */
  --ts-font-primary: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --ts-font-alt:      'Plus Jakarta Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --ts-font-system:   system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --ts-font-mono:     'Inter', ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  /* Tabular figures for anything numeric that needs columns to align —
     scores, currency, dates, percentages — critical for ATS/Analytics. */
  --ts-num:           'tnum' 1, 'lnum' 1;

  /* Weights — named, not just numbers, so intent reads in the CSS */
  --ts-fw-regular:    400;
  --ts-fw-medium:     500;
  --ts-fw-semibold:   600;
  --ts-fw-bold:       700;
  --ts-fw-extrabold:  800;

  /* Line height — per content type, not per element, so it's reusable */
  --ts-lh-tight:      1.1;   /* large display/H1 — big type needs less */
  --ts-lh-heading:    1.25;  /* H2–H4 */
  --ts-lh-body:       1.6;   /* paragraphs — spec'd, also WCAG 1.4.12-safe */
  --ts-lh-relaxed:    1.75;  /* long-form marketing copy, article bodies */
  --ts-lh-ui:         1.4;   /* buttons, labels, table cells — compact UI */

  /* Letter spacing — headings tighten slightly at large sizes (standard
     practice: big type has proportionally too much whitespace otherwise);
     uppercase labels need positive tracking to stay legible. */
  --ts-ls-tight:      -0.02em;
  --ts-ls-normal:     0;
  --ts-ls-wide:       0.01em;
  --ts-ls-caps:       0.08em;  /* for uppercase eyebrow/label text */

  /* Fixed sizes — per spec, static across breakpoints (not fluid). 16px
     base is also the WCAG/iOS baseline: any input below 16px triggers
     Safari's auto-zoom-on-focus on iPhone, a real, common accessibility
     papercut this system avoids by construction. */
  --ts-fs-body:       1rem;      /* 16px */
  --ts-fs-body-lg:     1.125rem; /* 18px — marketing lead paragraphs */
  --ts-fs-small:      0.875rem;  /* 14px */
  --ts-fs-caption:    0.75rem;   /* 12px — accessibility floor, see §12 */
  --ts-fs-micro:      0.6875rem; /* 11px — badges/tags ONLY, never body copy */

  /* Responsive breakpoint reference (documentation values — CSS custom
     properties cannot be used inside @media conditions per spec, so these
     are mirrored as literal px in every @media rule below; keep both in
     sync if you change one). See §13 for the full table. */
  --ts-bp-sm:  480px;
  --ts-bp-md:  768px;
  --ts-bp-lg:  1024px;
  --ts-bp-xl:  1440px;
  --ts-bp-2xl: 1920px;
}


/* ───────────────────────────────────────────────────────────────────────
   3. FLUID TYPE SCALE — clamp()-based, mobile → desktop
   ───────────────────────────────────────────────────────────────────────
   Every clamp() below interpolates linearly between a 400px mobile
   viewport and a 1440px desktop viewport (the same range for every step,
   which is what makes the scale feel coherent rather than arbitrary —
   this is the standard fluid-type methodology, same approach used by
   Utopia/Stripe/Linear's own systems). Beyond 1440px the size holds at
   its max — headings don't keep growing forever on a 4K monitor, they
   just get more surrounding white space, which is the correct premium-
   SaaS behavior (Stripe/Linear do the same — check their marketing pages
   at 2560px+ and the H1 doesn't scale past a ceiling).
   ─────────────────────────────────────────────────────────────────────── */
:root {
  /* Display — marketing hero headlines, bigger than H1, used sparingly */
  --ts-fs-display: clamp(2.5rem, 1.192rem + 6.15vw, 5rem);     /* 40px → 80px */

  --ts-fs-h1: clamp(2rem,    1.231rem + 3.08vw, 4rem);         /* 32px → 64px */
  --ts-fs-h2: clamp(1.5rem,  1.115rem + 1.54vw, 2.5rem);       /* 24px → 40px */
  --ts-fs-h3: clamp(1.25rem, 0.962rem + 1.15vw, 2rem);         /* 20px → 32px */
  --ts-fs-h4: clamp(1.125rem, 0.981rem + 0.58vw, 1.5rem);      /* 18px → 24px */
  --ts-fs-h5: clamp(1rem,    0.904rem + 0.385vw, 1.25rem);     /* 16px → 20px */
  --ts-fs-h6: clamp(0.875rem, 0.808rem + 0.269vw, 1.0625rem);  /* 14px → 17px */
}

@media (min-width: 1440px) {
  /* Belt-and-braces cap: clamp() already stops growing past its max
     argument on its own, this rule exists only to document the ceiling
     explicitly for anyone scanning the CSS rather than mentally evaluating
     the clamp() math. Safe to delete — purely documentation. */
  :root {
    --ts-fs-display: 5rem;
    --ts-fs-h1: 4rem;
    --ts-fs-h2: 2.5rem;
    --ts-fs-h3: 2rem;
    --ts-fs-h4: 1.5rem;
  }
}


/* ───────────────────────────────────────────────────────────────────────
   4. BASE ELEMENT STYLES — mobile-first, applied once
   ─────────────────────────────────────────────────────────────────────── */
html {
  /* Respect the user's browser font-size setting — never override this
     with a fixed px value at the root; that's what breaks WCAG 1.4.4
     (Resize Text) and browser/OS accessibility zoom for low-vision users. */
  font-size: 100%;
  -webkit-text-size-adjust: 100%; /* stop iOS auto-inflating text in landscape */
  text-size-adjust: 100%;
}

body {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-body);
  font-weight: var(--ts-fw-regular);
  line-height: var(--ts-lh-body);
  letter-spacing: var(--ts-ls-normal);
  font-feature-settings: var(--ts-num);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Never let a fallback font get fake-bolded/italicized while Inter
     loads — synthesized styles look broken and shift layout on swap. */
  font-synthesis: none;
}

h1, .ts-h1 {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-h1);
  font-weight: var(--ts-fw-extrabold);
  line-height: var(--ts-lh-tight);
  letter-spacing: var(--ts-ls-tight);
  text-wrap: balance; /* keeps multi-line headlines from orphaning a lone word */
}

h2, .ts-h2 {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-h2);
  font-weight: var(--ts-fw-bold);
  line-height: var(--ts-lh-heading);
  letter-spacing: var(--ts-ls-tight);
  text-wrap: balance;
}

h3, .ts-h3 {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-h3);
  font-weight: var(--ts-fw-bold);
  line-height: var(--ts-lh-heading);
  letter-spacing: var(--ts-ls-normal);
  text-wrap: balance;
}

h4, .ts-h4 {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-h4);
  font-weight: var(--ts-fw-semibold);
  line-height: var(--ts-lh-heading);
  letter-spacing: var(--ts-ls-normal);
}

h5, .ts-h5 {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-h5);
  font-weight: var(--ts-fw-semibold);
  line-height: var(--ts-lh-heading);
}

h6, .ts-h6 {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-h6);
  font-weight: var(--ts-fw-semibold);
  line-height: var(--ts-lh-heading);
  letter-spacing: var(--ts-ls-wide);
  text-transform: uppercase; /* h6 as an eyebrow/section-label is the
                                 conventional use at this size — remove
                                 if a given surface needs sentence case */
}

p, .ts-body {
  font-size: var(--ts-fs-body);
  line-height: var(--ts-lh-body);
  font-weight: var(--ts-fw-regular);
}

small, .ts-small {
  font-size: var(--ts-fs-small);
  line-height: var(--ts-lh-ui);
}

.ts-caption {
  font-size: var(--ts-fs-caption);
  line-height: var(--ts-lh-ui);
  color: var(--ts-text-tertiary);
}

a {
  color: var(--ts-text-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}
a:hover { color: var(--ts-text-link-hover); }

/* Every focusable text element gets a real, visible focus ring — WCAG
   2.4.7. Never remove outline without replacing it; this is that
   replacement, once, globally, so nobody has to remember to add it per
   component. */
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--ts-focus-ring, #3b82f6);
  outline-offset: 2px;
}

code, kbd, samp, pre {
  font-family: var(--ts-font-mono);
  font-size: 0.9em; /* relative to surrounding text, not a fixed px */
}


/* ───────────────────────────────────────────────────────────────────────
   5. TEXT-COLOR TOKENS + DARK MODE
   ───────────────────────────────────────────────────────────────────────
   Dark is the default here to match the rest of the app's convention
   (see public/css/theme-light.css — light mode is the explicit override
   via html[data-theme="light"], not the other way round). prefers-color-
   scheme is honored for users who haven't toggled anything, and
   html[data-theme] always wins over it either direction, matching the
   toggle behavior already used elsewhere in the app.
   ─────────────────────────────────────────────────────────────────────── */
:root {
  /* Dark (default) */
  --ts-text-primary:    rgba(255,255,255,0.94);
  --ts-text-secondary:  rgba(255,255,255,0.72);
  --ts-text-tertiary:   rgba(255,255,255,0.52);
  --ts-text-disabled:   rgba(255,255,255,0.32);
  --ts-text-inverse:    #0a0f1e;
  --ts-text-link:       #5eb1ff;
  --ts-text-link-hover: #8cc8ff;
  --ts-focus-ring:      #5eb1ff;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --ts-text-primary:    #0a0f1e;
    --ts-text-secondary:  rgba(10,15,30,0.72);
    --ts-text-tertiary:   rgba(10,15,30,0.55);
    --ts-text-disabled:   rgba(10,15,30,0.35);
    --ts-text-inverse:    #ffffff;
    --ts-text-link:       #1a5fc8;
    --ts-text-link-hover: #0e47a1;
    --ts-focus-ring:      #1a5fc8;
  }
}

html[data-theme="light"] {
  --ts-text-primary:    #0a0f1e;
  --ts-text-secondary:  rgba(10,15,30,0.72);
  --ts-text-tertiary:   rgba(10,15,30,0.55);
  --ts-text-disabled:   rgba(10,15,30,0.35);
  --ts-text-inverse:    #ffffff;
  --ts-text-link:       #1a5fc8;
  --ts-text-link-hover: #0e47a1;
  --ts-focus-ring:      #1a5fc8;
}

html[data-theme="dark"] {
  --ts-text-primary:    rgba(255,255,255,0.94);
  --ts-text-secondary:  rgba(255,255,255,0.72);
  --ts-text-tertiary:   rgba(255,255,255,0.52);
  --ts-text-disabled:   rgba(255,255,255,0.32);
  --ts-text-inverse:    #0a0f1e;
  --ts-text-link:       #5eb1ff;
  --ts-text-link-hover: #8cc8ff;
  --ts-focus-ring:      #5eb1ff;
}

body { color: var(--ts-text-primary); }


/* ───────────────────────────────────────────────────────────────────────
   6. UTILITY CLASSES
   ─────────────────────────────────────────────────────────────────────── */
.ts-display    { font-size: var(--ts-fs-display); font-weight: var(--ts-fw-extrabold); line-height: var(--ts-lh-tight); letter-spacing: var(--ts-ls-tight); text-wrap: balance; }
.ts-body-lg    { font-size: var(--ts-fs-body-lg); line-height: var(--ts-lh-relaxed); }
.ts-micro      { font-size: var(--ts-fs-micro); line-height: var(--ts-lh-ui); }

.ts-fw-regular   { font-weight: var(--ts-fw-regular); }
.ts-fw-medium    { font-weight: var(--ts-fw-medium); }
.ts-fw-semibold  { font-weight: var(--ts-fw-semibold); }
.ts-fw-bold      { font-weight: var(--ts-fw-bold); }
.ts-fw-extrabold { font-weight: var(--ts-fw-extrabold); }

.ts-text-primary   { color: var(--ts-text-primary); }
.ts-text-secondary { color: var(--ts-text-secondary); }
.ts-text-tertiary  { color: var(--ts-text-tertiary); }
.ts-text-disabled  { color: var(--ts-text-disabled); }
.ts-text-inverse   { color: var(--ts-text-inverse); }

.ts-label-caps {
  font-size: var(--ts-fs-caption);
  font-weight: var(--ts-fw-semibold);
  letter-spacing: var(--ts-ls-caps);
  text-transform: uppercase;
  color: var(--ts-text-tertiary);
}

.ts-nums { font-feature-settings: var(--ts-num); font-variant-numeric: tabular-nums; }

.ts-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ts-clamp-2, .ts-clamp-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ts-clamp-2 { -webkit-line-clamp: 2; }
.ts-clamp-3 { -webkit-line-clamp: 3; }

.ts-balance { text-wrap: balance; }
.ts-pretty  { text-wrap: pretty; } /* avoids orphans in body copy where supported */

/* Screen-reader-only text — visually hidden, still announced. Needed
   anywhere an icon-only control needs an accessible name. */
.ts-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;
}


/* ───────────────────────────────────────────────────────────────────────
   7. FORMS
   ───────────────────────────────────────────────────────────────────────
   Input text is deliberately 16px, not smaller — this is a hard
   accessibility/UX floor, not a style preference: any input under 16px
   triggers automatic zoom-on-focus in iOS Safari, which is jarring and
   fails several mobile-usability heuristics. Never shrink this to "fit
   more on screen"; adjust padding/layout instead.
   ─────────────────────────────────────────────────────────────────────── */
.ts-label {
  display: block;
  font-size: var(--ts-fs-small);
  font-weight: var(--ts-fw-medium);
  line-height: var(--ts-lh-ui);
  color: var(--ts-text-secondary);
  margin-bottom: 0.375rem;
}

.ts-input, .ts-textarea, .ts-select,
input[type="text"].ts-field, input[type="email"].ts-field,
input[type="password"].ts-field, input[type="search"].ts-field,
input[type="tel"].ts-field, input[type="number"].ts-field {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-body);      /* 16px — see note above, do not reduce */
  font-weight: var(--ts-fw-regular);
  line-height: var(--ts-lh-body);
  color: var(--ts-text-primary);
}

.ts-input::placeholder, .ts-textarea::placeholder {
  color: var(--ts-text-disabled);
  font-weight: var(--ts-fw-regular);
}

.ts-helper-text {
  font-size: var(--ts-fs-caption);
  line-height: var(--ts-lh-ui);
  color: var(--ts-text-tertiary);
  margin-top: 0.25rem;
}

.ts-error-text {
  font-size: var(--ts-fs-caption);
  font-weight: var(--ts-fw-medium);
  line-height: var(--ts-lh-ui);
  color: var(--ts-error, #ef4444);
  margin-top: 0.25rem;
}

fieldset legend.ts-legend {
  font-size: var(--ts-fs-body);
  font-weight: var(--ts-fw-semibold);
  color: var(--ts-text-primary);
}


/* ───────────────────────────────────────────────────────────────────────
   8. BUTTONS
   ─────────────────────────────────────────────────────────────────────── */
.ts-btn {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-body);   /* 16px */
  font-weight: var(--ts-fw-semibold);
  line-height: var(--ts-lh-ui);
  letter-spacing: var(--ts-ls-normal);
  white-space: nowrap;
}

.ts-btn-sm  { font-size: var(--ts-fs-small); }   /* compact/secondary actions */
.ts-btn-lg  { font-size: var(--ts-fs-body-lg); } /* marketing/hero CTAs */


/* ───────────────────────────────────────────────────────────────────────
   9. DASHBOARD / DATA-TABLE TYPOGRAPHY
   ───────────────────────────────────────────────────────────────────────
   Shared by every dense, data-driven surface: the general Dashboard, ATS
   Dashboard, Analytics Dashboard, Employer Portal, and Candidate Portal.
   Rather than four near-duplicate rule sets, these surfaces compose the
   same primitives below — that's what keeps a design system a system
   instead of four copies that drift out of sync. Where a surface needs
   something genuinely different, it's called out explicitly.

   Desktop table cells: 14px. Mobile: 13px, via the breakpoint below — one
   step down, not fluid; tabular data needs predictable, exact alignment,
   not a smoothly interpolating size.
   ─────────────────────────────────────────────────────────────────────── */
.ts-table {
  font-family: var(--ts-font-primary);
  font-size: var(--ts-fs-small);  /* 14px desktop */
  line-height: var(--ts-lh-ui);
  font-feature-settings: var(--ts-num);
  font-variant-numeric: tabular-nums;
}

.ts-table th {
  font-size: var(--ts-fs-caption);
  font-weight: var(--ts-fw-semibold);
  letter-spacing: var(--ts-ls-caps);
  text-transform: uppercase;
  color: var(--ts-text-tertiary);
}

.ts-table td { color: var(--ts-text-primary); }

@media (max-width: 767px) {
  .ts-table { font-size: 0.8125rem; } /* 13px mobile */
}

/* KPI / stat figures — the big numbers on any dashboard (ATS match %,
   analytics counts, employer pipeline totals, candidate application
   counts). Always tabular-nums so a column of figures aligns. */
.ts-kpi-value {
  font-size: var(--ts-fs-h3);
  font-weight: var(--ts-fw-bold);
  line-height: var(--ts-lh-tight);
  font-feature-settings: var(--ts-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--ts-ls-tight);
}

.ts-kpi-label {
  font-size: var(--ts-fs-caption);
  font-weight: var(--ts-fw-medium);
  letter-spacing: var(--ts-ls-caps);
  text-transform: uppercase;
  color: var(--ts-text-tertiary);
}

/* Sidebar/nav item text — same across every portal shell */
.ts-nav-item {
  font-size: var(--ts-fs-small);
  font-weight: var(--ts-fw-medium);
  line-height: var(--ts-lh-ui);
}

/* Status/score badges — ATS match scores, application-stage pills, etc. */
.ts-badge {
  font-size: var(--ts-fs-micro);
  font-weight: var(--ts-fw-semibold);
  letter-spacing: var(--ts-ls-wide);
  line-height: 1;
}

/* ATS Dashboard — one genuinely distinct need: match-score percentages
   are read at a glance and compared against each other constantly, so
   they get the mono/tabular treatment even more emphatically than a
   generic KPI figure. */
.ts-ats-score {
  font-family: var(--ts-font-mono);
  font-feature-settings: var(--ts-num);
  font-variant-numeric: tabular-nums;
  font-weight: var(--ts-fw-bold);
}

/* Analytics Dashboard — chart axis labels/legends need to be small and
   quiet without disappearing; caption size, medium weight (not the
   lighter tertiary-text default) keeps them legible against gridlines. */
.ts-chart-label {
  font-size: var(--ts-fs-caption);
  font-weight: var(--ts-fw-medium);
  fill: var(--ts-text-secondary); /* for SVG chart text nodes */
}

/* Employer Portal / Candidate Portal — both are otherwise the standard
   dashboard system above (.ts-table / .ts-kpi-* / .ts-nav-item); the only
   portal-specific addition is a slightly larger, friendlier empty-state
   message size, since these two surfaces are consumer-facing rather than
   power-user data grids. */
.ts-portal-empty-state {
  font-size: var(--ts-fs-body-lg);
  font-weight: var(--ts-fw-medium);
  color: var(--ts-text-secondary);
  line-height: var(--ts-lh-relaxed);
}


/* ───────────────────────────────────────────────────────────────────────
   10. MARKETING-PAGE TYPOGRAPHY
   ─────────────────────────────────────────────────────────────────────── */
.ts-marketing-eyebrow {
  font-size: var(--ts-fs-caption);
  font-weight: var(--ts-fw-bold);
  letter-spacing: var(--ts-ls-caps);
  text-transform: uppercase;
  color: var(--ts-text-link);
}

.ts-marketing-hero    { font-size: var(--ts-fs-display); font-weight: var(--ts-fw-extrabold); line-height: var(--ts-lh-tight); letter-spacing: var(--ts-ls-tight); text-wrap: balance; }
.ts-marketing-subhead { font-size: var(--ts-fs-body-lg); line-height: var(--ts-lh-relaxed); color: var(--ts-text-secondary); max-width: 42rem; }
.ts-marketing-lead     { font-size: var(--ts-fs-body-lg); line-height: var(--ts-lh-relaxed); }

/* Testimonial / quote blocks — a common marketing-page pattern that
   deserves its own size step distinct from body copy */
.ts-quote {
  font-size: var(--ts-fs-h4);
  font-weight: var(--ts-fw-medium);
  line-height: var(--ts-lh-heading);
  letter-spacing: var(--ts-ls-tight);
  text-wrap: balance;
}
.ts-quote-attribution {
  font-size: var(--ts-fs-small);
  font-weight: var(--ts-fw-semibold);
  color: var(--ts-text-secondary);
}


/* ───────────────────────────────────────────────────────────────────────
   11. AUTHENTICATION-PAGE TYPOGRAPHY
   ───────────────────────────────────────────────────────────────────────
   Login/signup/reset screens carry disproportionate trust weight for a
   product handling career and payment data — slightly larger, calmer
   type than the dashboard system, generous line-height, nothing dense.
   ─────────────────────────────────────────────────────────────────────── */
.ts-auth-title {
  font-size: var(--ts-fs-h2);
  font-weight: var(--ts-fw-bold);
  line-height: var(--ts-lh-heading);
  letter-spacing: var(--ts-ls-tight);
}

.ts-auth-subtitle {
  font-size: var(--ts-fs-body);
  line-height: var(--ts-lh-relaxed);
  color: var(--ts-text-secondary);
}

.ts-auth-label   { font-size: var(--ts-fs-small); font-weight: var(--ts-fw-medium); color: var(--ts-text-secondary); }
.ts-auth-input   { font-size: 1rem; } /* 16px — same iOS-zoom guard as §7, non-negotiable on an auth form */
.ts-auth-footnote{ font-size: var(--ts-fs-small); line-height: var(--ts-lh-body); color: var(--ts-text-tertiary); }
.ts-auth-legal   { font-size: var(--ts-fs-caption); line-height: var(--ts-lh-body); color: var(--ts-text-tertiary); }


/* ───────────────────────────────────────────────────────────────────────
   12. ACCESSIBILITY GUARANTEES (WCAG 2.1 AA)
   ───────────────────────────────────────────────────────────────────────
   • 1.4.4 Resize Text  — every size above is rem-based off html{font-size:
     100%}, so browser zoom and OS-level text scaling both work correctly;
     nothing here uses a fixed px root size that would defeat that.
   • 1.4.12 Text Spacing — body line-height (1.6) and UI line-height (1.4)
     both clear the 1.5x/1.5x minimums the criterion requires for the
     elements it covers; letter-spacing tokens stay within safe ranges.
   • 1.4.3 / 1.4.6 Contrast — text-color tokens in §5 are chosen to clear
     4.5:1 (body) / 3:1 (large text ≥24px or ≥19px bold) against this
     system's dark (#0a0f1e-adjacent) and light (white-adjacent)
     backgrounds; verify again against whatever background color a given
     component actually sits on, since contrast is background-dependent.
   • 2.4.7 Focus Visible — global :focus-visible ring in §4, not removed
     anywhere in this file.
   • 12px (--ts-fs-caption) is the practical floor in this system — nothing
     defined here goes smaller except --ts-fs-micro (11px), which is
     reserved for non-reading badge/tag glyphs, never body or instructional
     copy.
   • prefers-reduced-motion — this file defines no motion, but anything
     that animates text (counters, reveal-on-scroll headings, etc.) built
     on top of these tokens should still gate on:
       @media (prefers-reduced-motion: reduce) { ... }
   ─────────────────────────────────────────────────────────────────────── */


/* ───────────────────────────────────────────────────────────────────────
   13. RESPONSIVE BREAKPOINT REFERENCE
   ───────────────────────────────────────────────────────────────────────
     --ts-bp-sm   480px   large phones / phablets
     --ts-bp-md   768px   tablets (portrait)
     --ts-bp-lg   1024px  tablets (landscape) / small laptops
     --ts-bp-xl   1440px  desktop — the fluid scale's max reference width
     --ts-bp-2xl  1920px  large desktop / 4K starts scaling down from here
   Every clamp() in §3 already flows continuously through all of these —
   there is deliberately no heading-size media query, that's the point of
   using clamp(). The two hard breakpoints that DO exist in this file are
   both for content that genuinely shouldn't scale continuously: table
   text (§9, switches once at 768px) and the documented 1440px ceiling
   (§3, belt-and-braces only).
   ─────────────────────────────────────────────────────────────────────── */
