/* ==========================================================================
   Three Hearts Connect — design tokens
   ==========================================================================

   Custom properties only. No component rules live in this file, so it can be
   read as the single answer to "what colour/size is that?".

   Every colour below is copied verbatim from the grounding document section 9
   "Brand reference — confirm, don't change". Nothing here is invented,
   approximated or nudged to make a contrast number pass. Where a brand colour
   cannot be used for a given job, the token is annotated with the measured
   ratio and the reason, rather than the colour being altered.

   Contrast was computed, not eyeballed. Ratios in the comments are real WCAG
   2.2 figures for the pair named. The floor is AA: 4.5:1 for normal text,
   3:1 for large text and for non-text boundaries.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Fonts
   --------------------------------------------------------------------------

   SELF-HOSTED ONLY. No Google Fonts link, no CDN, not now and not later.
   D-006 keeps third-party origins out of an application that families use to
   read about their relative, and infrastructure section 4.3 wants a strict
   Content-Security-Policy — which stays achievable only while every asset
   origin is our own.

   ┌────────────────────────────────────────────────────────────────────────┐
   │ FONT FILES STILL TO BE SUPPLIED                                        │
   │ Drop these into  /home/wa3hs/threehearts/static/fonts/                 │
   │ (served by Caddy from /srv/threehearts/static/fonts/ — see             │
   │ deploy/Caddyfile.dev). Nothing renders in the brand faces until they   │
   │ are present; until then the fallback stack below is what shows.        │
   │                                                                        │
   │   REQUIRED                                                             │
   │     Nunito[wght].woff2                 variable, weight 400–900        │
   │     PlayfairDisplay[wght].woff2        variable, weight 400–900        │
   │     PlayfairDisplay-Italic[wght].woff2 variable, weight 400–900        │
   │                                                                        │
   │   OPTIONAL                                                             │
   │     Nunito-Italic[wght].woff2          variable, weight 400–900        │
   │       Only needed if <em> in body copy should use a true italic. If it │
   │       is absent the browser slants the upright face, which is poor but │
   │       not broken. Skipping it saves a request on bad signal.           │
   │                                                                        │
   │   FORMAT                                                               │
   │     woff2 only. Every browser this application supports has had woff2  │
   │     since 2018, so a woff or ttf fallback would be dead weight on a    │
   │     mobile connection — and poor rural signal is an explicit design    │
   │     constraint (grounding section 8), not an edge case.                │
   │                                                                        │
   │   WHY VARIABLE RATHER THAN STATIC WEIGHTS                              │
   │     The brand uses Nunito across 400–900. As static files that is four │
   │     or more downloads; as one variable file it is a single request of  │
   │     roughly the same size as two statics. Fewer round trips is the     │
   │     right trade on the signal this is used on.                         │
   │                                                                        │
   │   BEFORE COPYING THEM IN                                               │
   │     Subset to latin + latin-ext. Both families ship with Cyrillic and  │
   │     Vietnamese ranges that this application will never render, and     │
   │     they are most of the file size.                                    │
   │     Both faces are SIL Open Font License 1.1 — redistribution inside   │
   │     the application is fine; keep the OFL.txt alongside them.          │
   └────────────────────────────────────────────────────────────────────────┘

   The src paths below are RELATIVE (../fonts/…), which resolves to exactly
   /static/fonts/… from this file's location at /static/css/tokens.css.
   Relative is deliberate: Django's ManifestStaticFilesStorage rewrites
   relative url() references when it hashes filenames for cache-busting, and
   leaves absolute /static/ paths alone — so an absolute path here would
   quietly break the moment collectstatic starts hashing.
   -------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Brand fonts — VENDORED, never fetched from a CDN.

   D-006 and infrastructure §3 forbid an external origin serving assets to an
   authenticated personal-data application: the origin would see the URLs, IP
   addresses and timing of family members reading about their relative, which
   makes it a data processor requiring an assessment and an agreement. For a
   font file. It is also what makes a strict Content-Security-Policy reachable,
   because there are then no external origins to allow.

   These files are byte-identical to the ones the marketing site serves, taken
   from it on 2026-08-22, so the app and the site render the same. They are
   Google Fonts subsets split by unicode-range: a UK reader downloads only the
   latin subsets (~78K), never the cyrillic or vietnamese ones.

   Licence: SIL Open Font License 1.1 (both families). Vendoring is permitted.
   --------------------------------------------------------------------------- */

/* cyrillic-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-ext-c1ac3b.woff2") format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-373a90.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/nunito-vietnamese-941515.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/nunito-latin-ext-012b61.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/nunito-latin-798ec6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-ext-c1ac3b.woff2") format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-373a90.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/nunito-vietnamese-941515.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/nunito-latin-ext-012b61.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/nunito-latin-798ec6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-ext-c1ac3b.woff2") format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-373a90.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/nunito-vietnamese-941515.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/nunito-latin-ext-012b61.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/nunito-latin-798ec6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-ext-c1ac3b.woff2") format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-373a90.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/nunito-vietnamese-941515.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/nunito-latin-ext-012b61.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/nunito-latin-798ec6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-ext-c1ac3b.woff2") format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-373a90.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/nunito-vietnamese-941515.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/nunito-latin-ext-012b61.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/nunito-latin-798ec6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-ext-c1ac3b.woff2") format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("../fonts/nunito-cyrillic-373a90.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("../fonts/nunito-vietnamese-941515.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("../fonts/nunito-latin-ext-012b61.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("../fonts/nunito-latin-798ec6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-cyrillic-51fce2.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-vietnamese-b455bc.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-ext-cf184c.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-9385b6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-cyrillic-51fce2.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-vietnamese-b455bc.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-ext-cf184c.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-9385b6.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-cyrillic-64b566.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-vietnamese-2ac5e2.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-ext-413626.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-48d1e9.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-cyrillic-64b566.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-vietnamese-2ac5e2.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-ext-413626.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-48d1e9.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/playfair-display-cyrillic-64b566.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/playfair-display-vietnamese-2ac5e2.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-ext-413626.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-48d1e9.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/playfair-display-cyrillic-64b566.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/playfair-display-vietnamese-2ac5e2.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-ext-413626.woff2") format('woff2');
  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;
}
/* latin */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../fonts/playfair-display-latin-48d1e9.woff2") format('woff2');
  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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {

  /* ------------------------------------------------------------------------
     2. Brand palette — raw values, grounding section 9
     Use the semantic tokens in section 3 instead of these. These exist so
     there is exactly one place where a brand hex is written down.
     ------------------------------------------------------------------------ */

  --navy:            #1C2E4A;   /* primary, headings, dark bands */
  --navy-dark:       #16243B;   /* footer */
  --sage:            #7E8C4F;   /* secondary, icons, accents */
  --sage-light:      #A4B06B;   /* on navy only: eyebrows, accents */
  --cream:           #F5F2E9;   /* page background */
  --cream-light:     #F8F6EF;   /* cards, panels */
  --sage-tint:       #EDEFE2;   /* alternating bands, pills */
  --ink:             #3A3E33;   /* body text */
  --ink-muted:       #5A5E4F;   /* body text muted */
  --cream-on-navy:   #F7F5EC;   /* cream text on navy */
  --ink-on-navy:     #D7DAE0;   /* body text on navy */
  --border:          #EAE7D8;   /* card border */


  /* ------------------------------------------------------------------------
     3. Semantic colour — what each colour is FOR
     ------------------------------------------------------------------------
     Ratios below were computed with a WCAG 2.2 relative-luminance script, not
     estimated. Three pairs failed and are recorded here as prohibitions so
     the next person does not rediscover them the hard way.
     ------------------------------------------------------------------------ */

  /* Surfaces */
  --surface-page:      var(--cream);        /* the page ground */
  --surface-raised:    var(--cream-light);  /* cards and panels */
  --surface-tint:      var(--sage-tint);    /* alternating bands, pills */
  --surface-inverse:   var(--navy);         /* dark bands */
  --surface-footer:    var(--navy-dark);

  /* Text on light surfaces */
  --text-strong:       var(--navy);       /* 12.19:1 on page, 12.62:1 on raised */
  --text-body:         var(--ink);        /*  9.79:1 on page, 10.13:1 on raised */
  --text-muted:        var(--ink-muted);  /*  5.96:1 on page,  6.17:1 on raised */

  /* Text on navy surfaces */
  --text-on-inverse:        var(--cream-on-navy);  /* 12.49:1 on navy */
  --text-on-inverse-soft:   var(--ink-on-navy);    /*  9.74:1 on navy */
  --text-on-inverse-accent: var(--sage-light);     /*  5.85:1 on navy — eyebrows */

  /* ------------------------------------------------------------------------
     PROHIBITED — measured, failed, do not use. Kept visible on purpose.

       --sage as normal text on any light surface
           3.26:1 on page, 3.38:1 on raised, 3.14:1 on tint. All below the
           4.5:1 normal-text floor. Sage is legal ONLY as (a) large text at
           1.5rem/24px or above, where 3:1 applies, and (b) non-text marks
           such as icons and control boundaries, where 3:1 also applies.
           --text-display-accent below carries the large-text case.

       --sage-light as text on any light surface
           2.08:1 on cream. Fails even the large-text bar. Sage-light is an
           on-navy colour and the grounding table already scopes it that way.

       --cream-on-navy (or any cream) as a label on a --sage ground
           3.34:1. A sage primary button with a pale label fails AA. The
           primary button is therefore navy with a cream label at 12.49:1 —
           see --action-primary-* below. Sage stays a secondary accent.
     ------------------------------------------------------------------------ */

  /* Sage, used only where the measurement allows it */
  --accent:            var(--sage);   /* non-text marks and icons: 3.26:1 — SC 1.4.11 pass */
  --text-display-accent: var(--sage); /* LARGE text only, >= 1.5rem: 3.26:1 — AA large */

  /* Boundaries.

     --border (#EAE7D8) is 1.11:1 on cream, 1.15:1 on the raised surface and
     1.07:1 on the tint. None of those is a boundary anybody can see.

     The comment that stood here said that was fine on a card, "because a card
     is already identifiable by its own background". IT IS NOT. --cream-light
     on --cream is 1.04:1 and --sage-tint on --cream is 1.04:1 — recomputed
     with the same WCAG 2.2 relative-luminance script as everything else in
     this file. NO TWO OF THIS BRAND'S LIGHT SURFACES DIFFER PERCEIVABLY —
     cream, cream-light, sage-tint and this border all sit within 1.15:1 of
     each other — so a card is identified by neither its fill nor this border,
     and among the light surfaces "delineate by surface" is not a technique
     that exists.

     THE ONE SURFACE PAIR A READER REALLY CAN TELL APART is a light one
     against --surface-inverse: navy on cream is 12.19:1, base.css already
     carries `.surface-inverse` and `.band-tint` for exactly that, and the
     Brand Toolkit's "Using colour well" does say to alternate navy and cream
     when stacking panels. So the technique exists; it is simply not what
     separates one section of a screen from the next. Two reasons, both
     recorded rather than assumed: seven navy bands down a person's page is a
     brochure and this application is meant to read as a notebook, and every
     text, link, eyebrow and focus colour inside a band has to be flipped by
     hand — see base.css "SURFACES DESCRIBE THEMSELVES", which exists because
     that flip was once missed and painted cream on cream at 1.01:1.

     What --border-soft actually does is give a rounded box an edge to stop
     on. Keep it for that. It is trim, and it never was separation. Anything
     that has to be SEEN takes --accent (3.26:1, and drawn at --space-3xs or
     wider — see office.css §3a and base.css's hr), --border-control or
     --border-strong. WCAG 1.4.11 still applies hardest to a form control,
     where the outline is the only thing saying "you can type here", which is
     why controls use --border-control. */
  --border-soft:       var(--border);      /* TRIM ONLY — 1.11:1 separates nothing */
  --border-control:    var(--ink-muted);   /* 5.96:1 on page — form controls   */
  --border-strong:     var(--navy);        /* 12.19:1 — emphasis               */

  /* Actions */
  --action-primary-bg:      var(--navy);
  --action-primary-text:    var(--cream-on-navy);   /* 12.49:1 */
  --action-secondary-bg:    transparent;
  --action-secondary-text:  var(--navy);            /* 12.19:1 on page */
  --action-secondary-border: var(--navy);

  /* Links. Navy rather than sage: sage fails as normal text (3.26:1).
     Never colour alone — links carry an underline as well, per grounding
     section 8 "Never colour alone to convey state". */
  --link:              var(--navy);        /* 12.19:1 */
  --link-on-inverse:   var(--cream-on-navy);

  /* Focus. Navy clears 3:1 against every surface it can land on:
     page 12.19, raised 12.62, tint 11.73, sage 3.74. On navy grounds the
     ring flips to sage-light at 5.85:1. */
  --focus-ring:            var(--navy);
  --focus-ring-on-inverse: var(--sage-light);
  --focus-ring-width:      3px;   /* px on purpose: a hairline ring that scales
                                     with text can vanish; this is a constant */
  --focus-ring-offset:     2px;


  /* ------------------------------------------------------------------------
     4. Type
     ------------------------------------------------------------------------
     Two families only (grounding section 9). Playfair Display is a display
     face — section 9 is explicit that in the application it belongs on
     headings and the occasional warm line, never on interface furniture, so
     the UI stack below is Nunito and the display stack is used sparingly.

     Fallback stacks are ordered so a missing font file degrades to something
     of the same shape rather than to Times: a humanist sans for Nunito, a
     transitional serif for Playfair.
     ------------------------------------------------------------------------ */

  --font-ui: "Nunito", system-ui, -apple-system, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --font-display: "Playfair Display", Georgia, "Times New Roman",
                  "Nimbus Roman", serif;

  /* Weights. Nunito 400–900, Playfair 700/800 upright and 500 italic. */
  --weight-regular:   400;
  --weight-medium:    500;   /* Playfair italic accent line */
  --weight-semibold:  600;
  --weight-bold:      700;
  --weight-heavy:     800;
  --weight-black:     900;   /* eyebrows and pills only */

  /* ------------------------------------------------------------------------
     Type scale. Every step is rem so the whole interface scales with the
     reader's browser setting and stays usable at 200% (grounding section 8).
     There is deliberately NO step below 1.125rem / 18px. The 18px minimum is
     a hard rule in CLAUDE.md, and a token for 15px small print is how that
     rule gets broken six months from now — so the scale simply does not
     offer one. Metadata, captions and pill labels all sit at --size-body.
     ------------------------------------------------------------------------ */

  --size-body:  1.125rem;   /* 18px — the floor, nothing goes under it */
  --size-md:    1.25rem;    /* 20px — lead paragraphs */
  --size-lg:    1.5rem;     /* 24px — h4/h3; also the large-text contrast bar */
  --size-xl:    1.875rem;   /* 30px — h2 */
  --size-2xl:   2.25rem;    /* 36px — h1 */
  --size-3xl:   2.75rem;    /* 44px — page title on wide screens */

  /* Line height: generous, because the audience is 50–70 and 75+ */
  --leading-tight:  1.2;    /* display headings */
  --leading-snug:   1.35;   /* sub-headings */
  --leading-body:   1.6;    /* body copy */

  --tracking-eyebrow: 0.08em;   /* eyebrows are spaced, not shrunk */


  /* ------------------------------------------------------------------------
     5. Spacing — rem throughout, so gaps grow with text scaling and layouts
     do not collide at 200%.
     ------------------------------------------------------------------------ */

  --space-3xs: 0.25rem;   /*  4px */
  --space-2xs: 0.5rem;    /*  8px */
  --space-xs:  0.75rem;   /* 12px */
  --space-sm:  1rem;      /* 16px */
  --space-md:  1.5rem;    /* 24px */
  --space-lg:  2rem;      /* 32px */
  --space-xl:  3rem;      /* 48px */
  --space-2xl: 4rem;      /* 64px */


  /* ------------------------------------------------------------------------
     6. Radius, shadow, layout
     ------------------------------------------------------------------------ */

  --radius-sm:   6px;
  --radius-md:   10px;
  --radius-lg:   16px;
  --radius-pill: 999px;

  /* Soft and low. The brand is warm, not glossy. */
  --shadow-card: 0 1px 2px rgba(28, 46, 74, 0.06),
                 0 4px 12px rgba(28, 46, 74, 0.05);

  /* ------------------------------------------------------------------------
     Tap target. 44px minimum (grounding section 8).

     max() rather than a bare rem: 2.75rem grows with the reader's font size,
     which is what we want, but it would drop UNDER 44px for anyone who has
     set a base font smaller than 16px. 44px is a physical fingertip measure,
     so it needs a hard floor as well as room to grow.
     ------------------------------------------------------------------------ */
  --tap-min: max(2.75rem, 44px);

  /* Content column. 390px is the design width and 320px must still work, so
     the container is fluid first and only gains a maximum further up. */
  --container-max: 40rem;      /* 640px — comfortable measure for prose */
  --container-pad: var(--space-sm);

  --motion-fast: 120ms;
  --motion-base: 200ms;
  --motion-ease: cubic-bezier(0.2, 0, 0.2, 1);
}
