/* =============================================================================
   base.css — reset, typography defaults, layout primitives
   -----------------------------------------------------------------------------
   Every rule below consumes semantic aliases from tokens.css. No primitives,
   no off-scale values. Component-level styles live in components.css.
   ============================================================================= */


/* -----------------------------------------------------------------------------
   Reset
   ----------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--jf-font-body);
  font-size: var(--jf-size-body);
  line-height: var(--jf-lh-body);
  color: var(--jf-color-text);
  background: var(--jf-color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img, svg, picture, video, canvas { max-width: 100%; height: auto; display: block; }
ul, ol { list-style: none; }
button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}
a { color: inherit; text-decoration: none; }
address { font-style: normal; }


/* -----------------------------------------------------------------------------
   Focus (system-wide)
   ----------------------------------------------------------------------------- */
:focus-visible {
  outline: var(--jf-focus-outline-width) solid var(--jf-focus-outline-color);
  outline-offset: var(--jf-focus-outline-offset);
}


/* -----------------------------------------------------------------------------
   Typography defaults
   ----------------------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--jf-font-display);
  font-weight: var(--jf-weight-semibold);
  color: var(--jf-color-heading);
}

h1 {
  font-size: var(--jf-size-h1);
  line-height: var(--jf-lh-h1);
  letter-spacing: var(--jf-tracking-h1);
}
@media (max-width: 1024px) { h1 { font-size: var(--jf-size-h1-tablet); } }
@media (max-width: 768px)  { h1 { font-size: var(--jf-size-h1-mobile); } }

/* ORDER IS LOAD-BEARING. These two rules used to sit ABOVE the base h2
   declaration below, and at equal specificity the later rule won — so
   var(--jf-size-h2) applied at every width and the h2 tablet and mobile
   steps had never once taken effect. H2 rendered 48px on a phone against a
   38px H1: the hierarchy was not compressed, it was inverted. */
h2 { font-size: var(--jf-size-h2); line-height: var(--jf-lh-h2); }
@media (max-width: 1024px) { h2 { font-size: var(--jf-size-h2-tablet); } }
@media (max-width: 768px)  { h2 { font-size: var(--jf-size-h2-mobile); } }

h3 { font-size: var(--jf-size-h3); line-height: var(--jf-lh-h3); }

/* H3 and the lede step down by REDEFINING THE TOKEN rather than by adding a
   rule to the h3 element. --jf-size-h3 has fourteen consumers — card titles,
   team-card names, the numbered-steps titles, the author byline — and all of
   them are the same tier of the scale. Overriding the element alone would
   have moved bare <h3>s and left every one of those at 24px. */
@media (max-width: 768px) {
  :root {
    --jf-size-h3:         var(--jf-size-h3-mobile);
    --jf-size-lede:       var(--jf-size-lede-mobile);
    --jf-size-card-title: var(--jf-size-card-title-mobile);
  }
}

p { max-width: 65ch; }

a {
  color: var(--jf-color-link);
  transition: color var(--jf-transition);
}
a:hover { text-decoration: underline; }


/* -----------------------------------------------------------------------------
   Text helpers
   ----------------------------------------------------------------------------- */

/* Two-tone H1 second line */
.h1__muted {
  display: block;
  color: var(--jf-color-text-muted-large);
}

/* Two-tone H2 second line */
.h2__muted {
  display: block;
  color: var(--jf-color-text-muted-large);
}

/* Eyebrow — small caps label above H2 */
.eyebrow {
  font-family: var(--jf-font-body);
  font-size: var(--jf-size-eyebrow);
  letter-spacing: var(--jf-tracking-eyebrow);
  text-transform: uppercase;
  font-weight: var(--jf-weight-semibold);
  color: var(--jf-color-eyebrow);
  margin: 0 0 var(--jf-space-3);
}

/* Third metro on desktop only.

   "Miami · Fort Lauderdale · West Palm Beach · Since 1998" does not fit one
   line on a 375px phone, and a four-part eyebrow wrapping onto two lines reads
   as a mistake rather than as a list.

   MEASURED: the full string needs 479px and first fits on one line at a 540px
   viewport. The first attempt hid the span below 480 and left 481-539 wrapping
   to two lines — the exact failure it was meant to prevent, in a window nobody
   would have opened. It drops at the project's documented mobile breakpoint
   instead, which is 768 and therefore comfortably clear of 540.

   Nothing is lost for search: all three metros appear in the page copy, in the
   LocalBusiness areaServed, and in the footer. */
@media (max-width: 768px) {
  .eyebrow__wide { display: none; }
}

/* Small text */
.small {
  font-size: var(--jf-size-small);
  line-height: var(--jf-lh-small);
}

/* Inline TODO marker */
.todo {
  display: inline-block;
  padding: var(--jf-space-1) var(--jf-space-2);
  background: var(--jf-color-bg-alt);
  border: var(--jf-border-width) dashed var(--jf-color-border-hover);
  border-radius: var(--jf-radius-button);
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: var(--jf-size-small);
  color: var(--jf-color-heading);
  /* Wrap on narrow viewports rather than forcing horizontal overflow. */
  max-width: 100%;
  overflow-wrap: anywhere;
}


/* -----------------------------------------------------------------------------
   Layout — container
   ----------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--jf-container-max);
  margin-inline: auto;
  padding-inline: var(--jf-container-gutter);
}


/* -----------------------------------------------------------------------------
   Layout — section
   ----------------------------------------------------------------------------- */
.section { padding-block: var(--jf-section-py-desktop); }
@media (max-width: 1024px) { .section { padding-block: var(--jf-section-py-tablet); } }
@media (max-width: 768px)  { .section { padding-block: var(--jf-section-py-mobile); } }

.section--alt  { background: var(--jf-color-bg-alt); }
.section--dark { background: var(--jf-color-bg-dark); color: var(--jf-color-text-on-dark); }

/* Self-collapsing sections, for the CMS-native templates.

   The single-post template's author block and related-articles grid are both
   allowed to render nothing: a post whose author has no bio should not get an
   empty bio block, and the first article published has nothing to relate to.
   The SECTION around each still laid out — a post with no author bio showed
   192px of empty grey band between the body and "Keep Reading".

   :has() rather than a server-side condition because the emptiness is decided
   by a shortcode inside an Elementor container, and CSS is the only layer that
   can see the result. Measured, not assumed: the band was 192px at 1440. */
.section--author:not(:has(.author-bio)),
.section--related:not(:has(.article-card)) { display: none; }
.section--dark h1,
.section--dark h2,
.section--dark h3 { color: var(--jf-color-text-on-dark); }


/* -----------------------------------------------------------------------------
   Layout — grids
   ----------------------------------------------------------------------------- */
.grid {
  display: grid;
  gap: var(--jf-column-gap);
  /* All rows in the auto grid grow to the same height so cards never look
     ragged across rows when content lengths differ. */
  grid-auto-rows: 1fr;
  align-items: stretch;
}
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1024px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
}


/* -----------------------------------------------------------------------------
   Accessibility helpers
   ----------------------------------------------------------------------------- */
.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;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--jf-color-bg-dark);
  color: var(--jf-color-text-on-dark);
  padding: var(--jf-space-2) var(--jf-space-4);
  font-size: var(--jf-size-small);
  z-index: 1000;
  text-decoration: none;
  /* 41px natural height rounded up to the 44px AAA touch target. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  box-sizing: border-box;
}
.skip-link:focus { left: var(--jf-space-2); top: var(--jf-space-2); }


/* -----------------------------------------------------------------------------
   Responsive visibility utilities
   Mobile breakpoint == 768. Everything above uses u-hide-desktop / u-show-mobile.
   ----------------------------------------------------------------------------- */
@media (max-width: 768px) {
  .u-hide-mobile { display: none !important; }
}
@media (min-width: 769px) {
  .u-hide-desktop { display: none !important; }
}
