@charset "UTF-8";
/* ==========================================================================
   TWSS_styles_004.css — www.toptronicwebsites.com  (part 4: the globe switcher)
   Generated/Updated on: 2026-09-16T14:35:00+10:00
   Build Number: 004
   Version Number: (set manually by Jacques)

   © Copyright 1990-2026 Toptronic® Ltd, all rights reserved; no part of this
   document may be reproduced, modified or stored in a retrieval system, or
   transmitted in any form or by any means, electronic, mechanical,
   photocopying, recording or otherwise, without the prior written permission of
   Toptronic Limited. For copyright inquiries: jacques@toptronic.com

   Continuation from TWSS_styles_003.css (loaded after it, so anything here wins
   when both files describe the same element). Nothing in files 001-003 is
   touched: the old <select class="lang"> markup is gone, its CSS stays behind
   harmlessly, and this file describes only the NEW markup — TWSS_Contract_0097
   section 2, which is frozen. We style it; we never change it.

   WHAT IT IS
     The complete look of the small country / language chooser at the top of
     every page: the round pill with the globe, the floating panel that opens
     from it, the two filter boxes, the two scrolling lists (countries with their
     real flags, and languages), the group headings and the one-line hint.

   HOW IT WORKS (three ideas, no prior knowledge needed)
     1. THE PILL IS A <summary>. Opening, closing and the keyboard support all
        come from the browser's own <details> element; we only paint it, so the
        pill opens with no JavaScript at all.
     2. THE PANEL FLOATS. It is absolutely positioned, so it never pushes the
        page down. The country list holds 250 rows and scrolls inside itself.
     3. EVERY SIDE IS LOGICAL. There is no "left" and no "right" in this file: we
        say inline-start / inline-end / block-start / block-end, and the browser
        mirrors everything by itself for an Arabic visitor (dir="rtl"). The build
        checker refuses physical sides anyway.

   MEASURED COLOURS (measured, never guessed — every surface is checked)
     The panel is dark, --ink-2 #1D1D1F (session 0100 apple palette). Text on it:
       --text-dk  #F5F5F7 on #1D1D1F = 15.46 : 1   country / language names
       --muted-dk #A1A1A6 on #1D1D1F =  6.54 : 1   labels, hint, group text
       --muted-dk #A1A1A6 on #2C2C2E =  5.42 : 1   placeholders in the filters
       --brand-hi #2997FF on #1D1D1F =  5.58 : 1   the globe, the chosen row
       --teal     #30D158 on #1D1D1F =  8.32 : 1   the "chosen" marker rail
     WCAG asks 4.5:1 for small text and 3:1 for a user-interface boundary. All
     of the above pass, and so do the two thin edges (filter box 3.16:1, flag
     hairline 3.60:1). The panel's outer edge is 1.97:1 — decoration only: the
     panel is held off the page by its shadow, and every control inside carries
     its own 3:1 edge.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. THE HOST SPAN (the box the leader puts in the header)
   The markup arrives hidden (<span class="geo" hidden>) and the script removes
   that attribute only when it is truly ready. We must repeat display:none here,
   otherwise our own display:flex below would beat the browser's built-in rule
   for [hidden], and the empty pill would flash before the script fills it in.
   -------------------------------------------------------------------------- */
.geo[hidden] { display: none; }

.geo {
  position: relative;            /* the floating panel is measured from here */
  display: flex;
  align-items: center;
  min-inline-size: 0;            /* a long country name may shrink, never push */
}
.geo-switcher { margin: 0; }

/* --------------------------------------------------------------------------
   2. THE PILL (<summary>)
   It must stay SMALL: the header is a wrapping row and the content column is
   1100px wide, so the country name is capped and shortened with "..." instead
   of being given a fixed width. Height 40px and the same dark pill as the
   language select it replaces, so it looks native to the site.
   -------------------------------------------------------------------------- */
.geo-summary {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: 40px;
  padding-block: 7px;
  padding-inline: 13px 28px;     /* start / end — room at the end for the caret */
  border: 1px solid rgba(244, 246, 250, .38);   /* about 3.3:1 on the header */
  border-radius: var(--r-pill);
  background: var(--ink-2);
  color: var(--text-dk);
  font: 600 .875rem/1.2 var(--font-text);
  white-space: nowrap;           /* one row, always */
  cursor: pointer;
  list-style: none;              /* remove the browser's own triangle */
  transition: background var(--t-fast), border-color var(--t-fast);
}
.geo-summary::-webkit-details-marker { display: none; }  /* older Safari */
.geo-summary:hover { background: var(--ink-3); border-color: rgba(244, 246, 250, .55); }
.geo-switcher[open] > .geo-summary { background: var(--ink-3); border-color: var(--brand-hi); }

/* The caret, drawn with two borders (our fonts hold no arrow glyphs). It sits
   at the INLINE-END of the pill, so it swaps sides by itself in Arabic. Both
   borders are equally thick, so the shape is symmetrical: "down" is "down"
   whichever way the text runs, hence no [dir="rtl"] copy is needed. */
.geo-summary::after {
  content: "";
  position: absolute;
  inset-inline-end: 12px;
  inset-block-start: calc(50% - 5px);
  inline-size: 8px;
  block-size: 8px;
  border-inline-end: 2px solid var(--muted-dk);
  border-block-end: 2px solid var(--muted-dk);
  transform: rotate(45deg);
  transition: transform var(--t-fast) var(--ease);
}
.geo-switcher[open] > .geo-summary::after { transform: rotate(-135deg); }

/* The globe: 18px in the brand's light blue (6.83:1 on the pill, well past the
   3:1 a graphic needs). It comes with the markup: no image, no request. */
.geo-globe { inline-size: 18px; block-size: 18px; flex: 0 0 auto; color: var(--brand-hi); }

/* The country name: capped and shortened, never a fixed width (a fixed width is
   what would push the navigation onto a second row). 150px holds "Netherlands",
   "Deutschland" and the Arabic names comfortably. */
.geo-current {
  max-inline-size: min(38vw, 150px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The short language chip beside the name (for example "DE"). It is EMPTY on
   the first paint, and an empty bordered chip shows as a stray line, so it is
   taken out of the layout until the script has something to put in it. */
.geo-current-lang {
  flex: 0 0 auto;
  padding-inline-start: 8px;
  border-inline-start: 1px solid rgba(244, 246, 250, .30);   /* decoration */
  font: 600 var(--fs-micro)/1.2 var(--font-text);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-dk);
}
.geo-current-lang:empty { display: none; }

/* --------------------------------------------------------------------------
   3. THE FLOATING PANEL
   Two columns side by side on a desktop, the country column the wider one. It
   has a DEFINITE height on purpose: that is what makes a 250-row list scroll
   inside itself instead of stretching the panel. min(600px, screen - ...) so
   the whole panel stays reachable on a short screen; the vh line is the
   fallback for browsers that do not yet know dvh (which follows a phone's
   address bar).
   -------------------------------------------------------------------------- */
.geo-panel {
  position: absolute;
  z-index: var(--z-overlay);     /* over the header's own children; the header
                                    itself already sits above the hero */
  inset-block-start: calc(100% + 12px);
  inset-inline-end: 0;           /* grows towards the inline-start side, so it
                                    mirrors correctly in Arabic with no extra rule */
  inline-size: min(680px, calc(100vw - 48px));
  block-size: min(600px, calc(100vh - 116px));
  block-size: min(600px, calc(100dvh - 116px));
  display: grid;
  gap: var(--sp-4) var(--sp-5);
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);   /* countries wider */
  grid-template-rows: minmax(0, 1fr) auto;                   /* the note is row 2 */
  padding: var(--sp-4);
  background: var(--ink-2);
  color: var(--text-dk);
  text-align: start;
  border: 1px solid var(--line-dk-2);          /* decoration, 1.97:1 */
  border-radius: var(--r-3);
  box-shadow: var(--sh-3), var(--glow-d);
}
/* One column: a heading, a filter, and a list that takes whatever height is
   left over. min-block-size:0 is the one line that lets that list scroll. */
.geo-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-inline-size: 0;
  min-block-size: 0;
}
/* The column heading ("Country" / "Language"). Archivo is only ever asked for
   weight 700 — it is a single-weight file, so anything else would be faked. */
.geo-label {
  font: 700 var(--fs-eyebrow)/1.2 var(--font-display);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-dk);
}

/* --------------------------------------------------------------------------
   4. THE TWO FILTER BOXES
   16px text is deliberate: an iOS phone zooms the whole page when a focused
   field is smaller than that. The edge measures 3.16:1 on the field's own dark
   background — what the accessible-boundary rule asks for.
   -------------------------------------------------------------------------- */
.geo-filter {
  inline-size: 100%;
  min-block-size: 44px;
  padding-block: 10px;
  padding-inline: 12px;
  border: 1px solid rgba(244, 246, 250, .36);
  border-radius: var(--r-2);
  background: var(--ink-3);
  color: var(--text-dk);
  font: 400 1rem/1.4 var(--font-text);
}
/* The grey hint inside an empty box: 7.67:1, and we force it opaque because
   some browsers fade a placeholder so far that it becomes hard to read. */
.geo-filter::placeholder { color: var(--muted-dk); opacity: 1; }
.geo-filter:focus {
  border-color: var(--brand-hi);
  box-shadow: 0 0 0 3px rgba(41, 151, 255, .22);
}
/* The keyboard outline is NOT removed: file 001 already draws a brand-blue
   outline for :focus-visible and a keyboard visitor keeps it. */

/* --------------------------------------------------------------------------
   5. THE TWO SCROLLING LISTS (country rows and language rows)
   Each list gets its own scrollbar and stops the wheel leaking into the page
   when it reaches the end (overscroll-behavior). The rows are buttons, so they
   work with a finger, a mouse and the Tab key for free.
   -------------------------------------------------------------------------- */
.geo-list {
  flex: 1 1 auto;
  min-block-size: 0;
  margin: 0;
  padding: var(--sp-1);
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--line-dk);            /* decoration, 1.32:1 */
  border-radius: var(--r-2);
  background: var(--ink);
  scrollbar-width: thin;
  scrollbar-color: var(--line-dk-2) transparent;
}
.geo-list > li { margin: 0; }

/* One row. The chosen-marker rail on the inline-start side is painted by
   ::before, never by a physical side value, so it jumps to the other side in
   Arabic by itself. 44px is the smallest comfortable finger target. */
.country-option,
.lang-option {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  inline-size: 100%;
  min-block-size: 44px;
  padding-block: 6px;
  padding-inline: 10px;
  border: 0;
  border-radius: var(--r-1);
  background: none;
  color: var(--text-dk);
  text-align: start;
  font: 400 var(--fs-small)/1.35 var(--font-text);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.country-option::before,
.lang-option::before {
  content: "";
  position: absolute;
  inset-block: 6px;
  inset-inline-start: 0;
  inline-size: 3px;
  border-radius: 2px;
  background: transparent;
}
.country-option:hover,
.lang-option:hover { background: rgba(244, 246, 250, .08); }   /* text 14.4:1 */
/* The row the visitor has chosen: the words stay at 15.0:1 and the teal rail
   (10.3:1) marks it even for someone who cannot tell the two blues apart. */
.country-option.is-active,
.lang-option.is-active { background: rgba(0, 113, 227, .22); }
.country-option.is-active::before,
.lang-option.is-active::before { background: var(--teal); }

/* The language of a country, pushed to the far inline-end of its own row.
   margin-inline-start:auto is the logical way of saying "as far as possible
   from where the text starts"; the physical way would break in Arabic. */
.country-option-lang {
  margin-inline-start: auto;
  padding-inline-start: var(--sp-2);
  flex: 0 0 auto;
  font-size: var(--fs-micro);                  /* 8.3:1 on the panel */
  color: var(--muted-dk);
  white-space: nowrap;
}
/* A language row carries two names: the native one first, the English one at
   the inline-end, so the list reads the same way in every language. */
.lang-option-native { font: 500 var(--fs-small)/1.35 var(--font-text); }
.lang-option-name {
  margin-inline-start: auto;
  padding-inline-start: var(--sp-2);
  flex: 0 0 auto;
  font-size: var(--fs-micro);
  color: var(--muted-dk);
  white-space: nowrap;
}
/* The language list carries no flags, so its rows sit a little shorter than the
   country rows and the two columns read as balanced rather than ragged. */
.geo-list--lang .lang-option { min-block-size: 42px; }

/* The real flag: 21x14 by the contract's markup, cropped to fill the box
   (object-fit: cover). The hairline is a plain border on all four sides — no
   physical side is named — and measures 3.60:1 on the dark panel. The light
   neutral plate behind it matters: a flag that leaves part of itself
   transparent would otherwise show the panel through it and look like a hole. */
.country-flag {
  inline-size: 21px;
  block-size: 14px;
  flex: 0 0 auto;
  object-fit: cover;
  border: 1px solid rgba(244, 246, 250, .40);
  border-radius: 2px;
  background: var(--muted-dk);
}

/* --------------------------------------------------------------------------
   6. THE GROUP HEADINGS INSIDE A COUNTRY OR LANGUAGE LIST
   "Spoken in this country" and "Other languages of this site". The heading
   sticks to the block-start of the scrolling list, so a visitor never loses
   track of which group they are reading in a 250-row list.
   -------------------------------------------------------------------------- */
.geo-group {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding-block: var(--sp-2) var(--sp-1);
  padding-inline: 10px;
  background: var(--ink);                      /* hides rows sliding underneath */
  list-style: none;
}
.geo-group-text {
  flex: 0 0 auto;
  font: 700 var(--fs-micro)/1.3 var(--font-display);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted-dk);                      /* 8.3:1 at 11px */
}
/* A hairline running from the end of the words to the end of the list. Drawn
   with ::after so it follows the text direction on its own. */
.geo-group::after {
  content: "";
  flex: 1 1 auto;
  block-size: 1px;
  background: var(--line-dk-2);
}
/* The honest sentence "our site is not translated into the main language of
   this country yet": a sentence, not a heading, so it does not stick and it
   does not get a line running away from it. */
.geo-group--note {
  position: static;
  display: block;
  padding-inline: 10px;
  font: 400 var(--fs-micro)/1.55 var(--font-text);
  color: var(--muted-dk);
  overflow-wrap: anywhere;
}
.geo-group--note::after { content: none; }

/* --------------------------------------------------------------------------
   7. THE HINT LINE (aria-live, so a screen reader reads it out)
   The one paragraph inside the panel, spanning both columns. While the script
   has nothing to say the line keeps its place (so the panel cannot jump) but
   paints nothing. It is deliberately NOT display:none: a live region removed
   from the page at load is not announced when the script later fills it, and
   this line exists to be spoken by a screen reader.
   -------------------------------------------------------------------------- */
.geo-note {
  grid-column: 1 / -1;
  min-block-size: 1px;
  padding-block-start: var(--sp-3);
  border-block-start: 1px solid var(--line-dk);
  font: 400 var(--fs-micro)/1.55 var(--font-text);
  color: var(--muted-dk);                      /* 8.3:1 on the panel */
}
.geo-note:empty { border-block-start-color: transparent; }

/* --------------------------------------------------------------------------
   8. THE OPENING MOVEMENT
   A short fade and a 6px drop, so it reads as "this came out of the pill". It is
   switched off for anyone who asked their computer for less movement — the same
   pattern files 001-003 already use.
   -------------------------------------------------------------------------- */
@keyframes twss-geo-open {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.geo-switcher[open] > .geo-panel { animation: twss-geo-open 180ms var(--ease) both; }
@media (prefers-reduced-motion: reduce) {
  .geo-switcher[open] > .geo-panel { animation: none; }
  .geo-summary, .geo-summary::after,
  .country-option, .lang-option { transition: none; }
}

/* --------------------------------------------------------------------------
   9. PHONES AND NARROW SCREENS (below 860px)
   Here the panel is measured from the HEADER, not from the pill, and pulled in
   12px from both inline edges. That guarantees it can never stick out past the
   screen: a pill-anchored 680px panel would be cut off by the page's own
   overflow guard as soon as the menu button sits beside it. The two columns
   become one stacked column — countries first, then languages, then the hint.
   -------------------------------------------------------------------------- */
@media (max-width: 859px) {
  .geo { position: static; }                   /* the header becomes the anchor */
  .geo-summary { padding-inline: 10px 26px; gap: var(--sp-1); }
  .geo-current { max-inline-size: min(30vw, 112px); }
  .geo-panel {
    inset-block-start: calc(100% + 6px);       /* 100% of the header's height */
    inset-inline: 12px;                        /* sets both edges at once */
    inline-size: auto;
    block-size: min(540px, calc(100vh - 140px));
    block-size: min(540px, calc(100dvh - 140px));
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1.3fr) minmax(0, 1fr) auto;
    gap: var(--sp-3) 0;
    padding: var(--sp-3);
    border-radius: var(--r-2);
  }
  .country-option, .lang-option { min-block-size: 42px; }
}

/* A VERY SHORT SCREEN (a phone held sideways, a small laptop window). The panel
   height is already bounded by the viewport; below 620px the padding around the
   rows is trimmed so both lists keep a usable amount of room. */
@media (max-height: 620px) {
  .geo-panel { gap: var(--sp-3) var(--sp-4); padding: var(--sp-3); }
  .country-option, .lang-option { min-block-size: 38px; padding-block: 4px; }
}

/* Wide desktops have room, so the country name may breathe a little more. The
   cap is still a cap: the header row can never be pushed onto a second row. */
@media (min-width: 1280px) {
  .geo-current { max-inline-size: min(20vw, 170px); }
}

/* --------------------------------------------------------------------------
   10. ARABIC (right-to-left) AND THE TWO CHINESE PAGES
   Everything above is already written in logical sides, so the panel, the rows,
   the flag, the rail, the caret and the shortening all mirror themselves the
   moment <html dir="rtl"> is set. Three things are still worth saying plainly.
   -------------------------------------------------------------------------- */
/* (a) The panel needs NO rule here at all, and that is deliberate. It hangs
   from the inline-end edge of the pill (section 3), which in Arabic is the edge
   the text ENDS on, so it opens towards the middle of the screen by itself; and
   on a phone it is pinned 12px from both inline edges. A [dir="rtl"] rule
   written here would out-rank the phone rule and break that width — measured,
   and then removed. This is the whole point of writing in logical sides: the
   correct RTL is the one that needs no patch.
/* (b) Arabic letters join each other and are drawn taller, so these dense rows
   need more leading than the Latin ones. File 003 raises the page line-height;
   the panel rows are tighter than a paragraph and are raised separately. */
html[lang="ar"] .country-option,
html[lang="ar"] .lang-option { line-height: 1.75; }
html[lang="ar"] .geo-group--note { line-height: 1.9; }
html[lang^="zh"] .country-option,
html[lang^="zh"] .lang-option { line-height: 1.6; }
/* (c) Arabic and Chinese have no capitals and no useful letter spacing; file
   003 switches letter-spacing off for both, and the uppercase above simply does
   nothing there — exactly right. */

/* --------------------------------------------------------------------------
   11. PRINTING
   A printed sheet has nothing to choose from, so the widget is removed the same
   way file 003 removes the old language select: whoever prints, gets the page.
   -------------------------------------------------------------------------- */
@media print {
  .geo { display: none !important; }
  .geo-panel { display: none !important; }
}

/* --------------------------------------------------------------------------
   12. LEADER PATCH, session 0097 — two narrow-width compromises.
   MEASURED against the previous build (seeded 1024-1512 px, EN/DE/FR): the pill is
   16-35 px wider than the old <select>. (a) <= 430 px: at 360 px the header wrapped
   (pill 219 + brand 96 + button 44 = 415 of 360) and cost 44 px of the first screen,
   so the pill keeps the globe and the detected flag while the name and the language
   chip go - the panel shows both in full when it opens, and the summary keeps its
   aria-label. (b) <= 1200 px: German and French wrapped at 1152 px, so the chip
   (which repeats what the visitor already sees - the page IS in that language)
   goes and the country name stays; above 1200 px the chip returns.
   Full reasoning: docs/TWSS_Decision_0097_Leader.md. ------------------------ */
@media (max-width: 430px) {
  .geo-summary { padding-inline: 10px 24px; gap: 6px; }
  .geo-current, .geo-current-lang { display: none; }
}
@media (max-width: 1200px) {
  .geo-current-lang { display: none; }
}

/* End of TWSS_styles_004.css — the globe country / language switcher. */
