/* Socialhose brand typefaces — self-hosted.
 *
 * Univers (display/UI) + Melior (body) are the brand pair for marketing pages
 * and EDITORIAL email (newsletters, meetings, content downloads). Berkeley Mono
 * joins them for code — the same face the platform app runs on, so a curl
 * example on a landing page and the same command in the app read identically.
 * In marketing surfaces, prose never uses it.
 *
 * PRODUCT emails are the exception: alert and system/transactional templates
 * (templates/emails/tui/base.html and everything extending it) are set
 * entirely in Berkeley Mono — they are the app speaking, so they carry the
 * TUI grammar, not the marketing pair. Those templates declare their own
 * @font-face against https://socialhose.net/static/fonts/BerkeleyMono-*.woff2
 * and do not link this stylesheet.
 *
 * Charter is NOT a brand face any more. It stays declared purely as the serif
 * coverage fallback: Melior is Latin-only, and we ingest mentions in every
 * script, so a Greek or Cyrillic mention in a digest email picks up Charter
 * glyph-by-glyph. Every serif stack is therefore 'Melior', 'Charter', Georgia —
 * never Charter alone. (CJK is beyond both faces.)
 *
 * IBM Plex Sans Thai, IBM Plex Sans Arabic and IBM Plex Sans KR join them at
 * the bottom of this file. None is a brand face either — they exist because the
 * marketing site is published in Thai (/th/), Arabic (/ar/) and Korean (/ko/),
 * and no brand face covers a single Thai, Arabic or Hangul letter. All three
 * are unicode-range'd to their own script, so each draws that script and
 * nothing else.
 *
 * Loaded by:
 *   - marketing pages via {% static 'css/brand-fonts.css' %}
 *   - email templates via the absolute https://socialhose.net/... URL (a mail
 *     client has no notion of our dev/staging hosts)
 *
 * The Latin faces are subset to Latin/Latin-Ext; characters outside that range
 * fall back per-character, which is what we want for user content in a digest
 * email. Thai, Arabic and Hangul are the three scripts that fall back to a face
 * we ship rather than to whatever the OS happens to have.
 *
 * Adding a script here is two edits, and missing the second is silent: the
 * @font-face block at the bottom, and the face's name in every stack that
 * already lists its siblings (`grep "IBM Plex Sans Thai"`). A face declared but
 * absent from the stacks is downloaded by nobody and changes nothing.
 */

@font-face {
  font-family: 'Univers';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("../fonts/Univers-Light.dcb9d421e774.woff2") format('woff2');
}
@font-face {
  font-family: 'Univers';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Univers-Regular.6d5b5d3ca451.woff2") format('woff2');
}
@font-face {
  font-family: 'Univers';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Univers-Italic.5fcdc503babf.woff2") format('woff2');
}
@font-face {
  font-family: 'Univers';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/Univers-Medium.929a2757d718.woff2") format('woff2');
}
@font-face {
  font-family: 'Univers';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/Univers-Bold.81ec8da72280.woff2") format('woff2');
}
@font-face {
  font-family: 'Univers';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/Univers-BoldItalic.7917036e0129.woff2") format('woff2');
}

/* Melior (LT Std) — body. Zapf drew its bowls as superellipses rather than
 * ovals, which is why it sits under Berkeley Mono the way a conventional serif
 * doesn't; the two share a geometry.
 *
 * size-adjust: 103.4% makes the swap off Charter size-neutral. Melior's
 * x-height is 46.5% of the em against Charter's 48.1% (481/465 = 1.034), so at
 * an unchanged font-size it reads slightly small. Scaling the em restores the
 * previous apparent text size without touching a single font-size rule — the
 * same technique Berkeley uses at 106.18%.
 */
@font-face {
  font-family: 'Melior';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 103.4%;
  src: url("../fonts/Melior-Roman.6cfd3f3470aa.woff2") format('woff2');
}
@font-face {
  font-family: 'Melior';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  size-adjust: 103.4%;
  src: url("../fonts/Melior-Italic.a513dfd2fca1.woff2") format('woff2');
}
@font-face {
  font-family: 'Melior';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  size-adjust: 103.4%;
  src: url("../fonts/Melior-Bold.54243b8f55da.woff2") format('woff2');
}
@font-face {
  font-family: 'Melior';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  size-adjust: 103.4%;
  src: url("../fonts/Melior-BoldItalic.01968c125554.woff2") format('woff2');
}

/* Charter — coverage fallback only, never a brand face. Carries the Cyrillic and
 * Greek that Melior lacks, so a mention in either script still renders. It does
 * NOT cover Thai: Charter maps exactly one codepoint in the Thai block, ฿ (baht),
 * which Latin faces carry as a currency symbol. Thai is handled by IBM Plex Sans
 * Thai at the bottom of this file.
 *
 * Deliberately NOT size-adjusted, and it happens to need no adjustment: Melior
 * scaled by 1.034 lands an x-height of 0.481 em, which is exactly Charter's
 * natural x-height. A Greek or Cyrillic run sits optically level with the Latin
 * beside it for free. If the Melior size-adjust above ever changes, recheck this.
 */
@font-face {
  font-family: 'Charter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Charter-Roman.d14ccef9dd4b.woff2") format('woff2');
}
@font-face {
  font-family: 'Charter';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Charter-Italic.ddfe344b6b4d.woff2") format('woff2');
}
@font-face {
  font-family: 'Charter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/Charter-Bold.4f13cfc3eb27.woff2") format('woff2');
}
@font-face {
  font-family: 'Charter';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/Charter-BoldItalic.90226f335bec.woff2") format('woff2');
}

/* Berkeley Mono (TX-02) — code only. size-adjust matches the platform app's
 * faces (frontend/src/styles/theme.css): Berkeley's x-height is 51.8% of the em,
 * so at an unchanged font-size it reads noticeably small. The same 106.18% here
 * keeps one Berkeley across app and marketing rather than two apparent sizes. */
@font-face {
  font-family: 'Berkeley Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 106.18%;
  src: url("../fonts/BerkeleyMono-Regular.152c5a819cd3.woff2") format('woff2');
}
@font-face {
  font-family: 'Berkeley Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  size-adjust: 106.18%;
  src: url("../fonts/BerkeleyMono-Bold.e2a60c4e1c05.woff2") format('woff2');
}

/* IBM Plex Sans Thai (Thai), self-hosted, SIL OFL 1.1.
 *
 * Thai-only subsets, so this face never touches Latin: unicode-range keeps it to
 * the Thai block, and Univers/Melior/Berkeley continue to draw everything else in
 * a mixed line. That is what lets a single family ride in every stack below
 * without restyling a single English page.
 *
 * These are the same Fontsource WOFF2 subsets the React app loads
 * (frontend/src/assets/fonts/), so Thai is one typeface across app, marketing,
 * PDF exports and share cards rather than three near-misses.
 *
 * size-adjust: 110%. Thai has no capitals and no ascenders, so a Thai line's
 * whole silhouette is the consonant body (ka/tha top out at 0.558 em here) while
 * a Latin line keeps reaching to cap height. Matching x-heights therefore sets
 * Thai too small -- the body wants to land between Latin x-height and cap height,
 * which is where Thai type conventionally sits against Latin. Measured from
 * assets/fonts/ at 1000 upm:
 *
 *              x-height   cap-height   midpoint   implied size-adjust
 *   Univers      50.5%       72.3%       61.4%          112%
 *   Melior*      48.1%       71.9%       60.0%          109%
 *   (* after Melior's own 103.4% size-adjust above, i.e. as actually rendered)
 *
 * One @font-face carries one size-adjust, and marketing needs Thai in both the
 * Univers UI stack and the Melior body stack. The two targets are under 3% apart
 * -- below the point where the mismatch is legible -- so 110% splits them. It is
 * also exactly the value frontend/src/styles/theme.css uses, which is the more
 * valuable property: Thai is metrically identical in the app and on the site.
 * (Rejected: two aliased families at 112%/109%. Real precision, but it doubles
 * these declarations and makes every stack in marketing.css context-dependent.)
 *
 * No ascent-override/descent-override, unlike the app. theme.css clamps Plex
 * Thai's line box (111.6/53.4) onto Berkeley's (95.6/24.5) to hold the terminal
 * grid, and documents that as a deliberate, non-free trade: Thai stacks, so a
 * tone mark sitting above an upper vowel via mkmk paints outside the clamped box.
 * Marketing has no grid to hold, so the natural line box stays and stacked marks
 * get the room they need. A Thai marketing line is consequently a little taller
 * than the Latin one. That is correct, not a regression -- do not "fix" it by
 * adding the overrides back.
 *
 * Weights 400/500/700 match the Univers weights in use, so nothing synthesises.
 * Files keep their upstream Fontsource names so re-fetching is unambiguous.
 */
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 110%;
  src: url("../fonts/ibm-plex-sans-thai-thai-400-normal.e72e639292ac.woff2") format('woff2');
  unicode-range: U+0E01-0E5B, U+200B-200D;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  size-adjust: 110%;
  src: url("../fonts/ibm-plex-sans-thai-thai-500-normal.c40569bb727d.woff2") format('woff2');
  unicode-range: U+0E01-0E5B, U+200B-200D;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  size-adjust: 110%;
  src: url("../fonts/ibm-plex-sans-thai-thai-700-normal.029db11954e6.woff2") format('woff2');
  unicode-range: U+0E01-0E5B, U+200B-200D;
}

/* IBM Plex Sans Arabic (Arabic), self-hosted, SIL OFL 1.1.
 *
 * Same job as the Thai face above and declared the same way: Arabic-only
 * subsets, unicode-range'd so it draws Arabic and nothing else while
 * Univers/Melior/Berkeley keep every Latin glyph in a mixed line. Added when
 * the marketing site was published in Arabic at /ar/ -- neither brand face
 * maps a single Arabic codepoint, so without this every /ar/ page renders in
 * whatever the OS happens to have.
 *
 * Note what the range does NOT include. The upstream subset also carries
 * U+0020 (space) and U+00A0 (no-break space), and listing those would hand
 * this face the spaces in *English* pages -- word-spacing on the whole site
 * decided by a font that exists to draw Arabic. Only the Arabic blocks and the
 * two joiners are listed.
 *
 * Chosen to match the Thai decision -- one superfamily for the site's non-Latin
 * scripts -- and it is deliberately not the Arabic face used elsewhere in the
 * repo. There is no single one to match: the app sets Arabic in Kawkab Mono
 * because it has a monospace grid to hold, and share cards render it in Noto
 * Naskh / Tajawal because Pillow draws from the TTFs in assets/fonts. Those two
 * are incidental mention text; this is site chrome. See assets/fonts/FONTS.md.
 *
 * size-adjust: 107%. Arabic and Latin have no shared vertical anchor -- Arabic
 * has nothing that is an x-height and nothing that is a capital -- so the two
 * obvious targets disagree violently. Measured at 1000 upm:
 *
 *                          Plex Arabic   target        implied size-adjust
 *   alif/lam/kaf top          74.0%      Latin ascender      ~101%
 *   baa tooth (base body)     38.0%      Latin x-height      ~130%
 *
 * The gap is the whole problem: Arabic's body-to-alif ratio is 0.51 where
 * Latin's x-height-to-cap is 0.70, so anchoring on the tall strokes leaves the
 * body far too small to read, and anchoring on the body leaves alif towering
 * over the Latin beside it. 107% is the midpoint of the two optical targets
 * theme.css already settled on for Kawkab in the app -- alif a hair above the
 * Latin ascender, tooth height around 0.85 of the Latin x-height:
 *
 *              x-height   ascender    at 107%: alif 79.2%, tooth 40.7%
 *   Univers      50.5%      72.3%      alif clears it, tooth/x = 0.81
 *   Melior*      48.3%      77.0%      alif a hair above, tooth/x = 0.84
 *   (* as rendered, i.e. after Melior's own 103.4% size-adjust)
 *
 * No ascent-override/descent-override, for the reason the Thai block gives at
 * length: marketing has no grid to hold. Arabic descenders reach -30.4% against
 * Melior's -25.2%, so an Arabic line is a little taller than the Latin one.
 * That is correct -- do not "fix" it by copying the app's clamps, which exist
 * to hold a terminal grid this stylesheet does not have.
 *
 * Weights 400/500/700 match the Univers weights in use, so nothing synthesises.
 * Files keep their upstream Fontsource names so re-fetching is unambiguous
 * (@fontsource/ibm-plex-sans-arabic 5.3.0).
 */
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 107%;
  src: url("../fonts/ibm-plex-sans-arabic-arabic-400-normal.4fa3d81d41ab.woff2") format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  size-adjust: 107%;
  src: url("../fonts/ibm-plex-sans-arabic-arabic-500-normal.106892212ea7.woff2") format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  size-adjust: 107%;
  src: url("../fonts/ibm-plex-sans-arabic-arabic-700-normal.a4390abc98c2.woff2") format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D;
}

/* IBM Plex Sans KR (Hangul), self-hosted, SIL OFL 1.1.
 *
 * Same job as the Thai and Arabic faces above -- added when the marketing site
 * was published in Korean at /ko/, because no brand face maps a single Hangul
 * codepoint. Third face from the same superfamily, for the reason the Arabic
 * block gives: one superfamily for the site's non-Latin scripts.
 *
 * THE unicode-range HERE IS NOT OPTIONAL, AND IT IS NOT THE MILD VERSION OF
 * THE ARABIC WARNING. The upstream Fontsource CSS ships this subset with NO
 * unicode-range at all, and the subset carries U+0020-007E -- the whole of
 * ASCII, 95 glyphs, every English letter, digit and punctuation mark on the
 * site. Copying the upstream @font-face verbatim therefore does not "also
 * catch the spaces" the way listing U+0020 would for Arabic: it hands the
 * entire English site to a Korean face, silently, in every language. It
 * downloads half a megabyte on the English home page to draw Latin that
 * Univers already draws. The range below lists the Korean blocks and nothing
 * else, and FontTests pins its first entry.
 *
 * The subset's 31 ranges reduce to four that are actually Korean:
 *
 *   U+3131-318E   Hangul Compatibility Jamo -- single letters, as in a
 *                 keyboard legend or a "ㄱ, ㄴ, ㄷ" ordered list
 *   U+3200-321C   parenthesised Hangul, U+3260-327B circled Hangul
 *   U+AC00-D7A3   Hangul Syllables -- 11,172 of the 11,459 glyphs here, and
 *                 all of ordinary Korean text once it is NFC-composed
 *
 * The rest of the subset is Latin, Latin-1 symbols and general punctuation
 * that the brand faces already carry, so none of it is listed. Note U+1100-11FF
 * (conjoining Jamo) is absent from the face and therefore absent here too --
 * decomposed Hangul would fall through per-glyph to the OS. Django renders NFC
 * and so does every catalog string, so that path is not reachable from our copy.
 *
 * size-adjust: 93.5%, and it is the first face here that SHRINKS rather than
 * enlarges. Thai and Arabic have small bodies that need pushing up to Latin;
 * Hangul is the opposite problem -- a syllable fills its em box, so at 100% it
 * overshoots the Latin cap height every layout on the site was built around.
 * Hangul also has no x-height/cap distinction to anchor on: every syllable is
 * the same block, which makes cap height the only meaningful target. Measured
 * from the binaries at 1000 upm (한/글/가/힣/믿 agree to within 3%):
 *
 *                        Hangul top   target cap   implied size-adjust
 *   vs Univers              76.9%        72.3%            94.0%
 *   vs Melior*              76.9%        71.6%            93.1%
 *   (* after Melior's own 103.4% size-adjust above, i.e. as actually rendered)
 *
 * The two targets are 0.9% apart -- far tighter than Thai's 3% -- so 93.5%
 * splits them almost exactly, landing Hangul at 71.9% against 72.3% and 71.6%.
 * There is no app value to match here, unlike Thai: the React app ships no
 * Korean face at all and renders /ko/ from whatever the OS has. If it ever
 * gains one, this is the number to copy, not to re-derive.
 *
 * No ascent-override/descent-override, consistent with the two blocks above.
 * Worth noting that Korean is the one script here that does NOT make the line
 * taller: Hangul descends to -14.9% as rendered, well inside Melior's own
 * -25.2%, so a Korean line sits within the Latin line box rather than pushing
 * past it. Nothing to compensate for, and nothing to "fix".
 *
 * Weights 400 and 700 only -- see marketing/languages.py. The Hangul subset is
 * ~500 KB per weight against Thai's ~30 KB, so the 500 that Thai and Arabic
 * ship would cost another half megabyte to set buttons in medium. Text asking
 * for 500 on a /ko/ page gets 400 rather than a synthesised weight, because
 * that is what the browser does when a family declares 400 and 700 and the
 * request falls between them.
 *
 * Files keep their upstream Fontsource names so re-fetching is unambiguous
 * (@fontsource/ibm-plex-sans-kr 5.3.0).
 */
@font-face {
  font-family: 'IBM Plex Sans KR';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  size-adjust: 93.5%;
  src: url("../fonts/ibm-plex-sans-kr-korean-400-normal.291ccb10de14.woff2") format('woff2');
  unicode-range: U+3131-318E, U+3200-321C, U+3260-327B, U+AC00-D7A3;
}
@font-face {
  font-family: 'IBM Plex Sans KR';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  size-adjust: 93.5%;
  src: url("../fonts/ibm-plex-sans-kr-korean-700-normal.e700dcd9151d.woff2") format('woff2');
  unicode-range: U+3131-318E, U+3200-321C, U+3260-327B, U+AC00-D7A3;
}
