/*
 * CSS personnalisé — instance Catodon d'Antoine.
 * À coller dans Réglages > CSS personnalisé, puis recharger.
 *
 * PORTÉE : cette préférence vit dans le stockage local du navigateur. Le fichier
 * ne s'applique donc qu'à ce compte, sur cet appareil, et à personne d'autre sur
 * l'instance. Il est à recoller sur chaque appareil.
 *
 * RÈGLE D'ÉCRITURE : les classes des composants sont des modules CSS de la forme
 * `<fichier>-<classe>-<hash>`, par exemple `navbar-post-plJN`. Le hash dérive du
 * chemin du fichier et du nom de la classe, pas de leur contenu : il ne bouge
 * donc qu'au renommage ou au déplacement, ce qui arrive au fil des mises à jour.
 *
 * On vise en priorité ce qui ne bouge pas du tout : les variables `--MI-*`, les
 * classes globales (`_link`), les attributs posés par le code
 * (`data-selectable-note-content`, `data-navbar-item`, `data-cy-open-post-form`)
 * et les routes (`/tags/`). Quand rien de tel n'existe, on vise le préfixe et
 * jamais le hash : `[class*="navbar-iconOnly-"]` survit à un changement de hash,
 * `.navbar-iconOnly-ghTi` non.
 *
 * CASCADE, à connaître avant d'ajouter une règle : le CSS personnalisé est
 * injecté hors de `@layer base`, donc il bat toujours `style.scss`, qui y est
 * enfermé — c'est pourquoi les variables ci-dessous se redéfinissent sans effort.
 * Mais les styles des composants Vue ne sont PAS dans cette couche : face à eux,
 * c'est la spécificité qui tranche, et une règle de composant comme
 * `.root.iconOnly .item:hover::before` bat un simple `[data-navbar-item]::before`.
 * D'où les quelques `!important` ci-dessous, chacun signalé.
 */

/* ------------------------------------------------------------------ POLICE */

/*
 * Luciole, dessinée pour la basse vision, avec repli sur la police système.
 *
 * `local()` d'abord : si la police est installée sur l'appareil, rien n'est
 * téléchargé. Sinon, décommente les `url()` et remplace-les par les fichiers
 * hébergés sur ton instance (le Drive fait très bien l'affaire) — sans quoi
 * l'appareil retombera silencieusement sur la police système.
 */
@font-face {
	font-family: 'Luciole';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: local('Luciole'), local('Luciole-Regular');
	/* , url('https://catodon-dev.antoined.fr/files/xxx.woff2') format('woff2') */
}

@font-face {
	font-family: 'Luciole';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: local('Luciole Bold'), local('Luciole-Bold');
}

@font-face {
	font-family: 'Luciole';
	font-style: italic;
	font-weight: 400;
	font-display: swap;
	src: local('Luciole Italic'), local('Luciole-Italic');
}

@font-face {
	font-family: 'Luciole';
	font-style: italic;
	font-weight: 700;
	font-display: swap;
	src: local('Luciole Bold Italic'), local('Luciole-BoldItalic');
}

/*
 * `:not(.useSystemFont)` pour que le réglage « utiliser la police du système »
 * continue de fonctionner : sans lui, ce fichier l'écraserait, puisqu'il est
 * hors couche et gagne sur tout.
 */
html:not(.useSystemFont) {
	font-family: 'Luciole', system-ui, sans-serif;
}

/* ------------------------------------------------------------------ FORMES */

/*
 * Échelle de rayons Material Design 3, avec 24 px comme valeur de base, celle
 * qu'utilisent les conteneurs principaux (`--MI-radius`).
 *
 * Catodon a huit crans, MD3 en propose une échelle discrète (4, 8, 12, 16, 20,
 * 24, 28, 32, 40, 48) : chaque cran est aligné sur une valeur de cette échelle
 * plutôt que sur un multiple arbitraire, pour que les tailles restent
 * cohérentes entre elles. Par comparaison, le défaut de Catodon part de 26 px et
 * monte à 56 px, soit plus rond et plus étalé.
 *
 * Les deux derniers crans ne bougent pas : `ellipse` sert aux pastilles et aux
 * boutons en capsule, `full` aux avatars ronds.
 */
:root {
	--MI-radius-xs: 8px;
	--MI-radius-sm: 16px;
	--MI-radius: 24px;
	--MI-radius-md: 28px;
	--MI-radius-lg: 32px;
	--MI-radius-xl: 40px;
}

/* ------------------------------------------------------- BARRE LATÉRALE */

/*
 * Des rectangles arrondis à la place des gélules.
 *
 * Le fond d'une entrée n'est pas peint sur l'entrée elle-même mais sur un
 * `::before` posé en `border-radius: 999px`, d'où la forme de gélule. Même
 * chose pour le bouton de publication. On ne redéfinit donc pas un rayon sur
 * l'élément, qui n'en a aucun, mais sur ce pseudo-élément.
 *
 * Ancres stables : `data-navbar-item` sur chaque entrée du menu et
 * `data-cy-open-post-form` sur le bouton de publication, deux attributs posés
 * par le code.
 *
 * En barre réduite, aucune règle supplémentaire n'est nécessaire : le composant
 * y dessine déjà ces fonds carrés (`height: 100%; aspect-ratio: 1`, 52 px pour
 * le bouton de publication), et seul leur rayon en faisait des cercles.
 */
/*
 * Un bouton de publication plus haut, seulement quand la barre est déployée : en
 * mode réduit il est déjà un carré de 52 px, qu'il n'y a pas lieu d'étirer.
 *
 * C'est le seul endroit du fichier où aucun attribut ne permet de distinguer les
 * deux modes : la classe du mode réduit est la seule marque disponible, visée par
 * son préfixe.
 */
[class*="navbar-root-"]:not([class*="navbar-iconOnly-"]) [data-cy-open-post-form] {
	/* `!important` faute de mieux : la règle du composant est
	 * `.navbar-root-x:not(.navbar-iconOnly-y) .navbar-post-z`, soit exactement la
	 * même spécificité que celle-ci (0-3-0), et sa feuille est insérée après le
	 * CSS personnalisé. À égalité, c'est le dernier arrivé qui gagne. */
	height: 4rem !important;

	/* Le composant aligne ce bouton à gauche ; centré, il tient mieux la largeur
	 * de la barre. */
	text-align: center !important;
}

/* L'icône porte un `margin-left: 30px` qui pousse l'ensemble vers la droite du
 * centre : sans le neutraliser, « centré » ne l'est pas vraiment. La marge de
 * droite reste, elle sépare l'icône du libellé. */
[class*="navbar-root-"]:not([class*="navbar-iconOnly-"]) [data-cy-open-post-form] i {
	margin-left: 0 !important;
}

[data-navbar-item]::before,
[data-cy-open-post-form]::before {
	/* `!important` parce que la règle d'origine vit dans le composant, donc hors
	 * couche : sans lui, `.root.iconOnly .item:hover::before` l'emporte. */
	border-radius: var(--MI-radius-sm) !important;
}

/* ------------------------------------------------------------- LIBELLÉS */

/*
 * « Kwak ?! » sur les deux boutons de publication.
 *
 * Le texte d'origine n'est pas supprimé mais réduit à une taille nulle : il
 * reste dans l'arbre d'accessibilité, donc un lecteur d'écran continue
 * d'annoncer le vrai libellé. C'est le seul moyen honnête de faire ça en CSS,
 * qui ne remplace pas du texte mais en dessine par-dessus.
 *
 * À savoir : le bouton d'envoi affiche « Répondre », « Citer » ou « Modifier »
 * selon le contexte, et cette règle les remplace aussi, faute de pouvoir viser
 * un libellé plutôt qu'un autre en CSS. Si ça gêne, retirer le second sélecteur
 * ne laissera l'effet que sur le bouton qui ouvre le formulaire.
 */
[data-cy-open-post-form] span,
[data-cy-open-post-form-submit] span {
	/* `!important` obligatoire : les composants fixent eux-mêmes la taille de ce
	 * texte, avec une spécificité supérieure. Sans lui, le libellé d'origine reste
	 * affiché et « Kwak ?! » vient s'y coller. */
	font-size: 0 !important;
}

[data-cy-open-post-form] span::after,
[data-cy-open-post-form-submit] span::after {
	content: "Kwak\A0?!";
	/* En rem et non en em : le parent est à zéro, un em le serait aussi. */
	font-size: 1rem;
}

/* --------------------------------------------------- COLONNE VISITEUR */

/*
 * La colonne d'accueil affichée aux personnes non connectées : bannière et
 * encart d'inscription, à côté du contenu demandé.
 *
 * À savoir : ce fichier est une préférence de navigateur. La règle vaut donc
 * pour ce navigateur, y compris déconnecté, mais pas pour les visiteurs de
 * l'instance, qui continueront de voir la colonne. L'épurer pour eux demanderait
 * de toucher au thème par défaut ou au HTML servi.
 */
[class*="visitor-side"] {
	display: none;
}

/* ----------------------------------------------- APERÇU DE BIO DANS UN POST */

/*
 * Masquer la première ligne de la bio de l'auteur, affichée sous son nom en tête
 * de chaque post. Aucun réglage ne la gouverne : elle apparaît dès que le compte
 * a une bio.
 *
 * Visé par le conteneur, et non par le composant lui-même, parce que le même
 * aperçu sert ailleurs et y est utile : sur les demandes de suivi, où la bio est
 * ce qui permet de décider, et sur les cartes de compte ou de marque-page. Ces
 * écrans-là ne sont pas touchés.
 */
[class*="SkNoteHeader-"] > [class*="MkUserBioPreview-bioWrapper"],
[class*="SkNoteDetailed-"] > [class*="MkUserBioPreview-bioWrapper"] {
	display: none;
}

/* ---------------------------------------------- BARRE D'ACTION D'UN POST */

/*
 * Premier bouton collé à gauche, dernier collé à droite, le reste au centre.
 *
 * Le pied est déjà une rangée flex : deux marges automatiques suffisent, elles
 * absorbent tout l'espace disponible de part et d'autre du groupe central. Pas
 * besoin de toucher au `justify-content` du composant, une marge automatique
 * l'emporte sur lui.
 *
 * Viser `:first-child` et `:last-child` ne marche pas : le composant réordonne
 * ces boutons avec `order`, si bien que le premier du DOM n'est pas celui de
 * gauche. On vise donc les boutons par leur rôle. Le menu est le dernier dans
 * les deux ordres proposés par les réglages ; le premier, lui, en dépend, d'où
 * les deux cas ci-dessous.
 *
 * Visé par préfixe de classe, faute d'attribut ici : `SkNote-footer` ne désigne
 * que le pied d'un post de timeline. Celui de la vue détaillée est une autre
 * classe (`SkNoteDetailed-footer`), que ce sélecteur ne touche pas.
 */
[class*="SkNote-footer"] > [class*="SkNote-actionMenu"] {
	margin-left: auto;
}

[class*="SkNote-footer"][class*="postActionsOrderCatodon"] > [class*="SkNote-actionReact"],
[class*="SkNote-footer"]:not([class*="postActionsOrderCatodon"]) > [class*="SkNote-actionReply"] {
	margin-right: auto;
}

/* -------------------------------------------------- LIENS ET HASHTAGS -----
 *
 * Les mentions sont déjà des pastilles nativement : ce bloc donne la même forme
 * aux liens et aux hashtags, pour que les trois se lisent pareil dans un post.
 */

[data-selectable-note-content] ._link,
[data-selectable-note-content] a[href^="/tags/"] {
	/* Le fond dérive de `currentColor`, donc une seule règle habille le lien
	 * comme le hashtag, chacun gardant sa propre couleur de thème. C'est aussi ce
	 * qui évite un `!important` : la couleur du hashtag est posée en style inline
	 * par le rendu MFM, et on ne cherche pas à la remplacer, seulement à la lire. */
	background: color(from currentColor srgb r g b / 0.1);

	/* Sans `border-box`, le padding se rajoute à `max-width: 100%` et la pastille
	 * dépasse sa colonne d'exactement sa valeur. Catodon n'a pas de reset. */
	box-sizing: border-box;
	max-width: 100%;
	padding: 4px 8px;

	/* Une pastille est plus haute que sa ligne de texte, et une ligne grandit tout
	 * juste assez pour contenir son plus grand élément : sans cette marge, deux
	 * pastilles de lignes voisines se touchent bord à bord. C'est la boîte de
	 * marge qu'une ligne doit contenir, d'où l'effet. */
	margin-block: 2px;

	border-radius: var(--MI-radius-ellipse, 999px);
	text-decoration: none;
}

[data-selectable-note-content] ._link:hover,
[data-selectable-note-content] a[href^="/tags/"]:hover {
	background: color(from currentColor srgb r g b / 0.2);
	text-decoration: none;
}

/* Un hashtag ne se coupe pas : il tient sur une ligne ou il est raccourci. */
[data-selectable-note-content] a[href^="/tags/"] {
	display: inline-block;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	/* `overflow` autre que `visible` déplace la ligne de base d'un inline-block
	 * sur le bas de sa boîte : sans ça, la pastille remonte d'une douzaine de
	 * pixels par rapport au texte qui l'entoure. */
	vertical-align: middle;
	/* `html *` distribue `scrollbar-gutter: stable`, et `overflow: hidden` fait de
	 * cet élément un conteneur de défilement : 10 px seraient réservés pour une
	 * barre qui n'apparaîtra jamais. */
	scrollbar-gutter: auto;
}

/* Une adresse longue reste entière : la pastille s'agrandit en hauteur et le
 * texte va à la ligne à l'intérieur.
 *
 * `inline-block` est ce qui rend ça possible sans dégât. En `inline`, un padding
 * vertical et une marge ne poussent pas la ligne : le fond déborde sur les
 * lignes voisines et, sur une adresse de trois lignes, les fragments se
 * chevauchent au lieu de s'écarter. Une boîte, elle, occupe la place qu'elle
 * prend.
 *
 * La troncature a été essayée et abandonnée : le composant découpe l'adresse en
 * fragments (schéma, hôte, chemin, requête) sans conteneur commun, et leurs
 * classes sont hachées. En rangée flex chacun se tronque pour son compte, ce qui
 * donne « htt… codefl… /catodon/cat… » au lieu d'une fin d'adresse coupée. */
[data-selectable-note-content] ._link {
	display: inline-block;

	/* Le composant pose `word-break: break-all` en style inline pour qu'une
	 * adresse ne déborde jamais. Sur un fond de pastille ça se voit beaucoup plus,
	 * et sur le libellé d'un lien nommé, qui est une phrase écrite par quelqu'un,
	 * ça coupe les mots en deux (« Sept | embre »). `anywhere` coupe toujours ce
	 * qui ne rentre pas, mais seulement quand rien d'autre ne marche. Le
	 * `!important` n'est pas évitable : la déclaration à battre est en style
	 * inline, sur l'élément lui-même. */
	word-break: normal !important;
	overflow-wrap: anywhere;
}

/* Le `https://` d'un lien externe n'apprend rien et coûte une ligne sur deux.
 * `target="_blank"` est ce qui distingue un lien sortant d'un lien interne, dont
 * le premier fragment est le nom d'hôte et doit rester visible. */
[data-selectable-note-content] a._link[target="_blank"] > span:first-child {
	display: none;
}
