/* =============================================================================
   Joel Friend & Associates — Design Tokens
   -----------------------------------------------------------------------------
   Every value below is a single design decision.

   TWO LAYERS:
     1. Primitives (--jf-navy-800, --jf-gray-600, --jf-space-5, …)
        These translate 1:1 into Elementor Site Settings (Global Colors,
        Global Fonts, spacing controls). The primitive layer is the handoff
        surface for the WordPress build. See "ELEMENTOR MAPPING" at the
        bottom of this file for the full translation table.

     2. Semantic aliases (--jf-color-heading, --jf-color-btn-primary-bg, …)
        Components MUST consume these, not the primitives directly. This is
        an authoring convenience — re-theming stays a one-line edit — and
        the aliases resolve into primitives before any Elementor mapping
        happens, so nothing about them needs to survive translation.

   NUMBERING: darker = higher. --jf-navy-800 is darker than --jf-navy-700;
   --jf-gray-600 is darker than --jf-gray-200-nontext.
   ============================================================================= */


/* -----------------------------------------------------------------------------
   Font faces — self-hosted from ./fonts/. No CDN link.
   Latin subset only (Regular + SemiBold each). Add italic / other weights
   here if a real need appears; do not preload speculatively.
   ----------------------------------------------------------------------------- */
@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Source Serif 4';
  src: url('fonts/SourceSerif4-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Source Serif 4';
  src: url('fonts/SourceSerif4-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}


:root {

  /* ---------------------------------------------------------------------------
     PRIMITIVES — COLORS   (→ Elementor Global Colors)
     --------------------------------------------------------------------------- */
  --jf-navy-800:  #0E2549;   /* Brand navy — sampled from logo artwork.
                                Headings, primary button fill, footer, dark
                                band, focus outline. White on navy-800 =
                                15.22:1 (AAA); on gray-050-nontext = 14.16:1 (AAA).
                                See BRAND ASSETS note below. */
  --jf-navy-700:  #14366B;   /* Primary button hover — LIGHTENS from navy-800.
                                Derived from navy-800: same hue (H 216°),
                                same saturation (68%), luminance ~2.03x so
                                the state change reads. White on navy-700 =
                                11.87:1 (AAA). */
  --jf-blue-500:  #3A6EA5;   /* Accent. Eyebrows, links, hover borders. */
  --jf-gray-400:  #838D9B;   /* Muted headline line (two-tone H1). LARGE TEXT ONLY. */
  --jf-gray-600:  #5A6472;   /* Body text. 6.0:1 on white — WCAG AA normal. */
  /* The -nontext suffix is load-bearing, exactly as it is on
     --jf-color-text-muted-large. These two are 1.24:1 and 1.08:1 on white —
     text set in either is not low-contrast, it is invisible. The constraint
     lived only in the comment on gray-400 and was missed three times before
     the name was changed; these two carry a worse failure, so they carry the
     same warning. Read as: "the 200-weight grey, never for text". */
  --jf-gray-200-nontext:  #E3E7ED;   /* Hairline dividers, card borders. 1.24:1 — NEVER text. */
  --jf-gray-050-nontext:  #F4F7FA;   /* Alternating section background. 1.08:1 — NEVER text. */
  --jf-white:     #FFFFFF;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — FONT FAMILIES   (→ Elementor Global Fonts)
     --------------------------------------------------------------------------- */
  --jf-font-display: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  --jf-font-body:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — FONT WEIGHTS
     --------------------------------------------------------------------------- */
  --jf-weight-regular:  400;
  --jf-weight-medium:   500;   /* Nav links */
  --jf-weight-semibold: 600;   /* Display headings, buttons, eyebrows */
  --jf-weight-bold:     700;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — TYPE SCALE   (→ Elementor Global Typography)
     Sizes in px so values transcribe cleanly into Elementor inputs.
     --------------------------------------------------------------------------- */

  /* H1 — display serif, two-tone treatment */
  --jf-size-h1:         64px;
  --jf-size-h1-tablet:  52px;
  --jf-size-h1-mobile:  38px;
  --jf-lh-h1:           1.05;
  --jf-tracking-h1:     -0.02em;

  /* H2 — section titles */
  --jf-size-h2:         48px;
  --jf-size-h2-tablet:  40px;
  --jf-size-h2-mobile:  28px;
  --jf-lh-h2:           1.15;

  /* H3 — card titles */
  --jf-size-h3:         28px;   /* was 24px. At 24 the h2 -> h3 interval was
                                   2.00x, against 1.33x above it and 1.41x
                                   below — the only broken step in the scale,
                                   and 132 elements across six classes sat in
                                   it. 28 gives 1.71x / 1.65x. */
  /* CARD TITLE — a separate tier from h3, and it has to be.
     .card__title, .article-card__title and .team-card__name sit in fixed grid
     columns; every other h3 consumer flows in a container it can grow into.
     Moving them to 28 with the rest put "Small & Mid-Size Private Companies"
     onto three lines in the four-up industries grid, wrapped "Christopher
     Nowak" across two lines on a team card, and pushed thirteen article-card
     titles to three lines at 1024. A sweep of 25/26/27/28 cleared none of it:
     at 25px there were still eight. The size was never the problem — the
     column width is. Held at today's values, so nothing wraps that did not
     wrap before. A card title being smaller than a section h3 is correct:
     it is subordinate to the heading above the grid it sits in. */
  --jf-size-card-title:        24px;
  --jf-size-card-title-mobile: 21px;

  --jf-size-h3-mobile:  21px;   /* NOT rescaled with the desktop step. Mobile
                                   never had the cliff: h2-mobile is 28, so
                                   28 -> 21 is already 1.33x. Scaling this to
                                   24 to match would make it 1.17x — the
                                   opposite failure. Measured, not assumed. */
  --jf-lh-h3:           1.3;

  /* Body */
  --jf-size-body:       17px;
  --jf-lh-body:         1.65;

  /* Hero lede — one step above body */
  --jf-size-lede:        21px;   /* was 19px, which is 1.12x over 17px body —
                                   a standfirst you cannot see is not one.
                                   21 is 1.24x. */
  --jf-size-lede-mobile: 20px;   /* was 18px (1.06x over body). 20 gives 1.18x.
                                   Not 21: that collides exactly with
                                   h3-mobile, and a lede the same size as a
                                   card title reads as a heading. */

  /* Small — meta, captions, footnotes */
  --jf-size-small:      15px;

  /* WORDMARK — the firm name in the header lockup.
     It rode --jf-size-h3 (and --jf-size-lede below 1024) until the h3 step
     moved from 24 to 28. It is not a heading: it is set nowrap, the header
     grid is built around its width, and the mobile header's single-row
     layout was tuned to the exact size it is now. Coupling it to a scale it
     has no business being on meant a type decision silently resized the
     logo. These two values are the sizes it renders at today. */
  --jf-size-wordmark:        24px;
  --jf-size-wordmark-mobile: 19px;
  --jf-lh-small:        1.6;

  /* Stats-band figure on phones. Deliberately NOT --jf-size-h2-mobile, which
     it used to borrow: the mobile H2 dropped 34px -> 28px for the heading
     scale, and 28px undoes the stats-band sizing fixed immediately before
     this. 34px is the largest size that keeps "7 Years" inside its 140px
     column at 375 with all four figures on one line. */
  --jf-size-stat-mobile: 34px;

  /* Eyebrow — small caps label above H2 */
  --jf-size-eyebrow:    13px;
  --jf-tracking-eyebrow: 0.12em;

  /* Nav link */
  --jf-size-nav:        16px;

  /* Button label */
  --jf-size-button:     15px;

  /* Utility bar */
  --jf-size-utility:    13px;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — SPACING SCALE
     Only these values are permitted in layout. No arbitrary numbers.
     --------------------------------------------------------------------------- */
  --jf-space-1:   4px;
  --jf-space-2:   8px;
  --jf-space-3:   12px;
  --jf-space-4:   16px;
  --jf-space-5:   24px;
  --jf-space-6:   32px;
  --jf-space-7:   48px;
  --jf-space-8:   64px;
  --jf-space-9:   96px;
  --jf-space-10: 128px;
  --jf-space-11: 160px;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — LAYOUT
     --------------------------------------------------------------------------- */
  --jf-container-max:         1320px;
  --jf-container-gutter:      24px;
  --jf-column-gap:            32px;
  --jf-section-py-desktop:    96px;
  --jf-section-py-tablet:     72px;
  --jf-section-py-mobile:     56px;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — RADII
     Deliberately tight. No pill shapes anywhere.
     --------------------------------------------------------------------------- */
  --jf-radius-card:   4px;
  --jf-radius-button: 3px;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — BORDERS
     Thin hairlines carry the shape work — no shadows.
     --------------------------------------------------------------------------- */
  --jf-border-width:        1px;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — MOTION
     --------------------------------------------------------------------------- */
  --jf-transition:      150ms ease;
  --jf-arrow-shift:     3px;


  /* ---------------------------------------------------------------------------
     PRIMITIVES — FOCUS
     --------------------------------------------------------------------------- */
  --jf-focus-outline-width:  2px;
  --jf-focus-outline-offset: 2px;


  /* ===========================================================================
     SEMANTIC ALIASES
     Components consume ONLY these. Rebinding the alias re-themes the surface
     without touching every rule. Aliases have no representation in Elementor —
     they resolve to primitives before the WordPress translation happens.
     =========================================================================== */

  /* Backgrounds */
  --jf-color-bg:            var(--jf-white);
  --jf-color-bg-alt:        var(--jf-gray-050-nontext);
  --jf-color-bg-dark:       var(--jf-navy-800);   /* full-bleed dark bands, footer */

  /* Text */
  --jf-color-text:          var(--jf-gray-600);
  /* LARGE TEXT ONLY — the constraint is in the name because it was twice
     ignored when it lived only in this comment. Gray 400 is 3.36:1 on
     white: it clears the 3:1 large-text bar and fails the 4.5:1 normal-text
     bar. Anything under 24px (or 18.7px bold) wants --jf-color-text. */
  --jf-color-text-muted-large:  var(--jf-gray-400);
  --jf-color-text-on-dark:  var(--jf-white);

  /* Editorial */
  --jf-color-heading:       var(--jf-navy-800);
  --jf-color-eyebrow:       var(--jf-blue-500);
  --jf-color-link:          var(--jf-blue-500);

  /* Borders */
  --jf-color-border:        var(--jf-gray-200-nontext);
  --jf-color-border-hover:  var(--jf-blue-500);

  /* Buttons — primary. Hover LIGHTENS (navy-800 → navy-700). A darker
     hover was tried first and dropped: perceptual difference is near zero
     at those luminance levels. */
  --jf-color-btn-primary-bg:       var(--jf-navy-800);
  --jf-color-btn-primary-text:     var(--jf-white);
  --jf-color-btn-primary-bg-hover: var(--jf-navy-700);

  /* Buttons — secondary */
  --jf-color-btn-secondary-bg:     var(--jf-white);
  --jf-color-btn-secondary-text:   var(--jf-navy-800);
  --jf-color-btn-secondary-border: var(--jf-navy-800);

  /* Focus */
  --jf-focus-outline-color: var(--jf-navy-800);
}


/* =============================================================================
   ELEMENTOR MAPPING  —  handoff for the WordPress build
   -----------------------------------------------------------------------------
   Create these entries in Elementor Site Settings when rebuilding the site.
   The alias layer is a CSS convenience only; it does NOT translate. Every
   component in Elementor should reference one of the primitives listed here.

   -----------------------------------------------------------------------------
   GLOBAL COLORS  (Site Settings → Global Colors)
   -----------------------------------------------------------------------------
   Elementor Global Name      Hex        Primitive token       Used for
   ---------------------      -------    -------------------   --------------------------------
   Navy 800                   #0E2549    --jf-navy-800         Headings (H1 main line, H2, H3),
                                                               primary button fill, footer bg,
                                                               dark band bg, secondary button
                                                               text + border, focus outline.
                                                               Sampled from firm's logo artwork
                                                               (see BRAND ASSETS below).
                                                               White text on Navy 800 = 15.2:1.
   Navy 700                   #14366B    --jf-navy-700         Primary button hover fill
                                                               (lightens from Navy 800; same
                                                               hue + saturation, luminance ~2x).
                                                               White text on Navy 700 = 11.9:1.
   Blue 500                   #3A6EA5    --jf-blue-500         Eyebrow labels, text links,
                                                               card hover border
   Gray 400                   #838D9B    --jf-gray-400         Two-tone H1 second line ONLY
                                                               (large text — do not use at body size)
   Gray 600                   #5A6472    --jf-gray-600         Body copy default
   Gray 200                   #E3E7ED    --jf-gray-200-nontext Card borders, hairline dividers
                                                                (NEVER text — 1.24:1)
   Gray 050                   #F4F7FA    --jf-gray-050-nontext Alt section background
                                                                (NEVER text — 1.08:1)
   White                      #FFFFFF    --jf-white            Default section background,
                                                               button text on dark

   Alias → primitive quick reference (for anyone reading the CSS):
     --jf-color-heading             → Navy 800
     --jf-color-text                → Gray 600
     --jf-color-text-muted-large    → Gray 400   (LARGE TEXT ONLY, >=24px)
     --jf-color-text-on-dark        → White
     --jf-color-eyebrow             → Blue 500
     --jf-color-link                → Blue 500
     --jf-color-bg                  → White
     --jf-color-bg-alt              → Gray 050
     --jf-color-bg-dark             → Navy 800
     --jf-color-border              → Gray 200
     --jf-color-border-hover        → Blue 500
     --jf-color-btn-primary-bg      → Navy 800
     --jf-color-btn-primary-text    → White
     --jf-color-btn-primary-bg-hover→ Navy 700
     --jf-color-btn-secondary-bg    → White
     --jf-color-btn-secondary-text  → Navy 800
     --jf-color-btn-secondary-border→ Navy 800
     --jf-focus-outline-color       → Navy 800

   -----------------------------------------------------------------------------
   GLOBAL FONTS  (Site Settings → Global Fonts)
   -----------------------------------------------------------------------------
   Elementor Global Name      Family                Weights loaded    Used for
   ---------------------      -------------------   ---------------   -------------------------
   Display Serif              Source Serif 4        400, 600          H1, H2, H3
   Body Sans                  Inter                 400, 500, 600     Body, small, eyebrow,
                                                                      nav (500), button (600)

   Enable "Use System Fonts" fallback in Elementor performance settings so
   Georgia / system-sans stand in during the initial paint (matches the
   font-family stacks defined above).

   -----------------------------------------------------------------------------
   GLOBAL TYPOGRAPHY  (Site Settings → Global Fonts → Primary/Secondary/Text/Accent)
   -----------------------------------------------------------------------------
   Slot        Elementor preset name    Family           Size   Weight   Line-height   Letter-spacing
   ---------   ----------------------   --------------   ----   ------   -----------   --------------
   Primary     H1 Display               Display Serif    64px   600      1.05          -0.02em
   Secondary   H2 Section               Display Serif    48px   600      1.15          0
   Text        Body                     Body Sans        17px   400      1.65          0
   Accent      Eyebrow                  Body Sans        13px   600      1.4           0.12em (uppercase)

   H1 responsive steps (register as separate presets or configure the
   preset's per-breakpoint values in Elementor):
     H1 Display / tablet   Display Serif  52 / 600 / 1.05 / -0.02em
     H1 Display / mobile   Display Serif  38 / 600 / 1.05 / -0.02em

   H2 responsive steps:
     H2 Section / tablet   Display Serif  40 / 600 / 1.15 / 0
     H2 Section / mobile   Display Serif  34 / 600 / 1.15 / 0

   Additional typography presets to register (custom slots):
     H3 Card      Display Serif  28 / 600 / 1.3
     Lede         Body Sans      21 / 400 / 1.6
     Small        Body Sans      15 / 400 / 1.6
     Nav          Body Sans      16 / 500 / 1.4
     Button       Body Sans      15 / 600 / 1.0
     Utility      Body Sans      13 / 400 / 1.4
   ============================================================================= */


/* =============================================================================
   BRAND ASSETS  —  provenance for values that come from artwork, not design
   -----------------------------------------------------------------------------
   Do not "correct" the values in this section. They are sampled from the
   firm's actual brand artwork and must match it byte-for-byte. If the artwork
   ever changes, update this note and the tokens together.

   --jf-navy-800 = #0E2549
       Sampled from the firm's logo artwork. Source files versioned in this
       repo so provenance is auditable:
         design/brand/jf_logo.png          wordmark  · 2000 × 400 · PNG
         design/brand/jf_initial_logo.png  monogram  · 1200 × 1200 · PNG
       Colors present in that artwork:
         Logo navy          #0E2549  → --jf-navy-800 (this token)
         Logo neutral gray  #8B8B8B  → NOT promoted (see note below)
       No vector artwork exists yet — both files are bitmap PNG. A vector
       redraw is on the launch checklist and will replace the raster files
       in place at these same paths.
       This is the load-bearing brand color. The site must match the logo,
       not the other way around.

   --jf-navy-700 = #14366B
       Derived FROM --jf-navy-800, not sampled. Same hue (216.6°) and
       saturation (~68%), luminance approximately doubled so the primary
       button hover state is perceptually distinct. Recompute if navy-800
       ever changes.

   Logo neutral gray (#8B8B8B) exists inside the logo artwork but is NOT
   promoted into the token system. The site's grays (--jf-gray-*) are
   cool-tinted to harmonize with navy and stay in the neutrals family
   independently of the logo.
   ============================================================================= */
