/* ============================================================
   THE BREAKPOINT LADDER — canonical for every sheet in assets/css.
   Documented here because base.css loads before every section sheet.

   Structural rungs, each written as a matched pair:

     small phone   (width <  30rem)   /  (width >= 30rem)   480px
     phone/tablet  (width <  48rem)   /  (width >= 48rem)   768px
     tablet/desktop(width <  64rem)   /  (width >= 64rem)   1024px

   Range syntax, not min-width/max-width, and the reason is arithmetic.
   The old pairing was `max-width:63.9375rem` / `min-width:64rem`, and
   63.9375rem is 1023px exactly -- one whole CSS pixel below 1024, not
   the 0.02px it was assumed to be. Any viewport in between (browser
   zoom and fractional device-pixel-ratio displays produce these
   routinely: a 1126px window at 110% zoom is 1023.6 CSS px) matched
   NEITHER half, so at 1023.6 the tablet rules were off and the desktop
   rules were not yet on. `< 64rem` / `>= 64rem` is exclusive and
   exhaustive by definition -- exactly one side matches at every real
   number, so there is nothing to tune and no fudge factor to get wrong.
   Same for 48rem (was 47.9375rem = 767px) and 30rem (was two spellings,
   29.9375rem = 479px in categories/parts and 30rem elsewhere).

   The boundary value always belongs to the LARGER band: at exactly
   1024px the desktop rules apply, at exactly 768px the tablet rules do,
   at exactly 480px the small-phone tweaks do not. header.js already
   reads the desktop rung this way -- matchMedia('(min-width: 64rem)')
   -- so the JS drawer and the CSS drawer flip on the same pixel.

   Two relief valves are NOT rungs. They have no min-width partner, so
   no dead band exists for them and they stay inclusive, `<=`, which is
   exactly what `max-width` meant:

     (width <= 40rem)     640px  header utility strip drops the address
     (width <= 22.5rem)   360px  header utility strip drops the number

   and one band is bounded on both sides by rungs it shares with others:

     (64rem <= width <= 81.25rem)  cramped desktop nav, 1024-1300px

   If you add a query, add it here. A ladder that lives only in eight
   stylesheets is a ladder nobody can reason about. docs/responsive.md
   carries the prose version.
   ============================================================ */

/* ===== Reset & base ===== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;
  scroll-padding-top:var(--sp-6)}
body{margin:0;font-family:var(--font-body);font-size:var(--fs-base);
  font-weight:var(--fw-reg);line-height:var(--lh-body);color:var(--grey-600);
  letter-spacing:var(--tr-normal);
  background:var(--gps-white);
  /* Lato renders thin and slightly blurred at body sizes without
     these. Grayscale smoothing is the macOS/Firefox counterpart to
     -webkit-font-smoothing and is what stops the 400 weight looking
     washed out next to the reference, which applies the same pair. */
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility}
img,svg,video{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
/* Headings default to 700 with tight tracking, in near-black rather
   than pure black. The 900 weight is a display treatment -- it belongs
   on the hero, not on every sub-head, where it reads as shouting.
   .hero__title sets its own weight/case and is unaffected by this. */
h1,h2,h3,h4{font-family:var(--font-head);font-weight:var(--fw-bold);
  line-height:var(--lh-head);letter-spacing:var(--tr-snug);
  margin:0 0 var(--sp-4);color:var(--gps-black)}
h1,h2{letter-spacing:var(--tr-tight);line-height:var(--lh-display)}
p{margin:0 0 var(--sp-4)}
ul{margin:0;padding:0;list-style:none}

/* ===== Layout ===== */
/* ===== Icon sprite =====
   Four sections emit an inline <svg class="gps-sprite"> symbol library:
   header, about, brands and footer. The rule lives here rather than in
   header.css because every section stylesheet declares gps-base as its
   dependency and none of them declares gps-header -- so a page that
   loaded about.css without header.css rendered the sprite as a visible
   empty box and pushed the section down by its height.

   position/width/height/overflow rather than display:none. A sprite set
   to display:none is removed from the render tree, and several engines
   then refuse to resolve a <use> against symbols inside it. This
   spelling hides the box while leaving the symbols referenceable. */
.gps-sprite{position:absolute;width:0;height:0;overflow:hidden}

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

/* ===== Buttons — flat, sharp, high contrast ===== */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);
  min-height:3.25rem;padding:var(--sp-3) var(--sp-7);
  border:3px solid transparent;border-radius:var(--radius-0);
  font-family:var(--font-head);font-size:var(--fs-sm);font-weight:var(--fw-bold);
  letter-spacing:var(--tr-wide);text-transform:uppercase;white-space:nowrap;
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease),
             border-color var(--dur) var(--ease),transform var(--dur-fast) var(--ease)}
.btn:active{transform:translateY(1px)}

/* Phones. 40px of padding each side is a desktop proportion: on a
   280px full-width button it leaves 200px for a label that needs 155,
   so the type sits in a slot barely wider than itself. 24px restores
   the ratio. 48px tall is still comfortably over the 44px target, and
   two stacked calls to action give back 8px of a viewport that at 320
   has none to spare. */
@media (width < 30rem){
  .btn{min-height:3rem;padding-inline:var(--sp-5)}
}

/* Solid yellow — the primary call to action on every ground */
.btn--primary{background:var(--gps-yellow);color:var(--gps-black);
  border-color:var(--gps-yellow)}
.btn--primary:hover{background:var(--gps-white);border-color:var(--gps-white)}

/* Outlined, for use on red or black grounds */
.btn--onDark{background:transparent;color:var(--gps-white);
  border-color:var(--gps-white)}
.btn--onDark:hover{background:var(--gps-white);color:var(--gps-black)}

/* Outlined, for use on the yellow ground */
.btn--onLight{background:transparent;color:var(--gps-black);
  border-color:var(--gps-black)}
.btn--onLight:hover{background:var(--gps-black);color:var(--gps-white)}

/* ===== Section heading =====
   One centred heading, then straight into the content -- the reference
   runs no standfirst under its section titles, and adding one changes
   the rhythm of the whole page. Sizes track the reference: 36px at
   desktop, scaled down by viewport rather than by breakpoint. */
.section{padding-block:clamp(var(--sp-7),4.5vw,var(--sp-8))
                       clamp(var(--sp-8),5.5vw,var(--sp-10))}
.section-head{margin:0 0 clamp(var(--sp-6),3.2vw,var(--sp-8));text-align:center}
.section-head__title{
  margin:0;
  font-size:clamp(1.75rem,3.1vw,2.25rem);
  font-weight:var(--fw-bold);
  letter-spacing:var(--tr-tight);
  line-height:var(--lh-display);
  color:var(--gps-black);
  text-wrap:balance}

/* ===== Accessibility ===== */
.visually-hidden{position:absolute!important;width:1px;height:1px;padding:0;
  margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* Fixed, not absolute. The header pins itself on handhelds, so an
   absolutely positioned skip link would reveal itself at the top of the
   document — off screen — for anyone who reached it after scrolling. */
.skip-link{position:fixed;left:var(--sp-4);top:-100px;z-index:999;
  background:var(--gps-yellow);color:var(--gps-black);
  padding:var(--sp-3) var(--sp-5);font-weight:var(--fw-black);
  transition:top var(--dur) var(--ease)}
.skip-link:focus{top:var(--sp-4)}

/* A single focus style that stays visible on red, black, yellow and white */
:focus-visible{outline:3px solid var(--gps-yellow);outline-offset:3px;
  box-shadow:0 0 0 6px var(--gps-black)}
.hero--light :focus-visible,
[data-ground="yellow"] :focus-visible{outline-color:var(--gps-black);
  box-shadow:0 0 0 6px var(--gps-yellow)}
