/* ==========================================================================
   ESH'S TRUCK DRIVING SCHOOL — base.css
   Reset · design tokens · typography · utilities

   TOKEN RULE: every colour, space, size, radius, shadow, easing, duration and
   z-index used anywhere on this site is declared in this file and nowhere
   else. No literal hex value appears in layout.css, components.css,
   pages.css or animations.css.

   NAMING CONVENTION (BEM-flavoured):
     .block            standalone component        .site-header
     .block__element   part of a component         .site-header__nav
     .block--modifier  variant of a component      .btn--ghost
     .u-*              single-purpose utility      .u-mono
     .is-* / .has-*    JS-applied state            .is-scrolled
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* ---- Colour ------------------------------------------------------------
     Six brand values, all sampled from the supplied logo. Red is an ACCENT:
     it is reserved for the primary CTA, active nav state, licence-class
     plates, the motion arc and section ticks. It is never a page field.

     Contrast, measured: --red on --bone = 5.1:1 and white on --red = 5.3:1,
     so red clears AA for body text on light surfaces. --red on --ink is only
     3.7:1, so on dark surfaces red is used for rules, arcs, plate fills and
     headings 24px+ only — never for small dark-surface body text. */
  --ink:       #0B0B0C;   /* near-black: hero, ladder, CTA band, footer      */
  --asphalt:   #1A1B1E;   /* elevated dark surface, cards on dark           */
  --red:       #D31A22;   /* brand red from the logo arc                    */
  --red-deep:  #9E0F16;   /* pressed states, gradient end                   */
  --bone:      #F4F4F2;   /* dominant page surface                          */
  --line:      #D9D9D6;   /* hairlines, plate borders, dividers             */

  /* Neutral tints. These are mixes of --ink into --bone — no new hue enters
     the system. Contrast on --bone: --muted 6.9:1, --muted-strong 11.4:1. */
  --surface:        #FFFFFF;
  --muted:          #52545A;
  --muted-strong:   #35373C;
  --muted-on-dark:  #A9ABB0;  /* 8.6:1 on --ink                             */
  --line-on-dark:   #2E3035;

  /* Alpha derivations for scrims and overlays (no new hue). */
  --ink-a90:  rgba(11, 11, 12, .90);
  --ink-a72:  rgba(11, 11, 12, .72);
  --ink-a55:  rgba(11, 11, 12, .55);
  --ink-a12:  rgba(11, 11, 12, .12);
  --bone-a70: rgba(244, 244, 242, .70);
  --bone-a14: rgba(244, 244, 242, .14);
  --red-a40:  rgba(211, 26, 34, .40);
  --red-a14:  rgba(211, 26, 34, .14);

  /* ---- Type --------------------------------------------------------------
     Display  Manrope 700/800 — upright, professional, clearly distinct from
              the body face. It replaced an expanded italic grotesque, which
              read as novelty rather than as a business voice.
     Body     Public Sans — a civic/regulatory sans, deliberately not Inter
     Utility  Roboto Mono — licence codes, hours, phone numbers, plate stamps */
  --font-display: 'Manrope', 'Manrope Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body:    'Public Sans', 'Public Sans Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    'Roboto Mono', ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;

  /* Modular scale. Every value is fluid between a 360px and a 1440px
     viewport, so no heading needs a media query. Deliberately restrained:
     the previous scale topped out at 96px, which shouted. */
  --step--1: clamp(.8125rem, .792rem + .093vw, .875rem);   /* 13 → 14 */
  --step-0:  clamp(1rem,     .979rem + .093vw, 1.0625rem); /* 16 → 17 */
  --step-1:  clamp(1.125rem, 1.083rem + .185vw, 1.25rem);  /* 18 → 20 */
  --step-2:  clamp(1.25rem,  1.167rem + .37vw,  1.5rem);   /* 20 → 24 */
  --step-3:  clamp(1.375rem, 1.208rem + .741vw, 1.875rem); /* 22 → 30 */
  --step-4:  clamp(1.625rem, 1.333rem + 1.296vw, 2.5rem);  /* 26 → 40 */
  --step-5:  clamp(2rem,     1.583rem + 1.852vw, 3.25rem); /* 32 → 52 */
  --step-6:  clamp(2.375rem, 1.833rem + 2.407vw, 4rem);    /* 38 → 64 */

  --leading-tight: 1.08;
  --leading-snug:  1.18;
  --leading-body:  1.65;
  --tracking-display: -.018em;
  --tracking-mono:  .14em;

  /* ---- Space -------------------------------------------------------------- */
  --space-3xs: .25rem;
  --space-2xs: .5rem;
  --space-xs:  .75rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;
  --space-section: clamp(3.5rem, 7vw, 7rem);

  /* ---- Layout ------------------------------------------------------------- */
  --gutter:   clamp(1.25rem, 4vw, 3rem);
  --maxw:     87.5rem;  /* 1400px */
  --maxw-narrow: 46rem;
  --measure:  64ch;
  --rail-w:   9.5rem;   /* the kerb rail column, ≥1024px only */

  /* The header is three separate bands: a dark utility strip, a white brand
     band carrying the logo, and a dark navigation bar. The white band exists
     because the supplied logo is artwork on a solid white field — giving it
     its own light band lets the real logo sit on the page untouched, instead
     of being redrawn to survive a dark background. */
  --utility-h: 2.25rem;
  --brand-h:   5rem;
  --nav-h:     0rem;    /* no nav bar below 1024px — it lives in the menu */
  --header-total: calc(var(--utility-h) + var(--brand-h) + var(--nav-h));

  /* ---- Form ---------------------------------------------------------------- */
  --radius-sm: 2px;   /* this brand is squared and industrial: radii stay tiny */
  --radius-md: 3px;
  --radius-lg: 6px;
  --hairline:  1px;
  --tap:       2.75rem; /* 44px minimum tap target */

  --shadow-sm: 0 1px 2px rgba(11, 11, 12, .06), 0 2px 8px rgba(11, 11, 12, .05);
  --shadow-md: 0 4px 12px rgba(11, 11, 12, .09), 0 14px 34px rgba(11, 11, 12, .10);
  --shadow-lg: 0 18px 48px rgba(11, 11, 12, .22);
  --shadow-red: 0 8px 24px rgba(211, 26, 34, .28);

  /* ---- Motion -------------------------------------------------------------- */
  --ease-out:    cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --dur-fast: 160ms;
  --dur-mid:  320ms;
  --dur-slow: 560ms;   /* nothing on this site animates for longer */

  /* ---- Z-index scale ------------------------------------------------------
     Declared once so the fixed header, mobile menu, floating buttons,
     lightbox and skip link can never fight over stacking order. */
  --z-base:      1;
  --z-rail:      5;
  --z-raised:    10;
  --z-backtop:   55;
  --z-float:     58;
  --z-mobilebar: 60;
  --z-menu:      65;
  --z-header:    70;
  --z-lightbox:  90;
  --z-skip:      110;
}

/* The nav bar only exists from 1024px up; below that the links live in the
   mobile menu, so the header is two bands rather than three. */
@media (min-width: 64em) {
  :root {
    --brand-h: 7rem;
    --nav-h:   3.25rem;
  }
}

/* Metric-adjusted fallback faces. These keep the layout still while the web
   fonts swap in, which is most of our CLS budget. */
@font-face {
  font-family: 'Public Sans Fallback';
  src: local('Arial'), local('Helvetica Neue'), local('Liberation Sans');
  size-adjust: 104%;
  ascent-override: 92%;
  descent-override: 24%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Manrope Fallback';
  src: local('Arial'), local('Helvetica Neue'), local('Liberation Sans');
  size-adjust: 101%;
  ascent-override: 98%;
  descent-override: 25%;
  line-gap-override: 0%;
}

/* --------------------------------------------------------------------------
   2. RESET
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Anchor targets clear the fixed header instead of hiding beneath it. */
  scroll-padding-top: calc(var(--header-total) + var(--space-md));
}

/* SCROLLING — three deliberate omissions here, all of which were present
   earlier and all of which interfere with a plain mouse wheel:

   1. No `scroll-behavior: smooth` on the root. It turns every wheel tick into
      an animation, which stutters badly on Windows mice and makes the page
      feel stuck. Smooth scrolling is still used for the back-to-top button
      and for in-page anchor links, applied from JavaScript per interaction
      and skipped entirely under prefers-reduced-motion.

   2. No `overscroll-behavior-y: none`. It buys nothing on a normal page and
      it suppresses scroll chaining — which stops the wheel working at all
      when the site is viewed inside an embedded preview pane or iframe.

   3. `overflow-x: hidden` sits on the body only, not on html as well.
      Setting it on both makes the body its own scroll container alongside
      the viewport, which is a common source of dead-scroll bugs.

   The overflow guard is a safety net regardless: every actual overflow is
   fixed at its source, verified at fourteen widths across all fifteen pages. */
body {
  overflow-x: hidden;
}

body {
  min-height: 100%;
  background-color: var(--bone);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--leading-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Room for the mobile sticky action bar, including the iOS home indicator.
     Reset to 0 at ≥768px in layout.css where that bar is hidden. */
  padding-bottom: calc(4rem + env(safe-area-inset-bottom, 0px));
}

img,
picture,
video,
svg,
canvas {
  display: block;
  max-width: 100%;
}

img { height: auto; }

/* Deliberately NOT `svg { fill: currentColor }`. A CSS declaration beats a
   presentation attribute, so that rule would override every `fill="none"` on
   the stroked line icons and render them as solid shapes. Icons that want a
   fill declare it themselves. */

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button { background: none; border: 0; }

p,
h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

ul[class],
ol[class] {
  list-style: none;
  padding: 0;
}

a { color: inherit; }

table {
  border-collapse: collapse;
  width: 100%;
}

:target { scroll-margin-top: calc(var(--header-total) + var(--space-md)); }

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY
   -------------------------------------------------------------------------- */
/* Headings are upright, sentence case and only lightly tracked. Uppercase
   italics at 96px read as a poster, not as a business that wants to be taken
   seriously — the uppercase mono voice is kept for labels and licence codes,
   where it belongs. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-tight);
  text-wrap: balance;
}
h3, h4 { font-weight: 700; }

h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

/* Sub-headings inside body copy stay in the body face — the display face is
   used large and rarely, which is what keeps it feeling like a voice rather
   than a texture. */
h5, h6 {
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 700;
  line-height: var(--leading-snug);
}

p { text-wrap: pretty; }

p a:not([class]) {
  color: var(--red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  transition: color var(--dur-fast) var(--ease-out);
}
p a:not([class]):hover { color: var(--red-deep); }

strong, b { font-weight: 700; }

/* --------------------------------------------------------------------------
   4. FOCUS & SELECTION
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* On dark surfaces the red ring alone is too low-contrast, so it gets a bone
   halo behind it. */
.u-on-dark :focus-visible,
.site-footer :focus-visible,
.hero :focus-visible {
  outline-color: var(--bone);
  box-shadow: 0 0 0 6px var(--red-a40);
}

::selection {
  background-color: var(--red);
  color: var(--surface);
}

/* --------------------------------------------------------------------------
   5. UTILITIES
   -------------------------------------------------------------------------- */
.shell {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.shell--narrow { max-width: calc(var(--maxw-narrow) + var(--gutter) * 2); }

.u-visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: var(--space-2xs);
  left: var(--space-2xs);
  z-index: var(--z-skip);
  padding: var(--space-xs) var(--space-md);
  background-color: var(--red);
  color: var(--surface);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transform: translateY(-150%);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus-visible { transform: translateY(0); }

/* The mono voice: licence codes, hours, phone numbers, indices. Used
   everywhere a number wants to read like a compliance stamp. */
.u-mono {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.u-measure { max-width: var(--measure); }
.u-center  { margin-inline: auto; }

.u-lede {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--muted-strong);
}
.u-on-dark .u-lede { color: var(--muted-on-dark); }

.u-on-dark {
  background-color: var(--ink);
  color: var(--bone);
}

/* Flow: vertical rhythm without margin collapse surprises. */
.u-flow > * + * { margin-block-start: var(--flow-space, var(--space-sm)); }

/* Spacing utilities. These exist so no HTML file ever carries a style
   attribute — every value still comes from the token scale. */
.u-mt-xs { margin-block-start: var(--space-xs); }
.u-mt-sm { margin-block-start: var(--space-sm); }
.u-mt-md { margin-block-start: var(--space-md); }
.u-mt-lg { margin-block-start: var(--space-lg); }
.u-mt-xl { margin-block-start: var(--space-xl); }

/* No-JS guard: anything the JS would normally reveal must be visible when
   JS never runs. Reveal classes only take effect once <html class="js">
   is set — see animations.css. */
.no-js .u-js-only { display: none; }
