<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr"><title>Sam Candy</title><subtitle>Technologies, web, tentatives musicales et autres tergiversations</subtitle><link rel="self" type="application/atom+xml" href="https://sam.candy.pm/atom.xml"/><link rel="alternate" type="text/html" href="https://sam.candy.pm"/><generator uri="https://www.getzola.org/">Zola</generator><updated>2025-04-25T00:00:00+00:00</updated><id>https://sam.candy.pm/atom.xml</id><entry xml:lang="fr"><title>Le cluster Kubernetes gratuit, c'est fini !</title><published>2025-04-25T00:00:00+00:00</published><updated>2025-04-25T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-fin-mars-2025/"/><id>https://sam.candy.pm/articles/cluster-kubernetes-gratuit-fin-mars-2025/</id><content type="html" xml:base="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-fin-mars-2025/">&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Cet article est la suite de &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-avril-2024/"&gt;celui où je créais mon cluster Kubernetes gratuit chez Oracle&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Pour rappel, le cluster Kubernetes dont je parle tourne chez Oracle Cloud Infrastructure et ne me coûte strictement rien.&lt;/p&gt;
&lt;h2 id="un-petit-retour-sur-les-mises-a-jour-de-kubernetes"&gt;Un petit retour sur les mises à jour de Kubernetes&lt;/h2&gt;
&lt;p&gt;Du peu que je l'ai utilisé, Oracle Cloud Infrastructure (que je vais abbréger OCI) est plutôt aligné avec les autres gros fournisseurs cloud américains. En terme d'utilisation en tout cas.&lt;/p&gt;
&lt;p&gt;Mais le cluster Kubernetes était compliqué à mettre à jour : il faut mettre à jour le cluster, puis les groupes de nœuds. Ça aurait pu être facile si le groupe de nœud se mettait vraiment à jour mais il reste bloqué.&lt;/p&gt;
&lt;p&gt;En version gratuite, on n'a pas le choix d'utiliser une mise à jour "rolling" : un nouveau nœud démarre avant qu'un ancien nœud ne s'éteigne, et ainsi de suite jusqu'à ce que je tous les nœuds soient à jour.
Jusque là, rien de bien original ni complexe, c'est plutôt bien.&lt;/p&gt;
&lt;p&gt;Sauf qu'avec les restrictions de stockage offert (donc si on ne veut pas payer), impossible de démarrer un nouveau nœud.&lt;/p&gt;
&lt;p&gt;Deux solutions possibles : réduire le nombre de nœuds désirés (et donc la puissance totale du cluster) pour faire la mise à jour, ou bien détruire et recréer le groupe de nœuds.&lt;/p&gt;
&lt;p&gt;Vu que j'ai tout gérer en infrastructure as code, j'ai choisi de détruire et recréer le groupe de nœuds mais il faut accepter un downtime pendant la mise à jour du coup.&lt;/p&gt;
&lt;p&gt;Bref, pas un retour très bloquant mais il faut le savoir. Et de toute façon, je supprime ce cluster.&lt;/p&gt;
&lt;h2 id="pourquoi-je-supprime-mon-cluster"&gt;Pourquoi je supprime mon cluster&lt;/h2&gt;
&lt;p&gt;J'ai deux raisons d'arrêter l'utilisation de ce cluster.&lt;/p&gt;
&lt;p&gt;La première, c'est que le projet pour lequel je l'utilisais est dormant. Ce sont des choses qui arrivent, j'ai dû prioriser pas mal d'autres sujets et aussi prendre du temps pour moi, ce n'est que partie remise.&lt;/p&gt;
&lt;p&gt;La seconde, c'est parce que je souhaitais supprimer mon compte OCI suite aux prises de position du patron d'Oracle.&lt;/p&gt;
&lt;p&gt;Utiliser les fournisseurs cloud américains ou non, c'est déjà financer des grandes fortunes. Ça, on y échappe difficilement.&lt;/p&gt;
&lt;p&gt;Mais Larry Ellison, le président exécuif d'Oracle, a clairement indiqué qu'il souhaitait utiliser la surveillance de masse et l'intelligence artificielle. Sa vision "utopique" (de son point de vue) est que si tout le monde est surveillé, plus personne ne commet de crimes.&lt;/p&gt;
&lt;p&gt;Pour information, voici quelques sources au hasard sur ce qu'il a dit :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://kulturegeek.fr/news-317030/1984-larry-ellison-cofondateur-doracle-plaide-monde-constamment-surveille-ia"&gt;Kulture Geek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.404media.co/larry-ellisons-ai-powered-surveillance-dystopia-is-already-here/"&gt;404 media (lien en anglais)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://arstechnica.com/information-technology/2024/09/omnipresent-ai-cameras-will-ensure-good-behavior-says-larry-ellison/"&gt;Ars Technica (lien en anglais)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Au passage, il a soutenu Donald Trump lors de sa campagne, bref rien de bien original mais c'est assez pour faire un boycott au moins pour tout ce qui est personnel. J'aurai sûrement plus de mal si c'était un·e client·e qui l'utilisait (de toute façon, ma clientèle préfère les trois grands fournisseurs américains dont on sait que les patrons apprécient bien assez Trump, j'aimerais bien retrouver des client·e·s qui accepteraient d'utiliser un cloud européen comme j'ai pu en avoir par le passé).&lt;/p&gt;
&lt;p&gt;Voilà donc pourquoi je supprime ce cluster Kubernetes !&lt;/p&gt;
&lt;h2 id="une-suite"&gt;Une suite ?&lt;/h2&gt;
&lt;p&gt;J'ai par contre décidé de faire un peu plus d'auto-hébergement donc je pense que bientôt je vais parler de mon "homelab" (j'aime pas les anglicismes mais je ne trouve pas d'équivalent français, "labo à la maison" ça me semble pas aussi expressif). Il est en cours d'évolution (à ce stade je crois que je peux parler de révolution) pour accueillir un peu plus de charge, j'espère arriver à en faire un petite série d'articles "sympas" !&lt;/p&gt;</content></entry><entry xml:lang="fr"><title>"Homelab", un serveur à la maison : introduction</title><published>2025-03-05T00:00:00+00:00</published><updated>2025-03-05T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/homelab-partie-1/"/><id>https://sam.candy.pm/articles/homelab-partie-1/</id><content type="html" xml:base="https://sam.candy.pm/articles/homelab-partie-1/">&lt;p&gt;Je sais que je devrais &lt;a href="https://sam.candy.pm/articles/homelab-partie-1/@./2024-02-25_amelioration-trepied-didgeridoo-partie-1.md"&gt;terminer mon trépied pour mon didgeridoo&lt;/a&gt; (et promis : ça viendra, si possible avant que la première partie fête son anniversaire) mais j'ai été alpagué·e sur d'autres sujets, incluant celui dont je vais parler aujourd'hui.&lt;/p&gt;
&lt;p&gt;Voyons cet article comme une introduction sur le sujet d'un "homelab", terme utilisé pour parler d'un ou plusieurs serveur(s) qu'on a chez soi généralement dans le but de faire des tests de technologies ou autre.&lt;/p&gt;
&lt;h2 id="avant-propos"&gt;Avant-propos&lt;/h2&gt;
&lt;p&gt;Dans cette introduction, je vais évoquer pourquoi je souhaite avoir mon serveur à la maison et quelles sont mes contraintes matérielles et logicielles. D'autres articles suivront, le plan est encore indéfini mais je divulgâche un peu : j'ai fait deux itérations.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Au début j'ai commencé par écrire un article qui s'est étendu et devenait très long, en plus de ne pas contenir tout ce que je souhaitais raconter sur ce sujet. Alors j'ai tenté de le résumer et ça devenait désagréable à lire. Du coup je me suis dit qu'il vaudrait mieux découper tout ça en plusieurs parties plus courtes à lire et donc, voilà l'introduction.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Je ne sais pas combien de parties il y aura : j'ai fait deux itérations mais je me sens déjà obligé·e de faire une introduction à part entière (commune aux itérations donc). Il y aura probablement un article sur les réflexions que la première itération ont amené, en plus d'un part itération et probablement un ou deux autres sur des sujets plus globaux.&lt;/p&gt;
&lt;p&gt;Bref, il faut s'attendre à un peu de lecture ! Mais je vais tenter de découper les articles pour les rendre indépendants afin de permettre un peu de liberté aux personnes qui s'intéressent éventuellement à un sujet mais pas au reste.&lt;/p&gt;
&lt;h3 id="historique"&gt;Historique&lt;/h3&gt;
&lt;p&gt;Quand je vivais en appartement, j'avais mis en place un serveur sur un vieux PC portable avec un Core i7 Ivy Bridge (donc un processeur qui datait de 2012) et 8Go de RAM. Bien assez pour ce que j'en faisais : un serveur domotique et multimédia.&lt;/p&gt;
&lt;p&gt;Au déménagement, je l'ai décommissionné (traduction : « débranché puis jamais rebranché ») car on allait faire des travaux dans notre maison et je me rendais bien compte que je ne le gérais pas très bien en terme de mises à jour (il était sous Debian 9 si je me souviens bien, Debian 11 existait au moment où je l'ai débranché) et qu'il prenait une certaine place là où je pouvais le mettre.&lt;/p&gt;
&lt;aside class="note" data-type="Anecdote"&gt;
&lt;p&gt;J'ai quand même fini par le formater peu après notre arrivée à la maison pour y installer &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://boinc.berkeley.edu/"&gt;BOINC (lien en anglais)&lt;/a&gt; et faire tourner des calculs tout en chauffant un peu une petite pièce.&lt;/p&gt;
&lt;p&gt;Je peux d'ailleurs affirmer que même à 100% de CPU, un vieux Core i7 de 2012 chauffe mais pas assez pour servir de vrai chauffage. Il a dû me coûter aussi cher en électricité que les vieux radiateurs « grille-pains » qu'il y avait encore à ce moment dans la maison.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;D'un autre côté, j'avais une petite machine virtuelle chez un fournisseur cloud français qui hébergeait un serveur Nextcloud. Devinez quoi : 10€ par mois, tout sur le même serveur (PHP, MySQL et Redis) et, soyons honnête, peu de maintenance de ma part. C'était pas terrible mais ce temps est révolu !&lt;/p&gt;
&lt;p&gt;Pour cette machine virtuelle, j'avais quand même automatisé des sauvegardes sur un "object storage" type S3, c'était le minimum pour ne pas perdre mes contacts et mes calendriers.&lt;/p&gt;
&lt;h2 id="les-besoins"&gt;Les besoins&lt;/h2&gt;
&lt;p&gt;Cette liste n'est pas exhaustive et contient l'essentiel des mes besoins au moment de la création de mon homelab.&lt;/p&gt;
&lt;h3 id="domotique"&gt;Domotique&lt;/h3&gt;
&lt;p&gt;Sur mon ancien serveur à la maison, je faisais fonctionner &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.home-assistant.io/"&gt;Home Assistant (lien en anglais)&lt;/a&gt;. Dans l'appartement, ça me servait surtout à collecter des informations sur la température et l'humidité de la cuisine, du salon et de la salle de bain, ainsi que l'ouverture de la porte (étant au deuxième étage, les fenêtres avaient peu de chances d'être le point d'entrée pour un cambriolage). J'avais bien quelques idées supplémentaires mais je n'ai jamais pris le temps de les mettre à exécution.&lt;/p&gt;
&lt;p&gt;Dans la maison, j'aimerais surveiller ces paramètres et quelques autres choses : notre consommation d'électricité et notre production solaire (on a une petite production, sans batterie). Éventuellement, j'aimerais automatiser quelques petits trucs mais c'est encore ne réflexion.&lt;/p&gt;
&lt;p&gt;Bref, j'aimais bien mon serveur domotique et j'aimerais recommencer, en mieux !&lt;/p&gt;
&lt;h3 id="contacts-et-calendriers"&gt;Contacts et calendriers&lt;/h3&gt;
&lt;p&gt;Évidemment, le fameux Nextcloud précédemment cité, il était temps que je le migre autre part. Le but étant de ne plus payer un hébergeur, puisque je l'aurais chez moi, et de me motiver pour le maintenir (en voyant le serveur sous mes yeux, je me souviendrai facilement qu'il existe et qu'il faut le gérer).&lt;/p&gt;
&lt;p&gt;Je n'utilise pas tant Nextcloud pour les fichiers, c'est surtout pour les contacts et calendriers. Je le synchronise en CardDAV et CalDAV sur mes appareils (Linux et Android), ça me va bien comme système.&lt;/p&gt;
&lt;p&gt;J'aimerais avoir un peu "mieux" que Nextcloud pour faire ça, notamment plus léger, mais je ne trouve rien qui a le côté pratique de l'interface Nextcloud, pour envoyer des invitations par exemple. Et j'ai une autre contrainte qui arrive et à laquelle Nextcloud se plie sans problème.&lt;/p&gt;
&lt;h3 id="sso"&gt;SSO&lt;/h3&gt;
&lt;p&gt;Cette contrainte, c'est pour ma facilité : j'aimerais me connecter via un seul portail à toutes mes applications. Et Nextcloud est compatible avec &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://openid.net/"&gt;OpenID Connect (lien en anglais)&lt;/a&gt; notamment.&lt;/p&gt;
&lt;p&gt;Bon, Home Assistant ne l'est pas donc il me restera un compte à part pour ça, mais est-ce grave ?&lt;/p&gt;
&lt;h3 id="galerie-photos"&gt;Galerie photos&lt;/h3&gt;
&lt;p&gt;Je souhaite pouvoir téléverser automatiquement mes photos depuis mon mobile vers un serveur qui me permettrait de faire des albums par exemple.&lt;/p&gt;
&lt;p&gt;La référence dans ce domaine, pour l'instant, semble être &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://immich.app/"&gt;Immich (lien en anglais)&lt;/a&gt; mais j'ai vite constaté (en essayant de le démarrer lors de ma première itération) que ça prenait beaucoup de ressources que je n'avais pas.&lt;/p&gt;
&lt;p&gt;Bref, grâce à &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://meichthys.github.io/foss_photo_libraries/"&gt;ce chouette comparatif (lien en anglais)&lt;/a&gt;, j'ai décidé d'utiliser Nextcloud Memories, comme ça Nextcloud gagnerait en utilité. Mais on verra plus tard que ce n'était pas gagné non plus.&lt;/p&gt;
&lt;h2 id="mes-contraintes"&gt;Mes contraintes&lt;/h2&gt;
&lt;p&gt;On pourrait croire que la réponse à tout ça c'est « Installe Debian sur un vieux PC, comme tu l'avais déjà fait, et puis tu mets tous tes trucs dessus, voilà ! », sauf que ce serait mal me connaître.&lt;/p&gt;
&lt;h3 id="mises-a-jours-automatiques-ou-presque"&gt;Mises à jours automatiques (ou presque)&lt;/h3&gt;
&lt;p&gt;Un point sur lequel j'ai de plus en plus de mal à déroger : je ne veux pas avoir à trop « penser » à la maintenance. Je sais qu'il y en aura mais justement, plus elle peut être minimale, mieux c'est.&lt;/p&gt;
&lt;p&gt;Et maintenant, on a plusieurs OS (côté serveur comme côté bureau) qui répondent à ce besoin d'une belle manière : une fois installé, le système se met à jour automatiquement de manière régulière et il n'y a qu'à le redémarrer pour avoir la dernière version.
Mieux encore, sur les OS modernes, les mises à jour sont transactionnelles, ou « atomiques » : le système revient à la précédente version installée si la nouvelle ne fonctionne pas.&lt;/p&gt;
&lt;p&gt;Dans la théorie, cela réduit la maintenance à… Peu de choses.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Je sais qu'on peut installer le fameux &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://wiki.debian.org/fr/unattended-upgrades"&gt;Unattended Upgrades&lt;/a&gt; sur Debian mais les mises à jours majeures ne sont pas gérées et globalement Debian n'est pas "pensé" pour être un système qui se met à jour automatiquement.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="kubernetes"&gt;Kubernetes&lt;/h3&gt;
&lt;p&gt;Je fais partie des gens qui remarquent que Kubernetes résout beaucoup de problèmes. Et comme je l'utilise tous les jours chez la clientèle, autant garder les bonnes habitudes. Ce sujet mériterait un article à lui tout seul d'ailleurs. En plus, avec &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://k3s.io/"&gt;k3s (lien en anglais)&lt;/a&gt;, ça s'installe à peu près n'importe où, alors pourquoi se priver ?&lt;/p&gt;
&lt;p&gt;Ça veut aussi dire que je vais devoir mettre sur Kubernetes des choses qui ne sont pas forcément prévues pour à l'origine, comme Home Assistant justement. Bon, ça ne me fait pas peur (et d'ailleurs, ça fonctionne parfaitement à l'heure où j'écris ces lignes).&lt;/p&gt;
&lt;p&gt;Aussi, j'utilise beaucoup les outils GitOps comme &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://argoproj.github.io/cd/"&gt;ArgoCD (lien en anglais)&lt;/a&gt; ou &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://fluxcd.io/"&gt;FluxCD (lien en anglais)&lt;/a&gt;, ça fait partie de mon utilisation de Kubernetes et des choses que je trouve vraiment pratiques.&lt;/p&gt;
&lt;h3 id="consommation-et-silence"&gt;Consommation et silence&lt;/h3&gt;
&lt;p&gt;Mon précédent serveur ventilait pas mal quand même, la faute à l'espace où il était un peu confiné. Et un Core i7 de Ivy Bridge, même pour PC portable, on dirait pas mais ça consomme.&lt;/p&gt;
&lt;p&gt;Bref, au moment de m'y mettre on était en 2024 donc c'était déjà le bon moment pour utiliser un ordinateur à l'architecture aarch64 (ou arm64 selon comment vous l'écrivez) et sans ventilateur. Ça veut dire : non merci pour le Raspberry Pi 5 qui a besoin d'un refroidissement actif.&lt;/p&gt;
&lt;h3 id="stockage"&gt;Stockage&lt;/h3&gt;
&lt;p&gt;Généralement, les PC en aarch64 utilisent une carte SD et éventuellement une puce eMMC pour le stockage mais en terme de performance et de capacité, c'est rarement très élevé.&lt;/p&gt;
&lt;p&gt;Je souhaite donc avoir la possibilité de mettre un SSD supplémentaire pour les données. Idéalement NVMe plutôt que SATA, ça permet de ne pas avoir un câble (même petit) qui traînerait et de garder le boîtier d'origine de l'ordinateur s'il en existe un.&lt;/p&gt;
&lt;h2 id="et-la-suite"&gt;Et la suite ?&lt;/h2&gt;
&lt;p&gt;Au moment où je publie cet article, j'ai déjà choisi du matériel et presque arrêté mon choix sur le système d'exploitation. Par la suite je vais donc parler :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;De ma première itération à ce sujet, notamment :
&lt;ol&gt;
&lt;li&gt;Le matériel que j'ai choisi ainsi que l'OS.&lt;/li&gt;
&lt;li&gt;Ma manière de gérer les logiciels que j'installe.&lt;/li&gt;
&lt;li&gt;Probablement, la gestion de l'image Nextcloud que j'utilise, car tout n'est pas automatique.&lt;/li&gt;
&lt;li&gt;Les réflexions que m'ont apporté&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;De ma seconde itération, incluant :
&lt;ol&gt;
&lt;li&gt;Le matériel qui me permet de faire mieux que la première fois.&lt;/li&gt;
&lt;li&gt;Le système d'exploitation (c'est un sujet en cours, même une certaine aventure).&lt;/li&gt;
&lt;li&gt;Des évolutions sur la gestion des logiciels, si je décide de faire les évolutions que j'imagine.&lt;/li&gt;
&lt;li&gt;Des sauvegardes, parce que ma première itération n'est pas très fiable pour ça.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Je rappel que le plan n'est pas forcément définitif mais il y aura de quoi raconter ! &lt;span class="emoji" aria-hidden="true"&gt;😃&lt;/span&gt;
&lt;/p&gt;</content></entry><entry xml:lang="fr"><title>Nouveau didgeridoo</title><published>2024-11-10T00:00:00+00:00</published><updated>2024-11-10T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/experiences-sonores/2024-11-10/"/><id>https://sam.candy.pm/experiences-sonores/2024-11-10/</id><content type="html" xml:base="https://sam.candy.pm/experiences-sonores/2024-11-10/">
&lt;div class="widgets-grid" data-max-columns="2"&gt;
&lt;div class="widget"&gt;
&lt;h2 id="instrument-et-materiel-utilises"&gt;Instrument et matériel utilisés&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dideridoo « HexSpira Amplitude » en La ;&lt;/li&gt;
&lt;li&gt;Microphone Shure SM57 ;&lt;/li&gt;
&lt;li&gt;Loopstation Boss RC-202.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="widget"&gt;
&lt;h2 id="formats-et-qualite-des-fichiers"&gt;Formats et qualité des fichiers&lt;/h2&gt;
&lt;p&gt;Tous les fichiers sont au format FLAC, en échantillonnage de 44100Hz sur une profondeur de 16 bits. Il n'y a pas de stéréophonie, tout est en mono.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;J'ai produit moins de son que lors de mes &lt;a href="https://sam.candy.pm/experiences-sonores/2024-02-03/"&gt;premières expériences sonores&lt;/a&gt; mais c'était surtout pour jouer avec le « petit nouveau » que j'ai acheté &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.hexspira.fr/"&gt;à Colas&lt;/a&gt;. Bon, ce n'est pas la première fois que je soufflais dedans mais j'avais envie de l'enregistrer un peu, pour mon plaisir.&lt;/p&gt;
&lt;p&gt;Je n'ai activé aucun effet sur la loopstation, j'ai juste rajouté du gain au « mixage » avant d'exporter les fichiers (je mets des guillemets parce qu'à mon niveau, je sais juste couper des pistes sonores et appliquer quelques effets, ce qui me suffit amplement).&lt;/p&gt;
&lt;p&gt;J'ai commencé par un traditionnel « échauffement ». Enfin, c'était plus long que ça mais j'ai exporté seulement une trentaine de secondes parce que pour le reste, c'est pas terrible. &lt;span class="emoji" aria-hidden="true"&gt;😅&lt;/span&gt;
&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-11-10&amp;#x2F;01_echauffement.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;J&amp;#x27;adore cette note bien grave, ça m&amp;#x27;ancre au sol.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Ensuite, j'ai joué en champ libre, sans ajouter de rythme à la loopstation.&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-11-10&amp;#x2F;02_mono-instrumental.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Ça s&amp;#x27;est terminé sur une faute de souffle !&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Après, j'ai enregistré un tout petit rythme dans la RC-202 (la loopstation). Comme je le fais à traver le didgeridoo il y a une légère résonance.&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-11-10&amp;#x2F;03_resume.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;La version « résumée ».&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-11-10&amp;#x2F;04_version-longue.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Et la version longue.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Et j'ai terminé par l'enregistrement d'un autre rythme (toujours au travers du didgeridoo) et un jeu un peu expérimental.&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-11-10&amp;#x2F;05_sortons-de-la.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;C&amp;#x27;est pas parfait mais l&amp;#x27;idée globale de cet extrait me satisfait.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Quelles conclusions pour ce nouvel essai ?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Avoir un micro dédié pour le beatbox, je pense me commander un AKG D5 d'occasion ;&lt;/li&gt;
&lt;li&gt;Changer le micro du didgeridoo car je trouve que le Shure SM57 rend pas forcément bien (notamment le « grain » du didgeridoo me semble sous-représenté), j'aimerais trouver un Audix i5 d'occasion mais ça part vite ;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Bref, de l'investissement peut-être. &lt;span class="emoji" aria-hidden="true"&gt;💸&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Aussi, j'aimerais finir les modification de mon trépied pour utiliser les deux didgeridoos en même temps (il me faudra donc forcément un deuxième microphone).&lt;/p&gt;
&lt;p&gt;Je me rends compte que pour ce genre de tentatives, les deux pistes de la RC-202 sont très convenables, c'est juste limitant quand on veut faire quelques chose de plus long avec un changement de rythme, ou encore qu'on veut pouvoir activer et désactiver des parcelles du rythmes.&lt;/p&gt;
&lt;p&gt;Par ailleurs, je ne les ai pas uploadés mais j'avais fait quelques essais de kick au pied (je parlais de stompbox lors de mon dernier essai mais en fait, j'ai une pédale pour ma loopstation donc je peux l'utiliser comme kick en enregistrant un son au beatbox sur la loopstation et en le lançant en « one shot » plutôt qu'en boucle) : c'est intéressant et je veux creuser un peu pour voir si j'arrive à en faire quelque chose.&lt;/p&gt;
&lt;p&gt;Le temps manque encore, toujours dans les travaux (les finitions, ça prend un temps très long) mais j'aimerais vraiment faire plus d'expériences musicales ! &lt;span class="emoji" aria-hidden="true"&gt;🤞&lt;/span&gt;
&lt;/p&gt;</content></entry><entry xml:lang="fr"><title>Comment va mon cluster Kubernetes gratuit ?</title><published>2024-05-05T00:00:00+00:00</published><updated>2024-05-05T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/"/><id>https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/</id><content type="html" xml:base="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/">&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Cet article est la suite de &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-avril-2024/"&gt;celui où je créais mon cluster Kubernetes gratuit chez Oracle&lt;/a&gt; et est suivi de &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-fin-mars-2025/"&gt;celui où j'explique pourquoi j'arrête d'utiliser ce cluster gratuit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Je rappelle qu'aux moments où j'écris ces lignes et je publie cet article, je n'ai aucune affiliation avec Oracle (ni Kubernetes d'ailleurs, ni tout autre produit que je cite).
Je ne gagne donc rien à parler de tout ça, si ce n'est le plaisir de partager le « bon plan » qui permet d'avoir des ressources gratuites.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id="avis-sur-oracle-cloud"&gt;Avis sur Oracle Cloud&lt;/h2&gt;
&lt;p&gt;Cette première partie est un peu auxiliaire mais n'ayant jamais utilisé Oracle Cloud Infrastructure, je me dis que c'est le moment de rédiger un avis.
Si cette partie ne vous intéresse pas, il est tout à fait possible &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/#gratuit-vraiment"&gt;d'aller directement à la prochaine partie&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pour information, je précise où je me place, j'ai déjà utilisé (pour mon compte ou pour la clientèle) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Amazon Web Services ;&lt;/li&gt;
&lt;li&gt;Microsoft Azure ;&lt;/li&gt;
&lt;li&gt;Google Cloud Platform, dans une moindre mesure ;&lt;/li&gt;
&lt;li&gt;Orange Flexible Engine, qui se base sur la plateforme développée par Huawei et qui n'est franchement pas terrible ;&lt;/li&gt;
&lt;li&gt;Scaleway ;&lt;/li&gt;
&lt;li&gt;OVH ;&lt;/li&gt;
&lt;li&gt;Hetzner ;&lt;/li&gt;
&lt;li&gt;Exoscale, de manière très succinte ;&lt;/li&gt;
&lt;li&gt;OpenStack chez Infomaniak, juste pour de l'object storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il me surprend que la liste soit si longue, certes en comptant les utilisations « moindres ».
Un de ces jours, il faudrait vraiment que je fasse un comparatif entre OVH et Scaleway, il y a des choses à raconter ! &lt;span class="emoji" aria-hidden="true"&gt;🤔&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Déjà, j'apprécie beaucoup &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.oracle.com/fr/cloud/free/"&gt;la page de &lt;em&gt;free tier&lt;/em&gt;&lt;/a&gt; qui est très précise.
Pour les besoins au delà, il y a &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.oracle.com/fr/cloud/costestimator.html"&gt;un calculateur&lt;/a&gt; comme chez les « grands fournisseurs » cloud (et son ergonomie est discutable mais je n'ai jamais trouvé de calculateur de coûts qui me sied parfaitement chez les fournisseurs, c'est déjà bien quand ça existe).&lt;/p&gt;
&lt;p&gt;J'ai uniquement utilisé le module Opentofu/Terraform qui m'intéressait, il est plutôt bien si on exclue le besoin de faire le &lt;code&gt;tofu apply&lt;/code&gt; en plusieurs fois (je l'avais évoqué &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-avril-2024/"&gt;dans mon précédent article&lt;/a&gt;).&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Devrais-je ouvrir un ticket pour ce problème ? Sûrement.
Vais-je le faire ? Je ne pense pas.&lt;/p&gt;
&lt;p&gt;Je n'ai pas l'énergie pour faire un ticket complet (ce qui me paraît être le minimum quand on déclare un bug) et le dernier auquel j'ai participé sur Github a pris une tournure qui me déplaisait donc je n'ai pas envie de prendre le risque d'avoir encore une discussion négative.&lt;/p&gt;
&lt;p&gt;Peut-être que je devrais faire un article sur l'ouverture de tickets sur des projets open source, un de ces jours ? &lt;span class="emoji" aria-hidden="true"&gt;👀&lt;/span&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Le nombre de services a l'air intéressant, pas aussi grand que chez AWS ou Azure mais il y en a suffisamment pour couvrir tous les besoins de base et même un peu plus.&lt;/p&gt;
&lt;h3 id="l-interface-web"&gt;L'interface web&lt;/h3&gt;
&lt;p&gt;J'ai navigué un peu sur l'interface web d'Oracle Cloud (que j'appellerai aussi « console ») pour observer un peu les ressources qui étaient créées et chercher quelques informations sur mon utilisation des crédits offerts.
Je n'ai initié la création d'aucune ressource via ce portail, j'ai uniquement utilisé OpenTofu pour ça.&lt;/p&gt;
&lt;p&gt;Avant de parler d'ergonomie, je note que le « style » est basique. Pas très beau mais pas spécialement laid. Oui, c'est un avis un peu nul.
Je dirais que ça ressemble à la console d'AWS en 2018, donc un peu austère et « vieillot », mais sans les dégradés de gris qui laissaient croire (à l'époque) à un retard de 10 ans chez la direction artistique.&lt;/p&gt;
&lt;p&gt;Mais le vrai problème des console des fournisseurs cloud, ce n'est pas d'avoir de jolies couleurs, c'est surtout de faire en sorte que les gens se retrouvent dans les services, les ressources, les options et tout ce que le fournisseur propre.&lt;/p&gt;
&lt;aside class="note" data-type="Ma perception"&gt;
&lt;p&gt;À ma connaissance, je n'ai pas de problème visuel au delà du fait que je porte constamment des lunettes pour corriger ma vue. &lt;span class="emoji" aria-hidden="true"&gt;🤓&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Toutefois, la frustration monte vite en moi quand je ne trouve pas ce que je cherche ou que je ne comprends pas une indication.
Je ne m'énerve pas pour autant, j'ai une grande patience et j'ai appris à garder une bonne tolérance face à cette frustration mais je tombe facilement dans un cercle vicieux où par frustration, j'ai du mal à réfléchir sur une autre manière de trouver ce que je cherche.&lt;/p&gt;
&lt;p&gt;Donc pas de handicap notable quand je me balade sur une interface graphique, juste un cerveau qui n'aime pas trop travailler pour des broutilles.
Ah, j'ai aussi horreur des icônes sans texte, je préfère du texte sans icône (ça se voit probablement sur mon site).&lt;/p&gt;
&lt;p&gt;Petite parenthèse : j'aimerais beaucoup trouver des articles qui parlent de l'accessibilité des interfaces graphiques des fournisseurs cloud, avec des témoignages et des tests par des personnes qui ne sont pas aussi valides que moi.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Commençons par un bon point : Oracle n'a pas mis des icônes dans tous les sens, c'est très textuel et j'apprécie vraiment.
Mon cerveau se sent à l'aise pour trouver l'information sur une page.&lt;/p&gt;
&lt;p&gt;Aussi, la catégorisation des services est plutôt bien, sauf pour quelques outils.
Notamment, OKE (le service de Kubernetes auto-géré) est dans la catégorie « Developers services » qui a l'air d'être le fourre-tout pour tout ce qui ne rentre pas dans une autre catégorie.&lt;/p&gt;
&lt;p&gt;Enfin, la vue d'une ressource est… Particulière mais fonctionnelle.
On s'y fait et on comprend vite le fonctionnement de la page qui est d'ailleurs très cohérente entre tous les services (les gens qui ont utilisé AWS Beanstalk savent qu'il peut y avoir des produits qui ont une interface différente des autres chez un même fournisseur, en tout cas en 2016 c'était ça).
Et je dirais même que j'ai fini par apprécier cette ergonomie car je trouvais facilement les informations que je cherchais sur les ressources.&lt;/p&gt;
&lt;p&gt;Petit point bonus : les liens internes sont bien pensés et certains s'ouvrent dans un nouvel onglet quand ça mène vers une ressource d'un autre service.
Par exemple, quand on clique sur le nom d'une machine virtuelle qui est listée dans un groupe de nœuds du cluster Kubernetes, alors ça ouvre la ressource dans un nouvel onglet car on passe sur le service « Compute ».
On aime ou on n'aime pas, personnellement j'apprécie ce point.&lt;/p&gt;
&lt;p&gt;Entrons maintenant dans le vif du sujet !&lt;/p&gt;
&lt;h2 id="gratuit-vraiment"&gt;Gratuit, vraiment ?&lt;/h2&gt;
&lt;p&gt;Sachant qu'on a 250€ de crédits offerts sur un mois, comment savoir si le cluster avait un coût ?
Il suffit de regarder ce qui est consommé dans le crédit.&lt;/p&gt;
&lt;p&gt;Du coup : est-ce que j'ai pu utiliser le cluster sans que ça ne touche les crédits offerts par Oracle ? La réponse est : presque !
J'ai consommé 5,65€ au 4 mai (dernier jour de mon crédit), apparemment à cause d'un &lt;em&gt;load balancer&lt;/em&gt; que j'aurais créé le 22 avril. Ce qui me surprend, c'est qu'on a normalement droit à un &lt;em&gt;load balancer&lt;/em&gt; gratuit.&lt;/p&gt;
&lt;p&gt;En tout cas, c'était un service Kubernetes de type &lt;code&gt;LoadBalancer&lt;/code&gt; qui a créé la ressource sur Oracle Cloud, lorsque j'ai installé ma gateway.
Le &lt;em&gt;load balancer&lt;/em&gt; créé de manière automatique doit être d'une puissance qui va au delà de ce à quoi on a droit gratuitement.
J'avais pourtant changé la configuration pour utiliser un autre type de service mais il semblerait que le changement ne se soit pas passé comme prévu.
J'ai donc manuellement supprimé le service Kubernetes en question puisqu'il n'était plus censé servir.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Ce cluster me sert pour un projet pour lequel j'utilise &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.telepresence.io/"&gt;Telepresence&lt;/a&gt; donc je n'ai pas vraiment besoin d'IP publiques pour accéder à des services dans le cluster Kubernetes.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Donc il semblerait que l'objectif de gratuité puisse être atteint &lt;strong&gt;si on n'a pas besoin de load balancer&lt;/strong&gt;.
Mais « gratuit » ne veut pas dire « illimité » (personne n'a dit le contraire mais ça fait la transition pour la suite) !&lt;/p&gt;
&lt;h2 id="les-limitations-decouvertes"&gt;Les limitations découvertes&lt;/h2&gt;
&lt;h3 id="puissance-disponible"&gt;Puissance disponible&lt;/h3&gt;
&lt;p&gt;Avec tous les outils que j'ai installé dans le cluster (je ne suis pas assez minimaliste en terme technologique), ça m'a fait manquer de ressources.
Ça me fait penser que je devrais faire un petit wiki sur mon site avec la liste de mes logiciels essentiels.&lt;/p&gt;
&lt;aside class="note" data-type="Rappel"&gt;
&lt;p&gt;Petit rappel : Oracle Cloud a sa propre unité pour compter le CPU, ça s'appelle les &lt;em&gt;OCPU&lt;/em&gt; et un &lt;em&gt;OCPU&lt;/em&gt; vaut « au moins deux &lt;em&gt;vCPU&lt;/em&gt; » (sachant qu'un &lt;em&gt;vCPU&lt;/em&gt; représente normalement un cœur de CPU de machine virtuelle). &lt;span class="emoji" aria-hidden="true"&gt;🤯&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Oracle a &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://blogs.oracle.com/cloud-infrastructure/post/vcpu-and-ocpu-pricing-information"&gt;rédigé un article à ce sujet&lt;/a&gt; en 2021 (c'est en anglais et le temps de lecture est estimé à 4 minutes).&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;En architecture ARM, on a droit à 4 &lt;em&gt;OCPU&lt;/em&gt; (donc théoriquement l'équivalent de 8 &lt;em&gt;vCPU&lt;/em&gt;) et 24Go de RAM.
Je ne parle pas de l'architecture x86 car l'offre gratuite est très très faible et j'avais donc indiqué dans mon premier article que je m'intéressais qu'à l'offre ARM qui est assez généreuse.&lt;/p&gt;
&lt;h4 id="resources-des-pods"&gt;Resources des pods&lt;/h4&gt;
&lt;p&gt;En premier lieu, j'ai changé pas mal de &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"&gt;requêtes et limites de ressources&lt;/a&gt; sur certains outils qui n'ont pas besoin de leur puissance habituelle dans mon cas.
Aussi, comme un &lt;em&gt;OCPU&lt;/em&gt; est censé valoir « au moins deux &lt;em&gt;vCPU&lt;/em&gt; », j'ai considéré que quand un pod a besoin d'au moins 1 CPU, il faut donc considérer qu'il a besoin que d'un demi-CPU chez Oracle.
Pour retourner un peu la chose, j'ai considéré que 1 CPU vaut &lt;code&gt;500m&lt;/code&gt; (rappel : pour Kubernetes, 1 cœur de CPU vaut normalement &lt;code&gt;1000m&lt;/code&gt; donc mathématiquement, si 1 &lt;em&gt;OCPU&lt;/em&gt; vaut deux cœurs, ça signifie que 1 &lt;em&gt;OCPU&lt;/em&gt; vaut théoriquement &lt;code&gt;2000m&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Ça fait beaucoup de chiffres et d'unités, j'espère que c'est assez clair. &lt;span class="emoji" aria-hidden="true"&gt;😅&lt;/span&gt;
&lt;/p&gt;
&lt;h4 id="nombre-de-machines-virtuelles"&gt;Nombre de machines virtuelles&lt;/h4&gt;
&lt;p&gt;Aussi, à l'origine, j'avais créé un groupe de deux nœuds, chacun ayant 1 OCPU et 6Go de RAM ce qui faisait un total de 2 OCPU et 12Go de RAM.
Gratuitement, on a droit à un total de 4 OCPU et 24Go de RAM donc j'ai ajouté un nœud de la même puissance ce qui fait que j'utilise 3 OCPU et 18Gi de RAM.&lt;/p&gt;
&lt;aside class="note" data-type="À savoir"&gt;
&lt;p&gt;Attention : on doit obligatoirement garder la puissance pour une machine virtuelle « supplémentaire » (donc 1 OCPU et 6Go de RAM) car, pour résumer, le cluster gratuit a obligatoirement un roulement pendant les mises à jour et maintenances des nœuds.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Une solution possible est de plutôt tourner avec deux nœuds chacun d'une puissance de 1 OCPU et 8Go de RAM mais du coup on garde une certaine limite en terme de processeur (on ne pourrait pas avoir 2 OCPU par nœud car le roulement ne pourrait pas se faire à cause de la limite à 4 OCPU qui serait dépassée lors de celui-ci).
L'avantage de passer sur trois machines virtuelles est donc qu'on a 3 OCPU au total en temps normal et pas seulement 2 OCPU.&lt;/p&gt;
&lt;p&gt;Mais du coup, ça crée un blocage sur les volumes, ce qui fait une transition parfaite pour mon point suivant.&lt;/p&gt;
&lt;h3 id="volumes"&gt;Volumes&lt;/h3&gt;
&lt;aside class="note" data-type="Limitations"&gt;
&lt;p&gt;On peut utiliser jusqu'à 200Go de disques à partager entre les volumes blocs et les disques locaux des machines virtuelles.&lt;/p&gt;
&lt;p&gt;Sachant qu'une machine virtuelle pour un cluster Kubernetes doit utiliser minimum 50Go de disque, ça descend vite.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Si vous avez lu la partie précédente sur le CPU et la RAM, vous aurez noté que j'utilise trois machines en temps normal et que le roulement en cas de mise à jour ou de maintenance fait que les 200Go sont totalement utilisés.
Cette limite semble avoir été parfaitement calculée par Oracle pour être bien frustrante et forcer un peu le passage à la caisse mais je ne juge pas, il faut bien vendre. &lt;span class="emoji" aria-hidden="true"&gt;🙃&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;J'ai rapidement constaté que je n'arrivais plus à créer de &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://kubernetes.io/fr/docs/concepts/storage/persistent-volumes/"&gt;&lt;code&gt;PersistentVolumeClaim&lt;/code&gt;&lt;/a&gt; à cause de cette limitation du stockage qui est entièrement utilisée par mes machines et celle de roulement.&lt;/p&gt;
&lt;p&gt;Trois choix s'offraient à moi :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accepter de payer (haha, vous me prenez pour qui ?) ;&lt;/li&gt;
&lt;li&gt;Utiliser des volumes de type &lt;code&gt;hostPath&lt;/code&gt; là où c'était suffisant ;&lt;/li&gt;
&lt;li&gt;Installer &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://rook.io/"&gt;Rook&lt;/a&gt; ou &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://longhorn.io/"&gt;Longhorn&lt;/a&gt; pour pouvoir gérer moi-même les volumes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si vous n'avez pas envie de lire mes justifications et explications, je divulgâche : j'ai utilisé Longhorn (les raisons sont expliquées ci-dessous).
Voilà, vous pouvez aller directement &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/#conclusion"&gt;à la conclusion&lt;/a&gt; si vous n'avez pas besoin ni envie d'en savoir plus.&lt;/p&gt;
&lt;p&gt;En premier lieu, dans ma grande radinerie et mon habituelle flemme, j'ai choisi d'utiliser des &lt;code&gt;hostPath&lt;/code&gt; à gogo.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Dans le cas présent, je me fous un peu d'avoir un cluster très propre et de garder les hosts « vierges » mais en production (et même hors production chez mes clients) je n'utilise jamais les &lt;code&gt;hostPath&lt;/code&gt; pour des volumes persistants.
Et je vous recommande fortement de ne jamais en utiliser non plus (sauf cas très particuliers mais je préfère dire « jamais » pour que les exceptions restent… exceptionnelles).&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;En tout état de cause, ça m'a créé des problèmes avec les droits de certains outils sur les chemins montés dans les pods donc j'ai décidé que ce serait l'occasion de tester Rook (un collègue indépendant m'en avait parlé en bien).
Sauf que, surprise (ou pas), Rook est un peu complexe (ça démarre et gère un cluster &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://ceph.com/"&gt;Ceph&lt;/a&gt; notamment) et j'ai vite déchanté en essayant d'apprendre son architecture alors que sur le moment je voulais juste faire mes volumes sans réfléchir.
Toutefois, je donnerais une chance à Rook quand j'aurai du temps à lui donner, ça a l'air trop intéressant pour que je le laisse définitivement de côté ! &lt;span class="emoji" aria-hidden="true"&gt;😀&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Donc j'ai plutôt essayé Longhorn, l'architecture est assez simple : les volumes utilisent le disque des nœuds et les contenus sont répliqués pour la sûreté.
Ici je l'utilise de manière très basique mais Longhorn peut être très puissant et proprement configuré en utilisant des serveurs avec des disques physiques supplémentaires qui lui seront dédiés.&lt;/p&gt;
&lt;figure class="full-object"&gt;
&lt;p&gt;&lt;img src="/media/memes/longhorn-hostpath-extra-steps.jpg" alt="Extrait de la série Rick &amp;amp; Morty où Rick regarde un être vivant de sa création et lui dit « Utiliser Longhorn sans disques dediés ? Ça ressemble à des hostPath mais avec plus de complexité ! ». Cette image fait référence à l&amp;#39;épisode 6 de la saison 2 de la série." /&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;On pourrait croire que tout ça ressemble beaucoup à une utilisation des &lt;code&gt;hostPath&lt;/code&gt; avec un outil au milieu mais il y a quelques avantages :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si un pod se fait couper et est relancé sur un autre nœud, le volume sera déplacé et suivra le pod pour éviter une perte de données ;&lt;/li&gt;
&lt;li&gt;En théorie, Longhorn nettoie les données des volumes inutilisés (toutefois j'ai l'impression que ce n'est pas pleinement fonctionnel mais je ne sais pas si j'ai eu une bug ou si j'ai mal configuré tout ça) ;&lt;/li&gt;
&lt;li&gt;Certains paramètres de Longhorn sont utiles même pour un déploiement aussi basique : nettoyages des données orphelines, pourcentage minimum d'espace libre voulu sur le disque…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En toute transparence, je trouve que c'est une chouette technologie à avoir dans un coin de ma tête pour des besoins très spécifiques chez quelques clients.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Rappelons-nous que je n'ai fait que créer et utiliser un cluster Kubernetes (ainsi que le réseau et les sous-réseaux), qui lui-même crée des ressources annexes (comme les machines virtuelles).&lt;/p&gt;
&lt;p&gt;Je pense avoir quatre points principaux à évoquer :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Oracle Cloud me satisfait pour ce que j'en ai essayé ;&lt;/li&gt;
&lt;li&gt;La gratuité est réelle mais attention aux ressources annexes créées via Kubernetes (load balancers et volumes blocs par exemple) qui ne sont pas offertes ;&lt;/li&gt;
&lt;li&gt;La puissance disponible peut être limitante si, comme moi, on installe beaucoup de choses pour servir de base ;&lt;/li&gt;
&lt;li&gt;Il ne faut pas compter sur la possibilité de créer des volumes de type bloc, aussi je recommande d'installer Longhorn ou autre technologie du même genre pour compenser le manque de place.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;D'ailleurs, ça m'a fait plaisir de tester Longhorn mais j'aurais aimé aller du côté de Rook.
J'avais quand même testé l'installation mais ça prenait vraiment beaucoup de ressources.
Longhorn démarre pas mal de pods lui aussi mais Rook semble encore plus consommateur.&lt;/p&gt;
&lt;p&gt;Voilà, je me réserve la possibilité de faire une troisième partie ou une petite mise à jour si je découvre de nouvelles choses !&lt;/p&gt;
&lt;aside class="note" data-type="Mise à jour"&gt;
&lt;p&gt;J'ai publié une &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-fin-mars-2025/"&gt;troisième partie&lt;/a&gt; où j'indique les limitations du cluster gratuit.&lt;/p&gt;
&lt;/aside&gt;</content></entry><entry xml:lang="fr"><title>Un cluster Kubernetes gratuit ?</title><published>2024-04-07T00:00:00+00:00</published><updated>2024-05-05T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-avril-2024/"/><id>https://sam.candy.pm/articles/cluster-kubernetes-gratuit-avril-2024/</id><content type="html" xml:base="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-avril-2024/">&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Au moment où j'écris et publie cet article, je n'ai aucune affiliation avec les fournisseurs de service cités dans cet article.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="note" data-type="Mise à jour"&gt;
&lt;p&gt;J'ai publié une &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/"&gt;deuxième partie&lt;/a&gt; où j'indique les limitations du cluster gratuit.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id="mon-besoin"&gt;Mon besoin&lt;/h2&gt;
&lt;p&gt;Donc, je souhaite avoir un cluster Kubernetes gratuit.&lt;/p&gt;
&lt;p&gt;Bien sur, j'ai des critères en plus du coût qui doit rester nul :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Que ça tourne sur le territoire français (idéalement chez un fournisseur lui-même français ou européen mais pour quelque chose de gratuit, je ne suis pas ferme sur ce point) ;&lt;/li&gt;
&lt;li&gt;Que le cluster soit infogéré (je ne veux pas lancer un &lt;code&gt;k3s&lt;/code&gt; ou équivalent, je suis la flemme incarnée &lt;span class="emoji" aria-hidden="true"&gt;🥱&lt;/span&gt;
) ;&lt;/li&gt;
&lt;li&gt;Qu'il y ai au moins deux nœuds, comme ça lors des mises à jour il y en aurait toujours un en route pour les composants « essentiels » ;&lt;/li&gt;
&lt;li&gt;Avoir au moins 4 CPUs et 8Go de RAM en tout dans le cluster, ça peut paraître léger mais pour le stade de développement auquel je suis, ça suffira amplement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Du coup, j'ai trouvé une réponse à tout ça, avec les points d'attention suivant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;C'est géré par des américains (mais pas Amazon, ni Microsoft, ni Google, on va dire que c'est déjà ça) ;&lt;/li&gt;
&lt;li&gt;C'est bien dans une région française, il y a quelques autres régions européennes disponibles ;&lt;/li&gt;
&lt;li&gt;Les nœuds gratuits à vie ne sont pas en &lt;code&gt;amd64&lt;/code&gt;/&lt;code&gt;x86_64&lt;/code&gt; mais en… &lt;code&gt;aarch64&lt;/code&gt; (ou &lt;code&gt;arm64&lt;/code&gt; si vous préférez) !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je vais donc avoir un cluster gratuit, hébergé en France, avec une architecture ARM 64 bits.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;J'ai un client qui fait tourner quelques petites choses sur du &lt;code&gt;aarch64&lt;/code&gt; mais rien de développé en interne. Les outils qu'on fait fonctionner sur des nœuds &lt;code&gt;aarch64&lt;/code&gt; chez ce client étaient auparavant sur du &lt;code&gt;amd64&lt;/code&gt; et la transition n'a créé aucun problème dû à l'architecture, je suis donc optimiste sur face à tout ce qui est ARM coté serveur.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Mais qui fourni gratuitement ces ressources ? &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.oracle.com/cloud/"&gt;Oracle Cloud Infrastructure&lt;/a&gt; (qu'on abrège apparemment OCI, ce qui me crée une petite confusion avec l'&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://opencontainers.org/"&gt;Open Containers Initiative&lt;/a&gt; mais je vais m'y faire).&lt;/p&gt;
&lt;h2 id="a-propos-d-oracle"&gt;À propos d'Oracle&lt;/h2&gt;
&lt;p&gt;Je ne suis pas fan d'Oracle, tout comme je ne suis pas fan des trois gros fournisseurs cloud américains (AWS, Azure et GCP).&lt;/p&gt;
&lt;p&gt;En l'occurence, c'est le seul moyen que j'ai trouvé actuellement pour avoir un cluster Kubernetes gratuit : Oracle offre des nœuds &lt;code&gt;aarch64&lt;/code&gt; gratuitement &lt;strong&gt;à vie&lt;/strong&gt; !
Pour prototyper, c'est génial : ça peut grimper à 8 cœurs de processeur et 24Go de RAM, divisables en une à quatre machines virtuelles.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Le nombre de cœurs disponibles est un peu complexe car Oracle Cloud a sa propre unité pour compter le CPU, &lt;em&gt;OCPU&lt;/em&gt; de son petit nom, sachant qu'un &lt;em&gt;OCPU&lt;/em&gt; vaut &lt;em&gt;au moins deux vCPU&lt;/em&gt;. &lt;span class="emoji" aria-hidden="true"&gt;🤯&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;C'est compliqué ? Oui, disons simplement qu'un OCPU vaut deux cœurs de machine virtuelle.&lt;/p&gt;
&lt;p&gt;On a un peu plus de quatre OCPU gratuits à vie, soit l'équivalent de huit cœurs il semblerait.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Je n'aurais pas choisi Oracle s'il n'y avait eu aucune région disponible en Union Européenne, toutefois j'ai conscience qu'un doute plane sur la possibilité pour le gouvernement américain de réclamer des données hébergées chez des entreprises américaines, même en Union Européenne voire en France.&lt;/p&gt;
&lt;p&gt;Si le sujet du &lt;em&gt;Cloud Act&lt;/em&gt; vous intéresse, certais founisseurs proposent leurs solutions (sans évoquer les projets Bleu et S3NS) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.silicon.fr/cloud-act-aws-chiffrement-des-donnees-260865.html"&gt;AWS indique que chiffrer les données est suffisant&lt;/a&gt; alors qu'à l'époque de l'annonce du &lt;em&gt;Cloud Act&lt;/em&gt;, ils indiquaient que les demandes des USA ne seraient pas applicables (ce qui contrastait avec ce que disait IBM, à savoir que le cadre imposé par le gouvernement américain n'était pas contournable) ;&lt;/li&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.lemondeinformatique.fr/actualites/lire-microsoft-renforce-la-sanctuarisation-des-donnees-cloud-en-europe-92648.html"&gt;Azure cloisonne les données européenne&lt;/a&gt;, il me semble qu'à l'époque de l'annonce leur discours était nuancé et qu'ils évoquaient une possibilité de faire des remboursements en cas de demandes de données appliquées (c'est bien d'avoir un gros chéquier &lt;span class="emoji" aria-hidden="true"&gt;💰&lt;/span&gt;
) ;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mise-en-place"&gt;Mise en place&lt;/h2&gt;
&lt;h3 id="quelques-concepts-sur-oracle-cloud-infrastructure"&gt;Quelques concepts sur Oracle Cloud Infrastructure&lt;/h3&gt;
&lt;p&gt;On notera qu'Oracle permet de créer des &lt;em&gt;compartments&lt;/em&gt; (soit des &lt;em&gt;compartiments&lt;/em&gt; en français) et qu'un compte sur leur cloud fait partie d'un &lt;em&gt;tenant&lt;/em&gt; (ça se traduit par « &lt;em&gt;locataire&lt;/em&gt; » en français, je n'y avais jamais réfléchis malgré le fait que dans mon milieu on parle souvent de &lt;em&gt;tenants&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Chaque &lt;em&gt;tenant&lt;/em&gt; a un &lt;em&gt;compartment&lt;/em&gt; par défaut nommé « root ». Personnellement j'en ai créé un spécifique pour mon projet.&lt;/p&gt;
&lt;p&gt;Comme chez tout bon fournisseur cloud, on retrouvera (dans ce qui nous intéresse) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Des réseaux virtuels, nommés &lt;em&gt;Virtual Cloud Networks&lt;/em&gt; et abrégés &lt;em&gt;VCN&lt;/em&gt; ;&lt;/li&gt;
&lt;li&gt;Des sous-réseaux pour ces derniers, nommés &lt;em&gt;subnets&lt;/em&gt; (rien de très original, tant mieux) ;&lt;/li&gt;
&lt;li&gt;Diverses &lt;em&gt;gateways&lt;/em&gt; et &lt;em&gt;IP&lt;/em&gt; à mettre dans les &lt;em&gt;VCN&lt;/em&gt; ;&lt;/li&gt;
&lt;li&gt;Et le service de Kubernetes infogéré qui s'appelle &lt;em&gt;Container Engine for Kubernetes&lt;/em&gt; et qui est abrégé &lt;em&gt;OKE&lt;/em&gt; (donc ce n'est pas un acronyme puisque ça ne correspond pas au nom complet, c'est curieux mais ce n'est pas notre sujet du jour &lt;span class="emoji" aria-hidden="true"&gt;🤔&lt;/span&gt;
).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="configurer-le-cluster-kubernetes"&gt;Configurer le cluster Kubernetes&lt;/h3&gt;
&lt;p&gt;Je fais tout en « infrastructure as code » (qu'on abrège « IaC »), du coup cet exemple n'y échappe pas.
Habituellement, j'utilise &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt; mais j'ai profité de cette occasion pour tester &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://opentofu.org/"&gt;OpenTofu&lt;/a&gt;, le fork de Terraform sous licence réellement libre géré par la Linux Foundation (juste au cas où : le &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://opentofu.org/manifesto/"&gt;manifeste d'OpenTofu&lt;/a&gt; explique pourquoi ce fork a eu lieu) et ça a très bien fonctionné.&lt;/p&gt;
&lt;p&gt;J'aime optimiser les choses et Oracle a eu la bonne idée de publier un &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://registry.terraform.io/modules/oracle-terraform-modules/oke/oci/latest"&gt;module Terraform qui crée toutes les ressources nécessaires&lt;/a&gt;, ce qui permet de gagner beaucoup de temps !&lt;/p&gt;
&lt;p&gt;Voici le code HCL qui permet d'utiliser ce module, avec des commentaires pour donner quelques détails.
En réalité j'ai utilisé beaucoup de variables, que j'ai remplacées ici par des valeurs fixes pour l'exemple (sauf pour les choses qu'il faut, à mon avis, absolument passer en variables).&lt;/p&gt;
&lt;pre data-linenos data-lang="hcl" class="language-hcl z-code"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;terraform {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; required_version = &amp;quot;&amp;gt;= 1.6&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; required_providers {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; oci = {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; source = &amp;quot;oracle/oci&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # J&amp;#39;utilise Renovate pour mettre à jour automatiquement la version, d&amp;#39;où le fait que j&amp;#39;utilise une version précise.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; version = &amp;quot;5.36.0&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# Ces valeurs me permettent d&amp;#39;avoir une petite cohérence dans mes ressources quand je vais voir sur l&amp;#39;interface d&amp;#39;Oracle Cloud Infrastructure.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;locals {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; app_name = &amp;quot;example-application&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; environment = &amp;quot;development&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; resource_name = &amp;quot;${app_name}-${environment}&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; tags = {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; &amp;quot;name&amp;quot; = local.app_name,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; &amp;quot;environment&amp;quot; = local.environment,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# On doit fournir une IP déjà créée pour que les nœuds aient accès à internet, c&amp;#39;est dommage mais pourquoi pas.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;resource &amp;quot;oci_core_public_ip&amp;quot; &amp;quot;example&amp;quot; {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; compartment_id = var.oracle_compartment_ocid
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; display_name = local.resource_name
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; freeform_tags = local.tags
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;31&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; lifetime = &amp;quot;RESERVED&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;33&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;34&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;35&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;module &amp;quot;example&amp;quot; {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;36&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; depends_on = [resource.oci_core_public_ip.example]
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;37&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; source = &amp;quot;oracle-terraform-modules/oke/oci&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;39&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Comme pour le provider, le module sera mis à jour automatiquement par Renovate.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;40&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; version = &amp;quot;5.1.4&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;41&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; providers = {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;42&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; oci.home = oci
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;43&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;44&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;45&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; compartment_id = var.oracle_compartment_ocid
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;46&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; home_region = &amp;quot;eu-paris-1&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;47&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; region = &amp;quot;eu-paris-1&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;48&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;49&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Je n&amp;#39;ai aucune honte : tout se nommera pareil et aura les mêmes tags.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; vcn_name = local.resource_name
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;51&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; cluster_name = local.resource_name
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;52&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; freeform_tags = {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;53&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; bastion = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;54&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; cluster = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;55&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; iam = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;56&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; network = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;57&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; operator = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;58&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; persistent_volume = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;59&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; service_lb = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;60&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; workers = local.tags,
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;61&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;62&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;63&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Le label DNS permet d&amp;#39;avoir des noms DNS « propres » pour les nœuds dans leur réseau, en vrai ça m&amp;#39;est complètement inutile mais je le renseigne pour le principe.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; vcn_dns_label = &amp;quot;example&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;65&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;66&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # L&amp;#39;operator est une machine qui permet de gérer le cluster avec kubectl et Helm depuis le réseau du cloud, je ne souhaite pas faire ça.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;67&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; create_operator = false
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;68&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;69&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # De la meme manière, le bastion permet de se SSH dans les nœuds directement depuis le réseau du cloud, ce qui ne m&amp;#39;intéresse pas.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;70&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; create_bastion = false
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;71&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;72&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Je souhaite accéder au cluster depuis mon PC local, donc le control plane doit être publique, avec une IP assignée.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;73&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; control_plane_is_public = true
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;74&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; assign_public_ip_to_control_plane = true
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;75&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Ce paramètre n&amp;#39;est pas compatible IPv6 donc j&amp;#39;ai mis seulement mon IPv4, avec un `/32` à la fin pour qu&amp;#39;elle soit vue comme un bloc CIDR.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Donc je ne peux accéder au control plane que depuis chez moi.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;77&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Il est possible de mettre `[&amp;quot;0.0.0.0/0&amp;quot;]` mais quand même, la sécurité…
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;78&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; control_plane_allowed_cidrs = var.kubernetes_control_plane_allowed_cidrs
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;79&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;80&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Voilà donc l&amp;#39;IP publique pour que les nœuds et les pods puissent accéder à internet.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;81&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; nat_gateway_public_ip_id = resource.oci_core_public_ip.example.id
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;82&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;83&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Attention à bien rester à jour !
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;84&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Je n&amp;#39;ai as trouvé de système d&amp;#39;auto-upgrade de Kubernetes chez Oracle Cloud Infrastructure, dommage.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;85&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Chez les autres fournisseur, c&amp;#39;est généralement disponible donc on indique seulement la version globale qu&amp;#39;on veut, par exemple `v1.29`, et une fenêtre de maintenance qui fait que le fournisseur cloud patche les nœuds quand il le faut.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;86&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; kubernetes_version = &amp;quot;v1.29.1&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;87&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;88&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Ce sont les valeurs par défaut, pour le coup je suis plutôt Debian qu&amp;#39;autre chose coté serveur mais je me dis que quitte à être chez Oracle, autant utiliser leur OS qui est probablement optimisé pour les machines virtuelles fournies.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;89&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; worker_image_os = &amp;quot;Oracle Linux&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;90&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; worker_image_os_version = &amp;quot;8&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;91&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;92&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; worker_pools = {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;93&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; &amp;quot;${local.resource_name}-main&amp;quot; = {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;94&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Il faut préciser que le groupe de nœuds doit être créé, pourquoi pas hein !
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;95&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; create = true
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;96&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;97&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Je commence doucement avec deux nœuds.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;98&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; size = 2
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;99&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;100&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # J&amp;#39;utilise des machines basées sur un processeur Ampere 1.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;101&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; shape = &amp;quot;VM.Standard.A1.Flex&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;102&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Je rappelle qu&amp;#39;un OCPU vaut « au moins » deux CPU virtuels.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;103&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; ocpus = 1
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;104&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # La RAM est en gigaoctets.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;105&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; memory = 6
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;106&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Le volume de démarrage est en gigaoctets et 50Go est sa taille minimale requise (j&amp;#39;ai essayé moins, l&amp;#39;APi a retourné une erreur indiquant que 50Go est le minimum).
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;107&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; boot_volume_size = 50 # this is the minimum
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;108&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;109&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; # Je ne veux pas que deux nœuds soient indisponibles en même temps.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;110&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; node_cycling_enabled = true
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;111&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; node_cycling_max_surge = 0
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;112&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; node_cycling_max_unavailable = 1
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;113&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;114&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;115&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;116&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;117&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# Voilà comment on récupère un fichier kubeconfig avec accès publique.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;118&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;data &amp;quot;oci_containerengine_cluster_kube_config&amp;quot; &amp;quot;kube_config&amp;quot; {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;119&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; depends_on = [module.example]
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;120&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;121&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; cluster_id = module.example.cluster_id
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;122&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; endpoint = &amp;quot;PUBLIC_ENDPOINT&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;124&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;125&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# Et voilà comment on l&amp;#39;enregistre dans un coin.
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;126&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;resource &amp;quot;local_file&amp;quot; &amp;quot;kube_config&amp;quot; {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;127&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; depends_on = [data.oci_containerengine_cluster_kube_config.kube_config]
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;128&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;129&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; content = data.oci_containerengine_cluster_kube_config.kube_config.content
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;130&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; filename = &amp;quot;${abspath(path.root)}/kubeconfig.yaml&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;131&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="demarrer-le-cluster"&gt;Démarrer le cluster&lt;/h3&gt;
&lt;p&gt;Le fichier c'est bien, avoir le cluster en bonne et due forme c'est mieux !&lt;/p&gt;
&lt;p&gt;Déjà on n'oublie pas de configurer le &lt;em&gt;provider&lt;/em&gt; en exportant les variables d'environnement nécessaires, sachant que je me connecte avec une clé d'API créée pour mon compte (chez Oracle ce sont des clés RSA, après tout pourquoi pas) :&lt;/p&gt;
&lt;pre data-lang="sh" class="language-sh z-code"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_oracle_compartment_ocid&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-double z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;quot;&lt;/span&gt;&amp;lt;votre-compartment-ocid&amp;gt;&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_tenancy_ocid&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-double z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;quot;&lt;/span&gt;&amp;lt;votre-tenancy-id&amp;gt;&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_user_ocid&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-double z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;quot;&lt;/span&gt;…&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_fingerprint&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-double z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;quot;&lt;/span&gt;…&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="z-comment z-line z-number-sign z-shell"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-shell"&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt; fingerprint de la clé d&amp;#39;API utilisée&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_private_key_path&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-double z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;quot;&lt;/span&gt;…&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="z-comment z-line z-number-sign z-shell"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-shell"&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt; chemin vers le fichier PEM de la clé privée&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_region&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-double z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;quot;&lt;/span&gt;eu-paris-1&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="z-comment z-line z-number-sign z-shell"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-shell"&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt; en France, évidemment, d&amp;#39;ailleurs il y a une région à Marseille&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-variable z-other z-readwrite z-assignment z-shell"&gt;TF_VAR_kubernetes_control_plane_allowed_cidrs&lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-shell"&gt;=&lt;/span&gt;&lt;span class="z-string z-unquoted z-shell"&gt;&lt;span class="z-string z-quoted z-single z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;#39;&lt;/span&gt;[&amp;quot;&amp;lt;votre-ip-fixe&amp;gt;/32&amp;quot;]&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="z-comment z-line z-number-sign z-shell"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-shell"&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt; attention, c&amp;#39;est un tableau dans une string!&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ensuite, j'ai dû appliquer en plusieurs fois car une ressource ne peut ête créée avant que les autres ne le soient, donc j'ai fait trois &lt;code&gt;apply&lt;/code&gt; pour m'assurer que ça voulait bien se lancer (on notera que &lt;code&gt;tofu&lt;/code&gt; peut être remplacé par &lt;code&gt;terraform&lt;/code&gt;) :&lt;/p&gt;
&lt;pre data-lang="sh" class="language-sh z-code"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; tofu apply&lt;span class="z-variable z-parameter z-option z-shell"&gt;&lt;span class="z-punctuation z-definition z-parameter z-shell"&gt; -&lt;/span&gt;target&lt;/span&gt; &lt;span class="z-string z-quoted z-single z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;#39;&lt;/span&gt;module.example.module.vcn[0].oci_core_vcn.vcn&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-shell"&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt; …&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; tofu apply&lt;span class="z-variable z-parameter z-option z-shell"&gt;&lt;span class="z-punctuation z-definition z-parameter z-shell"&gt; -&lt;/span&gt;target&lt;/span&gt; &lt;span class="z-string z-quoted z-single z-shell"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-shell"&gt;&amp;#39;&lt;/span&gt;module.example.module.cluster[0].oci_containerengine_cluster.k8s_cluster&lt;span class="z-punctuation z-definition z-string z-end z-shell"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-shell"&gt;#&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt; …&lt;/span&gt;&lt;span class="z-comment z-line z-number-sign z-shell"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; tofu apply&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Et normalement, si on va sur l'interface d'Oracle Cloud Infrastructure, tout est bon ! &lt;span class="emoji" aria-hidden="true"&gt;🤩&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img src="/media/screenshots/oracle-cloud/2024-04-07_cluster-up.png" alt="Capture d&amp;#39;écran de l&amp;#39;interface d&amp;#39;Oracle Cloud Infrastructure qui montre le cluster créé, dont l&amp;#39;état est « Actif »." /&gt;&lt;/p&gt;
&lt;h3 id="acceder-au-cluster-avec-kubectl"&gt;Accéder au cluster avec kubectl&lt;/h3&gt;
&lt;p&gt;On a un &lt;code&gt;kubeconfig.yaml&lt;/code&gt; qui est généré par le code que j'ai proposé mais en l'utilisant, on verra qu'il nous manque un élément important : la CLI OCI qui permet de générer le token de connexion !
En effet, en décorticant le fichier &lt;code&gt;kubeconfig&lt;/code&gt;, on voit que l'authentification est gérée par cette fameuse CLI :&lt;/p&gt;
&lt;pre data-linenos data-lang="yaml" class="language-yaml z-code"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt;&lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;users&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;user-[REDACTED]&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;user&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;exec&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;apiVersion&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;client.authentication.k8s.io/v1beta1&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;command&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;oci&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;&lt;span class="z-entity z-name z-tag z-yaml"&gt;args&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-mapping z-yaml"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;ce&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;cluster&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;generate-token&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;--cluster-id&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-meta z-flow-sequence z-yaml"&gt;&lt;span class="z-punctuation z-definition z-sequence z-begin z-yaml"&gt;[&lt;/span&gt;&lt;span class="z-string z-unquoted z-plain z-in z-yaml"&gt;REDACTED&lt;/span&gt;&lt;span class="z-punctuation z-definition z-sequence z-end z-yaml"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;--region&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-yaml"&gt; &lt;span class="z-punctuation z-definition z-block z-sequence z-item z-yaml"&gt;-&lt;/span&gt; &lt;span class="z-string z-unquoted z-plain z-out z-yaml"&gt;eu-paris-1&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vous aurez deux choix pour installer la CLI :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Les &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm"&gt;instructions officielles&lt;/a&gt; ou…&lt;/li&gt;
&lt;li&gt;… un petit &lt;code&gt;python3 -m pip install oci-cli&lt;/code&gt; (avec éventuellement &lt;code&gt;--break-system-packages&lt;/code&gt; si vous avec le même empressement que moi).&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Je plaisante avec &lt;code&gt;--break-system-packages&lt;/code&gt; mais j'utilise &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/89luca89/distrobox"&gt;Distrobox&lt;/a&gt; donc je n'ai aucune contre-indication pour lancer cette commande avec cet argument. Vous ne pouvez donc pas me juger. &lt;span class="emoji" aria-hidden="true"&gt;🧑‍⚖️&lt;/span&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Ça vaut dire aussi qu'il faut avoir son fichier &lt;code&gt;~/.oci/config&lt;/code&gt;, que vous obtiendrez en générant votre clé d'API (qui, je le rappelle, est une clé RSA).&lt;/p&gt;
&lt;p&gt;Après ça, un petit &lt;code&gt;kubectl get nodes&lt;/code&gt; devrait vous prouver que tout fonctionne parfaitement et que vous avez deux nœuds qui sont en fonctionnement.&lt;/p&gt;
&lt;h2 id="utilisation"&gt;Utilisation&lt;/h2&gt;
&lt;h3 id="consommation-de-base"&gt;Consommation de base&lt;/h3&gt;
&lt;p&gt;Par défaut, le &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/kubernetes-sigs/metrics-server"&gt;serveur de métriques&lt;/a&gt; n'est pas installé.
Je l'ai donc appliqué manuellement, vite-fait bien-fait (à l'avenir je ferai en sorte qu'il soit ajouté par mon outil GitOps, avec une version fixe et toutes les recommandations habituelles) :&lt;/p&gt;
&lt;pre data-lang="sh" class="language-sh z-code"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; kubectl apply&lt;span class="z-variable z-parameter z-option z-shell"&gt;&lt;span class="z-punctuation z-definition z-parameter z-shell"&gt; -&lt;/span&gt;f&lt;/span&gt; https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Après une petite minute durant laquelle je laissais le serveur de métriques collecter quelques informations, j'ai pu voir les consommations des nœuds :&lt;/p&gt;
&lt;pre data-lang="sh" class="language-sh z-code"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; kubectl top nodes&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;NAME&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; CPU(cores&lt;/span&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;/span&gt;) &lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;CPU&lt;span class="z-meta z-group z-expansion z-job z-shell"&gt;&lt;span class="z-punctuation z-definition z-variable z-job z-shell"&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; MEMORY(bytes&lt;/span&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;/span&gt;) &lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;MEMORY&lt;span class="z-meta z-group z-expansion z-job z-shell"&gt;&lt;span class="z-punctuation z-definition z-variable z-job z-shell"&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;10.0.152.38&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; 47m 4&lt;span class="z-meta z-group z-expansion z-job z-shell"&gt;&lt;span class="z-punctuation z-definition z-variable z-job z-shell"&gt;%&lt;/span&gt;&lt;/span&gt; 1272Mi 22&lt;span class="z-meta z-group z-expansion z-job z-shell"&gt;&lt;span class="z-punctuation z-definition z-variable z-job z-shell"&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="z-source z-shell z-bash"&gt;&lt;span class="z-meta z-function-call z-shell"&gt;&lt;span class="z-variable z-function z-shell"&gt;10.0.158.90&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-function-call z-arguments z-shell"&gt; 44m 4&lt;span class="z-meta z-group z-expansion z-job z-shell"&gt;&lt;span class="z-punctuation z-definition z-variable z-job z-shell"&gt;%&lt;/span&gt;&lt;/span&gt; 1290Mi 23&lt;span class="z-meta z-group z-expansion z-job z-shell"&gt;&lt;span class="z-punctuation z-definition z-variable z-job z-shell"&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En réalité, en faisant un &lt;code&gt;kubectl top pods --all-namespaces&lt;/code&gt; et en additionnant la RAM réellement utilisée par chaque pod, j'obtiens environ &lt;code&gt;220Mi&lt;/code&gt; consommés (celle des nodes est en fait l'addition des limites de RAM de chaque pod, qui sont « surestimées » par rapport à l'utilisation que j'en aurais). Sachant que j'ai mis deux nœuds avec chacun six gigaoctets de RAM et qu'on peut même grimper à 24Go gratuitement, j'ai de la marge !&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Je parle plus de la consommation de RAM que de CPU parce que les pods qui y tournent seront latents la plupart du temps.
Et aussi parce qu'on peut considérer que le CPU est une ressource « sans fin » contrairement à la RAM, même si c'est un peu plus complexe que ça.&lt;/p&gt;
&lt;p&gt;Ça me ferait probablement un bon sujet pour un prochain article !&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;Pour ce projet, il m'arrivait de lancer des clusters chez des fournisseurs cloud et de les détruire peu de temps après donc j'ai fait en sorte de me faciliter la tâche au niveau du démarrage.&lt;/p&gt;
&lt;p&gt;Du coup, j'ai un petit script (en fait, un &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/casey/just"&gt;&lt;code&gt;Justfile&lt;/code&gt;&lt;/a&gt;) qui installe les composants de base dans mon cluster.
Ça installe notamment &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://argoproj.github.io/cd"&gt;ArgoCD&lt;/a&gt; qui va lui-même ajouter beaucoup de choses : des opérateurs de gestion de bases de données, Tekton et des pipelines que j'ai créé, un registre Docker léger, Renovate pour faire les mises à jour, etc.&lt;/p&gt;
&lt;p&gt;J'ai quand même eu deux problème de compatibilité avec des outils que j'utilise :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/cockroachdb/cockroach-operator"&gt;L'opérateur de CockroachDB&lt;/a&gt; ne propose que des images en &lt;code&gt;amd64&lt;/code&gt;, toutefois &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/cockroachdb/cockroach-operator/issues/942"&gt;un ticket est ouvert pour avoir des images aarch64&lt;/a&gt; et une personne a &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/cockroachdb/cockroach-operator/issues/942#issuecomment-1928576952"&gt;précisé en commentaire&lt;/a&gt; avoir construit une image pour &lt;code&gt;aarch64&lt;/code&gt; (attention, elle a une version de retard, je ferais peut-être une nouvelle image à jour moi-même) ;&lt;/li&gt;
&lt;li&gt;&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://zotregistry.dev/"&gt;Le registre d'images Zot&lt;/a&gt; propose des images en &lt;code&gt;aarch64&lt;/code&gt; mais ce ne sont pas des images à architectures multiples donc il faut &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://zotregistry.dev/v2.0.3/install-guides/install-guide-k8s/#customizing-the-helm-chart-using-set"&gt;préciser dans les valeurs Helm qu'on veut utiliser leur registre &lt;code&gt;aarch64&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et bien sûr, mon application était jusque là compilée pour des processeurs &lt;code&gt;amd64&lt;/code&gt; mais je devrais être en mesure de régler ça facilement (j'espère &lt;span class="emoji" aria-hidden="true"&gt;🤞&lt;/span&gt;
).&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Que dire ? Ça fonctionne, à première vue. Je pense mettre à jour cet article dans un mois environ (ou en faire un nouveau si j'ai beaucoup de choses à dire) pour indiquer si la consommation financière est bien restée nulle selon Oracle (j'ai 250€ de crédit vu que je viens d'y créer mon compte et je peux voir ce qui m'en reste) et si tout fonctionne toujours.&lt;/p&gt;
&lt;p&gt;Du coup, voilà les points positifs que je trouve « à chaud » :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le module fourni par Oracle pour &lt;code&gt;OpenTofu&lt;/code&gt;/&lt;code&gt;Terraform&lt;/code&gt; est complet et permet de démarrer facilement sur leur cloud ;&lt;/li&gt;
&lt;li&gt;La consommation de base sur les nœuds est normale (pas de mauvaise surprise) ;&lt;/li&gt;
&lt;li&gt;On peut avoir jusqu'à 8 cœurs de CPU (4 OCPU) et 24Go de RAM, ce qui est plutôt généreux !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et le négatif que je vois à l'heure actuelle :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le module fourni par Oracle nécessite de faire des &lt;code&gt;tofu apply&lt;/code&gt;/&lt;code&gt;terraform apply&lt;/code&gt; en plusieurs fois avec des &lt;code&gt;-target&lt;/code&gt; pour ne pas refuser de démarrer l'infrastructure, ça m'a fait batailler un peu au début ;&lt;/li&gt;
&lt;li&gt;Le seul CNI proposé est Flannel (et un autre spécifique qui s'intègre aux réseaux virtuels d'Oracle Cloud) et si on veut installer Cilium, il faut activer l'&lt;em&gt;operator&lt;/em&gt; dans leur module, ce qui fait une machine qui tourne inutilement (je vais me débrouiller autrement) ;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il me surprend aussi qu'en 2024, il y ai des « incompatibilités » avec l'architecture &lt;code&gt;aarch64&lt;/code&gt; mais heureusement elles se contournent.
Je ne met pas ça dans les points négatifs car ce n'est pas la faute d'Oracle, qui a la gentillesse de fournir des nœuds gratuits sous cette architecture donc je ne vais pas cracher dans la soupe. &lt;span class="emoji" aria-hidden="true"&gt;😅&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Sur ce, je vais tenter de compiler mon application pour cette architecture et je vous dis « à bientôt » pour voir si le prix s'élève bien à 0€ !&lt;/p&gt;
&lt;aside class="note" data-type="Mise à jour"&gt;
&lt;p&gt;J'ai publié une &lt;a href="https://sam.candy.pm/articles/cluster-kubernetes-gratuit-suite-mai-2024/"&gt;deuxième partie&lt;/a&gt; où j'indique les limitations du cluster gratuit.&lt;/p&gt;
&lt;/aside&gt;</content></entry><entry xml:lang="fr"><title>Amélioration du trépied de mon didgeridoo : partie 1</title><published>2024-02-25T00:00:00+00:00</published><updated>2024-02-25T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/amelioration-trepied-didgeridoo-partie-1/"/><id>https://sam.candy.pm/articles/amelioration-trepied-didgeridoo-partie-1/</id><content type="html" xml:base="https://sam.candy.pm/articles/amelioration-trepied-didgeridoo-partie-1/">&lt;h2 id="ou-trouver-un-trepied-pour-didgeridoo"&gt;Où trouver un trépied pour didgeridoo&lt;/h2&gt;
&lt;p&gt;J'ai un seul trépied malgré mes multiples instruments car jusqu'ici, j'utilise un seul didgeridoo à la fois. Quand je l'ai acheté, je ne savais pas à quel point je trouverais ça utile donc je ne souhaitais pas trop dépenser. Par chance, une personne avait diffusé sur Facebook une annonce Le Bon coin pour se séparer de son didgeridoo et de son trépied. J'ai acheté le trépied seul (et j'espère que le didgeridoo a trouvé sa nouvelle souffleuse ou son nouveau souffleur).&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Après plus d'un an d'utilisation de ce trépied, je dois bien avouer que j'aurais du mal à m'en passer. Il m'arrive de souffler un peu sans mettre le didgeridoo dessus mais dès que je veux y passer plus d'une demi-heure et/ou que j'ai envie de m'enregistrer, je ne peux plus faire sans.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Il y a une chose qu'on remarque rapidement dans le monde du didgeridoo : il y a peu de choses dédiées. Rares sont les trépieds uniquement destinés au didgeridoo et quand c'est indiqué, c'est plutôt un effet de bord (par exemple « trépied pour percussions, peut aussi être utilisé pour d'autres instruments comme les didgeridoos »). Du coup, celui que j'ai acheté d'occasion est en fait vendu neuf comme un trépied de djembé qui répond au doux nom de « DJS9000 » et qu'on trouve par exemple &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.musicstore.com/fr_FR/EUR/Fame-pied-Djembe-DJS9000-/art-DRU0020014-000"&gt;sur MusicStore&lt;/a&gt; pour 40€ environ (je n'ai aucune affiliation avec ce magain, je le cite car c'est le seul où il semble être encore en stock).&lt;/p&gt;
&lt;p&gt;D'ailleurs, le joueur Adrien B, qui fait partie notamment de &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://ucdidgs.com/"&gt;Underground Cosmic Didgs&lt;/a&gt; et de &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://kaophonic-tribu.com/"&gt;Kaophonic Tribu&lt;/a&gt; au moment où j'écris ces lignes, a fait &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.wakademy.online/blog/articles/ou-trouver-un-trepied-pour-votre-didgeridoo-et-comment-le-personnalise/"&gt;un excellent article sur Wakademy&lt;/a&gt; (je n'ai aucune affiliation avec Wakademy non plus, bien que c'est grâce à ce site et Gauthier Aubé que j'ai appris les bases du didgeridoo) dans lequel il indique qu'il faut parfois bricoler pour avoir ce qu'on veut.&lt;/p&gt;
&lt;p&gt;Sinon, quand on n'a pas la possibilité de bricoler (que ce soit par maque de moyens, d'énergie, de courage ou quoi que ce soit) et qu'on a les moyens, le magasin Didgeridoo Passion (là aussi, je n'y ai pas d'affiliation) propose &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.didgeridoo-passion.com/fr/trepied-didgeridoo-mains-libres"&gt;un trépied pré-modifié&lt;/a&gt; pour environ 140€ et optionnellement &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.didgeridoo-passion.com/fr/support-pince-micro-trepied-mains-libres"&gt;un support pour microphone&lt;/a&gt; qui va avec pour environ 30€. Personnellement ça me paraissait un peu cher à l'époque où j'ai acheté mon trépied mais je pense que l'investissement peut être très intéressant (surtout que les pièces sont adaptées par Didgeridoo Passion de manière plus professionnelle que ce que je vais présenter ici).&lt;/p&gt;
&lt;h2 id="anatomie-de-mon-trepied-avant-les-modifications"&gt;Anatomie de mon trépied avant les modifications&lt;/h2&gt;
&lt;p&gt;En nettoyant récemment mon trépied de fond en comble, je me suis rendu compte qu'il est démontable à souhait. J'ai d'ailleurs pu découvrir que certaines pièces pouvaient se régler et qu'elles avaient juste besoin d'être graissées (notamment, certaines parties que le vendeur me disait fixes étaient en fait mobiles).&lt;/p&gt;
&lt;figure class="full-object"&gt;
&lt;p&gt;&lt;img src="/media/photos/trepied.jpg" alt="Photo du trépied de didgeridoo que j&amp;#39;utilise." /&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Voilà à quoi ressemble le trépied (en tout cas, comme je l'ai reçu). Avec mes excuses pour le décors, l'OSB et le placo enduit ne font pas les plus beaux fonds. &lt;span class="emoji" aria-hidden="true"&gt;😁&lt;/span&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On peut donc diviser son anatomie en deux parties principales :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le corps et les pieds ;&lt;/li&gt;
&lt;li&gt;La tête, où l'instrument est posé.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Normalement, la tête est plutôt à la verticale lorsqu'on utilise le trépied avec un djembé mais on peut la pivoter très facilement pour une utilisation détournée (à tout hasard, afin d'y mettre un didgeridoo).&lt;/p&gt;
&lt;p&gt;Cette tête n'accueille qu'un seul instrument mais est très bien conçue pour ce faire :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Elle est réglable en longueur ;&lt;/li&gt;
&lt;li&gt;Entre deux embouts qui forment un « V » et permettent de placer l'instrument, il y a une sangle qui maintient celui-ci ;&lt;/li&gt;
&lt;li&gt;Au bout, il y a deux « crochets » qui empêchent l'instrument de glisser, ça me semble assez important.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;J'ai vite remarqué que le précédent propriétaire avait ajouté un petit patin de feutrine carré entre les embouts de maintient pour éviter qu'une tête de vis bien précise abîme l'instrument qu'on souhaite utiliser.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Il serait donc appréciable de garder à minima l'idée de la sangle et des crochets afin de stabiliser l'instrument.&lt;/p&gt;
&lt;h2 id="ameliorations-souhaitees"&gt;Améliorations souhaitées&lt;/h2&gt;
&lt;p&gt;Il y a deux choses que je souhaite faire :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Utiliser deux instruments en parallèle sans avoir à enlever et remettre chacun d'eux sur le support ;&lt;/li&gt;
&lt;li&gt;Placer un microphone microphone devant la cloche de chaque didgeridoo.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pour le second point, j'ai remarqué que la technique de certaines joueuses et de certains joueurs consistait à créer une « rallonge », percer le bout de la tête pour rattacher cette rallonge et fixer le support de microphone dessus. D'ailleurs, c'est ce que montre Adrien B &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.wakademy.online/blog/articles/ou-trouver-un-trepied-pour-votre-didgeridoo-et-comment-le-personnalise/"&gt;dans son article sur Wakademy&lt;/a&gt; dont je parlais tout-à-l'heure. Cette idée me plaît et il me semble difficile de trouver mieux donc je vais m'en inspirer.&lt;/p&gt;
&lt;p&gt;Toutefois, la tête actuelle me déplaît, car elle a quelques tête de vis (certes arrondies) et une arrête qui me font un peu peur de rayer mes didgeridoos. Et quand on connaît le prix qu'un bon instrument peut coûter, ça fait mal de l'abîmer, même si c'est seulement visuel.&lt;/p&gt;
&lt;p&gt;Du coup, ne serait-ce pas l'occasion de créer une nouvelle tête sur mesure pour accueillir les deux instruments avec des micros ? Oui, c'est l'occasion. En s'inspirant des bonnes idée de l'existante.&lt;/p&gt;
&lt;h2 id="dans-le-vif-du-sujet"&gt;Dans le vif du sujet&lt;/h2&gt;
&lt;p&gt;J'ai choisi de « construire » une seule tête pour commencer et si ça fonctionne bien j'en ferai une seconde en faisant en sorte de pouvoir les fixer ensemble sur le trépied (j'ai déjà une idée pour le faire mais on verra ça plus tard).&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Sans dire que j'ai un bon niveau de bricolage, je sais faire des choses. Je ne saurais pas estimer la difficulté de ce que j'ai fait pour des personnes qui n'ont pas l'habitude de bricoler.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="le-plan"&gt;Le plan&lt;/h3&gt;
&lt;p&gt;J'ai réalisé mes plans avec &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://cadquery.readthedocs.io/"&gt;CadQuery&lt;/a&gt;, je l'ai pris en main pour la première fois pour ce projet. J'avais appris à utiliser SolidWorks de manière très basique au collège et au lycée, du coup je voulais essayer &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.freecad.org/"&gt;FreeCAD&lt;/a&gt; mais autant dire que j'ai bien ramé et que j'ai eu des petits bugs qui m'ont fait un peu trop ramer à mon goût. &lt;span class="emoji" aria-hidden="true"&gt;🤯&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Vu le temps que j'ai passé sur la modélisation de mon idée, la prochaine fois je pense que je ferai des ébauches sur papier et j'improviserai un peu plus sur le moment. Ça me ressemble un peu plus et je passerai moins de temps sur l'ordinateur. Revers de la médaille, je n'aurais pas un beau modèle en trois dimensions à montrer sur ce blog. C'est un choix ! &lt;span class="emoji" aria-hidden="true"&gt;😅&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Plus concrètement, j'ai pris en compte certaines contraintes personnelle :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;J'utilise de l'OSB 18mm et de l'OSB 12mm car il m'en reste plein de chutes (les travaux à la maison ont menés à beaucoup de découpes &lt;span class="emoji" aria-hidden="true"&gt;😁&lt;/span&gt;
) ;&lt;/li&gt;
&lt;li&gt;La fixation actuelle de la tête sur la rotule (je souhaite conserver cette dernière) est constitué de quatre vis de 6mm de diamètres et espacées chacune de 4cm, du coup j'ai reproduis la même ;&lt;/li&gt;
&lt;li&gt;Le support fourni avec mon microphone est a pas de vis de diamètre 3/8" (apparemment c'est souvent comme ça) donc j'ai fait les trous de fixation du support en 9,525mm sur mes plans (dans la vraie vie, j'ai plutôt utilisé une mèche de 8mm parce que c'est ce que j'avais qui s'en rapprochait le plus sans dépasser ce diaètre mais je compte commander une mèche en 3/8" pour finaliser les trous au bon diamètre, au moins ça m'a permis de faire mes tests pour l'instant).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="full-object"&gt;
&lt;p&gt;&lt;img src="/media/plans/tete-trepied-prototype.svg" alt="Schéma en vue du isométrique d&amp;#39;un rectangle, avec plusieurs trous représentant des endroits à percer, et sur lequel il y a une partie mobile elle-même percée." /&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Voilà donc comment je me figure ce nouveau support, qui ira sur le trépied à la place de l'actuel. Les quatres trous qui forment un carré sont la partie qui sera fixée à la rotule du trépied (précisément là où la tête existante est fixée).&lt;/p&gt;
&lt;p&gt;La ligne de trous à l'opposé est celle qui servira à mettre un petit « bloqueur » qui évitera que le didgeridoo ne glisse vers l'avant. Ce bloqueur aura deux trous afin qu'il ne puisse pas pivoter sur lui-même et l'un d'eux permettra aussi de fixer le microphone.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Pourquoi avoir fait un ligne de trous pour le bloqueurs, plutôt que de fixer celui-ci directement ? Deux didgeridoos pouvant avoir des longueurs différents, je ferai un premier réglage de l'inclinaison de cette nouvelle tête via la rotule déjà existante sur le trépied (et sur laquelle cette nouvelle tête sera fixée à la place de l'ancienne) et ensuite je pourrai régler l'avancée (ou le recul selon comment on voit les choses) du bloqueur, donc du didgeridoo, pour que les embouchures (le côté où je souffle) soit toutes les deux à une hauteur convenable (je dois pouvoir être debout, les pieds bien ancrés au sol, le corps en position droite et la tête légèrement inclinée en avant afin de souffler confortablement et proprement).&lt;/p&gt;
&lt;h3 id="outils-et-materiaux"&gt;Outils et matériaux&lt;/h3&gt;
&lt;p&gt;En terme d'outils, il nous en faut deux, éventuellement trois :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;De quoi faire de la découpe (scie à onglet, scie circulaire, scie sauteuse ou bonne vieille scie à main) ;&lt;/li&gt;
&lt;li&gt;De quoi faire un peu de perçage (perceuse à colonne ou perceuse tout court) ;&lt;/li&gt;
&lt;li&gt;En option, pour faire plus propre, de quoi poncer (papier ponce, ponceuse à stationnaire ou encore toute autre option similaire).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personnellement, j'ai fait les « grandes » découpes à la scie circulaire, les plus petites à la scie sauteuse, les trous à la perceuse/visseuse et le ponçage à la ponceuse excentrique (j'ai eu la flemme de poser la stationnaire mais quand on aura notre atelier, elle sera bien plus accessible et agréable à utiliser).&lt;/p&gt;
&lt;p&gt;Pour ce qui est des matériaux, j'ai choisi :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Comme prévu, des chutes d'OSB 18mm et d'OSB 12mm ;&lt;/li&gt;
&lt;li&gt;Des boulons adaptés au diamètre de fixation de la tête et à l'épaisseur de mes chutes, sauf que je n'avais rien en 6mm donc j'ai utilisé du 4mm pour l'instant ;&lt;/li&gt;
&lt;li&gt;Des vis suffisantes pour finaliser le « bloqueur » (puisque sur mon super modèle 3D, on peut voir deux petites protubérances carrées afin de mieux caler le didgeridoo).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="le-resultat-et-les-futurs-changements"&gt;Le résultat et les futurs changements&lt;/h2&gt;
&lt;p&gt;Je n'ai aucunement pensé à prendre des photos pendant que je travaillais sur ce sujet donc je présente directement le résultat.&lt;/p&gt;
&lt;figure class="full-object"&gt;
&lt;p&gt;&lt;img src="/media/photos/trepied-ameliore-prototype.jpg" alt="Photo du même trépied mais avec la tête en OSB que j&amp;#39;ai fabriqué à la place de celle d&amp;#39;origine." /&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Voilà à quoi ressemble le trépied maintenant. N'ayant pas les fixations, j'ai scotché le « bloqueur » pour la photo.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Bon du coup, ça donne quoi ?&lt;/p&gt;
&lt;p&gt;Techniquement, ma satisfaction est mitigée : je n'ai pas encore trouvé de quoi sangler le didgeridoo et si celui-ci n'est pas assez « droit » dans sa conception our que le poids n'est pas plus élevée du côté de la cloche, il glisse par dessus la cale (le « bloqueur ») donc il tombe. &lt;span class="emoji" aria-hidden="true"&gt;😑&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Donc, que faire pour la suite ? Je sais déjà quelles sont mes prochaines étapes :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Modifier la cale pour avoir un genre de crochet, comme sur la tête d'origine (qui en a deux) afin de mieux tenir le didgeridoo ;&lt;/li&gt;
&lt;li&gt;Coller une bande de scratch (qui passerait sous la tête) pour pouvoir sangler le didgeridoo afin de le stabiliser latéralement ;&lt;/li&gt;
&lt;li&gt;Et bien sûr commander une mèche de diamètre 3/8" pour faire les trous correctement ;&lt;/li&gt;
&lt;li&gt;Enfin, commander aussi une tige filetée de diamètre 3/8" pour pouvoir faire les fixations de la cale et du microphone (n'ayant pas trouvé ce que je veux en "tout prêt").&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Pour mon premier point, j'aimerais éviter de réutiliser les crochets de la tête d'origine car ils sont un peu gros à mon goût et que pour deux didgeridoos, il m'en faudrait quatre au total alors que j'en ai qu'une paire.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Je pense déjà savoir comment je vais modifier la cale, potentiellement sans crochet, mais ce sera pour le « prochain épisode » ! &lt;span class="emoji" aria-hidden="true"&gt;😇&lt;/span&gt;
&lt;/p&gt;</content></entry><entry xml:lang="fr"><title>Switch de thème sans JavaScript</title><published>2024-02-16T00:00:00+00:00</published><updated>2024-02-16T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/theme-switch/"/><id>https://sam.candy.pm/articles/theme-switch/</id><content type="html" xml:base="https://sam.candy.pm/articles/theme-switch/">&lt;p&gt;En créant mon site, j'espérais parler peu de technologies et finalement, mes deux premiers sont dédiés à ça. Mais je sais déjà que le troisième sera sur une autre thématique.&lt;/p&gt;
&lt;p&gt;En attendant, pour lire cet article, il faut avoir quelques bases en HTML/CSS et éventuellement JavaScript. « Déso pas déso » comme on disait il fût un temps.&lt;/p&gt;
&lt;h2 id="l-objectif"&gt;L'objectif&lt;/h2&gt;
&lt;p&gt;Je souhaitais proposer un bouton qui permet de basculer entre un thème clair et un thème sombre. On trouve beaucoup d'exemples en ligne mais ils ne me convenaient pas pour deux raisons :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Soit ils utilisent beaucoup de JavaScript, hors je n'apprécie pas de mettre du JavaScript là où ça a peu de sens ;&lt;/li&gt;
&lt;li&gt;Soit ils ne permettaient pas de changer le thème de manière aussi complète que je le souhaitais (notamment avec le bouton un peu là où je le souhaites, voire un bouton dans le menu principal et un dans les informations de bas de page).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;En m'inspirant tout de même de ce que j'ai trouvé à droite et à gauche, mais aussi avec mes propres réfléxions, j'ai réussi à faire ce que je voulais. Je discuterais des avantages et inconvénients de ma solution à la fin de l'article.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Le sujet n'est pas de débattre de la bonne ou mauvaise utilisation de JavaScript, c'est une préférence personnelle. Je pense d'ailleurs qu'il peut être utile pour de petites choses mais tant que je peux faire sans, je m'applique à ne pas l'utiliser.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id="implementation-etape-par-etape"&gt;Implémentation étape par étape&lt;/h2&gt;
&lt;p&gt;Pour faire simple, les exemples que je vais montrer utilisent des couleurs très simplistes.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;J'utilise SCSS plutôt que CSS pour des raisons pratiques, toutefois les exemples sont en CSS pur (parce que pas tout le monde n'utilise SASS/SCSS).&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="un-theme-selon-la-preference-du-navigateur"&gt;Un thème selon la préférence du navigateur&lt;/h3&gt;
&lt;p&gt;Il est possible de régler une préférence entre le thème clair et le thème sombre dans le navigateur. La première étape est d'appliquer celle-ci.&lt;/p&gt;
&lt;p&gt;En CSS, la &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries"&gt;&lt;em&gt;media query&lt;/em&gt;&lt;/a&gt; &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme"&gt;&lt;code&gt;prefers-color-scheme&lt;/code&gt;&lt;/a&gt; permet d'obtenir cette préférence. En la combinant avec &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:root"&gt;l'élément &lt;code&gt;:root&lt;/code&gt;&lt;/a&gt; et les &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/var"&gt;variables CSS&lt;/a&gt;, on devrait pouvoir s'amuser un peu.&lt;/p&gt;
&lt;p&gt;Déjà, on peut simplement créer et appliquer des couleurs de thème clair :&lt;/p&gt;
&lt;pre data-linenos data-lang="css" class="language-css z-code"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;blue&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;body&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;background-color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;h1&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h2&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h3&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h4&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;strong&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Maintenant, préparons un peu le terrain avec des couleurs « inversées » qui seront utilisées pour le thème sombre, mais en utilisant seulement celles du thème clair :&lt;/p&gt;
&lt;pre data-linenos data-lang="css" class="language-css z-code"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;blue&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;red&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;body&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;background-color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;h1&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h2&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h3&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h4&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;strong&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Si vous avez regardé le lien qui documente &lt;code&gt;prefers-color-scheme&lt;/code&gt;, vous aurez vite compris qu'il devient facile d'appliquer les couleurs inversées quand le navigateur est configuré pour un thème clair :&lt;/p&gt;
&lt;pre data-linenos data-lang="css" class="language-css z-code"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;blue&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;red&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-at-rule z-media z-css"&gt;&lt;span class="z-keyword z-control z-at-rule z-media z-css"&gt;&lt;span class="z-punctuation z-definition z-keyword z-css"&gt;@&lt;/span&gt;media&lt;/span&gt; &lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;prefers-&lt;span class="z-support z-type z-property-name z-media z-css"&gt;color&lt;/span&gt;-scheme: dark&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt; &lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt; &lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;body&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;background-color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;h1&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h2&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h3&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h4&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;strong&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jusque là, on a donc un thème clair et un thème sombre, l'un ou l'autre étant appliqué selon la préférence du navigateur (normalement contrôlé par l'utilisatrice ou l'utilisateur de celui-ci, toutefois pas tout le monde ne connaît cette possibilité).&lt;/p&gt;
&lt;h4 id="theme-par-defaut"&gt;Thème par défaut&lt;/h4&gt;
&lt;p&gt;Il est volontaire de ma part de ne pas utiliser une requête &lt;code&gt;@media (prefers-color-scheme: light)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pourquoi ? Car si un navigateur ne supporte pas &lt;code&gt;prefers-color-scheme&lt;/code&gt;, ça évite de devoir faire une solution de secours. Toutefois, ce cher &lt;em&gt;Can I Use&lt;/em&gt; indique &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://caniuse.com/prefers-color-scheme"&gt;un support assez étendu&lt;/a&gt; (on ne remercie pas Internet Explorer et Opera Mini qui sont un peu en retard, leurs parts de marché rendant la chose peu problématique tout de même).&lt;/p&gt;
&lt;p&gt;Si le souhait est d'appliquer le thème sombre par défaut et le thème clair là où il est souhaité, il suffit d'inverser les valeurs par défaut pour utiliser le thème sombre et de changer la media query pour utiliser &lt;code&gt;@media (prefers-color-scheme: light)&lt;/code&gt; et d'y utiliser les couleurs claires.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Pour les besoins de cet article, je continuerai de mettre en place le thème clair par défaut et le thème sombre s'il est souhaité d'après la &lt;em&gt;media query&lt;/em&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="ajout-d-un-switch-en-pur-html-css-solution-habituelle"&gt;Ajout d'un switch en pur HTML/CSS : solution habituelle&lt;/h3&gt;
&lt;p&gt;J'expliquais au début de cet article que je souhaite répondre à une éventualité (que j'ai d'ailleurs appliqué sur ce site) : le besoin ou l'envie d'afficher plusieurs switchs.&lt;/p&gt;
&lt;p&gt;La technique purement HTML/CSS se base généralement sur le fait d'avoir un &lt;code&gt;&amp;lt;input type="checkbox"&amp;gt;&lt;/code&gt; et un &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; qui sont proches et qui précèdent le conteneur de l'application :&lt;/p&gt;
&lt;pre data-linenos data-lang="html" class="language-html z-code"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-html z-basic"&gt;&lt;span class="z-meta z-tag z-inline z-form z-html"&gt;&lt;span class="z-punctuation z-definition z-tag z-begin z-html"&gt;&amp;lt;&lt;/span&gt;&lt;span class="z-entity z-name z-tag z-inline z-form z-html"&gt;input&lt;/span&gt; &lt;span class="z-meta z-attribute-with-value z-html"&gt;&lt;span class="z-entity z-other z-attribute-name z-html"&gt;type&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-html"&gt;=&lt;/span&gt;&lt;span class="z-string z-quoted z-double z-html"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-html"&gt;&amp;quot;&lt;/span&gt;checkbox&lt;span class="z-punctuation z-definition z-string z-end z-html"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="z-meta z-attribute-with-value z-id z-html"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-html"&gt;id&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-html"&gt;=&lt;/span&gt;&lt;span class="z-string z-quoted z-double z-html"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-html"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-string z-quoted z-double z-html"&gt;&lt;span class="z-meta z-toc-list z-id z-html"&gt;theme-switch-state&lt;/span&gt;&lt;span class="z-punctuation z-definition z-string z-end z-html"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-definition z-tag z-end z-html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-html z-basic"&gt;&lt;span class="z-meta z-tag z-inline z-form z-html"&gt;&lt;span class="z-punctuation z-definition z-tag z-begin z-html"&gt;&amp;lt;&lt;/span&gt;&lt;span class="z-entity z-name z-tag z-inline z-form z-html"&gt;label&lt;/span&gt; &lt;span class="z-meta z-attribute-with-value z-html"&gt;&lt;span class="z-entity z-other z-attribute-name z-html"&gt;for&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-html"&gt;=&lt;/span&gt;&lt;span class="z-string z-quoted z-double z-html"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-html"&gt;&amp;quot;&lt;/span&gt;theme-switch-state&lt;span class="z-punctuation z-definition z-string z-end z-html"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-definition z-tag z-end z-html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;SWITCH&lt;span class="z-meta z-tag z-inline z-form z-html"&gt;&lt;span class="z-punctuation z-definition z-tag z-begin z-html"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="z-entity z-name z-tag z-inline z-form z-html"&gt;label&lt;/span&gt;&lt;span class="z-punctuation z-definition z-tag z-end z-html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-html z-basic"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-html z-basic"&gt;&lt;span class="z-meta z-tag z-block z-any z-html"&gt;&lt;span class="z-punctuation z-definition z-tag z-begin z-html"&gt;&amp;lt;&lt;/span&gt;&lt;span class="z-entity z-name z-tag z-block z-any z-html"&gt;div&lt;/span&gt; &lt;span class="z-meta z-attribute-with-value z-id z-html"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-html"&gt;id&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-html"&gt;=&lt;/span&gt;&lt;span class="z-string z-quoted z-double z-html"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-html"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-string z-quoted z-double z-html"&gt;&lt;span class="z-meta z-toc-list z-id z-html"&gt;content&lt;/span&gt;&lt;span class="z-punctuation z-definition z-string z-end z-html"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-definition z-tag z-end z-html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-block z-html"&gt;&lt;span class="z-punctuation z-definition z-comment z-begin z-html"&gt;&amp;lt;!--&lt;/span&gt; … &lt;span class="z-punctuation z-definition z-comment z-end z-html"&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-tag z-block z-any z-html"&gt;&lt;span class="z-punctuation z-definition z-tag z-begin z-html"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="z-entity z-name z-tag z-block z-any z-html"&gt;div&lt;/span&gt;&lt;span class="z-punctuation z-definition z-tag z-end z-html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cela permet de créer un fichier CSS simpliste, sans besoin d'utiliser &lt;code&gt;:root&lt;/code&gt; d'ailleurs :&lt;/p&gt;
&lt;pre data-linenos data-lang="css" class="language-css z-code"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt;&lt;span class="z-punctuation z-definition z-comment z-css"&gt;/*&lt;/span&gt; L&amp;#39;input est caché, on clique sur le label qui est très personnalisable &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*/&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;theme-switch-state&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-property-value z-css"&gt;none&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;content&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;blue&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;red&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-at-rule z-media z-css"&gt;&lt;span class="z-keyword z-control z-at-rule z-media z-css"&gt;&lt;span class="z-punctuation z-definition z-keyword z-css"&gt;@&lt;/span&gt;media&lt;/span&gt; &lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;prefers-&lt;span class="z-support z-type z-property-name z-media z-css"&gt;color&lt;/span&gt;-scheme: dark&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt; &lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;content&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt; &lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;theme-switch-state&lt;/span&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;checked&lt;/span&gt; &lt;span class="z-punctuation z-separator z-combinator z-css"&gt;~&lt;/span&gt; &lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;content&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;31&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;33&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;34&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-at-rule z-media z-css"&gt;&lt;span class="z-keyword z-control z-at-rule z-media z-css"&gt;&lt;span class="z-punctuation z-definition z-keyword z-css"&gt;@&lt;/span&gt;media&lt;/span&gt; &lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;prefers-&lt;span class="z-support z-type z-property-name z-media z-css"&gt;color&lt;/span&gt;-scheme: dark&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;35&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt; &lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;theme-switch-state&lt;/span&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;checked&lt;/span&gt; &lt;span class="z-punctuation z-separator z-combinator z-css"&gt;~&lt;/span&gt; &lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;content&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;36&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;37&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;39&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt; &lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;40&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sauf que ça force la création des éléments dans l'ordre et que du coup, si l'élément &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; est dans un menu, on ne peut déjà pas changer la couleur de ce menu.&lt;/p&gt;
&lt;p&gt;Ma solution se base donc sur le besoin (ou l'envie) de mettre le &lt;code&gt;&amp;lt;input type="checkbox" id="theme-switch-state"&amp;gt;&lt;/code&gt; où on souhaite et de créer autant de &lt;code&gt;&amp;lt;label for="theme-switch-state"&amp;gt;&lt;/code&gt; qu'on le désire, là où on le désire.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Pour rappel, un &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; est lié à un &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; quand la valeur du &lt;code&gt;for&lt;/code&gt; du &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; est égale à la valeur du &lt;code&gt;id&lt;/code&gt; du &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Un &lt;code&gt;id&lt;/code&gt; étant unique, mais un &lt;code&gt;for&lt;/code&gt; étant librement multiplié, on peut donc lier plusieurs &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; à un &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; unique.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="ajout-d-un-switch-en-pur-html-css-solution-miracle"&gt;Ajout d'un switch en pur HTML/CSS : solution « miracle »&lt;/h3&gt;
&lt;p&gt;Notons les guillemets du titre ci-dessus : il n'y a pas de solution miracle et j'évoquerais les inconvénients de ma solution à la fin de cet article.&lt;/p&gt;
&lt;p&gt;J'utilise simplement l'élément &lt;code&gt;:root&lt;/code&gt; avec le récent sélecteur &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:has"&gt;&lt;code&gt;:has&lt;/code&gt;&lt;/a&gt; et la (pas si récente) pseudo-class &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:checked"&gt;&lt;code&gt;:checked&lt;/code&gt;&lt;/a&gt;. Du coup, en gardant l'ID &lt;code&gt;theme-switch-state&lt;/code&gt; sur l'input, on peut écrire le code CSS suivant qui fonctionne :&lt;/p&gt;
&lt;pre data-linenos data-lang="css" class="language-css z-code"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;blue&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;black&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;white&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-support z-constant z-color z-w3c-standard-color-name z-css"&gt;red&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-light-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt;&lt;span class="z-punctuation z-definition z-comment z-css"&gt;/*&lt;/span&gt;*
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt; &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*&lt;/span&gt; Quand le thème est clair par défaut et qu&amp;#39;on a cliqué sur le label un nombre impair de fois (donc qu&amp;#39;on a coché l&amp;#39;input de type checkbox),
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt; &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*&lt;/span&gt; on change les variables de base pour utiliser les valeurs sombres
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt; &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*/&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;has&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;theme-switch-state&lt;/span&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;checked&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-at-rule z-media z-css"&gt;&lt;span class="z-keyword z-control z-at-rule z-media z-css"&gt;&lt;span class="z-punctuation z-definition z-keyword z-css"&gt;@&lt;/span&gt;media&lt;/span&gt; &lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;prefers-&lt;span class="z-support z-type z-property-name z-media z-css"&gt;color&lt;/span&gt;-scheme: dark&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt; &lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt; &lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;31&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt; &lt;span class="z-comment z-block z-css"&gt;&lt;span class="z-punctuation z-definition z-comment z-css"&gt;/*&lt;/span&gt;*
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;33&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt; &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*&lt;/span&gt; Quand le thème est sombre par défaut et qu&amp;#39;on a cliqué sur le label un nombre impair de fois (donc qu&amp;#39;on a coché l&amp;#39;input de type checkbox),
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;34&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt; &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*&lt;/span&gt; on change les variables de base pour utiliser les valeurs claires
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;35&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-comment z-block z-css"&gt; &lt;span class="z-punctuation z-definition z-comment z-css"&gt;*/&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;36&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt; &lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;root&lt;/span&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;has&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-other z-attribute-name z-id z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;#&lt;/span&gt;theme-switch-state&lt;/span&gt;&lt;span class="z-entity z-other z-pseudo-class z-css"&gt;&lt;span class="z-punctuation z-definition z-entity z-css"&gt;:&lt;/span&gt;checked&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;37&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;39&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-dark-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;40&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt; &lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;41&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;42&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;43&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;body&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;44&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;background-color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-background&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;45&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-foreground&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;46&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;47&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;48&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-selector z-css"&gt;&lt;span class="z-entity z-name z-tag z-css"&gt;h1&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h2&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h3&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h4&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;h5&lt;/span&gt;&lt;span class="z-punctuation z-separator z-sequence z-css"&gt;,&lt;/span&gt; &lt;span class="z-entity z-name z-tag z-css"&gt;strong&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;49&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt; &lt;span class="z-meta z-property-name z-css"&gt;&lt;span class="z-support z-type z-property-name z-css"&gt;color&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-key-value z-css"&gt;:&lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt; &lt;/span&gt;&lt;span class="z-meta z-property-value z-css"&gt;&lt;span class="z-meta z-function-call z-css"&gt;&lt;span class="z-support z-function z-var z-css"&gt;var&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-begin z-css"&gt;(&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-css"&gt;&lt;span class="z-punctuation z-definition z-custom-property z-css"&gt;--&lt;/span&gt;&lt;span class="z-support z-type z-custom-property z-name z-css"&gt;color-accent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-group z-css"&gt;&lt;span class="z-punctuation z-definition z-group z-end z-css"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-rule z-css"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-css"&gt;&lt;span class="z-meta z-property-list z-css"&gt;&lt;/span&gt;&lt;span class="z-punctuation z-section z-property-list z-css"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Et voilà, on a un bouton pleinement fonctionnel, en pur HTML/CSS, avec la possibilité de mettre plein de &lt;code&gt;&amp;lt;label for="theme-switch-state"&amp;gt;&lt;/code&gt; pour que nos visiteuses et visiteurs puissent changer le thème à volonté.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Libre à chacune et chacun de styliser le &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; (voire les si vous en mettez plusieurs) comme souhaité.&lt;/p&gt;
&lt;p&gt;Personnellement j'utilise &lt;code&gt;::before&lt;/code&gt; et &lt;code&gt;::after&lt;/code&gt; tout en exploitant la &lt;em&gt;media query&lt;/em&gt; &lt;code&gt;prefers-color-scheme: dark&lt;/code&gt; pour faire varier les choses ainsi que le &lt;code&gt;:root:has(#theme-switch-state:checked)&lt;/code&gt; que j'oppose à &lt;code&gt;:root:has(#theme-switch-state:not(:checked))&lt;/code&gt;. Oui, ça fait des sélecteurs assez particuliers.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id="sauvegarde-de-l-etat"&gt;Sauvegarde de l'état&lt;/h3&gt;
&lt;p&gt;Un inconvénient de cette méthode est que la &lt;code&gt;&amp;lt;input type="checkbox"&amp;gt;&lt;/code&gt; ne garde pas forcément son status coché ou décoché entre deux visites. Firefox a l'air de le garder si le cache n'est pas rafraichi en même temps que la page mais Chrome l'efface au moindre changement de page.&lt;/p&gt;
&lt;p&gt;Malheureusement (pour moi), je n'ai pas trouvé comment sauvegarder cet état sans JavaScript. Toutefois, le script est très simpliste : il se base sur le classique &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/fr/docs/Web/API/Window/localStorage"&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/a&gt; et la lecture de l'&lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://developer.mozilla.org/fr/docs/Web/API/EventTarget/addEventListener"&gt;évènement&lt;/a&gt; &lt;code&gt;change&lt;/code&gt; sur l'&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; qui gère l'état du thème.&lt;/p&gt;
&lt;p&gt;Déjà, posons les bases en écoutant les changements d'état de l'&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; et en l'enregistrant sur le &lt;code&gt;localStorage&lt;/code&gt; :&lt;/p&gt;
&lt;pre data-linenos data-lang="javascript" class="language-javascript z-code"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-var z-expr z-ts"&gt;&lt;span class="z-storage z-type z-ts"&gt;const&lt;/span&gt; &lt;span class="z-meta z-var-single-variable z-expr z-ts"&gt;&lt;span class="z-meta z-definition z-variable z-ts"&gt;&lt;span class="z-variable z-other z-constant z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-ts"&gt;=&lt;/span&gt; &lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;theme-switch-state&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt; &lt;span class="z-comment z-line z-double-slash z-ts"&gt;&lt;span class="z-punctuation z-definition z-comment z-ts"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-double-slash z-ts"&gt; la clé qu&amp;#39;on utilisera dans l&amp;#39;object storage&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-var z-expr z-ts"&gt;&lt;span class="z-storage z-type z-ts"&gt;const&lt;/span&gt; &lt;span class="z-meta z-var-single-variable z-expr z-ts"&gt;&lt;span class="z-meta z-definition z-variable z-ts"&gt;&lt;span class="z-variable z-other z-constant z-ts"&gt;themeState&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-ts"&gt;=&lt;/span&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;document&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;getElementById&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;theme-switch-state&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt; &lt;span class="z-comment z-line z-double-slash z-ts"&gt;&lt;span class="z-punctuation z-definition z-comment z-ts"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-double-slash z-ts"&gt; l&amp;#39;élément &amp;lt;input&amp;gt; qui contient notre état&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-variable z-other z-object z-ts"&gt;themeState&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;addEventListener&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;change&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-comma z-ts"&gt;,&lt;/span&gt;&lt;span class="z-meta z-arrow z-ts"&gt; &lt;span class="z-meta z-parameters z-ts"&gt;&lt;span class="z-punctuation z-definition z-parameters z-begin z-ts"&gt;(&lt;/span&gt;&lt;span class="z-punctuation z-definition z-parameters z-end z-ts"&gt;)&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-storage z-type z-function z-arrow z-ts"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-keyword z-control z-conditional z-ts"&gt;if&lt;/span&gt; &lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-object z-ts"&gt;themeState&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-variable z-property z-dom z-ts"&gt;checked&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;window&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-variable z-other z-object z-property z-ts"&gt;localStorage&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;setItem&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-readwrite z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;span class="z-punctuation z-separator z-comma z-ts"&gt;,&lt;/span&gt; &lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;checked&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="z-keyword z-control z-conditional z-ts"&gt;else&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;window&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-variable z-other z-object z-property z-ts"&gt;localStorage&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;removeItem&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-readwrite z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Comme &lt;code&gt;localStorage.setItem&lt;/code&gt; convertit tout en &lt;code&gt;String&lt;/code&gt;, j'enregistre directement une &lt;code&gt;String&lt;/code&gt;. Et comme je veux juste garder l'état &lt;code&gt;checked&lt;/code&gt; de l'&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, je me contente d'enregistrer le fait que la case est cochée. Si &lt;code&gt;localStorage.getItem(…)&lt;/code&gt; me renvoit une valeur, c'est que la case était cochée et si ça me renvoit &lt;code&gt;null&lt;/code&gt;, c'est que la case était décochée.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;On comprend facilement qu'il suffit alors d'utiliser &lt;code&gt;localStorage.getItem(…)&lt;/code&gt; au chargement de la page pour rétablir l'état du thème :&lt;/p&gt;
&lt;pre data-linenos data-lang="javascript" class="language-javascript z-code"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-keyword z-control z-conditional z-ts"&gt;if&lt;/span&gt; &lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;window&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-variable z-other z-object z-property z-ts"&gt;localStorage&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;getItem&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-readwrite z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt; &lt;span class="z-keyword z-operator z-comparison z-ts"&gt;!==&lt;/span&gt; &lt;span class="z-constant z-language z-null z-ts"&gt;null&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-variable z-other z-object z-ts"&gt;themeState&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-variable z-property z-dom z-ts"&gt;checked&lt;/span&gt; &lt;span class="z-keyword z-operator z-assignment z-ts"&gt;=&lt;/span&gt; &lt;span class="z-constant z-language z-boolean z-true z-ts"&gt;true&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt; &lt;span class="z-comment z-line z-double-slash z-ts"&gt;&lt;span class="z-punctuation z-definition z-comment z-ts"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-double-slash z-ts"&gt; c&amp;#39;est presque trop facile mais ça marche vraiment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Et voilà, on a une sauvegarde de l'état qui survit tant que le &lt;code&gt;localStorage&lt;/code&gt; n'est pas vidé !&lt;/p&gt;
&lt;p&gt;Voici le code complet, que j'encapsule dans un &lt;em&gt;scope&lt;/em&gt; parce que je suis un peu maniaque :&lt;/p&gt;
&lt;pre data-linenos data-lang="javascript" class="language-javascript z-code"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-comment z-line z-double-slash z-ts"&gt;&lt;span class="z-punctuation z-definition z-comment z-ts"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;span class="z-comment z-line z-double-slash z-ts"&gt; Ce script est chargé juste après la balise `&amp;lt;input type=&amp;quot;checkbox&amp;quot; id=&amp;quot;theme-switch-state&amp;quot;&amp;gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-storage z-type z-function z-ts"&gt;function&lt;/span&gt;&lt;span class="z-meta z-parameters z-ts"&gt;&lt;span class="z-punctuation z-definition z-parameters z-begin z-ts"&gt;(&lt;/span&gt;&lt;span class="z-punctuation z-definition z-parameters z-end z-ts"&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-var z-expr z-ts"&gt;&lt;span class="z-storage z-type z-ts"&gt;const&lt;/span&gt; &lt;span class="z-meta z-var-single-variable z-expr z-ts"&gt;&lt;span class="z-meta z-definition z-variable z-ts"&gt;&lt;span class="z-variable z-other z-constant z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-ts"&gt;=&lt;/span&gt; &lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;theme-switch-state&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-var z-expr z-ts"&gt;&lt;span class="z-storage z-type z-ts"&gt;const&lt;/span&gt; &lt;span class="z-meta z-var-single-variable z-expr z-ts"&gt;&lt;span class="z-meta z-definition z-variable z-ts"&gt;&lt;span class="z-variable z-other z-constant z-ts"&gt;themeState&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-keyword z-operator z-assignment z-ts"&gt;=&lt;/span&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;document&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;getElementById&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;theme-switch-state&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-comment z-block z-documentation z-ts"&gt;&lt;span class="z-punctuation z-definition z-comment z-ts"&gt;/**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-comment z-block z-documentation z-ts"&gt; * On pourrait faire ça sur un window.onload ou mieux, un window.addEventListener(&amp;#39;load&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-comment z-block z-documentation z-ts"&gt; * toutefois je souhaite que le thème soit appliqué au plus tôt donc je le fais de manière synchrone.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-comment z-block z-documentation z-ts"&gt; &lt;span class="z-punctuation z-definition z-comment z-ts"&gt;*/&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-keyword z-control z-conditional z-ts"&gt;if&lt;/span&gt; &lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;window&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-variable z-other z-object z-property z-ts"&gt;localStorage&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;getItem&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-readwrite z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt; &lt;span class="z-keyword z-operator z-comparison z-ts"&gt;!==&lt;/span&gt; &lt;span class="z-constant z-language z-null z-ts"&gt;null&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-variable z-other z-object z-ts"&gt;themeState&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-variable z-property z-dom z-ts"&gt;checked&lt;/span&gt; &lt;span class="z-keyword z-operator z-assignment z-ts"&gt;=&lt;/span&gt; &lt;span class="z-constant z-language z-boolean z-true z-ts"&gt;true&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-variable z-other z-object z-ts"&gt;themeState&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;addEventListener&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;change&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-punctuation z-separator z-comma z-ts"&gt;,&lt;/span&gt;&lt;span class="z-meta z-arrow z-ts"&gt; &lt;span class="z-meta z-parameters z-ts"&gt;&lt;span class="z-punctuation z-definition z-parameters z-begin z-ts"&gt;(&lt;/span&gt;&lt;span class="z-punctuation z-definition z-parameters z-end z-ts"&gt;)&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-storage z-type z-function z-arrow z-ts"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-keyword z-control z-conditional z-ts"&gt;if&lt;/span&gt; &lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-object z-ts"&gt;themeState&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-variable z-property z-dom z-ts"&gt;checked&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;window&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-variable z-other z-object z-property z-ts"&gt;localStorage&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;setItem&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-readwrite z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;span class="z-punctuation z-separator z-comma z-ts"&gt;,&lt;/span&gt; &lt;span class="z-string z-quoted z-single z-ts"&gt;&lt;span class="z-punctuation z-definition z-string z-begin z-ts"&gt;&amp;#39;&lt;/span&gt;checked&lt;span class="z-punctuation z-definition z-string z-end z-ts"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="z-keyword z-control z-conditional z-ts"&gt;else&lt;/span&gt; &lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-meta z-function-call z-ts"&gt;&lt;span class="z-support z-variable z-dom z-ts"&gt;window&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-variable z-other z-object z-property z-ts"&gt;localStorage&lt;/span&gt;&lt;span class="z-punctuation z-accessor z-ts"&gt;.&lt;/span&gt;&lt;span class="z-support z-function z-dom z-ts"&gt;removeItem&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-variable z-other z-readwrite z-ts"&gt;localStorageThemeSwitchKey&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-meta z-arrow z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt; &lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-source z-ts"&gt;&lt;span class="z-meta z-function z-expression z-ts"&gt;&lt;span class="z-meta z-block z-ts"&gt;&lt;span class="z-punctuation z-definition z-block z-ts"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;(&lt;/span&gt;&lt;span class="z-meta z-brace z-round z-ts"&gt;)&lt;/span&gt;&lt;span class="z-punctuation z-terminator z-statement z-ts"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On n'oublie pas de passer un outil de minification dessus, ça fait toujours quelques octets de gagnés. &lt;span class="emoji" aria-hidden="true"&gt;😉&lt;/span&gt;
&lt;/p&gt;
&lt;h2 id="avantages-et-inconvenients"&gt;Avantages et inconvénients&lt;/h2&gt;
&lt;p&gt;Ça fonctionne, c'est tout ce qu'on voulait. Mais il est bon de se poser la question : est-ce que c'est la solution parfait ? On sait déjà que la réponse est : ça n'existe pas. Alors quels avantages et inconvénients j'y trouve ?&lt;/p&gt;
&lt;p&gt;Les avantages selon mois :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S'adapte au thème choisi par défaut par la visiteuse ou le visiteur ;&lt;/li&gt;
&lt;li&gt;La sauvegarde de l'état est très simple à mettre en place ;&lt;/li&gt;
&lt;li&gt;On peut mettre autant de switchs qu'on veut puisque ce sont des &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; qui peuvent pointer vers la même &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les inconvénients de mon point de vue :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pour garder l'état, il faut un peu de JavaScript (je chipote beaucoup peut-être, c'est vraiment léger) ;&lt;/li&gt;
&lt;li&gt;Le sélecteur &lt;code&gt;:root:has(#theme-switch-state:checked)&lt;/code&gt;, surtout la partir &lt;code&gt;:root:has(…)&lt;/code&gt; doit être assez complexe à gérer pour le navigateur, je ne m'y connais pas assez pour savoir mais je sais que mon site n'a pas un DOM immense donc j'en déduis (peut-être maladroitement) que dans ce cas, ça ne doit pas être un problème réel ;&lt;/li&gt;
&lt;li&gt;La compatibilité n'est valable que pour les navigateurs très récents (en tout cas, au 16 février 2024), notamment le &lt;code&gt;:has(…)&lt;/code&gt; en CSS n'est pas supporté de partout (d'après &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://caniuse.com/css-has"&gt;Can I Use&lt;/a&gt;, au moment d'écrire ces lignes, on peut tabler sur presque 92% en global et presque 89% en France et pour une fois, c'est Firefox qui plombe un peu le score).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans ce qui me semble être un point d'amélioration sans être réellement un inconvénient, si une personne change sa préférence de thème sur son navigateur, ça va inverser le thème (puisque l'état sauvegardé ne dépend pas de la préférence du navigateur). C'est potentiellement indésiré et il faudrait avoir un script un peu plus intelligent qui utilise &lt;code&gt;window.matchMedia('(prefers-color-scheme: /* light|dark */)').matches&lt;/code&gt; pour garder l'état selon la préférence qui était en place. Toutefois, ça me semble très mineur et je préfère avoir un script le plus simple possible.&lt;/p&gt;</content></entry><entry xml:lang="fr"><title>Blog low tech et low maintenance</title><published>2024-02-09T00:00:00+00:00</published><updated>2024-02-09T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/articles/blog-low-tech/"/><id>https://sam.candy.pm/articles/blog-low-tech/</id><content type="html" xml:base="https://sam.candy.pm/articles/blog-low-tech/">&lt;h2 id="choix-de-la-plateforme"&gt;Choix de la plateforme&lt;/h2&gt;
&lt;h3 id="dis-comment-on-cree-un-blog"&gt;Dis, comment on crée un blog ? &lt;span class="emoji" aria-hidden="true"&gt;🤔&lt;/span&gt;
&lt;/h3&gt;
&lt;p&gt;Techniquement parlant, il y a de multiples façons de publier et gérer un blog. Peut-être pas autant de façon de faire que de personnes sur terre mais il y en a bien assez :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utiliser un &lt;em&gt;CMS&lt;/em&gt; (« Content Management System », traduisible par « Système de gestion de contenu »), le plus connu étant le fameux &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://wordpress.org/"&gt;WordPress&lt;/a&gt;, avec deux possibilité :
&lt;ul&gt;
&lt;li&gt;en l'installant et en l'hébergeant soi-même (par là, j'inclus le fait de passer par un hébergeur qui propose des facilités d'installation et de maintenance) ;&lt;/li&gt;
&lt;li&gt;en choisissant un service de gestion de contenu sans installation, d'ailleurs &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://wordpress.com/"&gt;WordPress en propose un sur wordpress.com&lt;/a&gt; mais on peut aussi évoquer des plateformes aux sources fermées comme &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://medium.com/"&gt;Medium&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Créer sa propre plateforme (et après, on peut même publier les sources ou encore en faire une plateforme d'hébergement payante &lt;span class="emoji" aria-hidden="true"&gt;🙃&lt;/span&gt;
) ;&lt;/li&gt;
&lt;li&gt;Utiliser un outil de génération statique et héberger ça là où ça nous intéresse (chez un hébergeur de contenu statique, sur un serveur chez un fournisseur cloud ou bien sur un serveur qu'on a chez soi).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà les solutions « habituelles », j'ai pu en oublier une ou deux moins courantes.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;De manière optionelle, pour les connaisseuses et connaisseurs, certains &lt;em&gt;CMS&lt;/em&gt; permettent maintenant d'utiliser le &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.w3.org/TR/activitypub/"&gt;protocole ActivityPub&lt;/a&gt; et donc de rendre ses articles visibles auprès de tout le &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://fr.wikipedia.org/wiki/Fediverse"&gt;fediverse (ou fédivers)&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Bien sûr, chaque personne ou entreprise choisira sa solution selon ses propres critères.&lt;/p&gt;
&lt;h3 id="mes-criteres"&gt;Mes critères&lt;/h3&gt;
&lt;p&gt;Justement, j'ai mes propres critères « de base ».&lt;/p&gt;
&lt;p&gt;Je souhaite respecter un objectif de faible consommation de ressources, c'est-à-dire que je ne veux pas une plateforme « usine à gaz » qui nécessiterait trop de puissance processeur ou de quantité de mémoire vive. J'ai déjà un serveur très peu cher (mais très peu performant) qui héberge le site statique de mon entreprise (vous me voyez venir, j'avais des critères similaires pour ce dernier), il m'arrangerait de mutualiser mon site dessus pour des raisons économiques et écologiques (surtout que je prévois très peu de traffic pour les deux sites).&lt;/p&gt;
&lt;p&gt;De manière un peu similaire, j'ai envie d'avoir pas ou peu de maintenance à faire (pour éviter de la consommation de mes ressources humaines, qui sont constituées de moi et qui dépendent fortement d'une liste de paramètre qui est trop longue pour être explicitée ici), ce qui sous-entend : pas trop de choses à mettre à jour, pas de migration lourde en cas de grosse mise à jour, pas trop de dépendances à installer.&lt;/p&gt;
&lt;p&gt;Aussi, j'apprécie vraiment l'utilisation d'un gestionnaire de version pour tout ce qui est code et j'ai tendance à trouver que c'est bien pratique au delà de ça, donc j'aimerais pouvoir stocker mes articles sur un dépôt &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://git-scm.com/"&gt;Git&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Éventuellement, j'aimerais une compatibilité ActivityPub mais c'est très optionnel et plutôt pour la satisfaction personnelle. Si toutefois ce critère n'est pas rempli, avoir la possibilité de générer des flux RSS/Atom me semble être le minimum.&lt;/p&gt;
&lt;p&gt;Enfin, je veux que la solution soit open source, parce qu'il y en a plein et que ça me ferait mal de choisir une plateforme propriétaire quand il y a du choix libre.&lt;/p&gt;
&lt;h3 id="qu-est-ce-qui-nous-reste"&gt;Qu'est-ce qui nous reste ?&lt;/h3&gt;
&lt;p&gt;De là, ça filtre :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les solutions qui utilisent une base de données, parce que soit je dois la gérer (donc ça me coûte en ressources personnelles de l'ordre de la charge de travail), soit je dois en prendre une gérée par un fournisseur (donc ça me coûte en ressources personnelles de type financières) ;&lt;/li&gt;
&lt;li&gt;Les solutions qui utilisent un langage interprété, comme PHP/Ruby/Python, parce que ça rajoute une dépendance lourd (on notera que je prône la conteneurisation donc la gestion peut être simplifiée, mais ça reste du CPU et de la RAM à consommer pour peu de choses).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il reste donc :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les générateurs de sites statiques, ça reste un peu de travail mais beaucoup moins (et rappelons que j'ai un déjà serveur pour un autre site statique donc ce sera mutualisé) ;&lt;/li&gt;
&lt;li&gt;Les solutions hébergées qui utilisent un &lt;em&gt;CMS&lt;/em&gt; open source comme plateforme.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bref, j'ai choisi un générateur de site statique. Et comme il faut en choisir un seul alors qu'il y en a plétore, j'utilise &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.getzola.org/"&gt;Zola&lt;/a&gt; car il correspond à mes critères et pour d'autres raisons qui nécessiteraient presque un nouvel article.&lt;/p&gt;
&lt;h2 id="maintenant-l-hebergement"&gt;Maintenant, l'hébergement&lt;/h2&gt;
&lt;p&gt;Tout ça c'est chouette et en sautant quelques étapes, admettons que j'ai maintenant mes fichiers HTML et CSS qui sont générés, comment je les déploie et comment je les sers ?&lt;/p&gt;
&lt;p&gt;Déjà, je réutilise le serveur que j'ai cité plus haut et qui me coûte presque rien (ce n'est pas de la radinerie, c'est du bon sens).&lt;/p&gt;
&lt;p&gt;En terme de logiciels, j'ai besoin d'un simple serveur HTTP qui permet de délivrer des fichiers statiques. Je dois aussi pouvoir configurer le HTTPS dessus : on est en 2024, ça fait presque dix ans qu'on peut avoir des certificats gratuits avec Let's Encrypt donc il est inconcevable de ne pas mettre en place du HTTPS (si vous voyez un site qui ne propose toujours pas du HTTPS, fuyez ne serait-ce que pour le principe, mais je m'égare).&lt;/p&gt;
&lt;p&gt;Ça tombe bien, j'ai fait le choix de la simplicité sur la machine virtuelle que j'ai déjà : on y trouve &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.debian.org/"&gt;Debian&lt;/a&gt; et &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://podman.io/"&gt;Podman&lt;/a&gt;. Et grâce à un conteneur lancé par ce dernier, &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt; tourne en dernière version.&lt;/p&gt;
&lt;p&gt;Caddy, c'est un serveur HTTP à la configuration très simpliste et lisible, qui intègre l'automatisation de la gestion des certificats HTTPS avec le protocole ACME (en utilisant Let's Encrypt par défaut). Il fait donc tout le travail dont j'ai besoin. Et pour prouver que c'est facile, voici la base de mon &lt;code&gt;Caddyfile&lt;/code&gt;, le fichier de configuration de Caddy :&lt;/p&gt;
&lt;pre data-linenos class="z-code"&gt;&lt;code&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# redirection permanente de ces deux domaines vers le domaine principal
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;candy.pm, www.candy.pm {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; redir https://sam.candy.pm{uri} permanent
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# le fameux domaine pricinpal
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;sam.candy.pm {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; encode zstd gzip # activation de la compression du contenu envoyé en HTTP
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; root * /var/www/sam.candy.pm # chemin du dossier qui contient les fichiers statiques
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; file_server # quand un chemin fini par /, on tente index.html
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sans aucune indication spécifique, Caddy va tenter de générer les certificats HTTPS pour tous les domaines listés automatiquement. Fini le &lt;code&gt;certbot&lt;/code&gt; ou autre (qui ne donnait pas un travail fastidieux mais il fallait configurer le serveur HTTP, tout ça… Bref, il fallait faire des choses et j'ai horreur de faire des choses &lt;span class="emoji" aria-hidden="true"&gt;🥱&lt;/span&gt;
) !&lt;/p&gt;
&lt;p&gt;De manière un peu plus complète, j'y ai ajouté la gestion du cache et des pages d'erreurs :&lt;/p&gt;
&lt;pre data-linenos class="z-code"&gt;&lt;code&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# les règles de caches : 90 jours pour les polices d&amp;#39;écritures, 30 jours pour les images
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;(cache) {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; @image {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; path *.svg *.png *.jpg *.jpeg *.gif *.ico
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; @font {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; path *.ttf *.eot *.woff2
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; header @font Cache-Control &amp;quot;public, no-transform, max-age=7776000&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; header @image Cache-Control &amp;quot;public, no-transform, max-age=2592000&amp;quot;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# la gestion des erreurs, il faut donc bien avoir un fichier 404.html et un 500.html
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;(errors_handling) {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; handle_errors {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; @404 {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; expression {http.error.status_code} == 404
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; @500 {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; expression {http.error.status_code} == 500
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; rewrite @404 /404.html
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; rewrite @500 /500.html
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; file_server
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; }
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;31&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;32&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;33&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# redirection permanente de ces deux domaines vers le domaine principal
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;34&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;candy.pm, www.candy.pm {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;35&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; redir https://sam.candy.pm{uri} permanent
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;36&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;37&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;# le fameux domaine pricinpal
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;39&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;sam.candy.pm {
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;40&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; encode zstd gzip # activation de la compression du contenu envoyé en HTTP
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;41&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; root * /var/www/sam.candy.pm # chemin du dossier qui contient les fichiers statiques
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;42&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt; file_server # quand un chemin fini par /, on tente index.html
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;43&lt;/td&gt;&lt;td&gt;&lt;span class="z-text z-plain"&gt;}
&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ce Caddyfile est dans un dépôt Git, le site Zola a son propre dépôt.&lt;/p&gt;
&lt;p&gt;Et voilà, cet article est donc sur tous les écrans qui le désirent grâce à Zola, Debian, Podman et Caddy.&lt;/p&gt;
&lt;h2 id="pour-plus-tard"&gt;Pour plus tard&lt;/h2&gt;
&lt;p&gt;Actuellement, je gère tout ça avec une certaine flemme, parce que c'était un des objectifs principaux (pas d'avoir la flemme mais de composer avec). Sauf que je suis irrécupérable et que je sais qu'un jour, je changerai complètement ma manière d'héberger tout ça.&lt;/p&gt;
&lt;p&gt;Pour l'instant, j'utilise un conteneur pour Caddy qui gère tous mes sites. Mais à terme j'espère avoir une architecture de qualité encore plus professionnelle :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chaque site (actuellement deux) serait dans son propre conteneur ;&lt;/li&gt;
&lt;li&gt;Les conteneurs ne feraient que lancer un &lt;code&gt;zola build&lt;/code&gt; en premier « &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://docs.docker.com/build/building/multi-stage/"&gt;stage&lt;/a&gt; » et récupérer les fichiers résultants dans un deuxième &lt;em&gt;stage&lt;/em&gt;, avec un simple serveur HTTP (sans HTTPS) comme commande par défaut ;&lt;/li&gt;
&lt;li&gt;Du coup, le serveur frontal ne servirait plus des fichiers statiques mais aurait plutôt un rôle de proxy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jusque là, on pourrait trouver peu d'intérêt à cette évolution. Pour mieux comprendre, voici deux rappels : je n'aime pas maintenir les choses et là, je dois maintenir un serveur Debian ainsi que mettre à jour le conteneur de Caddy. Du coup, pour héberger des fichiers statiques je pourrais me contenter de &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt; ou équivalent.&lt;/p&gt;
&lt;p&gt;Mais je n'aime pas trop ces plateformes, je ne saurais pas vraiment expliquer pourquoi, c'est peut-être simplement « pas mon genre ».&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Je ne saurais vraiment pas dire pourquoi ces plateformes ne me tentent pas, pour autant elles ont l'air très qualitative et je les recommande pour des projets similaires à mon site.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Je compte plutôt exploiter les connaissances que j'utilise professionnellement pour faire évoluer mon hébergement vers une solution d'orchestration de conteneurs avec un cluster Kubernetes auto-géré chez un fournisseur cloud français (certainement &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.ovhcloud.com/fr/public-cloud/kubernetes/"&gt;OVH&lt;/a&gt; ou &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://www.scaleway.com/fr/kubernetes-kapsule/"&gt;Scaleway&lt;/a&gt;) dans lequel j'installerai la &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://gateway.envoyproxy.io/"&gt;gateway Envoy&lt;/a&gt; avec &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://cert-manager.io/"&gt;cert-manager&lt;/a&gt; pour versionner le routage et automatiser le TLS. Oui, ça a l'air de faire « usine à gaz », pas très « low tech » (mais quand même « low maintenance » puisque le cluster serait infogéré). Pour couronner le tout, je ferais fonctionner &lt;a rel="noopener nofollow noreferrer" target="_blank" href="https://docs.renovatebot.com/"&gt;Renovate&lt;/a&gt; pour automatiser la mise à jour des dépendances sus-citées.&lt;/p&gt;
&lt;p&gt;Pour autant, c'est un projet qui n'a pas lieu d'être actuellement pour quelques raisons :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le fonctionnement actuel me convient ;&lt;/li&gt;
&lt;li&gt;Le coût de mon serveur actuel est dérisoire et ce serait dommage de payer plus cher ;&lt;/li&gt;
&lt;li&gt;Tant que je n'ai pas de besoins au delà de l'hébergement de fichiers statiques, ça ne vaudra donc pas les efforts que ça me demanderait ni le coût.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bref, c'est une ouverture que je regarde de loin pour l'instant et que j'approcherais quand j'aurais des besoins plus « importants » (le choix du futur conditionnel n'est pas anodin ici). En attendant, mon petit Caddy dans un conteneur m'est amplement suffisant (et je m'attache même un peu à lui).&lt;/p&gt;</content></entry><entry xml:lang="fr"><title>Premier essai</title><published>2024-02-03T00:00:00+00:00</published><updated>2024-02-11T00:00:00+00:00</updated><author><name>
Sam Candy</name></author><link rel="alternate" type="text/html" href="https://sam.candy.pm/experiences-sonores/2024-02-03/"/><id>https://sam.candy.pm/experiences-sonores/2024-02-03/</id><content type="html" xml:base="https://sam.candy.pm/experiences-sonores/2024-02-03/">
&lt;div class="widgets-grid" data-max-columns="2"&gt;
&lt;div class="widget"&gt;
&lt;h2 id="instrument-et-materiel-utilises"&gt;Instrument et matériel utilisés&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dideridoo « Dark Vador » (en Do) ;&lt;/li&gt;
&lt;li&gt;Microphone Shure SM57 ;&lt;/li&gt;
&lt;li&gt;Loopstation Boss RC-202.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="widget"&gt;
&lt;h2 id="formats-et-qualite-des-fichiers"&gt;Formats et qualité des fichiers&lt;/h2&gt;
&lt;p&gt;Tous les fichiers sont au format FLAC, en échantillonnage de 44100Hz sur une profondeur de 16 bits. Il n'y a pas de stéréophonie, tout est en mono.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Voilà donc les premiers enregistrement de mes expériences musicales que j'ai recoupé et publié. Au total, c'est environ une heure de bruit que j'ai découpé à la hache pour proposer à peu près un quart d'heure ici (je m'attendais à plus de pertes que ça, et pourtant j'ai réduit certaines boucles &lt;span class="emoji" aria-hidden="true"&gt;😌&lt;/span&gt;
).&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Sauf mention contraire, je n'ai pas activé de filtre sur la loopstation (qui en propose un bon nombre) excepté un compresseur pour que le niveau d'entrée reste assez lisse entre le beatbox et les divers sons du didgeridoo. Je pense d'ailleurs pouvoir faire un peu mieux sur ce point, j'apprends encore.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Allez, ça commence par un léger test sonore avec le didgeridoo.&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;01_warm-up.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Petit échauffement, qui fini sur un léger cafouillage.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Dans les deux extraits qui suivent, j'utilise la loopstation pour créer un rythme de base et je joue par dessus au didgeridoo.&lt;/p&gt;
&lt;aside class="note" data-type="Note"&gt;
&lt;p&gt;Tous les rythmes « beatbox » sont fait par moi-même, au travers du didgeridoo (d'où une petite résonance).&lt;/p&gt;
&lt;/aside&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;02_first-loop.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Une première utilisation de la loopstation.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;03_second-loop-bizarre.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Encore de la loopstation, avec un style un peu « bizarre » (pas le genre de choses que j&amp;#x27;écouterais mais apparemment le genre de choses que je produits intuitivement).&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;04_first-interlude.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Petit interlude pour m&amp;#x27;amuser.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Ensuite, j'ai tenté de faire des boucles d'abord avec du didgeridoo, sur lesquelles j'ai apposé mes rythmes. C'est un peu « chiant » de faire un rythme parfaitement continu sur la loopstation (je ne la maîtrise pas assez probablement) donc j'ai fait quelques petites corrections au montage pour ne pas avoir de « croisements » entre les boucles.&lt;/p&gt;
&lt;p&gt;J'en ai profité pour mettre des fondus de fermeture (la vérité étant que je ne savais pas trop comment les finir donc le montage m'a permis de rattraper &lt;span class="emoji" aria-hidden="true"&gt;😁&lt;/span&gt;
).&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;05_third-loop-with-fades-out.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Dans cet extrait, les décalages dans le rythme sont involontaires mais ont créé quelque chose que je trouvais finalement sympa.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;06_forth-loop-with-effect-and-fades-out.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Cette boucle est un peu hasardeuse, j&amp;#x27;y ai testé un effet de la loopstation (ça descend la note d&amp;#x27;entrée d&amp;#x27;un octave) mais c&amp;#x27;est un essai plutôt insatisfaisant et je trouve le résultat peu intéressant.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Par la suite, j'ai fait une boucle dans laquelle je pose d'abord un rythme en beatbox et ensuite je fais de même avec le didgeridoo. Puis sur la fin je rajoute de nouveau un peu de beatbox (j'espérais ainsi tester une superposition « alternée »).&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;07_loop-again.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;La fin est un peu soudaine parce que je ne savais encore pas comment finir. Je dois vraiment apprendre à clôturer ce que je fais !&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Et j'ai fini par tenter d'enchaîner les choses, c'est un peu n'importe quoi (surtout à la fin) mais je dois avouer que je trouve certaines parties du morceau assez intéressantes !&lt;/p&gt;
&lt;figure class="audio"&gt;
&lt;audio controls src="&amp;#x2F;audio&amp;#x2F;2024-02-03&amp;#x2F;08_loop-final.flac"&gt;&lt;/audio&gt;
&lt;figcaption&gt;Je ne sais pas comment on nomme ce style de musique mais je me demande si des artistes produisent et vendent ça de manière professionnelle, c&amp;#x27;est intéressant.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;De ces premières expérimentations, je conclus qu'il serait sympa de jouer avec deux ou trois didgeridoos de notes différentes. Ça tombe bien, j'ai commandé un « La » ! &lt;span class="emoji" aria-hidden="true"&gt;😇&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Aussi, je pense que j'aimerais essayer une stomp box pour me passer de la loopstation par moment. D'ailleurs, cette dernière est vite limitée avec ses deux pistes, toutefois les modèles avec plus de pistes sont bien plus onéreux et généralement plus complexe (l'idéal serait une Boss RC-505 pour garder les habitudes mais à 500€ ça fait cher pour mon niveau actuel).&lt;/p&gt;
&lt;p&gt;Enfin, il faut aussi que j'apprenne à mieux utiliser le logiciel de montage, mais ça c'est un autre problème ! &lt;span class="emoji" aria-hidden="true"&gt;😅&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;J'espère recommencer l'expérience bientôt mais le montage prend du temps, ça attendra donc un peu que j'avance sur certains travaux à la maison. &lt;span class="emoji" aria-hidden="true"&gt;👷&lt;/span&gt;
&lt;/p&gt;</content></entry></feed>