/* ==========================================================================
   English with Stefan — site.css
   Built from Final Implementation Brief 1.1.
   One stylesheet. Design tokens are the first block below (Brief §8.1, J02).
   No inline style attributes are used anywhere in the markup: the CSP sets
   style-src 'self' with no 'unsafe-inline' (Brief §11, acceptance A08).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. DESIGN TOKENS  (Brief §8.1, §8.5, §8.6)
   -------------------------------------------------------------------------- */
:root {
  /* Colour */
  --navy:        #17243B;
  --blue:        #315A7A;
  --coral:       #D85F3F;
  --coral-deep:  #C15538;
  --taupe:       #AAA69A;
  --cloud:       #F4F6F5;
  --sand:        #EEE9E1;
  --white:       #FFFFFF;
  --ink:         #293646;

  /* Type families */
  --font-head: "Source Serif 4", Georgia, "Times New Roman", serif;
  --font-body: "Source Sans 3", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;

  /* Chinese, from whatever the device already has. Source Serif 4 and Source
     Sans 3 contain no Chinese glyphs at all, so without this the Chinese page
     falls back to a different browser default on every platform. A CJK webfont
     is several megabytes -- it would cost more than the rest of the site put
     together, which is why the stack is system fonts only.
     PingFang SC: iOS and modern macOS. Hiragino Sans GB: older macOS.
     Microsoft YaHei: Windows. Noto / Source Han Sans SC: Android and Linux. */
  --font-zh: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
             "Noto Sans CJK SC", "Source Han Sans SC", sans-serif;

  /* Fluid type scale */
  --fs-h1:      clamp(2rem, 1.35rem + 3vw, 3.25rem);
  --fs-h2:      clamp(1.5rem, 1.2rem + 1.6vw, 2.125rem);
  --fs-h3:      clamp(1.125rem, 1.05rem + 0.5vw, 1.375rem);
  --fs-body:    1rem;
  --fs-small:   0.875rem;
  --fs-eyebrow: 0.8125rem;

  /* Spacing scale */
  --s1:  4px;  --s2:  8px;  --s3: 12px;  --s4: 16px;  --s5: 24px;
  --s6: 32px;  --s7: 48px;  --s8: 64px;  --s9: 96px;  --s10: 128px;

  /* Layout */
  --measure:   62ch;
  --container: 1120px;
  --gutter:    20px;
  --header-h:  72px;

  /* Radii */
  --r-btn:   6px;
  --r-panel: 10px;
}

@media (min-width: 720px) {
  :root {
    --fs-body: 1.0625rem;
    --gutter:  24px;
  }
}

/* --------------------------------------------------------------------------
   2. SELF-HOSTED FONTS  (Brief §10 A9–A11, acceptance G06, G07, G08)
   Source Serif 4 and Source Sans 3, SIL Open Font Licence — see OFL.txt in
   this folder. Never loaded from Google: fonts.googleapis.com and
   fonts.gstatic.com are unreliable or blocked from mainland China, and a
   render-blocking request to an unreachable host is a blank page for the
   exact audience this site exists for.

   Four files, which is the cap. Three carry the `latin` subset; the fourth
   carries `latin-ext` for the body weight only.

   On subsets: the brief requires latin-ext because "Gnjatić contains ć". The
   approved copy spells it Gnjatic, without the diacritic, and every non-ASCII
   character the page actually uses — © · — ' " " — sits inside the latin
   subset. The ext file is therefore insurance, not a requirement: the
   unicode-range below means a browser downloads it only if such a character
   ever appears. Today that costs zero bytes. Acceptance item G10 fails the
   build if copy is ever added that these files cannot render.
   -------------------------------------------------------------------------- */

/* Google's standard `latin` subset range. */
@font-face {
  font-family: "Source Serif 4";
  src: url("/assets/fonts/source-serif-4-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("/assets/fonts/source-sans-3-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("/assets/fonts/source-sans-3-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext, body weight only. Downloaded solely if a character in this range
   appears — e.g. if "Gnjatic" is ever written "Gnjatić". */
@font-face {
  font-family: "Source Sans 3";
  src: url("/assets/fonts/source-sans-3-ext-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                 U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* The Chinese page redefines the two family variables and nothing else. Every
   rule in this stylesheet reads var(--font-head) or var(--font-body), so the
   whole page switches from here -- and the English page, which never matches
   this selector, cannot be affected by it.
   The serif/sans distinction is dropped on purpose: Chinese headings in a
   serif face at small sizes are harder to read, not more elegant. */
html[lang^="zh"] {
  --font-head: var(--font-zh);
  --font-body: var(--font-zh);
}

/* --------------------------------------------------------------------------
   3. RESET AND BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-x: hidden;
}

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

h1, h2, h3 {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--navy);
  margin: 0 0 var(--s4);
}
h1 { font-size: var(--fs-h1); line-height: 1.12; }
h2 { font-size: var(--fs-h2); line-height: 1.18; }
h3 { font-size: var(--fs-h3); line-height: 1.3;  }

p { margin: 0 0 var(--s4); max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

a { color: var(--blue); text-decoration: underline; text-underline-offset: 2px; }
a:hover { color: var(--coral-deep); }

ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }

hr { border: 0; margin: 0; }

/* --------------------------------------------------------------------------
   4. FOCUS INDICATION  (Brief §8.9, acceptance E03, E04, C11)
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}
.btn--primary:focus-visible { outline-color: var(--white); }
.contact :focus-visible,
.site-footer :focus-visible { outline-color: var(--coral); }

/* Focus moved programmatically after an in-page CTA (Brief §4).
   Deliberately visible — a reader who has been relocated must see where
   they landed. Applied by class, never by :focus. */
.is-focus-target {
  outline: 2px solid var(--coral);
  outline-offset: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--navy);
  color: var(--white);
  padding: var(--s3) var(--s4);
  text-decoration: none;
  border-radius: 0 0 var(--r-btn) 0;
}
.skip-link:focus {
  left: 0;
  color: var(--white);
}

/* --------------------------------------------------------------------------
   5. LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(56px, 8vw, 112px); }
.section__title { margin-bottom: var(--s5); }
.subsection__title { margin-top: var(--s8); }
.section__cta { margin-top: var(--s7); }

/* Section backgrounds (Brief §8.3) */
.section--hero         { background: var(--sand);  }
.section--trust        { background: var(--white); }
.section--lessons      { background: var(--cloud); }
.section--about        { background: var(--white); }
.section--testimonials { background: var(--sand);  }
.section--quals        { background: var(--white); }
.section--trial        { background: var(--white); }

/* Every element carrying an anchor id (Brief §3) */
#trust, #lessons, #about, #approach, #qualifications, #free-trial, #privacy {
  scroll-margin-top: calc(var(--header-h) + 16px);
}

/* Thin coral rules — the signature treatment. At most four on the page. */
.rule {
  height: 1px;
  background: var(--coral);
  margin-block: var(--s6);
}
.rule--short { width: 48px; margin-block: var(--s6) var(--s4); }

.eyebrow {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--blue);
  font-weight: 600;
}
.lead  { font-size: 1.0625em; }
.note  { font-size: var(--fs-small); color: var(--ink); }
.aside { font-size: var(--fs-small); }

/* --------------------------------------------------------------------------
   6. BUTTONS  (Brief §9)
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  min-width: 44px;
  padding: 14px 24px;
  border: 0;
  border-radius: var(--r-btn);
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 120ms ease-out, border-color 120ms ease-out;
}
.btn--primary { background: var(--coral-deep); color: var(--white); }
.btn--primary:hover { background: #AB4B31; color: var(--white); }

.btn--secondary {
  background: transparent;
  border: 1.5px solid var(--blue);
  color: var(--blue);
}
.btn--secondary:hover { border-color: var(--coral-deep); color: var(--coral-deep); }

.btn--compact { min-height: 44px; padding: 10px 18px; }

/* --------------------------------------------------------------------------
   7. HEADER AND NAVIGATION  (Brief §3)
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--sand);
  transition: padding 160ms ease-out, background-color 160ms ease-out;
}
.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding-block: 20px;
  transition: padding 160ms ease-out;
}
.site-header.is-compact {
  background: var(--white);
  border-bottom: 1px solid var(--taupe);
}
.site-header.is-compact .site-header__inner { padding-block: 10px; }

/* Language switch. A quiet text link, not a second button: the orange CTA
   beside it is the only thing on this bar that should look like an action.
   It is set in its own language via lang="" on the element, so the Chinese
   label renders in the CJK stack even on the English page. */
.lang-switch {
  flex-shrink: 0;
  /* inline-flex with a min size, not a bare inline link: a 30x26 text link
     fails the 44x44 touch target rule, which the browser checks caught. The
     underline is text-decoration rather than a border, so it stays next to the
     text instead of sitting at the bottom of a 44px box. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 var(--s2);
  font-size: 0.9375rem;
  color: var(--navy);
  text-decoration: underline;
  text-decoration-color: var(--stone, #AAA69A);
  text-underline-offset: 3px;
}
.lang-switch:hover { color: var(--coral); text-decoration-color: var(--coral); }
/* The footer link is inside a grid cell, so it would stretch the full width
   and present an 875px-wide target. Keep it the size of its own text. */
.site-footer .lang-switch { color: inherit; justify-self: start; width: fit-content; }
.site-header.is-compact .wordmark { font-size: 1.0125rem; }

.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--navy);
  text-decoration: none;
  line-height: 1.2;
  margin-right: auto;
  transition: font-size 160ms ease-out;
}
.wordmark:hover { color: var(--navy); }

.site-nav { display: none; }
.site-nav__list { display: flex; gap: var(--s5); }
.site-nav__list a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Both dimensions, not just height. "About" is only 36px of text, so a
     height-only rule left it under the 44px target. */
  min-height: 44px;
  min-width: 44px;
  color: var(--navy);
  text-decoration: none;
  font-size: var(--fs-small);
  font-weight: 600;
}
.site-nav__list a:hover { color: var(--coral-deep); text-decoration: underline; }

/* Desktop navigation only (Brief §3). Below 720px the header is the wordmark
   plus the Free-trial button — no hamburger, no drawer, no focus trap. */
@media (min-width: 1080px) {
  .site-nav { display: block; }
}

/* --------------------------------------------------------------------------
   8. HERO  (Brief §2, §9)
   DOM order is the approved mobile order. The desktop two-column layout is
   a CSS Grid rearrangement of non-focusable content only: the sole focusable
   element here is the CTA, so focus order never diverges from visual order.
   -------------------------------------------------------------------------- */
.hero { display: grid; gap: var(--s5); }
.hero__eyebrow  { grid-area: eyebrow;  margin-bottom: 0; }
.hero__headline { grid-area: headline; margin-bottom: 0; }
.hero__portrait { grid-area: portrait; }
.hero__cta      { grid-area: cta;      margin-bottom: 0; max-width: none; }
.hero__support  { grid-area: support;  margin-bottom: 0; }
.hero__note     { grid-area: note;     margin-bottom: 0; }

.hero {
  grid-template-areas:
    "eyebrow"
    "headline"
    "portrait"
    "cta"
    "support"
    "note";
}

/* The portrait is a cutout composited onto Pale sand, so it sits directly on
   the section with no panel, no padding and no rounded corners. If the hero
   section background ever changes, the image must be regenerated - the colour
   is baked into the JPEG. See tools/prepare-images.ps1. */
.hero__portrait picture { display: block; }
.hero__portrait img {
  width: 100%;
  min-width: 260px;
  /* Capped on mobile so the CTA below it stays above the fold on a 375x812
     screen (acceptance F10). Cropping from the top keeps the head large;
     the trimmed edge is beige against beige, so the cut is invisible. */
  max-height: 42vh;
  object-fit: cover;
  object-position: center top;
}

@media (min-width: 720px) {
  .hero__portrait img { max-height: 52vh; }
}

@media (min-width: 1080px) {
  .hero {
    /* Wider column than the old panelled version. With the 24px panel padding
       gone as well, this renders the portrait about 20% larger: measured 482px
       against 402px before, at a 1440px viewport. */
    grid-template-columns: 1fr minmax(340px, 45%);
    grid-template-areas:
      "eyebrow  portrait"
      "headline portrait"
      "support  portrait"
      "cta      portrait"
      "note     portrait";
    column-gap: var(--s8);
    align-items: start;
  }
  .hero__portrait { align-self: start; }
  .hero__portrait img { max-height: none; object-fit: fill; }
}

/* --------------------------------------------------------------------------
   9. TRUST STRIP, PROBLEM, OUTCOMES
   -------------------------------------------------------------------------- */
.trust { display: grid; gap: var(--s6); }
.trust dt {
  font-weight: 600;
  color: var(--navy);
  margin-bottom: var(--s2);
}
.trust dd { max-width: var(--measure); }

@media (min-width: 720px) {
  .trust { grid-template-columns: repeat(2, 1fr); gap: var(--s6) var(--s7); }
}
@media (min-width: 1080px) {
  .trust { grid-template-columns: repeat(4, 1fr); }
}

.problem { margin-top: var(--s9); }

.outcomes {
  display: grid;
  gap: var(--s4);
  margin-top: var(--s7);
}
.outcomes li {
  position: relative;
  padding-left: var(--s5);
  font-weight: 600;
  color: var(--navy);
}
.outcomes li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 6px;
  height: 6px;
  background: var(--coral);
}
@media (min-width: 720px) {
  .outcomes { grid-template-columns: repeat(3, 1fr); gap: var(--s6); }
}

/* --------------------------------------------------------------------------
   10. LESSON GOALS, FIT NOTE, STEPS
   -------------------------------------------------------------------------- */
.goal { margin-top: var(--s7); }
.goal h3 { margin-bottom: var(--s3); }

.fit {
  margin-top: var(--s8);
  padding: 20px;
  background: var(--sand);
  border-radius: var(--r-btn);
  font-size: 0.9375rem;
}
.fit__lead { margin-bottom: var(--s2); }
.fit__lead strong { color: var(--navy); }

.steps { display: grid; gap: var(--s6); margin-top: var(--s5); counter-reset: step; }
.steps__item { counter-increment: step; }
.steps__title { margin-bottom: var(--s2); }
.steps__title::before {
  content: counter(step) " · ";
  font-family: var(--font-head);
  color: var(--coral-deep);
  font-weight: 600;
}
.steps__title strong { color: var(--navy); }

@media (min-width: 720px) {
  .steps { grid-template-columns: repeat(2, 1fr); gap: var(--s7); }
}

/* --------------------------------------------------------------------------
   11. ABOUT AND APPROACH
   -------------------------------------------------------------------------- */
.about { display: grid; gap: var(--s7); }
.about__text     { grid-area: text; }
.about__portrait { grid-area: portrait; }
.about__approach { grid-area: approach; }

.about {
  grid-template-areas:
    "text"
    "portrait"
    "approach";
}
.about__portrait img { width: 100%; border-radius: var(--r-panel); }
.about__approach h3 { margin-top: var(--s7); }
.about__approach h3:first-of-type { margin-top: 0; }

@media (min-width: 1080px) {
  .about {
    grid-template-columns: 1fr minmax(260px, 34%);
    grid-template-areas:
      "text     portrait"
      "approach portrait";
    column-gap: var(--s8);
    align-items: start;
  }
  .about__portrait { align-self: start; }
}

/* --------------------------------------------------------------------------
   12. TESTIMONIALS
   -------------------------------------------------------------------------- */
.quote { margin: 0; }
.quote p { font-size: 1rem; }
.quote cite {
  display: block;
  margin-top: var(--s3);
  font-style: normal;
  font-size: var(--fs-small);
  color: var(--blue);
}

.quote--featured {
  background: var(--white);
  border-radius: var(--r-panel);
  padding: var(--s6);
}
.quote--featured p { font-size: 1.125rem; }

.quotes { display: grid; gap: var(--s6); margin-top: var(--s7); }
.quotes .quote {
  border-left: 1px solid var(--taupe);
  padding-left: 20px;
}
@media (min-width: 1080px) {
  .quotes { grid-template-columns: repeat(3, 1fr); gap: var(--s7); }
}

/* --------------------------------------------------------------------------
   13. QUALIFICATIONS
   -------------------------------------------------------------------------- */
.quals { display: grid; gap: var(--s7); }
.qual__title {
  font-family: var(--font-head);
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--navy);
  margin-bottom: var(--s1);
}
.qual__detail  { margin-bottom: var(--s1); }
.qual__program { font-size: var(--fs-small); color: var(--blue); margin-bottom: 0; }

@media (min-width: 720px) {
  .quals { grid-template-columns: repeat(2, 1fr); }
}

/* --------------------------------------------------------------------------
   14. WECHAT CONTACT BLOCK  (Brief §6)
   Mobile renders in DOM order: title, fit, ID, copy, live region, hint,
   QR block, email, first message.
   Desktop moves the QR block into the visually primary column. The only
   focusable elements — the Copy button and the email link — stay in DOM
   order in the second column, so focus order and visual order do not
   diverge (WCAG 2.4.3). No flex `order` is used on focusable children.
   -------------------------------------------------------------------------- */
.contact {
  margin-top: var(--s8);
  background: var(--navy);
  color: var(--white);
  border-radius: var(--r-panel);
  padding: var(--s6);
  display: grid;
  gap: var(--s5);
}
.contact__title  { grid-area: title;  color: var(--white); margin-bottom: 0; }
.contact__fit    { grid-area: fit;    margin-bottom: 0; font-size: var(--fs-small); }
.contact__id     { grid-area: id;     }
.contact__copyslot { grid-area: copy; }
.contact__live   { grid-area: live;   margin-bottom: 0; min-height: 1.5em; font-size: var(--fs-small); }
.contact__hint   { grid-area: hint;   margin-bottom: 0; font-size: var(--fs-small); }
.contact__qrblock { grid-area: qr;    }
.contact__email  { grid-area: email;  }
.contact__first  { grid-area: first;  }

.contact {
  grid-template-areas:
    "title"
    "fit"
    "id"
    "copy"
    "live"
    "hint"
    "qr"
    "email"
    "first";
}

.contact__idlabel {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--taupe);
  margin-bottom: var(--s1);
}
.contact__idvalue {
  font-family: var(--font-head);
  font-size: clamp(1.5rem, 1.2rem + 1.6vw, 2rem);
  color: var(--white);
  margin-bottom: 0;
  user-select: all;
  word-break: break-all;
}
.contact__live { color: var(--taupe); }
.contact__live:not(:empty) { color: var(--white); }

/* The QR is a real <img>, lossless PNG, on its own white panel so the quiet
   zone survives against the navy ground. Fixed size, never fluid. */
.contact__qr {
  background: var(--white);
  border-radius: var(--r-btn);
  padding: 12px;
  width: max-content;
  max-width: 100%;
}
.contact__qr img { width: 240px; height: 240px; }

.contact__longpress,
.contact__scan { font-size: var(--fs-small); color: var(--taupe); margin-top: var(--s3); }
.contact__scan { margin-bottom: 0; }

.contact__emaillabel {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--taupe);
  margin-bottom: var(--s1);
}
.contact__emailvalue { margin-bottom: 0; }
.contact__emailvalue a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--white);
}
.contact__emailvalue a:hover { color: var(--coral); }

.contact__firstlead { font-size: var(--fs-small); color: var(--taupe); margin-bottom: var(--s2); }
.contact__firstbody {
  border-left: 1px solid var(--taupe);
  padding-left: var(--s4);
  font-size: 0.9375rem;
  margin-bottom: 0;
  user-select: all;
}

.contact .btn--secondary { border-color: var(--white); color: var(--white); }
.contact .btn--secondary:hover { border-color: var(--coral); color: var(--coral); }

@media (min-width: 720px) {
  .contact {
    grid-template-columns: minmax(264px, 45%) 1fr;
    grid-template-areas:
      "qr title"
      "qr fit"
      "qr id"
      "qr copy"
      "qr live"
      "qr hint"
      "qr email"
      "qr first";
    column-gap: var(--s7);
    padding: var(--s7);
    align-items: start;
  }
  .contact__qrblock { align-self: start; }
  .contact__qr img { width: 280px; height: 280px; }
  /* Long-press extraction is a touch behaviour — the instruction is noise on
     a desktop (Brief §6, acceptance D03). */
  .contact__longpress { display: none; }
}

/* --------------------------------------------------------------------------
   15. PRIVACY AND FOOTER
   -------------------------------------------------------------------------- */
.privacy { margin-top: var(--s8); }
.privacy p { font-size: var(--fs-small); }
.privacy__title { font-size: var(--fs-h3); }
.privacy__meta { color: var(--blue); }

.site-footer {
  background: var(--white);
  border-top: 1px solid var(--taupe);
  padding-block: var(--s7);
}
.site-footer__inner { display: grid; gap: var(--s5); }
.site-footer__brand {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--navy);
  margin-bottom: var(--s1);
}
.site-footer__tagline { font-size: var(--fs-small); margin-bottom: 0; }
.site-footer__links { display: grid; gap: var(--s2); font-size: var(--fs-small); }
.site-footer__links a {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-height: 44px;
  min-width: 44px;
}
.site-footer__copyright { color: var(--blue); display: flex; align-items: center; min-height: 44px; }

@media (min-width: 720px) {
  .site-footer__inner {
    grid-template-columns: 1fr auto;
    align-items: end;
  }
  .site-footer__links { justify-items: end; }
}

/* --------------------------------------------------------------------------
   16. MOTION  (Brief §8.8)
   HARD RULE: the base stylesheet never sets opacity:0 on content. The start
   state lives behind the .js-anim class, which JavaScript adds only when
   prefers-reduced-motion is not "reduce". A visitor without JavaScript, or
   with IntersectionObserver unsupported, sees everything immediately.
   -------------------------------------------------------------------------- */
.js-anim .reveal {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 240ms ease-out, transform 240ms ease-out;
}
.js-anim .reveal.is-visible {
  opacity: 1;
  transform: none;
}

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