/* Language editions: de, fr, es, ru. Loaded last in <head> on localized pages only; English
   pages never request this file, so nothing here can change them. Tokens come from
   /styles.css (loaded first); this file adds fonts, the header language menu, the EN badge
   and the sitemap language row. Receipts: scripts/i18n/font_coverage.py (before and after),
   build: scripts/i18n/build_fonts.py.

   FONTS. The brand roles are display, heading, UI and body (docs/brand/README.md, Type).
   styles.css sets each role as a custom property (--font-display, --font-heading, --font-ui,
   --font-body), so an edition swaps a role by redefining the property on <html>. A role is
   swapped whole or not at all, never stitched character by character from two faces.

   Verified coverage (fontTools cmap, 2026-10-09):
   - de, es: the English faces cover every needed letter. Nothing to change.
   - fr: Accidental Presidency has no oe (U+0153, U+0152), so the display role swaps to
     Oswald (the French h1 and big numbers can say "coeur", "oeuvre", "soeur"). Heading,
     UI and body keep Titillium Web, Expressway and Inter. None of the three has U+202F
     (narrow no-break space, French typography before : ; ! ? and inside guillemets); the
     one-glyph "WFG Narrow Space" font supplies that single space in every role. Capital
     Y with diaeresis (U+0178) is missing from Titillium Web, Expressway and the shipped
     Inter subset; it occurs in no French word the guides use and would render as one
     system-sans glyph (known gap, not stitched).
   - ru: none of Accidental Presidency, Titillium Web or Expressway has any Cyrillic and the
     shipped Inter subset has six letters, so all four roles swap: display Oswald 500,
     heading Exo 2 600, UI Fira Sans 400, body Inter 4.001 with Cyrillic (roman 400-600 and
     italic 400). Oswald stands in for the tall condensed Presidency, Exo 2 for squarish
     Titillium, Fira Sans for the highway-sign Expressway.

   Every file is SIL OFL 1.1 from its official upstream: Oswald, Exo 2 and Fira Sans from
   github.com/google/fonts (commit 51303ca9e8ac), Inter from github.com/rsms/inter (v4.1
   release files). License texts: /fonts/oswald-LICENSE.txt, exo-2-LICENSE.txt,
   fira-sans-LICENSE.txt and inter-LICENSE.txt (Inter's text is the one already shipped).
   File names carry the font version and a content hash because /fonts/* is served immutable.

   size-adjust matches the replaced face's cap height (display, UI) or x-height (heading);
   ascent-override and descent-override are the replaced face's metrics divided by size-adjust,
   so line boxes and baselines stay where the English layout put them. */

@font-face {
  font-family: "WFG Oswald";
  src: url("/fonts/oswald-4.103-500-latin-cyrillic-39228e22.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  size-adjust: 80.1%;
  ascent-override: 116.4%;
  descent-override: 27.6%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "WFG Exo 2";
  src: url("/fonts/exo-2-2.010-600-latin-cyrillic-b9553ee6.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  size-adjust: 102.7%;
  ascent-override: 110.3%;
  descent-override: 37.8%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "WFG Fira Sans";
  src: url("/fonts/fira-sans-4.203-400-latin-cyrillic-5eb78fbe.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  size-adjust: 100.4%;
  ascent-override: 97.7%;
  descent-override: 21.8%;
  line-gap-override: 0%;
}
/* Inter with Cyrillic. Same design and metrics as the "Inter" in styles.css, a different
   family name so the two files never merge into one stitched family. */
@font-face {
  font-family: "WFG Inter";
  src: url("/fonts/inter-4.001-latin-cyrillic-9e6d7711.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "WFG Inter";
  src: url("/fonts/inter-4.001-latin-cyrillic-italic-82a6e3bd.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
/* One empty glyph, U+202F at 0.2em. It only ever answers for that code point. */
@font-face {
  font-family: "WFG Narrow Space";
  src: url("/fonts/wfg-narrow-space-1.0-e76258cf.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+202F;
}

html[data-locale="fr"] {
  --font-display: "WFG Oswald", "WFG Narrow Space", "Arial Narrow", "Roboto Condensed", sans-serif;
  --font-heading: "Titillium Web", "WFG Narrow Space", "Titillium Web Fallback", "Segoe UI", system-ui, Arial, sans-serif;
  --font-ui: "Expressway", "WFG Narrow Space", "Segoe UI", system-ui, Arial, sans-serif;
}
html[data-locale="ru"] {
  --font-display: "WFG Oswald", "WFG Narrow Space", "Arial Narrow", "Roboto Condensed", sans-serif;
  --font-heading: "WFG Exo 2", "WFG Narrow Space", "Segoe UI", system-ui, Arial, sans-serif;
  --font-ui: "WFG Fira Sans", "WFG Narrow Space", "Segoe UI", system-ui, Arial, sans-serif;
  --font-body: "WFG Inter", "WFG Narrow Space", system-ui, "Segoe UI", Arial, sans-serif;
}
/* The talent calculator's shadow root defines its own --font-* on :host. A rule from the
   page outranks :host, so setting them on the host element swaps its roles too. */
html[data-locale="fr"] [data-talent-calculator] {
  --font-display: "WFG Oswald", "WFG Narrow Space", "Arial Narrow", sans-serif;
  --font-ui: "Expressway", "WFG Narrow Space", "Segoe UI", system-ui, sans-serif;
}
html[data-locale="ru"] [data-talent-calculator] {
  --font-display: "WFG Oswald", "WFG Narrow Space", "Arial Narrow", sans-serif;
  --font-ui: "WFG Fira Sans", "WFG Narrow Space", "Segoe UI", system-ui, sans-serif;
  --font-body: "WFG Inter", "WFG Narrow Space", system-ui, sans-serif;
}

/* ---------- Long words ----------
   German compounds ("Donaudampfschifffahrtsgesellschaftskapitaen") and Russian words run
   longer than the English they replace. Text breaks at a hyphenation point where the browser's
   dictionary for the page's lang has one, and at the last letter otherwise, instead of running
   past the screen where the body's overflow-x: hidden would cut it off. */
html[data-locale] main :is(h1, h2, h3, h4, h5, h6, p, li, dd, figcaption, summary, th, td) {
  overflow-wrap: break-word;
  hyphens: auto;
}

/* ---------- Language menu (header) ----------
   <details class="wfg-lang"> sits before .site-menu-link: a pill with the language code,
   a small panel under it aligned to the right edge. Same control look as the Menu button
   (line-control border, 2px radius, UI face). The list names every language in its own
   language, Cyrillic included, so it uses the body face: on de, fr and es pages that face
   has the letters of "Русский", where the UI face (Expressway) has none. */
.wfg-lang { position: relative; flex: none; }
.wfg-lang > summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  min-width: 2.5rem;
  min-height: 2.25rem;
  padding: 0 .55rem;
  border: 1px solid var(--line-control);
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--ink);
  font: 400 .85rem/1 var(--font-ui);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.wfg-lang > summary::-webkit-details-marker { display: none; }
.wfg-lang > summary::after {
  content: "";
  width: .38rem;
  height: .38rem;
  margin-top: -.15rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform .12s ease-out;
}
.wfg-lang > summary:hover { border-color: var(--ink-3); }
.wfg-lang[open] > summary { background: var(--panel-2); border-color: var(--ink-3); }
.wfg-lang[open] > summary::after { margin-top: .1rem; transform: rotate(225deg); }
.wfg-lang > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.wfg-lang-list {
  position: absolute;
  z-index: 45;
  top: calc(100% + (var(--header-h) - 2.25rem) / 2);
  right: 0;
  min-width: 10.5rem;
  max-width: calc(100vw - 2 * var(--gutter));
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--panel);
  border: 1px solid var(--edge);
  box-shadow: var(--panel-frame);
}
.wfg-lang-list li { margin: 0; padding: 0; }
.wfg-lang-list a {
  display: flex;
  align-items: center;
  gap: .55rem;
  min-height: 2.75rem;
  padding: 0 .75rem;
  border-radius: var(--r-ctl);
  color: var(--ink-2);
  font: 400 .95rem/1.2 var(--font-body);
  text-decoration: none;
}
.wfg-lang-list a::before {
  content: "";
  width: .4rem;
  height: .4rem;
  flex: none;
  border-radius: 50%;
  background: transparent;
}
.wfg-lang-list a:hover { background: var(--panel-2); color: var(--ink); }
.wfg-lang-list a:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
/* The current language is a dot and a color, never the color alone. */
.wfg-lang-list a[aria-current="true"] { color: var(--accent-text); }
.wfg-lang-list a[aria-current="true"]::before { background: currentColor; }
@container site-header (width < 63rem) {
  .wfg-lang > summary { min-height: 2.75rem; min-width: 2.75rem; }
  .wfg-lang-list { top: calc(100% + (var(--header-h) - 2.75rem) / 2); }
}
/* Desktop: the bar is already full (menu audit, 2026-10-08), so the pill gives up its
   chevron-sized padding and the bar's gaps tighten by a quarter rem. */
@container site-header (width >= 63rem) {
  .wfg-lang > summary { min-width: 2.25rem; padding: 0 .45rem; gap: .25rem; }
  html[data-locale] .site-header-bar { gap: .5rem; }
}
/* 63 to 74rem is where the bar is tightest (the English bar fits 1024px with nothing to spare):
   the search box may shrink a little further to make room for the pill. */
@container site-header (63rem <= width <= 74rem) {
  html[data-locale] .site-search { min-width: 6.25rem; }
}
/* Translated labels make the bar longer than the English one: the realm strip and the menu run
   up to 130px wider (Spanish and French; measured 2026-10-10 at 1024, 1366 and 1920px). So on
   editions the wordmark waits for 100rem (the logo still links home), the bar may widen to 94rem
   there, and up to 90rem the menu items drop their chevrons and letter-spacing. In the tightest
   band, 63 to 74rem, the items and the strip also take a smaller size. */
@container site-header (63rem <= width < 100rem) {
  html[data-locale] .brand-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@container site-header (width >= 100rem) {
  html[data-locale] .site-header-bar { width: min(100% - 2 * var(--gutter), 94rem); }
}
@container site-header (63rem <= width < 90rem) {
  html[data-locale] .site-nav-top { padding-inline: .3rem; letter-spacing: 0; }
  html[data-locale] .site-nav-chevron { display: none; }
}
@container site-header (63rem <= width <= 74rem) {
  html[data-locale] .site-header-bar { gap: .4rem; }
  html[data-locale] .site-nav-top { padding-inline: .2rem; font-size: .85rem; }
  html[data-locale] .site-status { column-gap: .25rem; font-size: .76rem; }
  html[data-locale] .site-status-tag, html[data-locale] .site-status-note { font-size: .72rem; }
}
/* Phones: the pill is the same 44px square as the Menu button, code only, and the realm
   strip tightens the way it does under 22rem (styles.css), so its titles stay whole beside
   the extra control. */
@container site-header (width < 25.6rem) {
  .wfg-lang > summary { width: 2.75rem; padding: 0; }
  .wfg-lang > summary::after { display: none; }
  html[data-locale] .site-header-bar { gap: var(--s-2); }
  html[data-locale] .site-status { grid-template-columns: auto auto minmax(3.5rem, auto); padding-inline: 0; column-gap: .25rem; font-size: .76rem; }
  html[data-locale] .site-status-wrap.is-enhanced > .site-status { padding-right: .8rem; }
  html[data-locale] .site-status-chevron { right: .05rem; }
  html[data-locale] .site-status-tag, html[data-locale] .site-status-note { font-size: .72rem; }
}
/* Under 20rem the bar wraps: logo and Menu on the first row, the language pill with the Menu. */
@container site-header (width < 20rem) {
  .wfg-lang { margin-left: auto; }
  .site-menu-link, .site-menu-toggle { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .wfg-lang > summary::after { transition: none; }
}

/* ---------- EN badge on links to pages without a translation yet ----------
   The localizer keeps the English URL and adds hreflang="en". Inside the page body the
   link gets a small "EN" tag, so a reader knows the next page is English before clicking.
   Not in the header or footer navigation: those lists stay mostly English while editions
   roll out, and a badge on every item would drown the menus. Not on the language links themselves, nor on buttons, which are
   actions with their own labels. The badge is decoration; the link's hreflang already tells
   assistive technology the language. */
/* Prose links only: a sentence, list item, cell or caption that sends the reader to an English
   page says so. Not on cards, tiles and rows (their own layout), not in the sitemap (where
   most rows are English while the rollout is open, and one sentence says so), the byline or
   the home page's news ticker and change list. */
html[data-locale] main :is(p, li, dd, td, th, figcaption, summary) > a[hreflang="en"]:not(:has(*)):not(.wfg-lang a, .wf-map-languages a, .wf-map a, .wfg-byline a, .hp-what-list a, .btn, .wfg-btn, .wfg-cta-btn, .xo-cta, .wfg-vrow-btn)::after {
  content: "EN";
  display: inline-block;
  margin-inline-start: .35em;
  padding: 0 .3em;
  border: 1px solid var(--line);
  border-radius: var(--r-ctl);
  color: var(--ink-3);
  font: 400 .66rem/1.45 var(--font-ui);
  letter-spacing: .06em;
  text-decoration: none;
  vertical-align: .12em;
  white-space: nowrap;
}

/* ---------- Sitemap language row ----------
   <p class="wf-map-languages"> holds one link per edition. A compact inline row; the
   sitemap's columns (.wf-map) never split it. */
.wf-map-languages {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .5rem;
  margin: 0 0 var(--s-4);
  color: var(--ink-3);
  font: 400 .9rem/1.4 var(--font-ui);
}
.wf-map > .wf-map-languages { column-span: all; }
.wf-map-languages a {
  display: inline-flex;
  align-items: center;
  min-height: 2rem;
  padding: 0 .65rem;
  border: 1px solid var(--line);
  border-radius: var(--r-ctl);
  color: var(--ink-2);
  font-family: var(--font-body);
  text-decoration: none;
}
.wf-map-languages a:hover { border-color: var(--ink-3); color: var(--ink); }
.wf-map-languages a:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.wf-map-languages a[aria-current="true"],
.wf-map-languages a[aria-current="page"] { border-color: var(--accent); color: var(--accent-text); }
@media (pointer: coarse) {
  .wf-map-languages a { min-height: 2.75rem; }
}

/* ---------- Translated readings of quotations ----------
   A player quote or blue post keeps the speaker's English (lang="en"); the localizer adds
   <span class="wfg-quote-reading"> with the translation, labeled, on its own line. */
html[data-locale] .wfg-quote-reading {
  display: block;
  margin-top: .4em;
  color: var(--ink-2);
  font-style: normal;
}
html[data-locale] .wfg-quote-reading-label {
  margin-inline-end: .45em;
  color: var(--ink-3);
  font: 600 .68rem/1.4 var(--font-ui);
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* ---------- Longer labels ----------
   The home planner's two buttons stack when a translation does not fit one row (French
   "Lire le guide Chasseur"), instead of clipping. */
html[data-locale] .hp-plan-act { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }
html[data-locale] .hp-plan-act .wfg-btn { white-space: normal; min-width: 0; line-height: 1.15; }
/* Client class names need enough room to remain visible on translated tools. */
html[data-locale] .mb-classes { grid-template-columns: repeat(auto-fit, minmax(5.25rem, 1fr)); }
html[data-locale] .tool-diff summary { display: block; position: relative; padding: .65rem 1.25rem .65rem 0; }
html[data-locale] .tool-diff summary::after { position: absolute; inset-inline-end: 0; top: 1.1rem; margin: 0; }
@media (max-width: 40rem) {
  html[data-locale] .tool-stage .wfg-board > .tool-diff,
  html[data-locale] .tool-stage .wfg-calc[data-calc-state="loaded"] > .wfg-calc-swap { grid-column: 1 / -1; }
}
/* Translated page titles run longer than English ones; on wide screens the current crumb gets
   more room before it is cut. */
@media (min-width: 63rem) {
  html[data-locale] .breadcrumb [aria-current="page"] { max-width: min(100%, 44ch); }
}
.wf-map > .wf-map-note { column-span: all; margin: calc(-1 * var(--s-3)) 0 var(--s-4); color: var(--ink-3); font: 400 .85rem/1.4 var(--font-body); }
