/* L'agenda de la prévention, tel qu'il s'affiche dans les espaces et sur le
 * site corporate.
 *
 * Cette feuille habille une page complète, et non un bloc injecté : elle vit
 * dans un cadre, sur notre domaine, où rien de la page d'accueil ne l'atteint
 * et où rien d'elle n'en sort. C'est ce qui permet d'écrire ici des règles sur
 * `body` ou `h3` sans risquer de déteindre sur l'espace client.
 *
 * Les couleurs des événements ne sont pas ici : la palette vit dans
 * `admin_prevention/inc/config.php`, et la page l'écrit elle-même dans un bloc
 * `<style>`. Cette feuille n'en connaît que les deux variables, `--fond` et
 * `--sur-fond`.
 */

/* --- la police -----------------------------------------------------------

   Asap, celle du site, servie depuis notre domaine. La politique de sécurité
   du cadre n'autorise aucun chargement extérieur : la charger chez Google
   demanderait d'y ouvrir une porte, et ferait dépendre l'affichage d'un
   service tiers. Les fichiers sont dans `polices/`, publiés avec le reste.

   Une fonte variable par style, qui couvre les graisses de 400 à 700 : une
   seule requête au lieu d'une par graisse, et la possibilité d'en demander
   d'autres plus tard sans rien télécharger.

   Deux sous-ensembles par style. `latin` suffit au français courant ;
   `latin-ext` couvre ce qui déborde — un nom polonais, une ville tchèque — et
   n'est chargé que si la page en contient, grâce à `unicode-range`.

   `font-display: swap` : le texte s'affiche tout de suite dans la police du
   système, et bascule quand la fonte arrive. Sans cela, un cadre resterait
   vide le temps du chargement, et un agenda vide est ce qu'on lit comme
   « il n'y a rien de prévu ».

   Asap est sous licence SIL Open Font 1.1, qui autorise cet hébergement. Le
   texte de la licence est dans `polices/OFL.txt`, comme elle le demande. */

@font-face {
    font-family: "Asap";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("polices/asap-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
        U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
        U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Asap";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("polices/asap-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
        U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
        U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Asap";
    font-style: italic;
    font-weight: 400 700;
    font-display: swap;
    src: url("polices/asap-italique-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
        U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
        U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Asap";
    font-style: italic;
    font-weight: 400 700;
    font-display: swap;
    src: url("polices/asap-italique-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
        U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
        U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Les couleurs et le rythme du texte reprennent ceux des pages du site
   corporate, pour que l'agenda n'y détonne pas : un violet profond pour les
   titres, un texte prune plutôt que gris — le gris neutre faisait un bloc
   étranger au milieu d'une page qui n'en contient nulle part — et des puces
   framboise.
   `--marque` et `--titre` sont celles du dépôt (`admin.css` les porte déjà) ;
   les autres sont relevées sur une page du site.

   La police est Asap, celle du site, déclarée juste au-dessus. */
:root {
    --texte: #46325e;
    --titre: #55257f;
    --discret: #7a6c8c;
    --puce: #d6558a;
    --trait: #e7e1ee;
    --carte: #fff;
    --marque: #6b2fa0;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    padding: 0;
    background: transparent;
    color: var(--texte);

    /* 1,65 plutôt que 1,5 : c'est l'interlignage des pages du site, et il rend
       une description de dix lignes nettement plus lisible. */
    /* La pile de repli sert deux fois : le temps qu'Asap arrive, et pour de
       bon si elle n'arrivait jamais. */
    font: 16px/1.65 "Asap", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    /* Le cadre est aussi large qu'on le pose, et la hauteur remonte par
       `hauteur.js` : rien n'a besoin de défiler à l'intérieur. Une barre de
       défilement dans un cadre est presque toujours le signe qu'on n'a pas su
       la hauteur — ici, on la sait. */
    overflow-x: hidden;
}

.agenda-vide {
    margin: 0;
    padding: 1.25rem;
    border: 1px dashed var(--trait);
    border-radius: .75rem;
    color: var(--discret);
}

/* Les fiches occupent toute la largeur du cadre. C'est la page qui l'accueille
   qui décide de cette largeur — la colonne d'un article WordPress, le bloc d'un
   espace — et lui en reprendre une part laisserait une marge que personne n'a
   demandée. Ce qui doit être borné, c'est la longueur des lignes de texte, et
   cela se règle sur la description elle-même, plus bas. */
.agenda-liste {
    display: flex;
    flex-direction: column;

    /* Les fiches sont hautes — un titre sur deux lignes, un extrait, deux
       boutons, une affiche — et douze pixels les faisaient se toucher. Trente
       suffisent à voir où l'une finit et où la suivante commence sans avoir à
       chercher le trait.
       En pixels et non en rem : c'est un écart entre des blocs, pas une
       mesure de texte, et il n'a pas à grandir si le lecteur agrandit la
       police. */
    gap: 30px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.evenement-fiche {
    display: flex;
    gap: 1rem;
    background: var(--carte);
    border: 1px solid var(--trait);
    border-radius: .75rem;
    overflow: hidden;
}

/* Le bloc de date, dans la couleur de l'événement. Il tient la même largeur
   d'une fiche à l'autre pour que les titres s'alignent : une colonne de dates
   qui se décale d'une ligne à l'autre se lit beaucoup moins vite.

   La date se cale en haut et non au milieu : une fiche avec affiche fait trois
   fois la hauteur d'une fiche sans, et un quantième centré s'y retrouverait à
   flotter loin du titre qu'il date. */
.evenement-date {
    flex: 0 0 4.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: .1rem;
    margin: 0;
    padding: .95rem .5rem;
    background: var(--fond, var(--marque));
    color: var(--sur-fond, #fff);
}

.evenement-jour {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1;
}

.evenement-mois {
    font-size: .8rem;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.evenement-texte {
    flex: 1 1 auto;
    min-width: 0;
    padding: .85rem 1rem .95rem 0;
}

/* La fiche doit englober l'affiche même quand le texte est plus court qu'elle :
   sans cela, une fiche repliée à deux lignes laisserait l'image déborder sous
   la suivante. */
.evenement-texte::after {
    content: "";
    display: block;
    clear: both;
}

.evenement-titre {
    margin: 0 0 .2rem;
    color: var(--titre);
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.35;
}

/* La date et le lieu, chacun derrière son pictogramme. Le dessin est aligné
   sur la première ligne et non centré : une adresse qui passe à la ligne
   laisserait sinon sa punaise flotter entre les deux. */
.evenement-quand,
.evenement-lieu {
    display: flex;
    align-items: flex-start;
    gap: .4rem;
    margin: 0;
    color: var(--discret);
    font-size: .9rem;
}

.picto {
    flex: 0 0 auto;
    width: 1em;
    height: 1em;
    margin-top: .22em;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.evenement-carte,
.evenement-action a {
    color: var(--fond, var(--marque));
}

.evenement-carte {
    margin-left: .35rem;
    font-size: .85rem;
    white-space: nowrap;
}

/* La description porte de la mise en forme depuis qu'elle se saisit dans un
   éditeur : gras, italique, listes et liens. Les marges sont posées ici, sur
   ce que la description peut contenir, et nulle part ailleurs — le cadre est
   isolé, mais une règle sur `p` sans préfixe atteindrait aussi la date et le
   lieu. */
/* La longueur des lignes est bornée ici, et non sur la fiche : au-delà d'une
   centaine de caractères, l'œil perd le début de la ligne suivante. La date, le
   titre et le lieu sont courts et n'ont pas besoin de cette limite ; la
   description, si. */
.evenement-description { margin: .6rem 0 0; max-width: 46rem; }

.evenement-description > :first-child { margin-top: 0; }
.evenement-description > :last-child { margin-bottom: 0; }

.evenement-description p { margin: 0 0 1rem; }

/* `list-style-type` est redit : la liste des événements est elle-même un `<ul>`,
   donc une liste de description compte pour un second niveau, et le navigateur
   lui donne des puces creuses. Ce n'est pas un niveau, c'est une liste
   ordinaire dans un texte. */
.evenement-description ul {
    list-style-type: disc;
}

.evenement-description ul,
.evenement-description ol {
    margin: 0 0 1rem;
    padding-left: 1.6rem;

    /* Une liste qui passe à côté de l'affiche se rétrécit au lieu de glisser
       dessous : ses puces, posées à gauche du texte, disparaîtraient derrière
       l'image. */
    overflow: hidden;
}

/* Les puces sont framboise et un peu plus grosses que celles du navigateur, et
   les points de la liste respirent : c'est ainsi qu'une énumération se lit sur
   les pages du site, et une liste serrée au milieu d'un texte aéré ferait un
   bloc compact au mauvais endroit. */
.evenement-description li { margin: 0 0 .55rem; padding-left: .25rem; }

.evenement-description li::marker {
    color: var(--puce);
    font-size: 1.15em;
}

.evenement-description a { color: var(--fond, var(--marque)); }

/* L'affiche est habillée par le texte : posée en haut à droite, elle laisse ce
   qui la dépasse reprendre toute la largeur. Une colonne fixe réservait à sa
   droite, sous elle, une place que rien ne venait occuper. */
.evenement-affiche {
    float: right;
    max-width: 17rem;
    margin: .2rem 0 1rem 1.5rem;
}

/* Deux bornes, une en largeur et une en hauteur, et l'image se range dans la
   plus contraignante des deux en gardant ses proportions. Les affiches étant de
   toutes les formes depuis qu'on ne leur impose plus rien, c'est ce qui fait
   qu'aucune ne domine sa fiche :
   - panoramique, elle est arrêtée par la largeur ;
   - en hauteur ou carrée, par la hauteur — et le flottant se rétrécit d'autant,
     ce qui laisse d'autant plus de texte à côté d'elle.
   Une fiche repliée tient ainsi en quelques lignes quelle que soit l'affiche,
   au lieu d'être étirée par elle — un événement sans description, à côté d'une
   affiche en hauteur, ferait sinon une fiche presque vide. */
.evenement-affiche img {
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 13rem;
    border-radius: .5rem;
}

/* Le texte replié : un extrait, puis deux boutons côte à côte, puis la
   description qui s'ouvre en dessous.

   Deux boutons sur une rangée ne se disputent rien tant qu'ils ne sont pas du
   même rang. L'inscription est l'action que la fiche existe pour proposer :
   elle est en aplat. « En savoir plus » ne fait qu'ouvrir ce qu'on a déjà sous
   les yeux : il est en contour, dans la même couleur, de la même taille. On
   voit lequel est lequel sans avoir à lire. */

.evenement-extrait { margin: .6rem 0 0; }

/* Une fois ouvert, l'extrait ferait doublon avec le début de la description
   qu'il annonce. Il précède le bouton dans la page — aucun sélecteur de frère
   ne remonte — d'où `:has()`, posé sur le bloc qui les contient tous les deux.
   Un navigateur qui ne le connaîtrait pas laisserait l'extrait affiché
   au-dessus de la description : redondant deux lignes, jamais cassé. */
.evenement-texte:has(.evenement-plus[open]) .evenement-extrait { display: none; }

/* Les deux boutons sont des éléments frères, mis sur une rangée par
   `inline-block` plutôt que par un conteneur en rangée : la description qui les
   suit doit rester un bloc ordinaire pour continuer d'habiller l'affiche, et
   un conteneur l'aurait enfermée avec eux. */
.evenement-plus,
.evenement-action {
    display: inline-block;
    vertical-align: top;
    margin: .85rem .5rem 0 0;
}

.evenement-plus > summary::-webkit-details-marker { display: none; }

/* Le bouton secondaire, en contour. */
.evenement-deplier {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .45rem .95rem;
    border: 1px solid currentColor;
    border-radius: .5rem;
    color: var(--fond, var(--marque));
    font-weight: 600;
    cursor: pointer;

    /* Le triangle que le navigateur pose de lui-même n'a pas sa place sur un
       bouton : le chevron ci-dessous le remplace, et lui suit l'état. */
    list-style: none;
}

.evenement-deplier:hover { background: color-mix(in srgb, currentColor 8%, transparent); }

.evenement-plus > summary:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* Le libellé est écrit ici et non dans le HTML : il change avec l'état, et deux
   libellés dans la page dont un seul s'affiche seraient lus tous les deux par
   un lecteur d'écran. */
.evenement-deplier::before { content: "En savoir plus"; }
.evenement-plus[open] .evenement-deplier::before { content: "Réduire"; }

/* Le chevron, dessiné avec deux bords d'un carré tourné : pas d'image à
   charger, et il prend la couleur du texte sans qu'on ait à la lui redire. Il
   dit que quelque chose s'ouvre ici même — ce que le bouton d'inscription, qui
   emmène ailleurs, ne dit pas. */
.evenement-deplier::after {
    content: "";
    width: .4em;
    height: .4em;
    margin-top: -.2em;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
}

.evenement-plus[open] .evenement-deplier::after {
    margin-top: .16em;
    transform: rotate(-135deg);
}

/* La description ne s'ouvre que sur l'état du `<details>` qui la précède. Elle
   reste hors de lui, donc hors de la rangée de boutons : c'est ce qui lui
   permet de continuer d'habiller l'affiche. */
.evenement-description-repliee { display: none; }
.evenement-plus[open] ~ .evenement-description-repliee { display: block; margin-top: .85rem; }

/* Le bouton principal, en aplat : c'est l'action que la fiche existe pour
   proposer. Même taille et même couleur que le secondaire — seul le remplissage
   les distingue, ce qui suffit à les classer sans les opposer. */
.evenement-action a {
    display: inline-block;
    padding: .45rem .95rem;
    border: 1px solid var(--fond, var(--marque));
    border-radius: .5rem;
    background: var(--fond, var(--marque));
    color: var(--sur-fond, #fff);
    text-decoration: none;
    font-weight: 600;
}

.evenement-action a:hover,
.evenement-action a:focus-visible { filter: brightness(1.15); }

/* Sur un téléphone, la colonne de date passe au-dessus plutôt que de manger la
   moitié de la largeur du titre. */
/* Sous cette largeur, une affiche de 17 rem ne laisse plus assez de place au
   texte pour qu'il s'y lise : elle cesse de flotter et coiffe la fiche. */
@media (max-width: 40rem) {
    .evenement-affiche {
        float: none;
        max-width: 100%;
        margin: 0 0 .85rem;
    }
}

/* Sur un téléphone, la colonne de date passe au-dessus plutôt que de manger la
   moitié de la largeur du titre. */
@media (max-width: 26rem) {
    .evenement-fiche { flex-direction: column; gap: 0; }

    .evenement-date {
        flex: 0 0 auto;
        flex-direction: row;
        gap: .4rem;
        padding: .4rem .85rem;
    }

    .evenement-jour { font-size: 1.1rem; }
    .evenement-texte { padding: .85rem 1rem .95rem; }
    .evenement-affiche { margin: 0 0 .85rem; }
}
