/* ============================================================
   ep.css — Five Dock Exercise Physiology.

   🚨 THIS IS THE ONE SITE IN THE NETWORK THAT FLIPS THE SHARED DARK SYSTEM TO A
   LIGHT ONE, AND IT IS A CLINICAL DECISION RATHER THAN A TASTE ONE.

   Jay's brief, 9 Aug 2026: the people who need exercise physiology are NDIS
   participants and older adults. The shared site.css was built for the
   anti-gravity treadmill site — deep navy, cyan accent, and body copy at
   `--ink-muted: rgba(234,241,255,0.64)`, which is roughly 4:1 against the navy.
   Three things make that the wrong base here:

     * Contrast sensitivity falls with age. 4:1 muted text is legible to a
       thirty-year-old designer and marginal to a seventy-five-year-old patient.
     * Light text on a dark field causes halation — the letterforms bloom and
       smear — and it is worse with uncorrected astigmatism, which is common in
       older adults.
     * A large proportion of this audience reads at a distance with reading
       glasses, so the 16px body of the shared system is small.

   So this file redefines the tokens to a light palette and raises the type. The
   layout, grid, components and spacing all still come from site.css: this is a
   repaint, not a fork.

   🚨 MEASURED, NOT CHOSEN BY EYE. Every pair below was computed, and build.mjs
   RE-COMPUTES THEM FROM THIS FILE ON EVERY BUILD and fails if one drops below
   its target. The numbers in the comments are what the guard asserts.

       ink      #0a1430 on #ffffff   18.17:1   (AAA, target 7)
       muted    #3b4762 on #ffffff    9.28:1   (AAA, target 7)
       muted    #3b4762 on #f4f7fb    8.63:1   (AAA, target 7)
       accent   #17439f on #ffffff    8.97:1   (AAA, target 7)
       white    on accent #17439f     8.97:1   (AAA, target 7)

   ⚠️ THE BRAND COLOURS CANNOT CARRY TEXT ON A LIGHT FIELD AND THAT IS THE WHOLE
   REASON --accent IS NOT --blue. SportsFit's blue #3f7dfb measures 3.79:1 on
   white, which fails even AA for body text, and the cyan #2dd6ec measures
   1.76:1, which is invisible. Both are kept for decoration only — a rule, a
   gradient edge, a hover wash — and never for a word anyone has to read.
   ============================================================ */

:root {
  /* --- Surfaces. The token NAMES stay navy-* so every rule in site.css that
         references them keeps working; only the values invert. Renaming them
         would mean patching site.css, which restyles the whole network. --- */
  --navy:      #ffffff;   /* page background */
  --navy-2:    #f4f7fb;   /* card / surface */
  --navy-3:    #e8eef7;   /* raised surface / hover */
  --navy-line: #cfd9e8;   /* solid divider */

  /* --- Ink --- */
  --ink:       #0a1430;   /* 18.17:1 on white */
  --ink-muted: #3b4762;   /*  9.28:1 on white, 8.63 on the soft surface */
  --ink-faint: #55617c;   /*  6.55:1 — LABELS AND EYEBROWS ONLY, never a sentence */

  /* --- Accent. Darkened from the brand blue so it can carry text. --- */
  --cyan:      #17439f;
  --cyan-soft: #1e50c8;
  --blue:      #17439f;
  --accent-grad: linear-gradient(100deg, #17439f, #0e2f78);

  /* Decoration only — see the header note. Never on text. */
  --brand-cyan: #2dd6ec;
  --brand-blue: #3f7dfb;

  --border:        #d7e0ed;
  --border-strong: #b9c7dd;
  --glass:         #f7fafd;
  --glass-2:       #eef3fa;

  /* Status. Darkened to clear 4.5:1 on white; the shared values are tuned for navy. */
  --green: #1c7a4f;
  --amber: #8a5a00;
  --red:   #b3261e;

  --shadow-card: 0 2px 4px rgba(10,20,48,0.04), 0 12px 28px -18px rgba(10,20,48,0.18);
  --shadow-glow: none;
}

/* ============================================================
   TYPE — the single biggest accessibility lever on this site
   ============================================================ */
/* 🚨 THE SCALE IS RAISED ON `html`, NOT ON `body`, AND THAT DISTINCTION IS THE
   WHOLE FIX. `rem` resolves against the ROOT element, so setting only
   `body { font-size: 19px }` left every rem-based size in site.css — which is
   most of them — still computed against a 16px root. Measured after that first
   attempt: body reported 19px while the service-card copy rendered at 14.5px and
   the smallest real paragraph on the page at 15.2px. The site LOOKED like it had
   been scaled up and had not.

   118.75% of 16px is 19px, so one declaration lifts the shared system's whole
   type scale proportionally — which is also the accessible way to do it, because
   it respects a reader who has changed their browser's default font size
   instead of overriding them with a fixed pixel value. */
html { font-size: 118.75%; }
body {
  background: var(--navy);
  color: var(--ink);
  font-size: 1rem;        /* = 19px; the shared system is 16px */
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
}
p, li { font-size: 1.05rem; line-height: 1.8; }
.lead { font-size: 1.3rem; line-height: 1.65; color: var(--ink); }
.prose p, .prose li { max-width: 68ch; }

/* ⚠️ NEVER let a heading go lighter than 600 here. A 300-weight display face at
   48px looks elegant and is markedly harder to read with reduced contrast
   sensitivity — the strokes thin out before the size compensates. */
h1, h2, h3, h4, h5 { color: var(--ink); font-weight: 700; letter-spacing: -0.01em; }
h1 { line-height: 1.15; }
h2 { line-height: 1.25; }

.eyebrow { color: var(--ink-faint); font-weight: 700; }
.fine { color: var(--ink-muted); font-size: 0.95rem; }
.serif { color: var(--ink); }

/* ============================================================
   COUNTERACTING THE LITERAL COLOURS IN THE SHARED site.css

   🚨 EVERY RULE IN THIS BLOCK EXISTS BECAUSE site.css HARD-CODES A DARK COLOUR
   THAT NO TOKEN CHANGE CAN REACH. build.mjs scans site.css for literal colours
   and FAILS THE BUILD if it finds one this file does not account for — so a new
   hard-coded navy added upstream becomes a build failure here rather than an
   invisible dark smear on a light page that nobody notices for a month.
   ============================================================ */

/* site.css L136 / L368: .btn-primary and .pagination .cur set color:#041022 for
   dark text on a bright cyan fill. Inverted here: white on deep blue, 8.97:1. */
.btn-primary,
.pagination .cur { color: #ffffff; }

/* site.css L121: the dot grid is a white dot at 6% — invisible on white. */
.dotgrid { background-image: radial-gradient(rgba(10,20,48,0.10) 1px, transparent 1px); }

/* site.css L235 / L354 / L376: media wells and quote blocks fill with a navy
   gradient. On a light page they read as holes. */
.media-well,
.post-card .thumb,
.pull-quote { background: linear-gradient(160deg, #f4f7fb, #e8eef7); }

/* site.css L283 / L296: text shadows sized for light text on a photograph. They
   are still correct over an image, so they are left alone deliberately — this
   comment exists so the build guard's accounting is complete. */

/* site.css L294: the video facade play arrow fills dark on hover. */
.video-facade:hover .play svg { fill: #ffffff; }

/* site.css L194: a cyan gradient border mask. Decorative, retinted. */
.grad-border::before { background: linear-gradient(140deg, rgba(23,67,159,0.35), transparent 45%); }

/* site.css L401: the footer is a near-black navy. A dark footer under a light
   page is legitimate design, but it would need every footer token re-inverted
   inside it — two colour systems in one document, and the second one is the one
   that drifts. It is light instead. */
.site-footer { background: var(--navy-2); border-top: 2px solid var(--border-strong); }
.site-footer h4, .site-footer h5 { color: var(--ink); }
.site-footer p, .site-footer a, .site-footer li { color: var(--ink-muted); }
.site-footer a:hover { color: var(--cyan); }

/* ============================================================
   🚨 COMPONENT TYPE SIZES — THE BODY RULE ALONE DOES NOT REACH THEM

   Setting `body { font-size: 19px }` looks like it has raised the whole site and
   has not. site.css sizes its components individually, so after the body change
   the rendered sizes measured in a browser were:

       .cond-card p     14.5px      (the service cards on the home page)
       .hero-badges li  14px
       .card p          15.5px
       .split-body p    16.8px
       .section-head p  17px

   i.e. the six blocks carrying most of the reading on the site were still at or
   below the shared system's original scale, on the one site in the network
   written for people with ageing eyes. Nothing flagged it: verify.mjs checks
   structure, the contrast guard checks colour, and both screens check words.
   It was found by measuring the rendered page.

   ⚠️ Small AND muted reads as faint even when the contrast ratio is fine. The
   colour here measures 9.28:1; it looked washed out purely because of the size.
   Do not "fix" a legibility complaint on this site by darkening the ink before
   checking what size it is actually rendering at.
   ============================================================ */
.card p, .cond-card p, .split-body p, .section-head p,
.faq-item .a, .group-note, .clinic-note, .post-card p, .prose li {
  font-size: 1.02rem;      /* >= 18px against the 18-19px base */
  line-height: 1.75;
}
.card h3, .cond-card h3, .post-card h3 { font-size: 1.28rem; }
/* ⚠️ THE SMALL PRINT IS WHERE THE FUNDING ANSWERS ARE, so it is the last place
   this site should shrink. Measured after the first pass, these were still
   rendering at 14–15.2px because site.css scopes them more specifically than a
   bare `.fine` (e.g. `.cta-band .fine`), so the base rule lost on specificity
   rather than on order. The fix is to match the scope, not to raise !important. */
.hero-badges li { font-size: 1rem; }
.cta-band .fine { font-size: 1rem; }
.site-footer p, .site-footer li, .site-footer a { font-size: 1rem; }
.site-footer .fine { font-size: 0.95rem; }
.section-head h2, .split-body h2 { font-size: clamp(1.7rem, 1.2rem + 1.6vw, 2.5rem); }
.eyebrow { font-size: 0.82rem; }

/* ============================================================
   TARGETS, FOCUS AND MOTION
   ============================================================ */

/* 🚨 56px, NOT THE 24px WCAG 2.2 AA MINIMUM. AA's target size is a floor for the
   general population; this audience includes people with tremor, arthritic
   hands, reduced fine motor control and low vision. 44px is the AAA figure and
   56 is what a phone in an older hand actually wants. */
.btn, .nav-links a, .nav-links button, .nav-phone,
.pagination a, .pagination .cur {
  min-height: 56px;
  display: inline-flex; align-items: center; justify-content: center;
}
.btn { font-size: 1.05rem; padding: 16px 28px; font-weight: 700; }
.btn-lg { font-size: 1.15rem; padding: 20px 34px; }

/* The mobile menu button measured 42px — the only target on the site under the
   44px AAA figure, and it is the control that opens navigation on a phone. */
.nav-toggle { min-height: 56px; min-width: 56px; }

/* A visible, thick focus ring on everything focusable. The shared system relies
   on the browser default, which is a 1px dotted line and effectively invisible
   against a light page for anybody who needs it. */
a:focus-visible, button:focus-visible,
input:focus-visible, summary:focus-visible {
  outline: 3px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Links inside body copy are underlined, always. Colour alone is not an
   accessible affordance, and it is the first thing to fail for a reader with a
   colour vision deficiency. */
.prose a, .article a, main p a { color: var(--cyan); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 2px; }
.prose a:hover, .article a:hover, main p a:hover { text-decoration-thickness: 3px; }

/* 🚨 THE SCROLL REVEAL IS OFF ON THIS SITE, FOR EVERYONE, ALWAYS.

   site.css opts every page into `.js .reveal { opacity: 0 }` and site.js adds
   `.in` as each block scrolls into view. It is a nice effect and it is the wrong
   trade here, for the same reason the Greenlees club page carries no JavaScript
   at all: on a page whose entire job is getting somebody to ring the clinic,
   "invisible if one script misbehaves" is not worth a fade.

   The audience sharpens it. Someone who scrolls in large jumps — a magnifier
   user, a keyboard user paging down, anyone on a phone with a flick — arrives at
   a section before the observer has fired and sees blank space where the answer
   to their question is. There is no version of that which is better than the
   content simply being there.

   ⚠️ site.js IS STILL LOADED and still needed: it runs the mobile nav toggle,
   the services dropdown and the video facade. Only the fade is neutralised, and
   `__revealAll()` on the script tag's onerror stays as the second line of
   defence. */
.reveal { opacity: 1 !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   COMPONENTS THE SHARED SHEET DOES NOT CARRY
   ============================================================ */

/* Skip link. site.css has no rule for it, so a bare <a class="skip"> renders as
   a visible stray link above the header on every page. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--ink); color: #ffffff;
  padding: var(--sp-4) var(--sp-6); border-radius: var(--r-sm);
  font-weight: 700; font-size: 1.05rem;
}
.skip:focus { left: var(--sp-4); top: var(--sp-4); }

/* Hero copy column — without min-width:0 a long unbroken word can force the
   grid wider than the viewport and give the whole page a sideways scroll. */
.hero-copy { min-width: 0; }

/* 🚨 THE PHONE NUMBER IS A PRIMARY CONTROL ON THIS SITE, NOT A FOOTER DETAIL.
   An older patient rings; they do not fill in a booking form. It sits in the
   header on every page, at text size, next to the booking button rather than
   behind it. */
.nav-actions { display: flex; align-items: center; gap: var(--sp-4); }
.nav-phone {
  gap: 10px; padding: 0 18px;
  color: var(--ink); font-weight: 700; font-size: 1.05rem;
  text-decoration: none; border: 2px solid var(--border-strong);
  border-radius: var(--r-full); white-space: nowrap;
}
.nav-phone svg { width: 20px; height: 20px; flex: 0 0 auto; }
.nav-phone:hover { border-color: var(--cyan); color: var(--cyan); }

/* Clinic card (contact page). */
.clinic-card {
  background: var(--navy-2); border: 2px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-8);
}
.clinic-card h3 { font-size: 1.5rem; }
.clinic-card address { font-style: normal; color: var(--ink-muted); margin-top: var(--sp-4); line-height: 1.8; }
.clinic-card address a { color: var(--cyan); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

/* Team cards. */
.team-card .role { color: var(--ink-muted); margin-top: 6px; }
.team-card .creds { margin-top: var(--sp-4); display: flex; flex-wrap: wrap; gap: 10px; }
.cred {
  display: inline-block; padding: 8px 14px;
  background: var(--navy-3); border: 1px solid var(--border-strong);
  border-radius: var(--r-full);
  font-size: 0.95rem; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* FAQ. A <details> is keyboard operable and needs no JavaScript, which matters
   on a site whose reveal script is already fail-open. */
.faq-item { border-bottom: 2px solid var(--border); }
.faq-item summary {
  cursor: pointer; padding: var(--sp-5) 0; font-weight: 700; font-size: 1.1rem;
  list-style: none; min-height: 56px; display: flex; align-items: center;
}
.faq-item summary::-webkit-details-marker { display: none; }
/* ⚠️ THE ANSWER IS `.a`, NOT A `<p>`. build.mjs renders `<div class="a">`, and
   styling `.faq-item p` instead silently does nothing — the same mistake this
   workspace already made on all five NDIS service pages, where it was invisible
   to the build, the link check and both content screens. */
.faq-item .a { color: var(--ink-muted); padding-bottom: var(--sp-5); }
.faq-item .a p { margin: 0; }

.article-back { color: var(--cyan); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.post-meta { color: var(--ink-muted); font-size: 0.95rem; border-top: 2px solid var(--border); padding-top: var(--sp-5); margin-top: var(--sp-8); }
.group-note { color: var(--ink-muted); }

/* The CTA band is the one deliberately dark surface: it is a single block, it
   carries no long-form reading, and the inversion is what makes it read as a
   call to action rather than another paragraph. White on #0a1430 is 18.17:1. */
.cta-band { background: var(--ink); border: none; }
.cta-band h2, .cta-band p { color: #ffffff; }
.cta-band .fine { color: rgba(255,255,255,0.82); }
/* 🚨 `background: transparent` IS LOAD-BEARING, NOT TIDYING. site.css gives
   .btn-ghost `background: var(--glass)`, which on the dark shared system is a
   barely-there white film and on this light one resolves to #f7fafd — so white
   text on it measured 1.05:1 and the button rendered as a blank white pill with
   invisible words in it, on the primary call to action. Every automated check
   passed: the contrast guard tests TOKEN pairs, and this was a pair no token
   describes. Found by measuring the rendered element. */
.cta-band .btn-ghost { color: #ffffff; background: transparent; border: 2px solid rgba(255,255,255,0.6); }
.cta-band .btn-ghost:hover { background: rgba(255,255,255,0.14); border-color: #ffffff; }
.cta-band .btn-primary { background: #ffffff; color: var(--ink); }

@media (max-width: 900px) {
  body { font-size: 18px; }
  .nav-phone span { display: none; }   /* the icon stays a 56px target */
}
