/* ============================================================================
   TYPE — the complete typographic system for a Staie build.
   Copy this file first. Write no other font-size, font-weight, font-family,
   text-transform or letter-spacing anywhere else in the stylesheet.

   The contract, in full, is build/COPY-AND-TYPOGRAPHY.md.
   The gate is:  python3 ../seo-ops/copy_type_audit.py --site ./website

   THE ONE IDEA: a reader counts PERCEPTIBLE TREATMENTS, not @font-face rules.
   A treatment = family + size + weight + slant + case + colour. Two typefaces
   can present eighteen treatments; a client will call that "a lot of different
   fonts" and they are perceptually correct. This file defines seven and no more.
   ========================================================================== */

:root {
  /* ---- FAMILIES — exactly two, and the boundary is drawn by ROLE ----
     Display face at --fs-lead and above. Body face at --fs-lead and below.
     --fs-lead is the only shared step, and there the family is decided by
     role (a statement is display, a lead paragraph is body), never by page.
     Load 400 and 700 ONLY. A third weight becomes an eighth treatment within
     a week — it always does. */
  /* iCareConnect (recorded in CLAUDE.md): display Montserrat 400, the face the
     Woojer website sets its headings and statements in (Anda, 28 Oct 2026: "can
     we make the font the same like in the Woojer web"); Woojer's headings are
     its 300, and this build loads 400 only. Body Atkinson Hyperlegible 400/700,
     drawn by the Braille Institute so I, l and 1 never look alike, for a
     readership of women over 60: Montserrat is a geometric sans whose I and l
     are the same bar, which section "Choosing the two faces" rules out for
     body text. The logo stays Lora, as outlines. Both faces SIL OFL 1.1,
     self-hosted from gwfh.mranftl.com. (Lora was the display face 22-27 Oct.) */
  --font-display: "Montserrat", "Display Fallback", Arial, sans-serif;
  --font-body   : "Atkinson Hyperlegible", "Body Fallback", Arial, sans-serif;

  /* ---- SIZE — five tokens, named by ROLE, never by tag or size.
     "--fs-h3" invites "--fs-h4"; "--fs-lead" does not.
     iCareConnect writes for women over 60, so the body is lifted to the 18-20px
     that COPY-AND-TYPOGRAPHY section H asks for, and the ladder is rescaled to
     keep its ~1.25 steps: 16 / 18-20 / 20-25 / 25-31 / 28-38.
     Largest heading is 1.90x body — the cap is 1.9x. A 40px+ hero over 16-19px
     body is the clearest "marketing page" tell there is.
     Each clamp keeps a rem term in the middle so the text still scales with
     browser zoom (a vw-only middle term breaks WCAG 1.4.4). */
  --fs-meta   : 1rem;                                           /* 16px flat     */
  --fs-body   : clamp(1.125rem,  1.07rem + 0.25vw, 1.25rem);    /* 18.1 -> 20px  */
  --fs-lead   : clamp(1.25rem,   1.12rem + 0.55vw, 1.5625rem);  /* 20.0 -> 25px  */
  --fs-section: clamp(1.5625rem, 1.33rem + 0.85vw, 1.9375rem);  /* 25.0 -> 31px  */
  --fs-page   : clamp(1.75rem,   1.45rem + 1.25vw, 2.375rem);   /* 28.0 -> 38px  */

  /* ---- LEADING — moves INVERSELY with size.
     Keeping 1.5 on a 36px heading fragments it into disconnected strips. */
  --lh-body   : 1.68;
  --lh-lead   : 1.55;
  --lh-h3     : 1.40;
  --lh-h2     : 1.22;
  --lh-h1     : 1.15;

  /* ---- MEASURE — 55-65 characters. Defined as a MULTIPLE of the body token so
     it tracks the fluid size automatically: that is what "move the measure
     whenever the body size moves" means in CSS. A fixed rem measure overshoots
     as soon as the body size changes, and `ch` measures the width of the digit
     zero, which drifts every time the face changes. Calibrate the multiplier
     once per client in the browser with the real webfont loaded. */
  --measure: calc(var(--fs-body) * 29);   /* ~58 characters — body copy */
  --col    : calc(var(--fs-body) * 34);   /* headings and statements, slightly wider */

  /* ---- TRACKING — the one permitted letter-spacing value, in em so it tracks
     the fluid size instead of drifting at every clamp step. Lowercase body text
     never needs it. If a run is ever set in caps it MUST carry 0.05-0.12em:
     letterspacing is the REMEDY for caps, not a second offence. */
  --track: 0.01em;

  /* ---- INK — three text colours, and a recessive tone is applied to a WHOLE
     BLOCK, never to a clause inside a sentence. Colour is a first-order
     grouping cue, so a tone change mid-sentence reads as a font change and
     lands the lower contrast on the readers least able to absorb it.
     Both inks must clear 7:1 on the page surface. Low-contrast SURFACES and
     AAA TEXT live at different layers — never lighten type to calm a page. */
  --ink     : #3A2621;   /* cocoa: 13.2:1 on the cream page, 11.4:1 on pale rose           */
  --ink-soft: #5C443A;   /* 8.3:1 on cream, 7.2:1 on pale rose                              */
  --link    : #6E361C;   /* deep copper: 8.9:1 on cream, 7.6:1 on rose; links also underlined */
}

/* ============================================================================
   FONT LOADING — self-hosted WOFF2, metric-matched, no third-party request.
   A Google Fonts <link> is a render-blocking request to another origin, and it
   is how four weights end up in a build that authorised two.

   `font-display: swap` shows the fallback immediately and swaps the real face
   in when it lands — which reflows the page unless the fallback is metric-
   matched. The four descriptors below make the fallback occupy the same space
   as the real face, so the swap is invisible and costs no CLS.

   Compute the numbers, do not guess them. Every metric is first divided by its
   OWN font's unitsPerEm:
     size-adjust       = (webAvgWidth / webUPM) / (fallbackAvgWidth / fallbackUPM)
     ascent-override   = (webAscent   / webUPM) / size-adjust
     descent-override  = (|webDescent| / webUPM) / size-adjust
     line-gap-override = (webLineGap  / webUPM) / size-adjust
   The three overrides are divided by size-adjust because size-adjust scales all
   metrics including them, so it has to be cancelled back out.
   ========================================================================== */
@font-face {
  font-family: "Atkinson Hyperlegible";
  src: url("/fonts/body-400.woff2?v=d64ba838") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible";
  src: url("/fonts/body-700.woff2?v=140e2bd2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Montserrat";
  src: url("/fonts/display-400.woff2?v=e66bcd27") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
/* The metric-matched fallbacks, computed by tools/font_metrics.py and recorded
   in CLAUDE.md:
   Atkinson Hyperlegible 400 against Arial:   99.79% / 95.20% / 29.06% / 0%
   Montserrat 400 against Arial:              114.51% / 84.54% / 21.92% / 0% */
@font-face {
  font-family: "Body Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 99.79%; ascent-override: 95.2%; descent-override: 29.06%; line-gap-override: 0%;
}
@font-face {
  font-family: "Display Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 114.51%; ascent-override: 84.54%; descent-override: 21.92%; line-gap-override: 0%;
}

/* ============================================================================
   RESET — remove the browser's own treatments before adding ours.
   ========================================================================== */
html {
  -webkit-text-size-adjust: 100%;   /* never let iOS inflate a size we chose */
  text-size-adjust: 100%;
  /* NEVER set font-size on html. `font-size: 16px` and the `62.5%` trick both
     destroy the reader's own browser font-size preference — which is the one
     accessibility control older readers are most likely to have already used. */

  /* Without this the browser fakes a bold or an italic we never shipped —
     an eighth treatment nobody authored. */
  font-synthesis-weight: none;
  font-synthesis-style: none;

  /* Photos must never zoom on a phone (LESSONS-LEARNED #39). iPhone Safari
     zooms into whatever is double-tapped, and flicking through a page of big
     photos registers as double taps. `manipulation` stops that and KEEPS
     two-finger pinch zoom, which WCAG 1.4.4 requires — never use
     maximum-scale=1 or user-scalable=no instead. */
  touch-action: manipulation;
}
body { touch-action: manipulation; }

/* No press-and-hold "preview" popping a photo up enlarged on iPhone. */
img { -webkit-touch-callout: none; }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  color: var(--ink);
  /* Never set -webkit-font-smoothing: antialiased on body text. It thins the
     stems, which costs contrast on exactly the readers who need it most. */
}

h1, h2, h3, .statement { margin: 0; font-family: var(--font-display); font-weight: 400; color: var(--ink); }
p, ul, ol  { margin: 0; }
a          { color: inherit; }
button     { font: inherit; color: inherit; }
address    { font-style: normal; }   /* the browser's italic is an 8th treatment */
strong     { font-weight: 700; }

/* Long words, UK postcodes and unbroken URLs must never overflow at 375px.
   Hyphenation stays MANUAL: a hyphenated word costs a word-recognition step,
   which is exactly the cost older readers can least afford (§G). Requires
   <html lang="en-GB"> — that attribute also selects the screen-reader voice
   and the correct quote marks. */
body { overflow-wrap: break-word; hyphens: manual; }
a, code, samp { overflow-wrap: anywhere; }
.grid > *, .flex > *, li, td, dd, .card { min-width: 0; overflow-wrap: anywhere; }

/* WRAPPING — the cheapest typographic win available.
   `balance` evens out the last lines of a heading and kills the one-word widow.
   Chromium abandons balancing above 6 wrapped lines and Firefox above 10, so it
   belongs on headings only — never globally, where it is inert and costs work.
   `pretty` does the same job for body copy: Chromium adjusts the last four
   lines, WebKit 26+ evaluates the whole paragraph and improves the rag. */
h1, h2, h3, .statement, .lead, .section-label, figcaption, blockquote {
  text-wrap: balance;
}
p, li, dd, dt, td, th, summary { text-wrap: pretty; }

/* Digits that sit above or below other digits must line up. */
table, .hours, .hours td, time, .phone { font-variant-numeric: tabular-nums lining-nums; }

/* Colour alone is never the link cue. The thickness grows with the fluid size
   instead of freezing once --fs-body hits its clamp maximum. */
.prose a, .lead a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: max(1px, 0.06em);
  text-underline-offset: 0.15em;
}
.prose a:hover { text-decoration-thickness: max(2px, 0.12em); }

/* `widows` and `orphans` do nothing in normal web flow — they only apply in
   fragmentation contexts. Their one real home is the print stylesheet. */
@media print {
  .prose > p, li { orphans: 3; widows: 3; }
  h1, h2, h3 { break-after: avoid; }
}

/* ============================================================================
   THE SEVEN TREATMENTS. There is no eighth.
   Cap: 7 sitewide, 4 visible in any one viewport. Screenshot every page at
   375px and 1440px and count. More than four on a screen -> merge the closest.

   CHANGE ONE ATTRIBUTE PER HIERARCHY LEVEL. If a heading is already larger it
   does not also need a different weight, a different colour and letter-spacing.
   ========================================================================== */

/* 1 — Page title */
h1                { font-size: var(--fs-page);    line-height: var(--lh-h1); max-width: var(--col); }

/* 2 — Section heading */
h2                { font-size: var(--fs-section); line-height: var(--lh-h2); max-width: var(--col); }

/* 3 — Display voice: h3, pull quotes, single-sentence statements */
h3, .statement    { font-size: var(--fs-lead);    line-height: var(--lh-h3); }

/* 4 — Lead: the opening paragraph, body face, recessive ink, WHOLE block */
.lead             { font-size: var(--fs-lead);    line-height: var(--lh-lead); color: var(--ink-soft); max-width: var(--measure); }

/* 5 — Body */
.prose > p        { max-width: var(--measure); margin-bottom: 1.25rem; }
.prose > p:last-child { margin-bottom: 0; }

/* 6 — Meta: captions, dates, notes, form help */
.meta             { font-size: var(--fs-meta);    line-height: 1.6; color: var(--ink-soft); }

/* 7 — Operable: the CTA and the submit button. Weight IS the signal here. */
.cta              { font-size: var(--fs-lead); font-weight: 700; color: var(--link);
                    min-height: 48px;   /* tap target 44-56px whatever the type does */
                    display: inline-flex; align-items: center; }

/* + ONE functional variant, not counted as an eighth: treatment 6 at weight
   700. Bold on a form label is operability, not hierarchy.
   The same rule serves the optional section eyebrow, deliberately — giving the
   eyebrow its own colour or its own tracking would make it a genuine eighth
   treatment, and a form label and a section eyebrow are never adjacent, so one
   set of values covers both. Sentence case. At most two eyebrows per page, four
   words, one line. NEVER uppercase: uppercase plus letter-spacing is the single
   commonest cause of a two-family site presenting eighteen treatments, and it
   costs reading speed. */
label, .section-label, .label { font-size: var(--fs-meta); font-weight: 700; color: var(--ink); }
/* a table cell is body text, not a heading: the browser's bold <th> would be an
   eighth treatment (body face 700 at body size) */
th { font-weight: 400; text-align: left; }
.section-label        { display: block; margin-bottom: 0.75rem; }

/* ============================================================================
   NEVER ADD THESE. Each one is a treatment the reader will count.
   The audit fails the build on the first four.

     font-style: italic          two typeface designs, not one tilted; also
                                 measurably slower to read
     text-transform: uppercase   costs reading speed; never on nav, buttons,
                                 form labels or CTAs
     font-weight: 300 / 500 / 600 / 800     two weights, 400 and 700
     font-size: <any literal>    every size goes through a token
     a second letter-spacing value
     a colour change inside a sentence (use a whole block)
     style="font-weight:700" in the HTML
     text-align: justify         and never indent AND space paragraphs

   REACH FOR WHITESPACE FIRST. Proximity separates content at zero cost to the
   perceived treatment count, because it changes nothing about the letterforms.
   Most requests for a new size token are requests for more margin.
   ========================================================================== */
