Material affiche son icône `translate` : un idéogramme 文 collé à un A. Elle dit « traduire », pas « vous êtes en français », et à la taille du bandeau on n'y voit qu'un symbole asiatique — remarque de Patrick, et elle est juste. Le bouton affiche désormais le drapeau de la langue courante et son code, comme sur etm-powersync.fr. Dans la liste déroulante, la langue courante passe en gras et en couleur d'accent : les trois lignes étaient identiques, on ne savait pas d'où l'on partait. Fait entièrement en CSS, sur `html[lang]` que mkdocs-static-i18n pose déjà par locale (`fr` à la racine, `de` sous /de/, `en` sous /en/). Aucun gabarit du thème n'est surchargé : rien à reprendre à chaque mise à jour de Material, et l'icône d'origine est masquée, pas supprimée. Trois points qui ne sont pas des détails : - Les drapeaux sont des SVG en `data:`, pas des emojis — un emoji drapeau ne se rend pas sous Windows, où Chrome affiche « FR » dans un carré. - Chaque drapeau porte un liseré : sans lui la bande blanche du français se perd dans le bandeau clair, et le noir de l'allemand dans le bandeau sombre. - Le `aria-label` du bouton (« Sélectionner la langue ») est inchangé et porte seul le sens pour les lecteurs d'écran ; il l'emporte sur le contenu, donc le « FR » du `::after` ne sera pas annoncé en double. Vérifié avant le push, faute de mkdocs installé en local : les trois pages réellement servies ont été rechargées dans Chrome headless avec cette feuille de style en remplacement, bandeau capturé dans les trois langues, plus la liste déroulante forcée ouverte pour contrôler les drapeaux et la mise en évidence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
170 lines
16 KiB
CSS
170 lines
16 KiB
CSS
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
POLICES AUTO-HÉBERGÉES — IBM Plex (2026-10-13)
|
|
|
|
Material injectait `theme.font: {text, code}`, ce qui ajoutait au <head> un
|
|
preconnect vers fonts.gstatic.com et une feuille depuis fonts.googleapis.com.
|
|
Chaque visite transmettait donc l'IP du visiteur à Google AVANT tout
|
|
consentement — et le site vitrine avait fait exactement l'inverse en T10,
|
|
délibérément, pour cette raison (jurisprudence LG München 2022, doctrine
|
|
CNIL) et pour ne pas contredire « vos données ne sortent pas de chez vous ».
|
|
La doc affichait donc le contraire de l'engagement du produit.
|
|
|
|
`theme.font: false` dans mkdocs.yml supprime les deux balises ; les 16 woff2
|
|
viennent du dépôt du site (mêmes fichiers, mêmes unicode-range, déjà éprouvés
|
|
en production depuis juin).
|
|
|
|
⚠️ LES ITALIQUES SONT SYNTHÉTISÉES. Google servait 4 fontes italiques
|
|
(Sans 300i/400i/700i, Mono 400i) que nous n'avons pas : le navigateur incline
|
|
donc la romaine. C'est visible sur `_Einstellungen:_` et les intertitres en
|
|
italique des blocs générés. Pour y remédier, récupérer les woff2 italiques
|
|
depuis le dépôt officiel IBM/plex (OFL) et ajouter les @font-face
|
|
correspondants — méthode déjà documentée au T10 du site.
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
|
|
:root {
|
|
--md-text-font: "IBM Plex Sans";
|
|
--md-code-font: "IBM Plex Mono";
|
|
}
|
|
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:300;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-ext-300.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-ext-400.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-ext-500.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-ext-600.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:700;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-ext-700.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:300;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-300.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-400.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-500.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-600.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:700;font-display:swap;src:url('../assets/fonts/ibm-plex-sans-latin-700.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url('../assets/fonts/ibm-plex-mono-latin-ext-400.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url('../assets/fonts/ibm-plex-mono-latin-ext-500.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url('../assets/fonts/ibm-plex-mono-latin-ext-600.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
|
|
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url('../assets/fonts/ibm-plex-mono-latin-400.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url('../assets/fonts/ibm-plex-mono-latin-500.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url('../assets/fonts/ibm-plex-mono-latin-600.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
|
|
/* ETM PowerSync — surcharge couleurs de marque sur Material (scheme slate) */
|
|
[data-md-color-scheme="slate"] {
|
|
--md-primary-fg-color: #31a3dd; /* cyan ETM */
|
|
--md-primary-fg-color--light: #5cb8e6;
|
|
--md-primary-fg-color--dark: #2589bd;
|
|
--md-accent-fg-color: #fec113; /* ambre ETM */
|
|
--md-default-bg-color: #0a1f2b;
|
|
--md-default-bg-color--light: #0d2b3b;
|
|
--md-code-bg-color: #06151d;
|
|
--md-footer-bg-color: #0d2b3b;
|
|
}
|
|
[data-md-color-scheme="slate"] .md-typeset a { color: var(--md-primary-fg-color); }
|
|
|
|
/* badges — 3 familles : canal APT · stabilité plugin · maturité fonctionnalité */
|
|
.badge{font-family:"IBM Plex Mono",monospace;font-size:.7rem;letter-spacing:.06em;
|
|
text-transform:uppercase;padding:2px 8px;border-radius:20px;font-weight:600;white-space:nowrap;
|
|
display:inline-block;vertical-align:middle;line-height:1.4}
|
|
|
|
/* canal APT */
|
|
.badge.stable {color:#3fd18a;background:rgba(63,209,138,.12);border:1px solid rgba(63,209,138,.3)}
|
|
.badge.testing {color:#fec113;background:rgba(254,193,19,.1);border:1px solid rgba(254,193,19,.3)}
|
|
.badge.nightly {color:#8fa9b5;background:rgba(143,169,181,.1);border:1px solid rgba(143,169,181,.3)}
|
|
|
|
/* stabilité plugin (meta.json) */
|
|
.badge.consumer {color:#31a3dd;background:rgba(49,163,221,.1);border:1px solid rgba(49,163,221,.3)}
|
|
.badge.community {color:#a78bfa;background:rgba(167,139,250,.1);border:1px solid rgba(167,139,250,.3)}
|
|
.badge.experimental {color:#fb923c;background:rgba(251,146,60,.1);border:1px solid rgba(251,146,60,.3)}
|
|
|
|
/* origine plugin (PORTING_STATUS.repo ou champ origin:) */
|
|
.badge.origin-nymea {color:#94a3b8;background:rgba(148,163,184,.1);border:1px solid rgba(148,163,184,.3)}
|
|
.badge.origin-etm {color:#4ade80;background:rgba(74,222,128,.1);border:1px solid rgba(74,222,128,.3)}
|
|
.badge.origin-tiers {color:#fb923c;background:rgba(251,146,60,.1);border:1px solid rgba(251,146,60,.3)}
|
|
|
|
/* maturité fonctionnalités (à la main) */
|
|
.badge.ok {color:#3fd18a;background:rgba(63,209,138,.12);border:1px solid rgba(63,209,138,.3)}
|
|
.badge.part {color:#fec113;background:rgba(254,193,19,.1);border:1px solid rgba(254,193,19,.3)}
|
|
.badge.road {color:#8fa9b5;background:rgba(143,169,181,.1);border:1px solid rgba(143,169,181,.3)}
|
|
|
|
/* permission scope badges (API JsonRPC) */
|
|
.badge.perm-none {color:#3fd18a;background:rgba(63,209,138,.12);border:1px solid rgba(63,209,138,.3)}
|
|
.badge.perm-control {color:#fec113;background:rgba(254,193,19,.1);border:1px solid rgba(254,193,19,.3)}
|
|
.badge.perm-configure {color:#fb923c;background:rgba(251,146,60,.1);border:1px solid rgba(251,146,60,.3)}
|
|
.badge.perm-admin {color:#ef4444;background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.3)}
|
|
.badge.perm-unknown {color:#94a3b8;background:rgba(148,163,184,.1);border:1px solid rgba(148,163,184,.3)}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
SÉLECTEUR DE LANGUE — drapeaux (2026-10-13)
|
|
|
|
Material rend son sélecteur en liste déroulante, chaque entrée portant un
|
|
`hreflang` : on l'habille en CSS, sans toucher au gabarit du thème.
|
|
|
|
Drapeaux en SVG inline (data-URI) et NON en emoji : 🇫🇷 ne s'affiche pas sous
|
|
Windows, où Chrome rend « FR » dans un carré faute de police de drapeaux.
|
|
Le NOM de la langue reste affiché à côté — un drapeau désigne un pays, pas
|
|
une langue, et l'anglais ici sert les deux marchés plus la communauté.
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
.md-select__link[hreflang]{display:flex;align-items:center;gap:.6rem}
|
|
.md-select__link[hreflang]::before{content:"";width:1.25em;height:.9em;flex:none;
|
|
background-size:cover;background-position:center;border-radius:1px;
|
|
box-shadow:0 0 0 1px rgba(255,255,255,.22)}
|
|
.md-select__link[hreflang="fr"]::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Crect width='3' height='2' fill='%23ED2939'/%3E%3Crect width='2' height='2' fill='%23FFFFFF'/%3E%3Crect width='1' height='2' fill='%23002395'/%3E%3C/svg%3E")}
|
|
.md-select__link[hreflang="de"]::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 3'%3E%3Crect width='5' height='3' fill='%23FFCE00'/%3E%3Crect width='5' height='2' fill='%23DD0000'/%3E%3Crect width='5' height='1' fill='%23000000'/%3E%3C/svg%3E")}
|
|
.md-select__link[hreflang="en"]::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 30'%3E%3Crect width='60' height='30' fill='%23012169'/%3E%3Cpath d='M0,0 60,30M60,0 0,30' stroke='%23FFFFFF' stroke-width='6'/%3E%3Cpath d='M0,0 60,30M60,0 0,30' stroke='%23C8102E' stroke-width='4'/%3E%3Cpath d='M30,0v30M0,15h60' stroke='%23FFFFFF' stroke-width='10'/%3E%3Cpath d='M30,0v30M0,15h60' stroke='%23C8102E' stroke-width='6'/%3E%3C/svg%3E")}
|
|
|
|
/* ──────────────────────────────────────────────────────────────────────────
|
|
LE BOUTON DU SÉLECTEUR — drapeau de la langue courante (2026-10-15)
|
|
|
|
Material affiche son icône `translate` : un idéogramme 文 collé à un A. Elle
|
|
dit « traduire », pas « vous êtes en français », et à la taille du bandeau on
|
|
ne la lit pas — on y voit un symbole asiatique. Remplacée par le drapeau de la
|
|
langue courante plus son code, exactement comme sur etm-powersync.fr.
|
|
|
|
Le drapeau se choisit sur `html[lang]`, que mkdocs-static-i18n pose déjà par
|
|
locale (`fr` à la racine, `de` sous /de/, `en` sous /en/) : aucun gabarit du
|
|
thème n'est surchargé, rien à maintenir à chaque mise à jour de Material.
|
|
|
|
Le `aria-label` du bouton (« Sélectionner la langue ») est inchangé et porte
|
|
seul le sens pour les lecteurs d'écran : il l'emporte sur le contenu, donc le
|
|
« FR » décoratif du ::after n'est pas annoncé deux fois.
|
|
────────────────────────────────────────────────────────────────────────── */
|
|
.md-header__option{margin-right:.2rem}
|
|
|
|
.md-header__option .md-select>.md-header__button{
|
|
display:flex;align-items:center;gap:.34rem;
|
|
width:auto;padding:.28rem .42rem;margin:.1rem;
|
|
border-radius:.15rem;opacity:1;
|
|
transition:background-color .2s;
|
|
}
|
|
.md-header__option .md-select>.md-header__button:hover{background:rgba(255,255,255,.1)}
|
|
/* l'icône `translate` du thème : on la masque, on ne la supprime pas */
|
|
.md-header__option .md-select>.md-header__button>svg{display:none}
|
|
|
|
.md-header__option .md-select>.md-header__button::before{
|
|
content:"";flex:none;width:1.3rem;height:.92rem;border-radius:2px;
|
|
background-size:cover;background-position:center;
|
|
/* liseré : sans lui, la bande blanche du drapeau français se perd dans le
|
|
bandeau clair, et le noir du drapeau allemand dans le bandeau sombre */
|
|
box-shadow:0 0 0 1px rgba(255,255,255,.45);
|
|
}
|
|
.md-header__option .md-select>.md-header__button::after{
|
|
font-family:var(--md-code-font-family,monospace);
|
|
font-size:.62rem;font-weight:700;letter-spacing:.08em;line-height:1;
|
|
}
|
|
|
|
html[lang="fr"] .md-header__option .md-select>.md-header__button::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Crect width='3' height='2' fill='%23ED2939'/%3E%3Crect width='2' height='2' fill='%23FFFFFF'/%3E%3Crect width='1' height='2' fill='%23002395'/%3E%3C/svg%3E")}
|
|
html[lang="de"] .md-header__option .md-select>.md-header__button::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 3'%3E%3Crect width='5' height='3' fill='%23FFCE00'/%3E%3Crect width='5' height='2' fill='%23DD0000'/%3E%3Crect width='5' height='1' fill='%23000000'/%3E%3C/svg%3E")}
|
|
html[lang="en"] .md-header__option .md-select>.md-header__button::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 30'%3E%3Crect width='60' height='30' fill='%23012169'/%3E%3Cpath d='M0,0 60,30M60,0 0,30' stroke='%23FFFFFF' stroke-width='6'/%3E%3Cpath d='M0,0 60,30M60,0 0,30' stroke='%23C8102E' stroke-width='4'/%3E%3Cpath d='M30,0v30M0,15h60' stroke='%23FFFFFF' stroke-width='10'/%3E%3Cpath d='M30,0v30M0,15h60' stroke='%23C8102E' stroke-width='6'/%3E%3C/svg%3E")}
|
|
html[lang="fr"] .md-header__option .md-select>.md-header__button::after{content:"FR"}
|
|
html[lang="de"] .md-header__option .md-select>.md-header__button::after{content:"DE"}
|
|
html[lang="en"] .md-header__option .md-select>.md-header__button::after{content:"EN"}
|
|
|
|
/* dans la liste déroulante, la langue courante se distingue des deux autres :
|
|
sinon les trois lignes sont identiques et on ne sait pas d'où l'on part */
|
|
html[lang="fr"] .md-select__link[hreflang="fr"],
|
|
html[lang="de"] .md-select__link[hreflang="de"],
|
|
html[lang="en"] .md-select__link[hreflang="en"]{font-weight:700;color:var(--md-accent-fg-color)}
|
|
/* les deux langues non courantes : drapeau légèrement en retrait, il reprend
|
|
ses couleurs au survol — même convention que sur le site */
|
|
.md-select__link[hreflang]::before{opacity:.65;transition:opacity .2s}
|
|
.md-select__link[hreflang]:hover::before,
|
|
html[lang="fr"] .md-select__link[hreflang="fr"]::before,
|
|
html[lang="de"] .md-select__link[hreflang="de"]::before,
|
|
html[lang="en"] .md-select__link[hreflang="en"]::before{opacity:1}
|