/* Frontier IT Consulting — frontieritconsulting.com
   Palette sampled from the brand mark: warm brown wordmark, slate-blue accents,
   moose tan, cream paper. */

:root {
  --ink:        #2b211a;
  --ink-soft:   #5a4a3d;
  --brown:      #4a3a2e;
  --tan:        #b5834e;
  /* Darkened from #94683a: the old value was 4.16:1 on --cream-deep, under AA
     for the small-bold eyebrow labels. This clears 4.5:1 on every background. */
  --tan-dark:   #8d6236;
  /* Footer headings sit on --brown, where --tan is only 3.27:1. */
  --tan-light:  #d2a06a;
  --slate:      #2f4858;
  --slate-soft: #4a6b7c;
  --cream:      #faf7f2;
  --cream-deep: #f2ece3;
  --paper:      #ffffff;
  --line:       #e2d8ca;

  --serif: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --wrap: 68rem;
  --pad:  clamp(1.25rem, 4vw, 2.5rem);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  /* Column layout so the footer is pinned to the bottom of a short page --
     the 404 left it floating mid-screen with cream underneath. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  font-family: var(--sans);
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  line-height: 1.65;
  color: var(--ink);
  background: var(--cream);
}

h1, h2, h3 { font-family: var(--serif); font-weight: 700; line-height: 1.15; color: var(--brown); margin: 0 0 0.5em; }
h1 { font-size: clamp(2rem, 1.4rem + 2.8vw, 3.25rem); letter-spacing: -0.01em; }
/* Even out ragged multi-line headings; harmless where unsupported. */
h1, h2 { text-wrap: balance; }
h2 { font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.125rem); }
h3 { font-size: 1.1875rem; }
p  { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

a { color: var(--slate); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--tan-dark); }

img { max-width: 100%; height: auto; display: block; }

main { flex: 1 0 auto; }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--pad); }

/* Skip link ------------------------------------------------------------- */
.skip {
  position: absolute; left: -9999px;
  background: var(--brown); color: #fff; padding: 0.75rem 1.25rem; z-index: 100;
}
.skip:focus { left: 1rem; top: 1rem; }

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

/* Header ---------------------------------------------------------------- */
.site-header {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.site-header > .wrap {
  display: flex; align-items: center; gap: clamp(0.75rem, 2vw, 1.5rem);
  flex-wrap: wrap;
  padding-block: 0.875rem;
}

.brand { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; margin-right: auto; }
.brand img { width: 52px; height: 52px; flex: none; }
/* One moose at a time: from 52rem up the big hero moose is on screen, so the
   header shows the wordmark alone; below 52rem the hero moose is hidden and
   the small mark returns. Same breakpoint as .moose-backdrop -- keep in sync. */
@media (min-width: 52rem) { .brand img { display: none; } }
.brand-text { display: flex; flex-direction: column; line-height: 1.05; }
.brand-name {
  font-family: var(--serif); font-size: 1.4rem; font-weight: 700;
  color: var(--brown); letter-spacing: -0.005em;
}
.brand-sub {
  font-family: var(--serif); font-size: 0.8125rem; color: var(--ink-soft);
  letter-spacing: 0.08em; text-transform: uppercase;
}

.nav { display: flex; align-items: center; gap: clamp(0.75rem, 2vw, 1.5rem); flex-wrap: wrap; }

/* :not(.btn) matters — `.nav a` outranks `.btn-primary` on specificity, so
   without it the button in the nav inherits brown link text on its slate
   background and becomes unreadable. */
.nav a:not(.btn) {
  color: var(--ink-soft); text-decoration: none; font-size: 0.9375rem; font-weight: 500;
  padding-block: 0.25rem; border-bottom: 2px solid transparent;
}
.nav a:not(.btn):hover { color: var(--brown); border-bottom-color: var(--tan); }
.nav a:not(.btn)[aria-current="page"] { color: var(--brown); border-bottom-color: var(--tan); }

/* Buttons --------------------------------------------------------------- */
.btn {
  display: inline-block; text-decoration: none; font-weight: 600; font-size: 1rem;
  padding: 0.75rem 1.5rem; border-radius: 4px; border: 2px solid transparent;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.btn-primary { background: var(--slate); color: #fff; border-color: var(--slate); }
.btn-primary:hover { background: var(--brown); border-color: var(--brown); color: #fff; }
.btn-ghost { color: var(--brown); border-color: var(--line); background: transparent; }
.btn-ghost:hover { border-color: var(--tan); color: var(--tan-dark); background: var(--paper); }
.site-header .btn { padding: 0.5rem 1.05rem; font-size: 0.9375rem; }
/* The call CTA in the help band -- the page's single most important action,
   so it is the only button allowed to outsize the rest. */
.btn-lg { font-size: 1.0625rem; padding: 0.9rem 1.75rem; text-align: center; }

/* Moose backdrop ---------------------------------------------------------
   Narrow screens: the moose is an ordinary image sitting under the copy. A
   phone has no room for a full-width column of text AND the art on the same
   screen, and a fixed illustration behind body copy is unreadable.

   52rem and up: the same element is lifted out of the flow and fixed to the
   bottom-right of the viewport. It sits inside .hero, which is a stacking
   context one layer below every section that follows, so the page appears to
   rise over a moose that never moves.

   position: fixed on the element, NOT background-attachment: fixed -- iOS
   Safari ignores the latter and the art jitters on every scroll.

   The copy is capped well clear of it at every width, so no text ever lands
   on the art and the page's AA contrast audit is untouched. */
/* Hidden outright on phones: at half a phone screen the moose crowds the copy,
   and shrunk down to fit it reads as a sticker rather than the hero. The page
   stands on its own without it. */
.moose-backdrop { display: none; }
.moose-backdrop img { width: 100%; height: auto; }

@media (min-width: 52rem) {
  .moose-backdrop {
    display: block;
    pointer-events: none;
    position: fixed;
    /* Deliberately bled off three edges: the desk runs down behind the next
       band, the antler tips run up behind the header, and the rump runs off
       the right. The art was drawn oversized for exactly this. Bleeding is
       what lets it be big -- fitting it whole between header and fold capped
       it near 50vw. */
    bottom: -6vh;
    right: -4vw;
    z-index: 0;
    /* Five limits, smallest wins. Only the copy is actually protected now --
       every other edge is allowed to clip:
         72vw                    the size wanted
         calc(50vw + 11rem)      keeps the desk off the button row. The desk
                                 runs to the art's left edge while the head
                                 above it is inset ~28%, so the buttons are
                                 the binding collision, not the lede. Still
                                 load-bearing: the home hero dropped its
                                 buttons on 2026-08-17, but /education and
                                 the 404 both still have a button row here
         calc(100vw - 30rem)     below 68rem the wrap is not centred, so the
                                 copy needs reserving separately
         calc(100vh + 4rem)      keeps the moose's HEAD below the header --
                                 antler tips may clip, the face may not
         86rem                   stops it going cartoonish on a huge display */
    width: min(72vw, calc(50vw + 11rem), calc(100vw - 30rem), calc(100vh + 4rem), 86rem);
    margin: 0;
    /* Its own compositor layer, so scrolling never repaints the animation. */
    transform: translateZ(0);
  }
}
/* A short landscape screen has room for the copy or the moose, not both. */
@media (min-width: 52rem) and (max-height: 32rem) {
  .moose-backdrop { display: none; }
}

/* Tablet portrait (600px to the 52rem breakpoint): an iPad at 768 is not the
   "smaller screen" the hiding rule is for, and 834 already shows the moose --
   having it appear between two iPad widths was the inconsistency. In flow
   under the copy, not fixed: there is not enough width to sit beside it. */
@media (min-width: 37.5rem) and (max-width: 51.9375rem) and (min-height: 34rem) {
  .moose-backdrop {
    display: block;
    width: min(58%, 22rem);
    margin: 1.75rem 0 0 auto;
    pointer-events: none;
  }
}

/* Everything carrying its own background paints above the backdrop. */
.site-header { position: relative; z-index: 2; }
main > section, .site-footer { position: relative; z-index: 1; }

/* Hero ------------------------------------------------------------------ */
/* Deliberately transparent -- this is the one band where the backdrop shows,
   against the body's cream. */
.hero { position: relative; z-index: 1; background: transparent; }
.hero > .wrap { padding-block: clamp(2.5rem, 6vw, 4.5rem); }
/* Above the art, so a long line of copy can never be overpainted by it. */
.hero-copy { position: relative; z-index: 1; max-width: 34rem; }
@media (min-width: 52rem) {
  /* Fill what is left of the first screen -- 7.5rem is the header plus the
     sliver of the next band -- so the whole moose clears the section that
     covers it. Assume a short header: a taller one only pushes the hero
     further down, which is safe; a shorter one would crop the art.

     52rem, not the usual 46rem: at 46rem the copy cap below still ran the
     last line of the lede into the antlers. */
  .hero > .wrap {
    /* vh, deliberately, not svh: the dynamic units resolve to the SMALL
       viewport where a browser UI bar can retract, which makes the hero
       shorter than the screen and lets the next band crop the moose. Too
       tall only costs the sliver; too short cuts the art. */
    min-height: calc(100vh - 7.5rem);
  }
  .hero-copy { max-width: min(34rem, 44%); }
  /* Home only. Without the button row the copy no longer reaches the fold, and
     the next band showed as an anonymous white sliver -- the only cue that the
     page continues. 3.5rem shorter breaks the help card's top edge into the
     first screen instead. It crops a little more of the desk, which is a flat
     slab and survives it; the head and antler rules are untouched. Must stay
     AFTER the .hero rule above -- equal specificity, source order decides.
     /education and the 404 keep the full height: both still have button rows
     and neither has a help band to reveal. */
  .hero-home > .wrap { min-height: calc(100vh - 11rem); }
}
.hero p.lede { font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem); color: var(--ink-soft); max-width: 34em; }
/* Closes the home hero now that it carries no buttons. Quiet on purpose: a
   rule and one line of small text, so the first screen stays a statement. */
.hero-note {
  margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--line);
  max-width: 28rem; font-size: 0.9375rem; line-height: 1.55; color: var(--ink-soft);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; }

.eyebrow {
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 700;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--tan-dark);
  margin: 0 0 0.85rem;
}

/* Sections -------------------------------------------------------------- */
section { padding-block: clamp(2.5rem, 6vw, 4.25rem); }
section.tint { background: var(--cream-deep); }
section.paper { background: var(--paper); }
/* The one strong colour moment on the page. The white .spotlight card sits on
   this ground, so no inner styles need overriding. */
section.slate { background: var(--slate); }
.section-head { max-width: 46em; margin-bottom: clamp(1.75rem, 4vw, 2.5rem); }
/* When a section is nothing but its heading block, that trailing margin is
   dead space stacked on top of the section's own padding. */
.section-head:last-child { margin-bottom: 0; }
.section-head p { color: var(--ink-soft); }

/* Card grid ------------------------------------------------------------- */
.grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
.card {
  background: var(--paper); border: 1px solid var(--line); border-radius: 6px;
  padding: 1.5rem 1.5rem 1.6rem;
}
section.paper .card { background: var(--cream); }
.card h3 { margin-bottom: 0.35em; color: var(--slate); font-size: 1.3125rem; }
.card p { font-size: 0.9688rem; color: var(--ink-soft); }

/* Principles list ------------------------------------------------------- */
.principles { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.4rem; }
@media (min-width: 46rem) { .principles { grid-template-columns: 1fr 1fr; gap: 1.75rem 2.5rem; } }
.principles > li { border-left: 3px solid var(--tan); padding-left: 1.1rem; }
.principles h3 { margin-bottom: 0.25em; }
.principles p { color: var(--ink-soft); font-size: 0.9688rem; }

/* Need-help-now band -----------------------------------------------------
   The one block outside the footer that prints the phone number, and a
   deliberate exception rather than a lapse. The rule exists because two
   earlier sections merely restated the footer's contact details; this one
   carries an offer -- free look, priced before any work, no contract -- and a
   "call us" band that made the reader scroll to the footer for the number
   would defeat itself. Everywhere else, the closer included, contact still
   belongs to the footer alone.

   Built from the same parts as .spotlight (card, hairline, thick tan edge) so
   the two strong asks on the page read as one family. It sits on section.paper
   with a cream card, matching `section.paper .card` below. */
.help-card {
  background: var(--cream);
  border: 1px solid var(--line);
  border-left: 6px solid var(--tan);
  border-radius: 6px;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  align-items: center;
}
/* auto, not a fraction: the call button is sized by its own text, and a
   fractional track stretched it across half the card. */
@media (min-width: 50rem) { .help-card { grid-template-columns: 1fr auto; } }
.help-card h2 { margin-bottom: 0.4em; }
.help-card p { color: var(--ink-soft); max-width: 42em; }
.help-actions { display: grid; gap: 0.8rem; justify-items: start; }
@media (min-width: 50rem) { .help-actions { justify-items: stretch; } }
.help-note { font-size: 0.9375rem; color: var(--ink-soft); }

/* Schools spotlight ----------------------------------------------------- */
.spotlight {
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 6px solid var(--tan);
  border-radius: 6px;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: center;
}
@media (min-width: 50rem) {
  /* Stacked, the DOM order (text, bullets, CTA) is the reading order we want:
     pitch, then detail, then the ask. Side by side we want the CTA back under
     the text, so the areas put it there without a second copy in the markup. */
  .spotlight {
    grid-template-columns: 1.6fr 1fr;
    grid-template-areas: "text points" "actions points";
    align-items: start;
    column-gap: clamp(1.25rem, 3vw, 2.5rem);
    row-gap: 0;
  }
  .spotlight > :first-child { grid-area: text; }
  .spotlight-points { grid-area: points; align-self: center; }
  .spotlight-actions { grid-area: actions; margin-top: 1.5rem; }
}
.spotlight h2 { margin-bottom: 0.4em; }
.spotlight p { color: var(--ink-soft); }
.spotlight-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.spotlight-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.spotlight-points li {
  position: relative; padding-left: 1.5rem;
  font-size: 0.9688rem; color: var(--ink-soft);
}
.spotlight-points li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 8px; height: 8px; border-radius: 50%; background: var(--tan);
}

/* Closing line ----------------------------------------------------------
   A full stop for the page, not a second contact block -- the phone and email
   belong to the footer alone, so this only links there. Lighter padding than a
   real section so it reads as a sign-off. */
.closer {
  background: var(--cream);
  border-top: 1px solid var(--line);
  padding-block: clamp(1.75rem, 3.5vw, 2.5rem);
}
.closer p {
  max-width: 44em; margin-inline: auto; text-align: center;
  color: var(--ink-soft);
}
.closer-moose { width: 6.5rem; margin: 0 auto 1.1rem; }

/* Footer ---------------------------------------------------------------- */
.site-footer {
  scroll-margin-top: 0;
  background: var(--brown); color: #ded4c8;
  padding-block: clamp(2rem, 4vw, 2.75rem);
  font-size: 0.9375rem;
}
.site-footer a { color: #f0e7db; }
.site-footer a:hover { color: var(--tan); }
.footer-grid { display: grid; gap: 1.75rem; }
@media (min-width: 46rem) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr; gap: 2.5rem; } }
.site-footer h2 { font-size: 0.75rem; font-family: var(--sans); font-weight: 700;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--tan-light); margin-bottom: 0.75rem; }
.footer-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.45rem; }

/* Contact is the footer's job now, so give the phone and email more weight
   than an ordinary footer link. */
.footer-contact { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.footer-contact a {
  font-size: 1.0625rem; color: #fff;
  text-decoration-color: rgba(255, 255, 255, 0.35);
}
.footer-contact a:hover { color: var(--tan); text-decoration-color: var(--tan); }
.footer-note { color: #bfb2a2; font-size: 0.875rem; }
.footer-brand-name { font-family: var(--serif); font-size: 1.25rem; color: #fff; margin-bottom: 0.4rem; }
.colophon {
  margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid rgba(255,255,255,0.14);
  font-size: 0.875rem; color: #bfb2a2;
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; justify-content: space-between;
}

/* Narrow screens ---------------------------------------------------------
   The header was 189px on a 390px-wide phone -- 22% of the screen gone before
   any content, with the nav on two rows below the brand and the button alone
   on the third. Tightening the type and gaps fits the links and the button on
   one row, which takes the whole header to ~130px. Two rows is the floor
   without a JS menu, so the brand keeps its own row. */
@media (max-width: 51.9375rem) {
  /* Two rows, both fully used: brand and the CTA share the first, the links
     take the second. Letting the links and the CTA share a row instead fits
     only at 390px and up -- at 375 (iPhone SE) and 360 the CTA dropped to a
     third row and the header hit 159px. This is ~105px at every width. */
  .site-header > .wrap {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "brand cta" "nav nav";
    align-items: center;
    gap: 0.5rem 0.75rem;
    padding-block: 0.7rem;
  }
  .brand { grid-area: brand; margin-right: 0; }
  .brand img { width: 44px; height: 44px; }
  .brand-name { font-size: 1.25rem; }
  .brand-sub { font-size: 0.75rem; }
  .nav { grid-area: nav; gap: 0.85rem; }
  .nav a:not(.btn) { font-size: 0.875rem; }
  .site-header .btn { grid-area: cta; padding: 0.45rem 0.85rem; font-size: 0.875rem; }

  /* The hero carries no art on a phone, so it needs the breathing room the
     illustration used to provide. */
  .hero > .wrap { padding-block: 3rem 3.5rem; }

  /* Six stacked cards is a long scroll; this trims roughly a card's height
     off it without crowding the text. */
  .card { padding: 1.25rem 1.25rem 1.35rem; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
