/* =============================================================================
 * TOP CALENDAR — vues publiques
 *
 * ── CETTE FEUILLE N'EST PAS CELLE DE LA CONSOLE, ET C'EST VOULU ────────────
 *
 * La console est DENSE : un gerant y passe sa journee, chaque pixel doit porter
 * une information. Le front est AERE : un visiteur y passe quinze secondes et
 * doit comprendre « quand puis-je venir ». Les faire se ressembler donnerait
 * soit une console illisible, soit un formulaire de reservation qui a l'air
 * d'un tableur.
 *
 * Ce que les deux PARTAGENT, en revanche, n'est pas negociable : les quatre
 * couleurs d'etat — disponible, dernieres places, complet, ferme. C'est ce qui
 * permet a un gerant et a son client de parler des memes couleurs au telephone.
 *
 * ── LA REGLE QUI GOUVERNE TOUT LE FICHIER : ON N'IMPOSE PAS DE POLICE ──────
 *
 * `font-family: inherit` sur les titres, et aucune police embarquee ici. Un
 * formulaire de reservation qui impose ses propres polices sur un site soigne
 * se voit immediatement — et se voit comme un GREFFON. Le client a paye un
 * theme ; notre travail est de nous y fondre, pas de le recouvrir.
 *
 * On ne pose donc que trois choses : la STRUCTURE (grilles, espacements), les
 * COULEURS D'ETAT (la seule information que le theme ne peut pas connaitre), et
 * les CIBLES TACTILES. Tout le reste vient du theme.
 *
 * Seule exception : `--tcf-mono` sur les heures et les references. Un horaire
 * en police proportionnelle danse quand les chiffres changent, et une colonne
 * d'heures qui danse est illisible. La pile est generique (`ui-monospace`), pas
 * une police embarquee.
 *
 * ── CONTRASTES ────────────────────────────────────────────────────────────
 *
 * Mesures par `bin/contraste.php` sur les SIX fonds reellement rencontres —
 * carte, page, et les quatre pastilles teintees. `--tcf-ink-3` est a `#6E655B`
 * et non au `#8C8377` des maquettes : celui-la tombait a 3,28 sur la pastille
 * la plus teintee, sous le seuil AA de 4,5. C'est exactement le defaut qui a
 * coute une reprise complete dans Top Translate, et il ne se voit pas a l'oeil
 * de celui qui l'ecrit.
 * ========================================================================== */

.topcal-front{
  /* Neutres CHAUDS — le front n'est pas une console. Saturation tres basse :
     au-dela, un blanc casse tire vers le beige et date la page. */
  /*
   * ── LA PALETTE DU THEME GAGNE, ET C'EST TOUT L'OBJET DE CE SOCLE ──────
   *
   * Depuis WordPress 5.9, tout theme portant un `theme.json` EMET sa palette
   * en variables CSS : `--wp--preset--color--<nom>`. On les lit par une
   * chaine de replis `var()` — aucun PHP, aucun JavaScript, aucune
   * detection. Si le theme les declare, elles gagnent ; sinon le repli
   * suivant s'applique.
   *
   * ⚠ POURQUOI LE DERNIER REPLI EST `currentColor` ET `transparent`, ET NON
   * NOS PROPRES COULEURS.
   *
   * Mesure du 11/09 sur un WordPress local : en posant sur `body` ce que pose
   * n'importe quel theme sombre, le calendrier devenait NOIR SUR NOIR. Titre
   * de journee 1,01:1, nom de seance 1,01:1, prix 1,01:1. La cause est une
   * demi-decision — la feuille IMPOSAIT son encre et HERITAIT du fond. Un
   * couple dont une moitie vient d'ailleurs n'a aucune garantie.
   *
   * `currentColor` sur `transparent`, c'est le couple que le theme emploie
   * DEJA pour son propre corps de texte. Son concepteur a garanti qu'il se
   * lit. Ce n'est pas une esperance, c'est une preuve — et c'est la seule
   * facon d'etre lisible sur un theme qu'on n'a jamais vu.
   *
   * Les valeurs litterales restent declarees JUSTE AVANT : un navigateur
   * sans `var()` imbrique garde le comportement d'hier plutot que rien.
   */
  --tcf-bg:#FCFBF9;
  --tcf-bg:var(--wp--preset--color--base, var(--wp--preset--color--background, transparent));
  --tcf-ink:#171310;
  --tcf-ink:var(--wp--preset--color--contrast, var(--wp--preset--color--foreground, currentColor));
  /*
   * LA SURFACE N'EST PLUS UN BLANC : c'est une TEINTE DE L'ENCRE posee sur ce
   * qu'il y a derriere. Un blanc en dur sous une encre claire — le cas d'un
   * theme sombre — donnait du blanc sur blanc, et c'est ce que la bande de
   * semaine a montre le 12/09 : 1,12:1 sur ses jours fermes. Une teinte de
   * l'encre suit forcement l'encre, donc le couple reste juste des deux cotes.
   */
  --tcf-surface:#FFFFFF;
  --tcf-surface:color-mix(in srgb, var(--tcf-ink) 4%, transparent);
  --tcf-line:#E8E3DC;
  --tcf-line:color-mix(in srgb, var(--tcf-ink) 14%, transparent);
  /*
   * ── LES GRIS SUIVENT L'ENCRE, PARCE QU'ILS NE SAVENT PAS OU ILS SONT ──
   *
   * Ces deux valeurs etaient absolues, et mesurees contre NOS fonds clairs.
   * Elles servent pourtant aussi a des textes poses sur le fond du THEME —
   * les jours de la semaine, le sur-titre, les legendes — ou elles n'avaient
   * plus rien a voir avec ce qu'il y a derriere : 3,27:1 mesure sur un theme
   * sombre, et 1,01:1 pour le titre du mois juste a cote.
   *
   * `currentColor` resout la question sans la deviner : un `var()` est
   * substitue au point d'USAGE, donc le melange se fait contre l'encre qui
   * s'applique REELLEMENT a cet endroit — la notre sur nos cartes, celle du
   * theme sur son fond. Un seul jeton, les deux cas justes.
   *
   * Les valeurs absolues restent declarees juste avant : un navigateur sans
   * `color-mix` garde le comportement d'avant plutot que rien du tout.
   */
  --tcf-ink-2:#5A5248;
  --tcf-ink-2:color-mix(in srgb, var(--tcf-ink) 82%, transparent);
  /*
   * ⚠ UN SEUL GRIS DE SECOND RANG, A 82 %, ET C'EST UNE MESURE.
   *
   * Il y en avait deux — 78 % et 65 % — et le second etait NON CONFORME. Le
   * dessin l'a mesure sur SEPT themes reels, seuil AA de 4,5 pour du petit
   * texte : a 58 % il tombait sous le seuil sur QUATRE themes sur sept, et il
   * portait tout le texte secondaire du front — durees, prix, legendes,
   * « il reste N places ». Le defaut etait dans le socle, donc partout.
   *
   * ⚠ ET ON NE PEUT PAS LE RATTRAPER EN MONTANT LE POURCENTAGE. Un theme dont
   * l'encre est DEJA faible — `#4A4A4A` sur `#FAFAFA`, cas parfaitement legal
   * — echoue encore a 70 %. Aucune transparence sous 100 % ne peut garantir
   * AA sur une encre qu'on ne connait pas : c'est une limite de la methode,
   * pas une valeur mal choisie. On garde donc UN gris, a 82 %, dont le pire
   * cas mesure est 5,18 — et la hierarchie se fait par la TAILLE, qui ne
   * depend d'aucune couleur.
   *
   * `--tcf-ink-3` reste defini pour ne rien casser, et vaut exactement le
   * meme : deux noms, une valeur, plutot qu'un troisieme niveau indefendable.
   */
  --tcf-ink-3:#6E655B;
  --tcf-ink-3:var(--tcf-ink-2);

  /* ── L'ACCENT : L'ENCRE, ET RIEN QUI NOUS APPARTIENNE ─────────────────
   *
   * Ordre du proprietaire, 04/09/2026 : « en front pas de bleu, il faut que
   * ca s'integre a n'importe quel site tout en etant super moderne ».
   *
   * Ce fichier portait l'indigo de la charte TOP CALENDAR. Sur la page d'un
   * client, entre son logo et ses photos, c'etait une couleur ETRANGERE qui
   * s'invitait : la notre, pas la sienne. Le front n'a donc plus de couleur
   * a lui — de l'encre, du papier, un filet.
   *
   * UNE SEULE VARIABLE porte l'action, et c'est le seul point d'entree pour
   * qui veut la sienne. Le reglage « couleur d'accent » de la console ecrit
   * ces trois lignes-la, et un theme peut faire pareil a la main :
   *
   *     .topcal-front{ --tcf-ac:#B0343C; --tcf-ac-contraste:#FFF }
   *
   * CE QUI RESTE COLORE, ET POURQUOI. Les quatre etats ci-dessous et les huit
   * teintes de nomenclature plus bas ne DECORENT pas : ils DISENT quelque
   * chose — libre, presque plein, complet ; et « cette seance n'est pas
   * celle-la ». Les eteindre pour faire sobre effacerait une information au
   * lieu de la rendre discrete. La ligne n'est pas « pas de couleur », elle
   * est « aucune couleur qui parle de NOUS ». */
  --tcf-ac:#171310;
  /*
   * ⚠ LE DERNIER REPLI DE L'ACCENT N'EST PAS `currentColor`, ET LE DESSIN SE
   * TROMPE SUR CE POINT PRECIS.
   *
   * `background: currentColor` sur un element qui fixe AUSSI son propre
   * `color` prend SA couleur de texte : fond et texte deviennent identiques.
   * Mesure du 12/09 : les quarante-deux boutons « Book » de la vue Liste a
   * 1,00 de contraste — un rectangle plein, sans un mot dessus. `currentColor`
   * n'est jamais fige : il se resout au point d'USAGE, et le bouton est
   * justement l'endroit ou il ne faut pas.
   *
   * Quand le theme ne declare RIEN, on retombe donc sur NOTRE couple, dont on
   * connait le rapport — 15:1 mesure. Il ne s'accordera pas a un theme sombre,
   * mais il se LIRA. Un bouton qui detonne fait hausser un sourcil ; un bouton
   * illisible fait perdre la vente.
   */
  --tcf-ac:var(--wp--preset--color--primary, var(--wp--preset--color--accent, var(--wp--preset--color--accent-1, #171310)));
  /*
   * Le contraste de l'accent suit le FOND : le bouton plein est le couple du
   * theme RETOURNE — son encre en fond, son fond en texte. Un couple retourne
   * garde exactement le meme rapport de contraste : s'il etait lisible dans
   * un sens, il l'est dans l'autre. C'est la seule facon de garantir un
   * bouton lisible sur un theme qu'on n'a jamais vu.
   *
   * ⚠ MAIS IL NE PEUT PAS VALOIR `var(--tcf-bg)`, ET C'EST UN TROU DU DESSIN.
   *
   * `--tcf-bg` retombe sur `transparent` — ce qui est JUSTE pour un fond de
   * page : on herite alors de celui du theme. Mais ON N'ECRIT PAS EN
   * TRANSPARENT. Mon premier jet a fait exactement cela, et les quarante-deux
   * boutons « Book » de la vue Liste sont passes a 0,00 de contraste : un
   * rectangle plein, sans un mot dessus. La planche du dessin ne pouvait pas
   * le montrer, son artboard posant un fond concret.
   *
   * On refait donc la chaine ICI, avec un dernier repli OPAQUE : le fond du
   * theme s'il le declare, sinon notre blanc casse. Jamais `transparent`.
   */
  --tcf-ac-contraste:#FFFFFF;
  --tcf-ac-contraste:var(--wp--preset--color--base, var(--wp--preset--color--background, #FCFBF9));
  /*
   * ── LE COUPLE INVERSE : LA PAIRE DU THEME, RETOURNEE ─────────────────
   *
   * ⚠ ON NE MET JAMAIS DE TEXTE SUR L'ACCENT, ET CE DEFAUT A ETE VU A L'OEIL.
   *
   * Le theme du banc declare un `primary` JAUNE VIF. Le jour selectionne de
   * la bande de semaine prenait ce jaune en fond et le `base` du theme — du
   * BLANC — en texte : « SAM 12 · Complet » illisible, sur l'element meme qui
   * dit au visiteur ou il se trouve. Aucun instrument ne le voyait : les
   * themes simules ne declaraient pas de palette, donc la voie de l'accent
   * n'etait jamais empruntee. Ils en declarent une depuis.
   *
   * Le socle du dessin le dit pourtant : la couleur du theme sert de TRAIT,
   * de POINT, de FILET — jamais de fond sous du texte. On ne connait pas sa
   * luminosite, donc on ne peut RIEN garantir de ce qu'on ecrit dessus.
   *
   * Ce qui se garantit, en revanche, c'est la paire du theme RETOURNEE : son
   * encre en fond, son fond en texte. Un couple retourne garde exactement le
   * meme rapport de contraste — s'il etait lisible dans un sens, il l'est
   * dans l'autre. Et le concepteur du theme a deja garanti ce sens-la.
   *
   * ⚠ AUCUN `currentColor` ICI. Il se resout au point d'USAGE : sur un
   * element qui fixe son propre `color`, `background: currentColor` prend sa
   * couleur de TEXTE, et les deux se confondent. Mesure du 12/09 : 1,00.
   */
  --tcf-inverse-fond:#171310;
  --tcf-inverse-fond:var(--wp--preset--color--contrast, var(--wp--preset--color--foreground, #171310));
  --tcf-inverse-encre:#FCFBF9;
  --tcf-inverse-encre:var(--wp--preset--color--base, var(--wp--preset--color--background, #FCFBF9));
  --tcf-ac-doux:#F1EDE7;
  --tcf-ac-doux:color-mix(in srgb, var(--tcf-ac) 12%, transparent);
  /* Meme defaut que la console, et il touche LE CLIENT : l'anneau de focus
     etait translucide, donc mesure entre 1,98 et 2,47:1 sur tout le front —
     bouton « Reserver » compris, sur 138 rendus. Un visiteur au clavier ne
     voyait pas ou il etait dans le formulaire qui prend son argent.
     Opaque, le meme jeton donne 18:1. WCAG 1.4.11 et 2.4.11. */
  --tcf-ring:var(--tcf-ac);

  /* Les quatre etats. Identiques a la console, au chiffre pres. */
  --tcf-free:#0F7A4C;      --tcf-free-soft:#EFF6F1;
  --tcf-tight:#925E15;     --tcf-tight-soft:#F7F1E6;
  --tcf-full:#C04128;      --tcf-full-soft:#F9EEEA;
  --tcf-closed:#6E655B;    --tcf-closed-soft:#F4F1EC;

  /* Le fond plein d'un bouton d'heure. Entre le fond de page et le filet :
     assez pose pour que le bouton se lise sans bordure, assez discret pour que
     douze d'affilee ne fassent pas un damier. */
  --tcf-fill:#F3F1ED;
  --tcf-fill:color-mix(in srgb, var(--tcf-ink) 5%, transparent);
  --tcf-fill-fort:#EAE7E1;
  --tcf-fill-fort:color-mix(in srgb, var(--tcf-ink) 9%, transparent);

  /* ── LA NOMENCLATURE : HUIT TEINTES POUR HUIT TYPES D'EVENEMENT ────────
   *
   * Decision du proprietaire, 02/09 : la couleur ne dit plus l'ETAT, elle dit
   * le TYPE. Chaque evenement publie recoit un rang stable — voir
   * `TOPCAL_Front::rang_couleur()` — et ce rang choisit sa teinte ici.
   *
   * Deux valeurs par teinte : le TRAIT, pose sur du blanc ou du pale, et le
   * FOND du pave, tres desature. Sans le second, huit pastilles saturees cote
   * a cote font un jeu de cartes ; avec lui, elles font une nomenclature.
   *
   * Les huit traits sont choisis a luminosite comparable — c'est ce qui evite
   * qu'une teinte paraisse « importante » et une autre « secondaire » alors
   * qu'elles ne nomment que des seances differentes. Toutes tiennent AA sur le
   * blanc, mesure par `bin/contraste.php`. */
  --tcf-ev-1:#4338CA;  --tcf-ev-1-doux:#EEEDFB;
  --tcf-ev-2:#0F766E;  --tcf-ev-2-doux:#E8F3F1;
  --tcf-ev-3:#9A3412;  --tcf-ev-3-doux:#F8EDE7;
  --tcf-ev-4:#9F1239;  --tcf-ev-4-doux:#F9EAEE;
  --tcf-ev-5:#6D28D9;  --tcf-ev-5-doux:#F1EBFB;
  --tcf-ev-6:#1D4ED8;  --tcf-ev-6-doux:#E9EFFC;
  --tcf-ev-7:#15803D;  --tcf-ev-7-doux:#E9F4EC;
  --tcf-ev-8:#475569;  --tcf-ev-8-doux:#EDEFF2;
  /* Le rang zero : un creneau sans evenement nomme — une location a la
     journee, par exemple. Il garde le gris du pave, et la nomenclature ne le
     nomme pas, puisqu'il n'a pas de nom. */
  --tcf-ev-0:var(--tcf-ink-3);  --tcf-ev-0-doux:var(--tcf-fill);

  --tcf-r:14px;
  --tcf-r-sm:11px;
  --tcf-mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  /* La cible tactile minimale. Nommee plutot que recopiee : c'est une regle
     d'accessibilite, pas une preference, et elle doit se retrouver d'un grep. */
  --tcf-touch:44px;

  /* Le filet d'un CHAMP DE SAISIE, et non d'une separation. `--tcf-line`
     (#E8E3DC) separe deux zones : a 1,28:1 sur du blanc, il est juste assez
     visible pour cela. La limite d'une commande demande 3:1 (WCAG 1.4.11) —
     c'est elle qui dit « ecrivez ici ».

     ⚠ PREMIERE VALEUR : `#949494`, choisie pour donner exactement 3,04 sur du
     BLANC. Elle tombait a 2,69 sur un fond creme — un gris moyen perd du
     contraste des que le fond s'assombrit, et « exactement au seuil sur le cas
     le plus favorable » ne laisse aucune marge aux themes reels. `#767676` est
     le gris accessible classique : 4,54 sur blanc, 4,09 sur creme. */
  --tcf-bord-champ:#767676;

  /*
   * ⚠ ICI VIVAIT LE DEFAUT LE PLUS COUTEUX DU FRONT.
   *
   * La ligne disait `color: var(--tcf-ink)` — une encre presque noire — juste
   * au-dessus de `background: transparent`. Elle IMPOSAIT donc son encre et
   * HERITAIT du fond : un couple dont une moitie vient d'ailleurs n'a aucune
   * garantie, il vaut ce que vaut le theme d'en face.
   *
   * Mesure du 11/09 sur un theme sombre ordinaire : titre du mois 1,01:1, nom
   * de seance 1,01:1, horaire 1,01:1, prix 1,01:1. Il ne restait a l'ecran
   * qu'une colonne de boutons « Book » flottant dans le vide. Le visiteur ne
   * pouvait lire ni le jour, ni l'heure, ni le prix de ce qu'il reserve.
   *
   * ── LA REGLE, DESORMAIS : ON POSE LES DEUX, OU ON N'EN POSE AUCUN ────
   *
   * Sur le fond du THEME, on herite son encre — lui seul sait ce qui se lit
   * chez lui, et c'est exactement la promesse de l'en-tete de ce fichier.
   * Sur NOS surfaces (cartes, pastilles, boutons), qui posent leur fond, on
   * pose aussi l'encre : la on controle les deux moities, et les contrastes
   * mesures par `bin/contraste.php` valent.
   *
   * `bin/front-sur-theme.mjs` mesure les deux cas sur quatre themes.
   */
  color:inherit;
  background:transparent;
  line-height:1.6;
}
.topcal-front *,.topcal-front *::before,.topcal-front *::after{box-sizing:border-box}

/* Les titres HERITENT. Voir l'en-tete : c'est la regle la plus importante du
   fichier. On ne fixe que ce qui structure — graisse et interlignage — pour
   qu'un theme aux titres tres lourds ne rende pas la liste illisible. */
.topcal-front h1,.topcal-front h2,.topcal-front h3,.topcal-front h4{
  font-family:inherit;line-height:1.15;margin:0;color:inherit;
}
.topcal-front p{margin:0}
/* ⚠ UN LIEN PREND L'ENCRE DE LA PAGE, PAS L'ACCENT.
   Il prenait `--tcf-ac`, dont le dernier repli est desormais une couleur
   OPAQUE ecrite en dur — necessaire pour le fond d'un bouton, ruineux pour du
   texte : sur un theme sombre, « Show more dates » mesurait 1,01. Le socle du
   dessin le dit sans detour, `a{color:inherit}` : l'accent sert de trait, de
   point, de filet — jamais a porter un mot. Ce qui porte du texte prend
   l'encre de la page, et celle-la est lisible par construction puisque le
   concepteur du theme l'a deja garantie sur son propre fond. */
.topcal-front a{color:inherit}

/* Le focus ne se retire jamais : c'est la seule affordance de qui navigue au
   clavier. Un `outline:none` pose « pour faire propre » rend la reservation
   impossible sans souris. */
.topcal-front a:focus-visible,.topcal-front button:focus-visible,
.topcal-front input:focus-visible,.topcal-front select:focus-visible{
  outline:3px solid var(--tcf-ring);outline-offset:2px;border-radius:6px;
}
.topcal-front .tcf-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ── Sur-titre, chapeau ─────────────────────────────────────────────────── */
.topcal-front .tcf-eyebrow{
  font-family:var(--tcf-mono);font-size:.68rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--tcf-ink-3);display:block;
}
.topcal-front .tcf-lead{margin-bottom:2.2rem;max-width:60ch}
.topcal-front .tcf-lead h2{font-size:2.1rem;margin-top:.6rem}
.topcal-front .tcf-lead p{color:var(--tcf-ink-2);margin-top:.7rem}

/* ── ALLER A UN AUTRE MOIS ───────────────────────────────────────────────
   La grille du mois n'offrait AUCUN chemin vers le mois suivant : un client
   arrive en fin de mois voyait des cases grises et concluait « ils n'ont plus
   rien ». Ces liens sont donc une NAVIGATION, pas une decoration — d'ou la
   cible de 44 px au doigt, la meme que partout ailleurs dans ce produit. */
.topcal-front .tcf-mois-nav{display:flex;flex-wrap:wrap;gap:10px;margin-top:1rem}
/* ⚠ `:not(.tcf-mois-pas)` — FUSION DU 15/09, MEME CAUSE QUE PLUS BAS.
   Une autre branche a pose dans le MEME `<nav class="tcf-mois-nav">` des pas
   fleches `.tcf-mois-pas`, qui sont eux aussi des `<a>`. Sans cette exclusion,
   la regle ci-dessous les attrapait : `.tcf-mois-nav a` (0,2,1) l'emporte sur
   `.tcf-mois-pas` (0,2,0), et les pas heritaient du rembourrage `0 16px` et du
   rayon des liens en toutes lettres au lieu de leur carre de 44 px. Deux
   composants sous une meme classe — voir la note complete au second
   `.tcf-mois-nav`. */
.topcal-front .tcf-mois-nav a:not(.tcf-mois-pas){
  display:inline-flex;align-items:center;min-height:var(--tcf-touch);
  padding:0 16px;border:1px solid var(--tcf-line);border-radius:var(--tcf-r-sm);
  color:var(--tcf-ink);text-decoration:none;font-size:.9rem;
}
.topcal-front .tcf-mois-nav a:not(.tcf-mois-pas):hover{border-color:var(--tcf-ac);color:var(--tcf-ac)}

/* ══ LE CHAPEAU — LE TITRE A GAUCHE, LA NOMENCLATURE DANS LE VIDE A DROITE ═
 *
 * Le chapeau d'une vue tient sur deux lignes et laisse les deux tiers droits
 * de la colonne inutilises. L'encart s'y range : la page ne gagne pas un pixel
 * de hauteur sur un bureau. En dessous de 720 px il passe a la ligne, sous le
 * titre — deux lignes de puces, contre un pave de bas de page auparavant.
 *
 * `align-items:flex-end` et non `center` : l'encart s'aligne sur la LIGNE DE
 * BASE du titre, pas sur son milieu. Centre, il flottait au-dessus du mois et
 * on lisait deux blocs sans rapport ; pose au meme niveau, il se rattache.
 */
.topcal-front .tcf-entete{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;
  gap:16px 32px;margin-bottom:2.2rem;
}
/* Le chapeau porte l'ecart : le titre ne le porte plus, sinon il compte double. */
.topcal-front .tcf-entete .tcf-lead{margin-bottom:0}

/* ── Boutons ────────────────────────────────────────────────────────────── */
.topcal-front .tcf-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  min-height:var(--tcf-touch);padding:12px 22px;border-radius:12px;
  font-family:var(--tcf-mono);font-size:.8rem;font-weight:500;letter-spacing:.02em;
  text-decoration:none;white-space:nowrap;border:none;cursor:pointer;
  transition:transform .15s,filter .15s,border-color .15s;
}
/*
 * ── LE BOUTON DOIT AVOIR UNE FORME, PAS SEULEMENT UN MOT ────────────
 *
 * `--tcf-ac` vaut `#171310` par defaut, et c'est une DECISION du proprietaire :
 * « aucune couleur qui parle de NOUS ». On n'y touche pas.
 *
 * Mais un fond `#171310` sur la page d'un theme sombre mesure 1,01:1 : le
 * bouton n'a plus de contour, il ne reste que le mot « Book » blanc qui flotte
 * dans le vide. C'est ce qu'un agent a decrit en regardant la capture, et ce
 * que 6440 mesures de TEXTE ne pouvaient pas dire — le texte, lui, est a
 * 15,9:1 contre son propre fond.
 *
 * WCAG 1.4.11 demande 3:1 pour la limite d'une commande, et la limite peut
 * etre le fond OU la bordure. On ajoute donc un filet de la couleur du TEXTE
 * du bouton : il est visible exactement quand le fond ne l'est pas, et
 * invisible quand le fond suffit — un liseret blanc autour d'un bouton noir
 * ne se voit pas sur du blanc, et se voit sur du sombre. Aucune couleur
 * nouvelle, aucune supposition sur le theme.
 */
.topcal-front .tcf-btn-primary{
  /* ⚠ FUSION DU 15/09 — LE FOND VIENT D'UNE BRANCHE, LE HALO DE L'AUTRE.
   *
   * LE FOND ET L'ENCRE : le couple INVERSE, pas l'accent. Poser du texte sur
   * `--tcf-ac` est le defaut que le socle de ce fichier documente vingt lignes
   * plus haut — « ON NE MET JAMAIS DE TEXTE SUR L'ACCENT » : le theme du banc
   * declare un `primary` JAUNE VIF, et `--tcf-ac-contraste` y ecrivait du
   * blanc. Le couple retourne du theme, lui, garde par construction le rapport
   * que le concepteur du theme a deja garanti.
   *
   * LE FILET reste : WCAG 1.4.11 demande 3:1 pour la limite d'une commande, et
   * sur un theme sombre le fond du bouton mesure 1,01:1 contre la page. Le
   * filet est de la couleur du TEXTE du bouton — aucune couleur nouvelle.
   *
   * LE HALO vient de l'autre branche, et c'est elle qui a raison. Il valait
   * `rgba(79,107,255,.5)` — l'indigo de la charte de la CONSOLE — sur le
   * bouton le plus important du front, alors que l'ordre du proprietaire du
   * 04/09 est « en front pas de bleu ». Un accent rouge choisi par
   * l'exploitant gardait un halo bleu. Le repli suit desormais l'encre, pour
   * que le defaut soit coherent tout seul. */
  background:var(--tcf-inverse-fond);color:var(--tcf-inverse-encre);
  border:1px solid var(--tcf-inverse-encre);
  box-shadow:0 18px 44px -18px var(--tcf-ac-ombre,rgba(23,19,16,.40));
}
.topcal-front .tcf-btn-primary:hover{transform:translateY(-1px);filter:saturate(1.08)}
.topcal-front .tcf-btn-ghost{
  border:1px solid var(--tcf-line);color:var(--tcf-ink);background:var(--tcf-surface);
}
.topcal-front .tcf-btn-ghost:hover{border-color:var(--tcf-ac)}
/* « Complet » n'est PAS un bouton desactive : c'est un etat, et il ne doit ni
   avoir l'air cliquable ni disparaitre. Un creneau complet qu'on retire de la
   liste fait croire au visiteur qu'il n'a jamais existe — et il rappelle. */
.topcal-front .tcf-btn-off{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:var(--tcf-touch);padding:12px 22px;border-radius:12px;
  border:1px solid var(--tcf-line);color:var(--tcf-ink-3);
  font-family:var(--tcf-mono);font-size:.8rem;cursor:not-allowed;
}

/* ── Pastilles d'etat ───────────────────────────────────────────────────── */
.topcal-front .tcf-state{
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  font-family:var(--tcf-mono);font-size:.7rem;padding:5px 11px;border-radius:100px;
}
/* ⚠ LE POINT PORTE SA COULEUR D'ETAT, LE MOT PORTE L'ENCRE — et les deux
   sont INDEPENDANTS depuis le 12/09. Le point suivait `currentColor` : des
   qu'une pastille a pris l'encre du theme pour son mot (dans les cases du
   mois, ou le fond n'est pas teinte), son point est devenu NOIR et les quatre
   etats ont cesse de se distinguer.

   C'est aussi la regle que le dessin pose : « le mot vaut 14,13 partout, le
   point 5 et plus. Le mot prend l'encre du theme, pas la couleur d'etat :
   celles-ci sont les seules qui ne s'heritent pas, et sur trois themes sombres
   du lot douze couples sur vingt-quatre tombaient sous 4,5. » */
.topcal-front .tcf-state i{width:6px;height:6px;border-radius:50%;flex:none;background:currentColor}
.topcal-front .tcf-state.is-free i{background:var(--tcf-free)}
.topcal-front .tcf-state.is-tight i{background:var(--tcf-tight)}
.topcal-front .tcf-state.is-full i{background:var(--tcf-full)}
.topcal-front .tcf-state.is-closed i{background:var(--tcf-closed)}
.topcal-front .tcf-state.is-free{background:var(--tcf-free-soft);color:var(--tcf-free)}
.topcal-front .tcf-state.is-tight{background:var(--tcf-tight-soft);color:var(--tcf-tight)}
.topcal-front .tcf-state.is-full{background:var(--tcf-full-soft);color:var(--tcf-full)}
.topcal-front .tcf-state.is-closed{background:var(--tcf-closed-soft);color:var(--tcf-closed)}

/* ── LA NOMENCLATURE, EN ENCART ───────────────────────────────────────────
 *
 * Elle fermait la page : un filet, 2,4 rem de marge, 1,6 rem de rembourrage,
 * puis quatre mots. C'est une bande entiere de hauteur pour une information
 * qu'on veut AVANT de lire le calendrier, pas apres.
 *
 * `width:fit-content` la fait tenir a la largeur de ce qu'elle nomme : un site
 * a deux seances n'obtient pas un encart de 1 100 px avec un desert a droite.
 * `max-width:100%` la ramene dans la colonne quand elle a huit noms a porter.
 */
.topcal-front .tcf-legend{
  display:flex;gap:6px 18px;flex-wrap:wrap;align-items:center;
  width:fit-content;max-width:100%;
  padding:9px 14px;border:1px solid var(--tcf-line);border-radius:12px;
  background:var(--tcf-surface);
  /*
   * ⚠ LE PIEGE DE `currentColor`, PAYE ICI.
   *
   * La ligne disait `color: var(--tcf-ink-2)`, et ce jeton est devenu un
   * melange de `currentColor`. Sur NOTRE fond blanc, `currentColor` vaut
   * encore l'encre HERITEE — celle du theme. Un theme sombre donnait donc du
   * gris clair a 78 % sur du blanc : 1,15:1. Le jeton derive est juste, son
   * point d'application ne l'etait pas.
   *
   * Une surface qui peint son fond doit d'abord POSER son encre ; les gris
   * qu'elle contient se derivent alors de celle-la. Le gris de cette legende
   * descend donc d'un cran, sur `span`.
   */
  font-family:var(--tcf-mono);font-size:.68rem;line-height:1.5;color:var(--tcf-ink);
}
.topcal-front .tcf-legend span{display:inline-flex;align-items:center;gap:7px;color:var(--tcf-ink-2)}
/* ── LA RANGEE DES ACTIVITES : UNE LEGENDE DEVENUE UN FILTRE ────────────
   Chaque activite est un LIEN qui filtre le calendrier. La cible fait au
   moins 44 px de haut — c'est une commande, pas une etiquette — et le nom est
   ECRIT : rien ne repose sur l'appariement d'une couleur. */
.topcal-front .tcf-filtre{
  display:inline-flex;align-items:center;gap:7px;min-height:var(--tcf-touch);
  padding:4px 10px;border-radius:100px;color:var(--tcf-ink-2);
  text-decoration:none;border:1px solid transparent;
}
.topcal-front .tcf-filtre:hover{border-color:var(--tcf-line);color:var(--tcf-ink)}
/* L'activite retenue porte le couple du theme RETOURNE : le seul fond dont on
   puisse garantir le contraste sur un theme qu'on n'a jamais vu. */
.topcal-front .tcf-filtre.is-on{
  background:var(--tcf-inverse-fond);color:var(--tcf-inverse-encre);
  border-color:var(--tcf-inverse-fond);
}
.topcal-front .tcf-filtre.is-on i{background:var(--tcf-inverse-encre)}
/* « + N autres activites » mene au catalogue : pas de pastille, ce n'est pas
   une activite mais une sortie. */
.topcal-front .tcf-filtre-suite{text-decoration:underline;text-underline-offset:3px}

/*
 * L'ETOILE DES CHAMPS OBLIGATOIRES.
 *
 * Elle etait ecrite en `style="color:var(--tcf-full)"` DANS le PHP — deux
 * defauts en une ligne :
 *
 *  · `--tcf-full` est la couleur d'ETAT « complet ». L'en-tete de ce fichier
 *    dit que les quatre couleurs d'etat existent pour qu'un gerant et son
 *    client parlent des memes couleurs au telephone ; leur donner un second
 *    sens les use ;
 *  · sur un theme sombre elle mesurait 3,59:1, sous le seuil. Une etoile qui
 *    ne se voit pas ne dit pas qu'un champ est obligatoire.
 *
 * Elle herite donc l'encre qui s'applique, ce qui est lisible par
 * construction des deux cotes. Son sens tient a sa FORME et a sa place, pas a
 * sa couleur — et le champ porte de toute facon `required`, seul signal que
 * lit une synthese vocale.
 */
.topcal-front .tcf-requis{color:inherit;font-weight:600}

/*
 * ── LES CHAMPS DE SAISIE SE VOIENT, SUR N'IMPORTE QUELLE PAGE ───────
 *
 * Leur style etait ecrit en `style="…"` DANS le PHP, avec un filet
 * `var(--tcf-line)` — `#E8E3DC`, soit 1,28:1 sur la page blanche d'un theme
 * clair. Le champ n'avait donc pas de forme : sur l'ecran ou le visiteur donne
 * son nom et son courriel, rien ne disait « ecrivez ici ».
 *
 * Ce n'etait pas un defaut de theme sombre : il etait la depuis toujours, sur
 * le cas le plus ordinaire, et aucun instrument ne regardait les COMMANDES.
 *
 * `#949494` est la valeur mesuree qui atteint 3:1 sur du blanc (WCAG 1.4.11) ;
 * elle en donne 5,6 sur un fond sombre. Un seul filet, les deux cas tenus.
 *
 * Les regles quittent le PHP au passage : un `style=""` en ligne ne peut etre
 * ni surcharge par le theme du client, ni mesure, ni falsifie.
 */
.topcal-front .tcf-champ{
  width:100%;min-height:var(--tcf-touch);
  border:1px solid var(--tcf-bord-champ);border-radius:var(--tcf-r-sm);
  padding:0 14px;font-size:.95rem;
  background:var(--tcf-surface);color:var(--tcf-ink);
}
.topcal-front .tcf-champ-l{display:block;min-width:0}
.topcal-front .tcf-champ-l>span{display:block;font-size:.86rem;font-weight:600;margin-bottom:.35rem}
.topcal-front .tcf-vous{margin-top:2.4rem}
.topcal-front .tcf-vous h3{font-size:1.4rem}
/* ── `tcf-vous-connu` — D'OU VIENNENT CES COORDONNEES ────────────────────
   Un formulaire qui se remplit tout seul surprend quand rien ne dit d'ou. Le
   remplissage du navigateur, le client le reconnait ; celui-ci vient de nos
   registres. La phrase repond avant la question — donc elle est SOUS le titre
   et AU-DESSUS des champs, la ou le regard passe en descendant.
   Discrete, jamais une alerte : ce n'est pas un probleme, c'est un service.

   ⚠ `--tcf-ink-2` ET PAS UN GRIS A MOI. Le socle n'a QU'UN gris de second
   rang, a 82 %, mesure sur sept themes reels — et son commentaire dit
   pourquoi il n'y en a pas deux. Un jeton invente ici ne serait defini nulle
   part : la phrase heriterait de la couleur du texte courant, donc ne serait
   plus discrete du tout, et rien ne l'aurait dit. */
.topcal-front .tcf-vous-connu{margin:.5rem 0 0;font-size:.92rem;color:var(--tcf-ink-2)}
.topcal-front .tcf-vous-grille{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:1rem}
@media (max-width:560px){
  .topcal-front .tcf-vous-grille{grid-template-columns:1fr}
}
.topcal-front .tcf-legend i{width:8px;height:8px;border-radius:50%;display:block;flex:none}
/* La nomenclature. Elle nommait quatre ETATS ; elle nomme les SEANCES. */
.topcal-front .tcf-legend .tcf-ev-0{background:var(--tcf-ev-0)}
.topcal-front .tcf-legend .tcf-ev-1{background:var(--tcf-ev-1)}
.topcal-front .tcf-legend .tcf-ev-2{background:var(--tcf-ev-2)}
.topcal-front .tcf-legend .tcf-ev-3{background:var(--tcf-ev-3)}
.topcal-front .tcf-legend .tcf-ev-4{background:var(--tcf-ev-4)}
.topcal-front .tcf-legend .tcf-ev-5{background:var(--tcf-ev-5)}
.topcal-front .tcf-legend .tcf-ev-6{background:var(--tcf-ev-6)}
.topcal-front .tcf-legend .tcf-ev-7{background:var(--tcf-ev-7)}
.topcal-front .tcf-legend .tcf-ev-8{background:var(--tcf-ev-8)}

/* ══ BARRE DE VUE — UNE CARTE VIDE A NEUF DIXIEMES N'EST PAS UNE CARTE ════
 *
 * Elle portait un fond, une bordure, un rayon et seize pixels de rembourrage
 * — c'est-a-dire tout le vocabulaire d'une carte — pour ne contenir QU'UN
 * groupe d'onglets de 190 px, pousse a droite par `margin-left:auto`.
 *
 * Mesure du 01/09 sur la vue Liste en 1 200 px : la barre fait 1 136 px de
 * large, son contenu 190. Neuf cent quarante-six pixels de boite vide, en
 * haut de la page publique — la premiere chose que voit un visiteur, et deux
 * des quatre captures que le proprietaire a envoyees.
 *
 * Un selecteur de vue est un CONTROLE, pas un panneau. Il se pose seul, a
 * gauche, la ou commence tout le reste de la page. La boite disparait ; il ne
 * restait rien a mettre dedans.
 *
 * `margin-left` devient `margin-inline-start` — la barre existe aussi en
 * arabe, ou « a gauche » veut dire a droite. */
.topcal-front .tcf-bar{
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;margin-bottom:2.4rem;
}
.topcal-front .tcf-views{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);
  display:inline-flex;background:var(--tcf-bg);border:1px solid var(--tcf-line);
  border-radius:12px;padding:3px;gap:2px;flex-wrap:wrap;
}
/* ⚠ MESURE DU 21/09 — 38 px, ECRIT A LA MAIN A COTE D'UN JETON QUI DIT 44.
   La barre de vues est la commande la plus touchee du calendrier public : c'est
   par elle qu'un visiteur passe de la liste au mois. A 390 px elle rendait
   38 px de haut, sur les six vues — six pixels sous la pulpe d'un pouce, sur
   trente cibles. `--tcf-touch` valait deja 44 px et servait a dix autres
   endroits de cette feuille ; personne n'avait branche celui-ci. */
.topcal-front .tcf-views a{
  font-family:var(--tcf-mono);font-size:.74rem;padding:9px 15px;border-radius:10px;
  color:var(--tcf-ink-2);text-decoration:none;min-height:var(--tcf-touch);display:inline-flex;align-items:center;
}
.topcal-front .tcf-views a[aria-current]{background:var(--tcf-surface);color:var(--tcf-ink);box-shadow:0 1px 2px rgba(23,19,16,.06)}

/* ══════════════════ LE CRENEAU — LA BRIQUE DES TROIS VUES ═══════════════
 *
 * ── CE QUI A DISPARU, ET POURQUOI ────────────────────────────────────────
 *
 * `.tcf-date` : un bloc de 74 px portant trois lettres de jour au-dessus d'un
 * chiffre de 2,4 rem. C'est LE trait reconnaissable de The Events Calendar et
 * des greffons qui l'ont copie ; nous l'avions au pixel pres. Le proprietaire
 * a demande le 02/09 que le calendrier public cesse d'y ressembler.
 *
 * Ce n'est pas qu'une question d'apparence. Un agenda d'evenements ANNONCE :
 * sa question est « qu'est-ce qui se passe, et quand ». Un moteur de
 * reservation VEND UNE PLACE : sa question est « puis-je encore venir, et a
 * quelle heure ». La date en gros chiffres repond a la premiere ; l'heure et
 * les places restantes repondent a la seconde.
 *
 * Trois consequences dans cette feuille :
 *
 * · la journee devient un TITRE (`.tcf-jour-titre`), annonce une fois, au
 *   lieu de se repeter a chaque ligne — un samedi a trois seances affichait
 *   trois fois « SAM 5 » ;
 * · l'HEURE prend la premiere colonne, en chasse fixe, alignee — la forme
 *   d'un carnet de rendez-vous, pas celle d'une affiche ;
 * · la JAUGE de places remplace la mention seule. C'est la donnee que nous
 *   sommes seuls a avoir : un agenda d'evenements ne sait pas combien il
 *   reste de places, parce qu'il ne vend rien.
 */

/* Le mois : un surtitre discret. Il change douze fois par an quand la journee
   change tous les jours — l'oeil doit pouvoir les hierarchiser. */
.topcal-front .tcf-mois{display:flex;align-items:center;gap:18px;margin:3.2rem 0 0}
.topcal-front .tcf-mois:first-of-type{margin-top:0}
.topcal-front .tcf-mois span{
  font-family:var(--tcf-mono);font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--tcf-ink-3);white-space:nowrap;
}
.topcal-front .tcf-mois i{flex:1;height:1px;background:var(--tcf-line);display:block}

/* La journee : le vrai titre de la liste.
 *
 * ⚠ `::first-letter`, ET SURTOUT PAS `capitalize`.
 *
 * `wp_date('l j F')` rend « mercredi 2 septembre ». `text-transform:capitalize`
 * met une majuscule a CHAQUE mot : « Mercredi 2 Septembre ». En francais, un
 * mois ne prend pas de majuscule — pas plus qu'un jour de la semaine — et la
 * faute se voit sur chaque titre de chaque journee de chaque liste.
 *
 * Elle ne se verrait pas en anglais, ou « Wednesday 2 September » est correct.
 * C'est le genre de defaut qu'une seule langue revele, et le francais est la
 * langue du proprietaire. */
/* Ce titre est pose sur le fond du THEME, pas sur une de nos surfaces : il
   herite donc son encre. Avec `var(--tcf-ink)` en dur il mesurait 1,01:1 sur
   un theme sombre — le nom du jour, invisible, au-dessus de ses creneaux. */
.topcal-front .tcf-jour-titre{
  font-size:1.15rem;margin:1.9rem 0 .2rem;color:inherit;
}
.topcal-front .tcf-jour-titre::first-letter,
.topcal-front .tcf-jour-h h3::first-letter{text-transform:uppercase}

.topcal-front .tcf-creneau{
  display:grid;grid-template-columns:var(--tcf-col-heure,128px) minmax(0,1fr) auto;
  gap:28px;align-items:start;
  padding:1.35rem 0;border-top:1px solid var(--tcf-line);
}
.topcal-front .tcf-creneau > *{min-width:0}
/* ══ MES RESERVATIONS — la page du compte client ═══════════════════════════
 *
 * « Retrouver ses evenements ». Le client arrive ici pour UNE chose : relire
 * la date et l'heure de ce qu'il a reserve, sans rappeler l'exploitante.
 *
 * ── LA DATE EN BLOC, A GAUCHE ────────────────────────────────────────────
 *
 * Trois lignes serrees — le quantieme en gros, le mois, l'annee — plutot
 * qu'une phrase. On ne LIT pas cette colonne, on la BALAIE : c'est un
 * ephemeride, et l'oeil y retrouve « le 12 » sans passer par les mots.
 * L'annee est en tout petit parce qu'elle ne sert que deux fois par an,
 * autour du 31 decembre — mais ces deux fois-la, elle evite un appel.
 *
 * ── ET LA MISE EN PAGE CEDE SOUS 560 px ─────────────────────────────────
 *
 * Trois colonnes sur un telephone donneraient un prix de neuf pixels de
 * large. La ligne devient alors une pile, l'etat et le prix passent cote a
 * cote sous le titre. C'est la meme regle que les fiches de creneau, et pour
 * la meme raison : cette page se lit debout, dehors, une main sur le guidon.
 */
/* Le bloc entier. Pas de carte, pas de bordure : il se pose sur la page du
   client comme le calendrier, et la page porte deja son cadre. */
.topcal-front.tcf-compte{margin-block:1.2rem}
.topcal-front .tcf-compte-liste{list-style:none;margin:0;padding:0}
.topcal-front .tcf-compte-l{
  display:grid;grid-template-columns:64px minmax(0,1fr) auto;
  align-items:center;column-gap:22px;
  padding:1.15rem 0;border-top:1px solid var(--tcf-line);
}
.topcal-front .tcf-compte-l:first-child{border-top:0}

.topcal-front .tcf-compte-quand{
  display:flex;flex-direction:column;align-items:center;
  line-height:1.1;color:var(--tcf-ink-2);
}
.topcal-front .tcf-compte-quand .j{font-size:1.5rem;font-weight:600;color:var(--tcf-ink);font-variant-numeric:tabular-nums}
.topcal-front .tcf-compte-quand .m{font-size:.78rem;text-transform:lowercase}
.topcal-front .tcf-compte-quand .a{font-size:.68rem;color:var(--tcf-ink-3);margin-top:2px;font-variant-numeric:tabular-nums}

.topcal-front .tcf-compte-quoi{min-width:0;display:flex;flex-direction:column;gap:3px}
.topcal-front .tcf-compte-quoi b{font-size:1rem;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.topcal-front .tcf-compte-quoi .h{font-family:var(--tcf-mono);font-size:.8rem;color:var(--tcf-ink-2);font-variant-numeric:tabular-nums}
.topcal-front .tcf-compte-quoi .m{font-size:.78rem;color:var(--tcf-ink-3)}

.topcal-front .tcf-compte-etat{display:flex;flex-direction:column;align-items:flex-end;gap:5px}
.topcal-front .tcf-compte-prix{font-size:.95rem;font-weight:600;font-variant-numeric:tabular-nums}

@media (max-width:560px){
  .topcal-front .tcf-compte-l{grid-template-columns:52px minmax(0,1fr);row-gap:9px}
  .topcal-front .tcf-compte-etat{
    grid-column:1 / -1;flex-direction:row;align-items:center;
    justify-content:space-between;gap:12px;
  }
}

/* ══ UNE FAMILLE DE CRENEAUX, DANS LA LISTE — 09/09 ═══════════════════════
 *
 * Quand une meme seance revient trois fois ou plus dans la journee, la liste
 * ne rend plus une fiche par occurrence mais UN bloc : le nom une fois, les
 * heures en pastilles. Mesure d'avant : jeudi 10 septembre portait douze
 * fiches « Consultation » identiques, puis vendredi recommencait.
 *
 * Le bloc prend le RYTHME d'une ligne de liste — meme filet en haut, meme
 * respiration — pour qu'il se lise dans la meme colonne que les fiches qui
 * l'entourent. Il ne porte PAS de filet de couleur sur son bord : la teinte
 * de la seance est deja sur chacune de ses pastilles, et la reprendre sur le
 * bord ferait un aplat de couleur haut de dix lignes la ou les fiches n'ont
 * qu'un trait. */
.topcal-front .tcf-famille{padding:1.35rem 0;border-top:1px solid var(--tcf-line)}
.topcal-front .tcf-famille .tcf-g + .tcf-g{margin-top:.9rem}

/* La ligne porte la teinte de sa seance sur son bord de depart — c'est ce qui
   rattache la nomenclature a la vue Liste, ou il n'y a pas de pave. Un filet,
   pas un fond : quatorze jours de lignes teintees feraient un damier. */
.topcal-front .tcf-creneau.tcf-ev-1{box-shadow:inset 3px 0 0 var(--tcf-ev-1)}
.topcal-front .tcf-creneau.tcf-ev-2{box-shadow:inset 3px 0 0 var(--tcf-ev-2)}
.topcal-front .tcf-creneau.tcf-ev-3{box-shadow:inset 3px 0 0 var(--tcf-ev-3)}
.topcal-front .tcf-creneau.tcf-ev-4{box-shadow:inset 3px 0 0 var(--tcf-ev-4)}
.topcal-front .tcf-creneau.tcf-ev-5{box-shadow:inset 3px 0 0 var(--tcf-ev-5)}
.topcal-front .tcf-creneau.tcf-ev-6{box-shadow:inset 3px 0 0 var(--tcf-ev-6)}
.topcal-front .tcf-creneau.tcf-ev-7{box-shadow:inset 3px 0 0 var(--tcf-ev-7)}
.topcal-front .tcf-creneau.tcf-ev-8{box-shadow:inset 3px 0 0 var(--tcf-ev-8)}
.topcal-front .tcf-creneau[class*="tcf-ev-"]:not(.tcf-ev-0){padding-inline-start:16px}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-1{box-shadow:inset -3px 0 0 var(--tcf-ev-1)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-2{box-shadow:inset -3px 0 0 var(--tcf-ev-2)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-3{box-shadow:inset -3px 0 0 var(--tcf-ev-3)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-4{box-shadow:inset -3px 0 0 var(--tcf-ev-4)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-5{box-shadow:inset -3px 0 0 var(--tcf-ev-5)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-6{box-shadow:inset -3px 0 0 var(--tcf-ev-6)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-7{box-shadow:inset -3px 0 0 var(--tcf-ev-7)}
[dir="rtl"] .topcal-front .tcf-creneau.tcf-ev-8{box-shadow:inset -3px 0 0 var(--tcf-ev-8)}
/* L'heure : chasse fixe et chiffres tabulaires. Sans eux, « 9 » est plus
   etroit que « 18 » et la colonne danse d'une ligne a l'autre.
 *
 * `white-space:nowrap` et 128 px : a 104, « 09:00 — 12:00 » se coupait APRES
 * le tiret, et l'heure de fin tombait seule sur une deuxieme ligne. Une plage
 * horaire brisee au milieu se lit comme deux horaires.
 *
 * Le decalage haut aligne le chiffre sur la premiere ligne du titre, qui est
 * plus grand : sans lui, l'heure flotte deux pixels trop haut. */
/* Meme cas : l'heure est posee sur le fond du theme. C'est la faute la plus
   repetee du fichier — 292 des 360 textes illisibles mesures le 11/09. */
.topcal-front .tcf-heure{
  font-family:var(--tcf-mono);font-size:.84rem;color:inherit;
  font-variant-numeric:tabular-nums;line-height:1.5;
  white-space:nowrap;padding-top:.2rem;
}
/* La colonne du milieu. Elle porte le titre, la description et la jauge —
   c'est-a-dire tout ce qui se lit, et rien de ce qui s'aligne. */
.topcal-front .tcf-corps{display:flex;flex-direction:column}
.topcal-front .tcf-creneau h3{font-size:1.22rem;margin:0;line-height:1.35}
.topcal-front .tcf-desc{
  margin:.4rem 0 0;color:var(--tcf-ink-2);font-size:.9rem;line-height:1.55;max-width:58ch;
}
/* Le prix ET le bouton sur UNE ligne.
 *
 * Empiles, ils ajoutaient a chaque creneau la hauteur du bouton sous celle du
 * prix — et le bouton se retrouvait plus bas que la jauge de sa propre ligne,
 * donc visuellement detache d'elle. Sur quatorze jours de liste, ces deux
 * lignes de trop par creneau font une page deux fois plus longue pour la meme
 * information.
 *
 * Cote a cote, ils se lisent comme ce qu'ils sont : un prix, et le geste qui
 * l'accepte. */
.topcal-front .tcf-action{
  text-align:end;display:flex;flex-direction:row;align-items:center;
  justify-content:flex-end;gap:18px;padding-top:.1rem;
}
.topcal-front .tcf-price,.topcal-front .tcf-action .amount{
  display:block;font-size:1.32rem;font-variant-numeric:tabular-nums;
}

/* ── LA JAUGE DE PLACES ──────────────────────────────────────────────────
 *
 * `--tcf-part` est ECRITE PAR LE PHP et ne porte qu'une donnee : la part de
 * places deja prises. La feuille decide seule de la couleur et de la forme —
 * c'est la regle du depot depuis le premier jour, aucune couleur en dur dans
 * du PHP.
 *
 * Le repli `0%` n'est pas decoratif : si un jour la variable n'etait pas
 * ecrite, la barre serait VIDE — « personne n'a reserve » — plutot que
 * pleine, qui dirait « complet » et ferait fuir un client sur un creneau
 * libre. Entre deux erreurs possibles, on choisit celle qui ne coute pas une
 * vente. */
.topcal-front .tcf-jauge{display:flex;align-items:center;gap:12px;margin:.75rem 0 0;flex-wrap:wrap}
.topcal-front .tcf-jauge-barre{
  width:132px;height:5px;border-radius:100px;flex:none;
  background:var(--tcf-line);overflow:hidden;display:block;
}
.topcal-front .tcf-jauge-barre i{
  display:block;height:100%;border-radius:inherit;
  width:var(--tcf-part,0%);background:var(--tcf-free);
}
.topcal-front .is-tight .tcf-jauge-barre i{background:var(--tcf-tight)}
.topcal-front .is-full .tcf-jauge-barre i{background:var(--tcf-full)}
.topcal-front .is-closed .tcf-jauge-barre i{background:var(--tcf-closed)}
.topcal-front .tcf-jauge-txt{font-family:var(--tcf-mono);font-size:.74rem;color:var(--tcf-ink-2)}

/* Sans capacite, pas de barre — une jauge sans denominateur serait un
   mensonge dessine. La pastille et la phrase suffisent. */
.topcal-front .tcf-etat{display:flex;align-items:center;gap:12px;margin:.75rem 0 0;flex-wrap:wrap}
.topcal-front .tcf-etat-txt{font-family:var(--tcf-mono);font-size:.74rem;color:var(--tcf-ink-2)}

/* ── VUE MOIS ───────────────────────────────────────────────────────────── */
/* ══ LA GRILLE DU MOIS TIENT DANS UN ECRAN, ET C'EST UNE CONTRAINTE ══════
 *
 * Mesure du 02/09 en 1 200 px : chaque case faisait 149 x 149 px pour une
 * encre de 14 x 22 — un numero de jour et un point de 7 px. Vingt-deux mille
 * pixels carres de boite pour quatre cents d'information, et la grille
 * entiere montait a 825 px de haut : plus qu'un ecran d'ordinateur portable.
 * Le panneau de la journee depliee tombait donc sous la ligne de flottaison,
 * c'est-a-dire hors de vue au moment meme ou on vient de le demander.
 *
 * ── LA CAUSE ETAIT `aspect-ratio:1` ─────────────────────────────────────
 *
 * Il attache la hauteur a la largeur, SANS BORNE. Sept colonnes dans 1 100 px
 * font 149 px de large, donc 149 de haut. Sur un ecran plus large encore,
 * elles auraient continue de grossir. Une case de calendrier n'a pourtant
 * aucune raison d'etre carree : ce qu'elle porte ne grandit pas avec l'ecran.
 *
 * Une hauteur FIXE, donc, et la largeur reste elastique. La grille passe de
 * 825 px a environ 390 : le mois et la journee depliee tiennent ensemble dans
 * un ecran, ce qui est toute la raison d'avoir mis la journee sous la
 * grille. */
.topcal-front .tcf-cal{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;
  /* ── ⚠ `grid-auto-rows:1fr` A ETE RETIRE LE 21/09, ET IL COUTAIT CHER ───
     Le commentaire qui etait ici promettait : « toutes les cases d'une semaine
     font la hauteur de la plus haute, et la grille cesse d'etre en escalier ».
     La promesse est juste. `1fr` n'y est pour RIEN.

     MESURE DU 21/09, `grid-auto-rows:auto`, rangee par rangee :
         31,9 x7  |  60,4 x7  |  60,4 x7  |  60,4 x7  |  95,0 x7  |  82,3 x3
     ZERO rangee inegale. Les sept cases d'une semaine PARTAGENT leur rangee de
     grille : le grid les etire a la plus haute sans qu'on le demande. C'est
     exactement ce que la feuille de la console enonce de son cote, et elle n'a
     aucun `grid-auto-rows`.

     CE QUE `1fr` AJOUTAIT, personne ne l'avait demande : il egalisait aussi
     les SEMAINES ENTRE ELLES — et il embarquait la rangee des en-tetes
     « lun mar mer… », qui passait de 31,9 a 95 px. Soixante-trois pixels de
     vide pur au-dessus du mois.

         au repos          610,1 px  →  430,4 px
         journee depliee  3 073,5 px →  870,6 px

     ⚠ ET LA SECONDE LIGNE EST LE VRAI DEFAUT. Le bandeau de la journee
     depliee est un ENFANT de cette grille : `1fr` l'egalisait avec tout le
     reste, et les sept rangees passaient a 432 px CHACUNE. L'en-tete de
     `bin/grille.mjs` enregistre cette meme grille a 599 px le 04/09. Elle en
     faisait 3 073 — cinq fois — c'est-a-dire tres exactement le defaut que cet
     instrument a ete ecrit pour empecher : « la journee depliee tombe hors de
     l'ecran au moment ou on vient de la demander ».

     Rouge depuis le 12/09 (`963081f`), cinq jours AVANT le gel de la CI. Le
     lanceur existait ; c'est le VERDICT qui n'arrivait plus. */
  max-width:var(--tcf-cal-max,980px)}
.topcal-front .tcf-cal .dow{
  font-family:var(--tcf-mono);font-size:.62rem;letter-spacing:.14em;color:var(--tcf-ink-3);
  padding:0 0 1rem;text-align:center;text-transform:uppercase;
}
/* ── DE VRAIS PETITS CARRES ──────────────────────────────────────────────
 *
 * Largeur ET hauteur fixes, egales : la case est un carre de 56 px, centre
 * dans sa colonne. La grille, elle, reste elastique — c'est ce qui permet au
 * bandeau de la journee de prendre les sept colonnes sans que les carres
 * enflent avec la place.
 *
 * C'est la difference avec `aspect-ratio:1`, qui produisait le meme carre
 * mais SANS BORNE : a 1 100 px de colonne il valait 149 x 149. Ici la taille
 * est ecrite ; la colonne peut grandir, le carre non. `GRILLE-01` verifie
 * exactement ca. */
/* ⚠ LA CASE N'EST PLUS UN CARRE DE 56 PX, ET C'EST OBLIGE.
   Elle porte desormais un MOT — « 4 creneaux », « Complet » — et non plus
   trois points. Un carre fixe le couperait ou le ferait deborder selon la
   langue : « Fully booked » tient sur 56 px en anglais et pas en allemand.

   `minmax(0,1fr)` sur la grille et `min-width:0` ici : sans eux, une case dont
   le mot ne se coupe pas ELARGIT sa colonne, et les six autres retrecissent
   d'autant. La grille resterait valide et serait visiblement de travers. */
.topcal-front .tcf-day{
  min-width:0;min-height:var(--tcf-touch);border-radius:12px;
  display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;
  gap:4px;padding:7px;text-decoration:none;color:inherit;
}
/* Le numero a droite, comme sur un calendrier de bureau : c'est la ou l'oeil
   le cherche quand il balaie une colonne. */
.topcal-front .tcf-day .n{align-self:flex-end;font-size:.9rem;font-weight:600;line-height:1}
/* L'etat en bas de case, toujours a la meme hauteur d'une case a l'autre. */
.topcal-front .tcf-day .et{margin-top:auto;width:100%;min-width:0}
.topcal-front .tcf-day .et .tcf-state{
  font-size:.68rem;padding:2px 0;background:none;max-width:100%;
  /* Le mot prend l'encre du theme ; seul le POINT porte la couleur d'etat.
     Une encre coloree sur un theme sombre tombait sous le seuil AA — mesure
     du dessin : « douze couples sur vingt-quatre, tous sur fond sombre ». */
  color:var(--tcf-ink);
}
/* ⚠ MEME DEFAUT QUE LA BANDE DE SEMAINE, AUTRE REGLE.
   « 5 creneaux » devenait « 5 creneau » et « 11 creneaux » devenait
   « 11 crenea » : une case qui coupe son dernier caractere se lit comme une
   faute de frappe du produit, pas comme un manque de place. Le mot passe a la
   ligne ; la grille garde ses rangees egales — non par `grid-auto-rows:1fr`,
   retire le 21/09, mais parce que les sept cases d'une semaine PARTAGENT leur
   rangee de grille. Voir la note de `.tcf-cal` : mesure rangee par rangee,
   zero rangee inegale sans lui. */
.topcal-front .tcf-day .et .tcf-state span,
.topcal-front .tcf-day .et .tcf-state{white-space:normal;line-height:1.15}

/* AUJOURD'HUI : un disque d'encre sous le chiffre. Le premier repere qu'un
   oeil cherche dans un calendrier, et la grille ne le donnait pas. */
.topcal-front .tcf-day.is-today .n{
  /* ⚠ DEUX CHIFFRES TIENNENT DANS CE DISQUE. Ma premiere version le posait a
     24 px de large sans marge : « 12 » debordait et se faisait rogner par le
     `border-radius`. Un jour sur trois est a deux chiffres — le cas courant,
     pas le cas limite. */
  display:grid;place-items:center;box-sizing:content-box;
  min-width:1.4em;height:1.4em;padding:3px;border-radius:999px;
  /* ⚠ LE COUPLE INVERSE, ET NI `--tcf-ink` SUR `--tcf-bg` NI L'ACCENT.
     Les premiers retombent sur `currentColor` et `transparent` quand le theme
     ne declare rien : le fond prend alors la couleur de texte de l'element
     lui-meme, et le texte devient invisible — douze disques a 1,00. L'accent,
     lui, peut etre un jaune vif, et on n'ecrit rien sur une couleur qu'on ne
     connait pas. Le couple du theme RETOURNE est le seul dont le rapport soit
     garanti par construction. */
  background:var(--tcf-inverse-fond);color:var(--tcf-inverse-encre);line-height:1;
}
/* ⚠ ET DANS LA CASE SELECTIONNEE, ON RETOURNE UNE SECONDE FOIS.
   Cette case porte DEJA le couple inverse : un disque du meme fond dessus
   fait encre sur encre, 1,00 mesure le 12/09 sur les trois themes clairs.
   Deux inversions successives ramenent au couple de depart, qui se lit — et
   le disque redevient visible parce qu'il TRANCHE sur sa case. */
.topcal-front a.tcf-day.is-on.is-today .n{
  background:var(--tcf-inverse-encre);color:var(--tcf-inverse-fond);
}
/* Un jour OUVERT est une carte ; un jour ferme n'en est pas une. La difference
   se voit avant meme de lire le point de couleur — c'est ce qui rend la grille
   lisible en un coup d'oeil plutot qu'en la dechiffrant. */
.topcal-front a.tcf-day{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);background:var(--tcf-surface);border:1px solid var(--tcf-line)}
.topcal-front a.tcf-day:hover{border-color:var(--tcf-ac)}
/* La case choisie : c'est elle que le panneau deplie, il faut pouvoir la
   retrouver sans relire la date. */
/* ⚠ LA CASE SELECTIONNEE NE PREND PLUS L'ACCENT EN FOND.
   Elle posait `background: var(--tcf-ac); color:#fff` — un blanc EN DUR sur
   une couleur qu'on ne connait pas. Sur le theme du banc, dont le `primary`
   est un jaune vif, le numero du jour mesurait 1,52. Elle prend donc le
   couple du theme RETOURNE, dont le rapport est garanti par construction ;
   l'accent reste sur le filet et l'ombre, ou il ne porte aucun texte. */
.topcal-front a.tcf-day.is-on{
  border-color:var(--tcf-ac);background:var(--tcf-inverse-fond);color:var(--tcf-inverse-encre);
  box-shadow:0 6px 18px -8px var(--tcf-ac);
}
.topcal-front .tcf-day .n{font-size:1.05rem;line-height:1}
.topcal-front .tcf-day.is-out .n{color:var(--tcf-ink-3);opacity:.4}
.topcal-front .tcf-day.is-closed .n{color:var(--tcf-ink-3)}
/* ⚠ AUJOURD'HUI PEUT ETRE FERME, ET LE DISQUE Y PERDAIT SON TEXTE.
   Ces deux regles ont la meme specificite que celle du disque et viennent
   APRES : le gris des jours fermes ecrasait donc l'encre du disque, et le
   numero devenait un gris sur un fond sombre — 1,05 mesure sur les trois
   themes clairs le 12/09. Un jour ferme sur trois est un deux-chiffres ;
   celui d'aujourd'hui, une fois par mois, l'etait sans qu'on le voie. */
.topcal-front .tcf-day.is-closed.is-today .n,
.topcal-front .tcf-day.is-out.is-today .n{color:var(--tcf-inverse-encre);opacity:1}
/* Un point PAR TYPE present ce jour-la, trois au maximum : la case fait 56 px
   et au-dela les points se touchent. */
.topcal-front .tcf-day .dots{display:flex;gap:3px;margin-top:6px;min-height:6px}
.topcal-front .tcf-day .dots i{width:6px;height:6px;border-radius:50%;display:block}
.topcal-front .tcf-day .dots .tcf-ev-0{background:var(--tcf-ev-0)}
.topcal-front .tcf-day .dots .tcf-ev-1{background:var(--tcf-ev-1)}
.topcal-front .tcf-day .dots .tcf-ev-2{background:var(--tcf-ev-2)}
.topcal-front .tcf-day .dots .tcf-ev-3{background:var(--tcf-ev-3)}
.topcal-front .tcf-day .dots .tcf-ev-4{background:var(--tcf-ev-4)}
.topcal-front .tcf-day .dots .tcf-ev-5{background:var(--tcf-ev-5)}
.topcal-front .tcf-day .dots .tcf-ev-6{background:var(--tcf-ev-6)}
.topcal-front .tcf-day .dots .tcf-ev-7{background:var(--tcf-ev-7)}
.topcal-front .tcf-day .dots .tcf-ev-8{background:var(--tcf-ev-8)}
/* Sur la case SELECTIONNEE, le fond est l'encre du theme : les points y
   disparaitraient. Ils prennent le fond du theme — on ne lit plus le type sur
   cette case-la, mais on l'a sous les yeux dans le bandeau qu'elle vient
   d'ouvrir. `#fff` en dur devenait invisible des que le theme ouvrait clair. */
.topcal-front a.tcf-day.is-on .dots i{background:var(--tcf-inverse-encre)}
/* ⚠ ET LE MOT D'ETAT SUIT LE MEME RETOURNEMENT.
   Il prend `--tcf-ink`, qui n'est PLUS `currentColor` des que le theme
   declare une palette : c'est alors une couleur concrete — la meme que le
   fond de cette case-ci, qui porte l'encre du theme. Mesure du 12/09 :
   1,00 sur les deux themes a palette. Un jeton qui « suit le contexte » cesse
   de le suivre au moment ou il vaut quelque chose. */
.topcal-front a.tcf-day.is-on .et .tcf-state{color:var(--tcf-inverse-encre)}

/* ══════════════ LA JOURNEE DEPLIEE SOUS LA GRILLE DU MOIS ═══════════════
 *
 * Cliquer une date ouvrait la vue Jour : on perdait la grille, donc le mois,
 * donc la comparaison entre les jours — qui est la seule raison de regarder
 * un calendrier. Le panneau la garde sous les yeux.
 *
 * Il est visiblement RATTACHE a la grille : meme surface, un filet de marque
 * en haut, et la case choisie porte la meme marque. Sans ce lien, un bloc
 * apparaissant sous une grille se lit comme un second contenu sans rapport. */
/* ══════ LA JOURNEE S'OUVRE SOUS SA SEMAINE, DANS LA GRILLE ══════════════
 *
 * Deux dessins ont ete essayes, et le proprietaire a tranche le 02/09.
 *
 * Une FENETRE par-dessus, avec un voile, laissait la grille immobile — son
 * seul avantage. Mais elle COUPE le calendrier : on ne voit plus les autres
 * jours pendant qu'on lit celui-la, et sur un telephone la feuille couvre
 * tout. Or comparer deux journees est precisement ce qu'on vient faire.
 *
 * Le bandeau prend les sept colonnes, a l'endroit meme ou la semaine finit.
 * `grid-column:1/-1` est ce qui garantit qu'il ne decale pas les jours
 * suivants : il occupe une rangee entiere, et le mois reprend dessous.
 *
 * ── ET C'EST DU HTML, PAS UN SCRIPT ──────────────────────────────────────
 *
 * Le mandat est net : « LE FRONT n'a aucun JavaScript de production
 * aujourd'hui : c'est une decision, pas un oubli. » Il n'y en a pas besoin :
 * le SERVEUR sait deja quelle journee est ouverte, `topcal_date` le lui dit.
 * Le bandeau est du HTML present dans la page, donc INDEXE, donc partageable
 * par son adresse, et il s'ouvre meme si le script du theme a plante. */
.topcal-front .tcf-jour{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);
  grid-column:1 / -1;
  margin:.5rem 0;padding:.95rem 1.1rem 1rem;
  background:var(--tcf-surface);border:1px solid var(--tcf-line);
  border-top:2px solid var(--tcf-ac);border-radius:var(--tcf-r);
  scroll-margin-top:1.5rem;
}
/* La croix. Cible de 40 px : un « × » de 16 px se rate au doigt. */
/* 34 px et non 44 : ce n'est pas une cible principale — on referme le bandeau
   en cliquant une autre date, ce que la grille offre partout autour. Sur
   telephone elle reprend sa taille de doigt, plus bas. */
.topcal-front .tcf-fermer{
  margin-inline-start:auto;flex:none;
  width:34px;height:34px;margin-block:-4px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:1.25rem;line-height:1;color:var(--tcf-ink-2);text-decoration:none;
}
.topcal-front .tcf-fermer:hover{background:var(--tcf-bg);color:var(--tcf-ink)}
.topcal-front .tcf-jour:focus{outline:none}
/* `nowrap`, et l'eyebrow qui cede.
 *
 * En `wrap`, sur un telephone de 390 px, la croix ne tenait plus sur la
 * premiere ligne et passait dessous : quarante pixels de hauteur pour un
 * caractere, dans un encart qu'on venait justement de reduire de moitie.
 *
 * L'en-tete tient donc sur une ligne, et c'est le compte de seances qui se
 * laisse tronquer s'il le faut — c'est la seule des trois informations dont on
 * peut se passer : la date se lit deja dans la case selectionnee, et la croix
 * est un geste. */
.topcal-front .tcf-jour-h{
  display:flex;align-items:center;gap:12px;flex-wrap:nowrap;
  padding-bottom:.65rem;border-bottom:1px solid var(--tcf-line);
}
.topcal-front .tcf-jour-h h3{flex:none}
.topcal-front .tcf-jour-h .tcf-eyebrow{
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.topcal-front .tcf-jour-h h3{margin:0;font-size:1rem}
.topcal-front .tcf-jour .tcf-creneau:first-of-type{border-top:none}
.topcal-front .tcf-jour-vide{margin:1.3rem 0 1.7rem;color:var(--tcf-ink-2);font-size:.95rem}

/* ══════════════ LE SELECTEUR D'HEURES — LA JOURNEE, EN BOUTONS ══════════
 *
 * Le bandeau montrait des LIGNES completes : heure, titre, description, jauge,
 * prix, bouton. C'est la bonne forme pour parcourir quatorze jours ; c'en est
 * une mauvaise pour choisir une heure dans une journee qu'on a deja choisie.
 *
 * `auto-fill` et non `auto-fit` : a trois creneaux dans une largeur qui en
 * tiendrait six, `auto-fit` etire chaque bouton sur deux cents pixels et la
 * grille cesse d'etre une grille. `auto-fill` garde le pas, et les boutons
 * gardent la taille d'un bouton. */
/* ── LE NOM A COTE DE SES HEURES, PAS AU-DESSUS ──────────────────────────
 *
 * Mesure du 02/09 : l'encart faisait 760 x 451 px pour montrer TROIS boutons.
 * Le nom de chaque seance occupait sa propre ligne au-dessus de sa grille —
 * vingt-quatre pixels, plus vingt-deux de marge, TROIS fois — pour un mot.
 *
 * Cote a cote, le nom et ses heures partagent la meme rangee. La colonne du
 * nom est fixe : trois noms de longueurs differentes qui commenceraient
 * chacun a un endroit different rendraient la lecture verticale impossible. */
.topcal-front .tcf-g + .tcf-g{margin-top:.55rem}
@media (min-width:560px){
  .topcal-front .tcf-g.nomme{
    display:grid;grid-template-columns:minmax(0,190px) minmax(0,1fr);
    gap:14px;align-items:center;
  }
}
/* ── TROIS COLONNES, DES PAVES PLEINS, L'HEURE AU MILIEU ─────────────────
 *
 * Disposition demandee par le proprietaire le 02/09, capture a l'appui. Elle
 * remplace une grille `auto-fill` de petits boutons bordes.
 *
 * TROIS colonnes fixes, et non `auto-fill` : c'est ce qui donne aux paves leur
 * proportion — larges, poses, lisibles de loin. En `auto-fill`, le nombre de
 * colonnes suit la place disponible, et le meme ecran rend six boutons etroits
 * ici et trois larges la. La disposition demandee est une PROPORTION, pas une
 * densite maximale.
 *
 * ⚠ Elle occupe plus de place que ce qu'elle remplace, et c'est assume : la
 * demande precedente etait « que l'encart soit plus petit ». Les paves valent
 * plus haut. Le choix est au proprietaire ; le nom de la seance reste a COTE
 * de ses heures, ce qui garde l'essentiel de l'economie d'hier. */
.topcal-front .tcf-heures{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:12px;margin:.6rem 0 0;
}
.topcal-front .tcf-g.nomme .tcf-heures{margin:0}
/* Pas de bordure : c'est le FOND qui dessine le pave. Une bordure en plus du
   fond ferait deux contours pour une seule forme, et douze fois de suite ca
   se voit comme une grille de tableur. */
.topcal-front .tcf-heure-btn{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
  min-height:56px;padding:12px 8px;
  border:0;border-radius:12px;
  background:var(--tcf-fill);color:var(--tcf-ink);text-decoration:none;
  transition:background .15s,color .15s;
}
/* ⚠ PAS DE CHASSE FIXE ICI, ET C'EST UNE EXCEPTION ASSUMEE.
 *
 * L'en-tete de cette feuille pose `--tcf-mono` sur les horaires, et sa raison
 * est bonne : « un horaire en police proportionnelle danse quand les chiffres
 * changent, et une colonne d'heures qui danse est illisible ». Elle vise une
 * COLONNE d'heures alignees a gauche, comme dans la vue Liste.
 *
 * Ici les heures sont CENTREES dans des cellules de grille de largeur egale :
 * rien ne peut danser, la cellule ne bouge pas. Et `tabular-nums` aligne deja
 * les chiffres entre eux. La police du theme donne le pave de la capture ; le
 * mono donnait un ticket de caisse. */
.topcal-front .tcf-heure-btn .h{
  font-size:1.05rem;font-variant-numeric:tabular-nums;line-height:1.2;
}
/* La duree est une PRECISION, pas une seconde information : plus petite, plus
   pale, et elle ne se montre que si l'evenement en declare une fixe. */
.topcal-front .tcf-heure-btn .d{font-size:.72rem;color:var(--tcf-ink-3);line-height:1.2;margin-top:1px}

/* ── LE PAVE PREND LA TEINTE DE SA SEANCE ────────────────────────────────
 *
 * Le fond doux, et le trait sur le bord de depart. Le fond seul ne suffit
 * pas : huit teintes desaturees a ce point se confondent deux a deux sur un
 * ecran mal calibre. Le trait de 3 px porte la couleur pleine, celle de la
 * nomenclature, et c'est lui qu'on retrouve dans la legende.
 *
 * ⚠ « DERNIERES PLACES » NE PASSE PLUS PAR LA. Une meme dimension ne peut pas
 * dire deux choses : depuis que la couleur nomme le type, une teinte ambre
 * signifierait a la fois « seance du soir » et « il en reste peu », et la
 * nomenclature ne pourrait pas la decoder. L'etat reste ecrit — dans le
 * `aria-label` du pave, sur l'ecran de reservation, et en toutes lettres dans
 * la vue Liste. « Complet », lui, n'a jamais dependu de la couleur : le pave
 * est BARRE et ce n'est pas un lien. */
.topcal-front .tcf-heure-btn.tcf-ev-0{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);background:var(--tcf-fill)}
/* ⚠ LA COULEUR D'EVENEMENT EST UN TRAIT, JAMAIS UN APLAT SOUS DU TEXTE.
   Ces huit regles posaient un fond `-doux` — huit couleurs claires FIGEES.
   L'heure et la duree ecrites dessus prennent `--tcf-ink`, qui suit le theme :
   sur un theme sombre, une encre claire sur un aplat clair. Mesure du 12/09 :
   vingt-six textes a 1,03 sur la vue Mois+Jour, tous ici.
   Le trait de 3 px, lui, ne porte aucun texte : il nomme l'activite sans
   jamais rien mettre en peril. C'est la regle du socle, et elle vaut ici. */
.topcal-front .tcf-heure-btn.tcf-ev-1{box-shadow:inset 3px 0 0 var(--tcf-ev-1)}
.topcal-front .tcf-heure-btn.tcf-ev-2{box-shadow:inset 3px 0 0 var(--tcf-ev-2)}
.topcal-front .tcf-heure-btn.tcf-ev-3{box-shadow:inset 3px 0 0 var(--tcf-ev-3)}
.topcal-front .tcf-heure-btn.tcf-ev-4{box-shadow:inset 3px 0 0 var(--tcf-ev-4)}
.topcal-front .tcf-heure-btn.tcf-ev-5{box-shadow:inset 3px 0 0 var(--tcf-ev-5)}
.topcal-front .tcf-heure-btn.tcf-ev-6{box-shadow:inset 3px 0 0 var(--tcf-ev-6)}
.topcal-front .tcf-heure-btn.tcf-ev-7{box-shadow:inset 3px 0 0 var(--tcf-ev-7)}
.topcal-front .tcf-heure-btn.tcf-ev-8{box-shadow:inset 3px 0 0 var(--tcf-ev-8)}
/* `inset-inline` n'existe pas pour `box-shadow` : en ecriture arabe le trait
   resterait a gauche. On le retourne a la main. */
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-1{box-shadow:inset -3px 0 0 var(--tcf-ev-1)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-2{box-shadow:inset -3px 0 0 var(--tcf-ev-2)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-3{box-shadow:inset -3px 0 0 var(--tcf-ev-3)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-4{box-shadow:inset -3px 0 0 var(--tcf-ev-4)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-5{box-shadow:inset -3px 0 0 var(--tcf-ev-5)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-6{box-shadow:inset -3px 0 0 var(--tcf-ev-6)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-7{box-shadow:inset -3px 0 0 var(--tcf-ev-7)}
[dir="rtl"] .topcal-front .tcf-heure-btn.tcf-ev-8{box-shadow:inset -3px 0 0 var(--tcf-ev-8)}
.topcal-front a.tcf-heure-btn:hover{filter:brightness(.97)}
/* COMPLET : visible — savoir que ce creneau existe est une information — mais
   pas cliquable. C'est un `<span>` cote serveur, pas un lien desactive. */
.topcal-front .tcf-heure-btn.est-plein{
  color:var(--tcf-ink-3);background:var(--tcf-bg);
  box-shadow:inset 0 0 0 1px var(--tcf-line);cursor:default;
  text-decoration:line-through;text-decoration-thickness:1px;
}

/* Le nom de la seance, quand la journee en porte plusieurs. */
.topcal-front .tcf-groupe{
  display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  margin:.55rem 0 0;font-size:.88rem;line-height:1.3;color:var(--tcf-ink);
}
@media (min-width:560px){
  /* En colonne, le nom et le prix s'EMPILENT.
   *
   * `display:block` seul les collait : « Seance decouverte45,00 € ». Le `gap`
   * du flex tenait l'espace, et le passer en bloc l'a supprime sans que rien
   * ne le remplace. C'est le genre de defaut qu'on ne voit qu'en rendant —
   * dans le balisage, les deux elements sont toujours separes. */
  .topcal-front .tcf-g.nomme .tcf-groupe{margin:0;display:block}
  .topcal-front .tcf-g.nomme .tcf-groupe-prix{display:block;margin-top:1px}
}
.topcal-front .tcf-groupe-prix{font-family:var(--tcf-mono);font-size:.72rem;color:var(--tcf-ink-2)}
/* La pastille rattache le nom a sa teinte : sans elle, la nomenclature nomme
   des couleurs que rien ne relie a ce qu'on lit juste a cote. */
.topcal-front .tcf-groupe i{
  width:9px;height:9px;border-radius:50%;display:inline-block;
  margin-inline-end:7px;vertical-align:baseline;
}
.topcal-front .tcf-groupe .tcf-ev-0{background:var(--tcf-ev-0)}
.topcal-front .tcf-groupe .tcf-ev-1{background:var(--tcf-ev-1)}
.topcal-front .tcf-groupe .tcf-ev-2{background:var(--tcf-ev-2)}
.topcal-front .tcf-groupe .tcf-ev-3{background:var(--tcf-ev-3)}
.topcal-front .tcf-groupe .tcf-ev-4{background:var(--tcf-ev-4)}
.topcal-front .tcf-groupe .tcf-ev-5{background:var(--tcf-ev-5)}
.topcal-front .tcf-groupe .tcf-ev-6{background:var(--tcf-ev-6)}
.topcal-front .tcf-groupe .tcf-ev-7{background:var(--tcf-ev-7)}
.topcal-front .tcf-groupe .tcf-ev-8{background:var(--tcf-ev-8)}

/* ── VUE CARTES ─────────────────────────────────────────────────────────── */
.topcal-front .tcf-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:22px}
.topcal-front .tcf-cards > *{min-width:0}
.topcal-front .tcf-card{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);
  background:var(--tcf-surface);border:1px solid var(--tcf-line);border-radius:18px;
  overflow:hidden;display:flex;flex-direction:column;
}
/* `.fig` reste dessine : le jour ou un evenement porte une image, elle a sa
   place. Ce qui a disparu, c'est la boite RENDUE SANS image — voir
   `TOPCAL_Front::view_cards()`. */
/* Le liesere de type, comme sur un creneau. `overflow:hidden` sur la carte
   couperait une ombre interieure au rayon : on la pose donc en bordure. */
.topcal-front .tcf-card.tcf-ev-1{border-inline-start:3px solid var(--tcf-ev-1)}
.topcal-front .tcf-card.tcf-ev-2{border-inline-start:3px solid var(--tcf-ev-2)}
.topcal-front .tcf-card.tcf-ev-3{border-inline-start:3px solid var(--tcf-ev-3)}
.topcal-front .tcf-card.tcf-ev-4{border-inline-start:3px solid var(--tcf-ev-4)}
.topcal-front .tcf-card.tcf-ev-5{border-inline-start:3px solid var(--tcf-ev-5)}
.topcal-front .tcf-card.tcf-ev-6{border-inline-start:3px solid var(--tcf-ev-6)}
.topcal-front .tcf-card.tcf-ev-7{border-inline-start:3px solid var(--tcf-ev-7)}
.topcal-front .tcf-card.tcf-ev-8{border-inline-start:3px solid var(--tcf-ev-8)}
.topcal-front .tcf-card .fig{height:132px;position:relative;display:grid;place-items:center;background:var(--tcf-closed-soft)}
.topcal-front .tcf-card .fig img{width:100%;height:100%;object-fit:cover}
.topcal-front .tcf-card .fig .tcf-state{position:absolute;top:12px;inset-inline-end:12px}
/* ── LA MEME FIGURE, PLUS HAUTE, SUR L'ECRAN DE RESERVATION ───────────────
   C'est l'ecran ou l'on decide : la photo y merite plus que 132 px. Elle
   garde son `object-fit:cover`, donc une photo verticale ne deforme pas —
   elle se recadre. `aspect-ratio` plutot qu'une hauteur fixe : sur un
   telephone, une bande de 220 px de haut sur 360 de large mange l'ecran. */
.topcal-front .tcf-book .fig{aspect-ratio:16/9;max-height:280px;border-radius:14px;overflow:hidden;
  margin-bottom:20px;background:var(--tcf-closed-soft)}
.topcal-front .tcf-book .fig img{width:100%;height:100%;object-fit:cover;display:block}
.topcal-front .tcf-card .body{padding:24px 24px 26px;display:flex;flex-direction:column;flex:1}
.topcal-front .tcf-card .when{font-family:var(--tcf-mono);font-size:.7rem;color:var(--tcf-ink-3)}
/* ⚠ DEUX LIGNES RESERVEES, ET C'EST CE QUI ALIGNE LES JAUGES. Mesure du 10/09 :
   trois cartes cote a cote, et celle dont le titre passe a la ligne poussait sa
   jauge 25 px plus bas. Une rangee de barres a des hauteurs differentes se lit
   comme un defaut d'assemblage. Reserver la place coute du blanc sous les titres
   courts ; ne pas la reserver coute l'alignement de toute la rangee, et il
   suffit d'UNE traduction plus longue pour le perdre dans une langue qu'on ne
   regarde pas. */
.topcal-front .tcf-card h3{font-size:1.35rem;margin:8px 0 0;min-height:2.3em}
.topcal-front .tcf-card .meta{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:14px}
.topcal-front .tcf-card .left{font-family:var(--tcf-mono);font-size:.72rem;color:var(--tcf-ink-2)}
.topcal-front .tcf-card .amount{font-size:1.5rem;margin:18px 0 16px;display:block}
.topcal-front .tcf-card .act{margin-top:auto}
.topcal-front .tcf-card .act > *{width:100%}

/* ── FORMULAIRE DE RESERVATION ──────────────────────────────────────────── */
.topcal-front .tcf-book{display:grid;grid-template-columns:1.55fr 1fr;gap:56px;align-items:start}
.topcal-front .tcf-book > *{min-width:0}
/* ── LA DESCRIPTION DE L'ECRAN DE RESERVATION ────────────────────────────
   Elle vivait dans un `style=` ecrit en PHP. Elle en sort parce qu'elle a
   change de nature : depuis le 10/09 elle se rend EN ENTIER — c'est l'ecran ou
   le client decide, il n'y a plus rien a y parcourir — donc elle peut faire
   vingt lignes la ou elle en faisait deux, et sa mesure de ligne devient une
   vraie decision de lecture. `max-width` en `ch` et pas en `px` : la limite
   suit la police REELLEMENT rendue par le theme du client, alors qu'une
   valeur en pixels supposerait la notre.

   ⚠ PAS DE `white-space:pre-line` ICI, ET CE N'EST PAS UN OUBLI. Les sauts de
   ligne arrivent deja en `<br />` (`nl2br` cote PHP) et le saut d'origine
   reste dans le texte : la propriete compterait chaque retour une seconde
   fois et doublerait l'ecartement des paragraphes. */
.topcal-front .tcf-book-desc{margin-top:.9rem;color:var(--tcf-ink-2);max-width:52ch}
.topcal-front .tcf-panel{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);
  background:var(--tcf-surface);border:1px solid var(--tcf-line);
  border-radius:16px;padding:26px;position:sticky;top:24px;
}
.topcal-front input.tcf-count{width:110px;font-size:1.1rem;font-family:var(--tcf-mono)}
.topcal-front .tcf-count{display:inline-flex;align-items:center;gap:14px}
.topcal-front .tcf-count button{
  width:var(--tcf-touch);height:var(--tcf-touch);border-radius:var(--tcf-r-sm);
  border:1px solid var(--tcf-line);background:var(--tcf-surface);color:var(--tcf-ink-2);
  display:grid;place-items:center;font-family:var(--tcf-mono);font-size:1.05rem;cursor:pointer;
}
.topcal-front .tcf-count button:hover:not(:disabled){border-color:var(--tcf-ac);color:var(--tcf-ac)}
.topcal-front .tcf-count button:disabled{opacity:.4;cursor:not-allowed}
.topcal-front .tcf-count output{font-size:1.7rem;min-width:34px;text-align:center}

.topcal-front .tcf-opt{
  display:flex;align-items:flex-start;gap:13px;padding:13px 0;
  border-top:1px solid var(--tcf-line);cursor:pointer;
}
.topcal-front .tcf-opt.is-out{opacity:.55;cursor:not-allowed}
.topcal-front .tcf-opt input{
  width:22px;height:22px;flex:none;margin:0;accent-color:var(--tcf-ac);cursor:inherit;
}
.topcal-front .tcf-opt .lbl{flex:1;min-width:0}
.topcal-front .tcf-opt .lbl b{font-weight:600;font-size:.96rem}
.topcal-front .tcf-opt .lbl small{display:block;font-family:var(--tcf-mono);font-size:.68rem;color:var(--tcf-ink-3);margin-top:2px}
.topcal-front .tcf-opt.is-out .lbl small{color:var(--tcf-full)}
.topcal-front .tcf-opt .amount{font-family:var(--tcf-mono);font-size:.82rem;color:var(--tcf-ink-2);flex:none}

.topcal-front .tcf-recap{display:flex;justify-content:space-between;gap:14px;font-size:.92rem;padding:7px 0}
.topcal-front .tcf-recap span:first-child{color:var(--tcf-ink-2)}
.topcal-front .tcf-recap span:last-child{font-family:var(--tcf-mono);font-size:.84rem}
.topcal-front .tcf-total{
  border-top:1px solid var(--tcf-line);margin-top:12px;padding-top:16px;
  display:flex;justify-content:space-between;align-items:baseline;
}
.topcal-front .tcf-total .amount{font-size:2rem}

/* Le panneau de reservation, sorti des attributs `style` du PHP — sans quoi
   aucune regle de media ne peut le reduire en barre epinglee (voir plus bas). */
.topcal-front .tcf-panel-titre{font-size:1.25rem;margin:.8rem 0 .2rem}
.topcal-front .tcf-panel-quand{font-family:var(--tcf-mono);font-size:.76rem;color:var(--tcf-ink-2)}
.topcal-front .tcf-panel-geste{margin-top:1.3rem}
.topcal-front .tcf-panel-geste .tcf-btn{width:100%}
.topcal-front .tcf-panel-note{
  font-family:var(--tcf-mono);font-size:.68rem;color:var(--tcf-ink-3);
  margin-top:.9rem;line-height:1.6;
}

/* ── CHOIX D'UNE UNITE ──────────────────────────────────────────────────── */
.topcal-front .tcf-units{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:20px}
.topcal-front .tcf-units > *{min-width:0}
.topcal-front .tcf-unit{
  /* NOTRE fond, donc NOTRE encre : les deux moities, ou aucune. */
  color:var(--tcf-ink);
  background:var(--tcf-surface);border:1px solid var(--tcf-line);border-radius:16px;
  overflow:hidden;position:relative;display:block;cursor:pointer;
}
.topcal-front .tcf-unit input{position:absolute;opacity:0;width:1px;height:1px}
.topcal-front .tcf-unit .fig{height:104px;display:grid;place-items:center;background:var(--tcf-closed-soft);font-size:1.9rem;color:var(--tcf-ink-3)}
.topcal-front .tcf-unit .body{padding:15px 16px 17px}
.topcal-front .tcf-unit .body b{font-size:1.3rem;font-weight:400}
.topcal-front .tcf-unit .body .ref{font-family:var(--tcf-mono);font-size:.66rem;color:var(--tcf-ink-3);margin-inline-start:9px}
.topcal-front .tcf-unit .body .desc{display:block;font-size:.86rem;color:var(--tcf-ink-2);margin-top:5px}
.topcal-front .tcf-unit .body .st{display:block;font-family:var(--tcf-mono);font-size:.68rem;margin-top:10px;color:var(--tcf-free)}
.topcal-front .tcf-unit:has(input:checked){border:2px solid var(--tcf-ac);box-shadow:0 0 0 4px rgba(23,19,16,.08)}
/* Repli sans `:has()` — le navigateur qui ne le connait pas doit quand meme
   montrer une selection, sinon le client coche sans retour visuel. */
.topcal-front .tcf-unit.is-picked{border:2px solid var(--tcf-ac);box-shadow:0 0 0 4px rgba(23,19,16,.08)}

/* ── LES DEUX ETATS QUI NE SE CHOISISSENT PAS ────────────────────────────
 *
 * Une unite prise ou en entretien reste VISIBLE : la cacher ferait croire que
 * le parc est plus petit qu'il n'est. Elle cesse seulement d'etre cliquable,
 * et le curseur le dit avant meme le clic.
 *
 * ⚠ LA COULEUR NE PORTE RIEN TOUTE SEULE. Chaque carte ecrit son etat en
 * toutes lettres dans `.st` — c'est ce texte qui informe. Ces regles-ci ne
 * font que le doubler pour l'oeil qui balaie, et le hachure du hors-service
 * est ce qui le distingue d'un simple gris sur un telephone au soleil. */
.topcal-front .tcf-unit.is-taken,
.topcal-front .tcf-unit.is-out{cursor:not-allowed}
.topcal-front .tcf-unit.is-taken .body b,
.topcal-front .tcf-unit.is-out .body b{text-decoration:line-through;color:var(--tcf-ink-2)}
.topcal-front .tcf-unit.is-taken .body .st{color:var(--tcf-full)}
.topcal-front .tcf-unit.is-out .body .st{color:var(--tcf-ink-2)}
.topcal-front .tcf-unit.is-taken .fig{background:var(--tcf-full-soft)}
.topcal-front .tcf-unit.is-out .fig{
  background:repeating-linear-gradient(45deg,var(--tcf-fill),var(--tcf-fill) 5px,transparent 5px,transparent 10px);
}

/* ── LA SECTION QUI PORTE LE CHOIX ──────────────────────────────────────
 *
 * Le meme ecartement que les autres sections du formulaire — « combien de
 * personnes », « options » — qui le portaient en attribut `style`. Celle-ci
 * nait avec sa classe : ce qui n'a pas de classe ne peut etre ni repris par
 * une regle de media, ni redefini par le theme du client. */
.topcal-front .tcf-choix{margin-top:2.4rem}
.topcal-front .tcf-choix h3{font-size:1.4rem}
.topcal-front .tcf-choix .tcf-eyebrow{display:block;margin-top:.3rem}
.topcal-front .tcf-choix-note{color:var(--tcf-ink-3);font-size:.88rem;margin:.3rem 0 1rem}
.topcal-front .tcf-choix .tcf-units{margin-top:1rem}
.topcal-front .tcf-choix .tcf-choix-note:last-child{margin:1rem 0 0}

/* ── « CE QUI VA SE PASSER » ────────────────────────────────────────────
 *
 * La suite numerotee de la confirmation. Les etapes sont CONDITIONNELLES —
 * un site sans rappel en affiche deux, un client revenu par son lien deux
 * autres — donc les numeros ne peuvent pas etre ecrits dans le balisage : un
 * `<ol>` les recompte tout seul, et rien n'est a traduire.
 *
 * ⚠ LE COMPTEUR SE POSE SUR LA LISTE ET S'INCREMENTE SUR L'ELEMENT. Pose sur
 * l'element, il repartirait de zero a chaque ligne et les trois pastilles
 * diraient « 1 ». On retire la puce native (`list-style:none`) parce que
 * l'ordre reste porte par `<ol>` pour les lecteurs d'ecran : la pastille est
 * un DOUBLE visuel, jamais la seule facon de savoir qu'on est a l'etape 2. */
/* ⚠ `tcf-etapes` ET NON `tcf-suite` : ce nom-la est DEJA PRIS, huit cents
 * lignes plus bas, par le bouton « voir la suite des dates ». Les deux regles
 * auraient cohabite sans une erreur, sans un avertissement, et
 * `bin/css-classes-inventees.php` n'y voit rien — il refuse une classe
 * APPELEE et jamais dessinee, jamais deux dessins pour un meme nom. Le
 * resultat aurait ete une liste numerotee centree et un bouton de pagination
 * sans puce : deux defauts de mise en forme que seul un oeil attrape. */
.topcal-front .tcf-etapes-t{font-size:1.15rem;margin:1.6rem 0 .2rem}
.topcal-front .tcf-etapes{list-style:none;margin:0;padding:0;counter-reset:tcf-etape}
.topcal-front .tcf-etapes li{
  counter-increment:tcf-etape;
  display:flex;gap:14px;padding:14px 0;border-top:1px solid var(--tcf-line);
}
.topcal-front .tcf-etapes li::before{
  content:counter(tcf-etape);
  width:30px;height:30px;border-radius:50%;flex:none;
  display:grid;place-items:center;
  background:var(--tcf-fill);color:var(--tcf-ink-2);
  font-family:var(--tcf-mono);font-size:.8rem;font-weight:700;
}
.topcal-front .tcf-etapes li b{display:block;font-weight:600;font-size:.96rem}
.topcal-front .tcf-etapes li p{margin:.2rem 0 0;color:var(--tcf-ink-2);font-size:.92rem;line-height:1.55}

/* ── ETATS VIDES ET ERREURS ─────────────────────────────────────────────── */
/* ── LES SEMAINES A VENIR, REPLIEES ──────────────────────────────────────
 *
 * ⚠ Une activite quotidienne ouverte trois mois rendait 90 lignes identiques,
 * l'une sous l'autre. Rien ne distinguait une ligne d'une autre, donc rien
 * n'aidait a choisir : une liste qui ne hierarchise pas ne se lit pas, elle se
 * subit.
 *
 * Un repli NATIF, pas du script : le front n'a aucun JavaScript, par decision.
 * Et il garde tout le contenu DANS la page, donc indexable — paginer aurait
 * vendu la raison d'etre du produit contre de la mise en page. */
/* ── L'ACTIVITE, DITE UNE FOIS ───────────────────────────────────────────
 *
 * ⚠ La vue Liste JETAIT la photo, la description et la duree. Elle rendait une
 * heure, un nom repete 90 fois, une jauge vide, un prix et un bouton — un
 * horaire de train, pas une offre. C'est la raison de fond du « c'est moche le
 * front », et aucune retouche de style ne rattrape une page qui n'a rien a
 * montrer.
 *
 * La photo prend la moitie sur bureau et passe au-dessus sur telephone : une
 * image de 768 px comprimee dans une colonne de 340 px ne montre plus rien de
 * ce qu'elle voulait montrer. */
.topcal-front .tcf-offre{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);
  gap:2rem;align-items:center;
  margin:0 0 2.6rem;
}
.topcal-front .tcf-offre .fig{
  margin:0;border-radius:var(--tcf-r);overflow:hidden;
  aspect-ratio:4/3;background:var(--tcf-fill);
}
.topcal-front .tcf-offre .fig img{width:100%;height:100%;object-fit:cover;display:block}
.topcal-front .tcf-offre-mots h2{margin:0 0 .7rem;font-size:1.75rem;line-height:1.15;letter-spacing:-.01em}
.topcal-front /* ── OU ÇA SE PASSE, ET QUI L'ENCADRE ───────────────────────────────────────
 *
 * Une liste, pas deux paragraphes : ce sont deux faits de meme nature, et une
 * liste le dit sans le repeter. Les puces sont retirees — elles ajouteraient un
 * ornement a une information qui se lit seule.
 *
 * L'adresse est un lien : elle porte donc le soulignement de son etat, mais
 * discret. Un lien trop marque au milieu d'une fiche de reservation entre en
 * concurrence avec le seul bouton qui compte. */
.tcf-lieu{list-style:none;margin:.9rem 0 0;padding:0;display:flex;flex-direction:column;gap:.25rem}

/* ── LES AUTRES DATES DE LA MEME ACTIVITE ──────────────────────────────────
 *
 * Un pli, sous le formulaire. Ferme, il ne coute qu'une ligne ; ouvert, il rend
 * des liens ordinaires. Aucun JavaScript — c'est le meme `<details>` que les
 * semaines de la vue Liste.
 *
 * ⚠ ET ON DECLARE `display` SUR LES ENFANTS FERMES. L'agent masque les enfants
 * d'un `<details>` ferme, mais un `display` d'auteur le bat : c'est exactement
 * ce qui est arrive aux plis de la vue Liste le 06/09 — douze plis, et les
 * quatre-vingt-dix creneaux visibles quand meme. */
.tcf-autres{margin-top:2rem;border-top:1px solid var(--tcf-line);padding-top:1.1rem}
.tcf-autres:not([open]) > *:not(summary){display:none}
.tcf-autres > summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem}
.tcf-autres > summary::-webkit-details-marker{display:none}
.tcf-autres > summary::after{content:"";width:.5rem;height:.5rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);opacity:.5}
.tcf-autres[open] > summary::after{transform:rotate(225deg)}
.tcf-autres-titre{font-family:var(--tcf-mono);font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--tcf-ink-2)}
.tcf-autres-l{list-style:none;margin:1rem 0 0;padding:0;display:flex;flex-direction:column;gap:.15rem}
.tcf-autres-l a{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:.6rem;
  padding:.6rem .75rem;border-radius:var(--tcf-r-sm);color:inherit;text-decoration:none;min-height:var(--tcf-touch)}
/* `--tcf-bg`, le fond de page, et non un `--tcf-surface-2` qui n'existe pas :
   c'est le controle des jetons qui l'a dit, ligne 887. Un `var()` sans jeton ne
   casse rien de VISIBLE — la propriete prend sa valeur initiale, donc
   transparent — et n'ecrit nulle part. La console a vecu ainsi avec un
   formulaire sans bordure. */
.tcf-autres-l a:hover{background:var(--tcf-bg)}
.tcf-autres-quand{font-size:.95rem}
.tcf-autres-etat{font-family:var(--tcf-mono);font-size:.7rem;color:var(--tcf-ink-3)}
.tcf-autres-plus a{font-family:var(--tcf-mono);font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--tcf-ink-2)}
.tcf-lieu li{color:var(--tcf-ink-2);font-size:.95rem;line-height:1.5}
.tcf-lieu-ou a{color:inherit;text-decoration:underline;text-decoration-color:var(--tcf-ac-ombre,rgba(23,19,16,.35));text-underline-offset:.18em}
.tcf-lieu-ou a:hover{text-decoration-color:currentColor}
.tcf-lieu-par{font-size:.9rem}

.tcf-offre-desc{
  margin:0 0 1.2rem;max-width:46ch;
  font-size:1rem;line-height:1.65;color:var(--tcf-ink-2);
}
/* Les faits se lisent d'un trait, separes par un point median : trois lignes a
   puces pour trois mots courts occuperaient plus de place qu'ils n'en valent. */
.topcal-front .tcf-offre-faits{display:flex;flex-wrap:wrap;gap:.4rem 1rem;margin:0;padding:0;list-style:none}
.topcal-front .tcf-offre-faits li{
  font-family:var(--tcf-mono);font-size:.78rem;letter-spacing:.02em;
  color:var(--tcf-ink-3);display:flex;align-items:center;gap:1rem;
}
.topcal-front .tcf-offre-faits li+li::before{content:"·";color:var(--tcf-line)}

/* Sans photo, les mots prennent toute la largeur au lieu de laisser un trou. */
.topcal-front .tcf-offre:not(:has(.fig)){grid-template-columns:minmax(0,1fr)}

@media (max-width:720px){
  .topcal-front .tcf-offre{grid-template-columns:minmax(0,1fr);gap:1.2rem}
  .topcal-front .tcf-offre-mots h2{font-size:1.45rem}
}

.topcal-front .tcf-semaine{border-top:1px solid var(--tcf-line)}
/* ⚠ SANS CETTE LIGNE, UN REPLI FERME NE CACHE RIEN — et c'est contre-intuitif.
 *
 * Le navigateur masque les enfants d'un `<details>` ferme par sa feuille PAR
 * DEFAUT. Une regle d'AUTEUR qui pose un `display` sur ces enfants la bat donc
 * en specificite : `.tcf-mois{display:flex}` suffisait a faire reapparaitre
 * toute la semaine. Mesure du 07/09 sur un vrai WordPress : douze semaines
 * repliees, et 90 creneaux sur 90 toujours visibles.
 *
 * Le repli avait l'air de marcher — le chevron tournait, l'attribut `open`
 * s'ecrivait — et il ne repliait rien. C'est le pire etat : un mecanisme qui
 * repond sans agir. */
.topcal-front .tcf-semaine:not([open]) > *:not(summary){display:none}
.topcal-front .tcf-semaine > summary{
  display:flex;align-items:baseline;gap:1rem;
  padding:1.1rem .2rem;cursor:pointer;list-style:none;
  transition:color .15s;
}
.topcal-front .tcf-semaine > summary::-webkit-details-marker{display:none}
/* Le chevron est dessine, pas ecrit : un caractere dependrait de la police du
   theme, et il tournerait de travers dans la moitie des cas. */
.topcal-front .tcf-semaine > summary::before{
  content:"";flex:none;width:7px;height:7px;
  border-right:2px solid var(--tcf-ink-3);border-bottom:2px solid var(--tcf-ink-3);
  transform:rotate(-45deg);transition:transform .15s;
}
.topcal-front .tcf-semaine[open] > summary::before{transform:rotate(45deg)}
.topcal-front .tcf-semaine > summary:hover{color:var(--tcf-ac)}
.topcal-front .tcf-semaine > summary:hover::before{border-color:var(--tcf-ac)}
.topcal-front .tcf-semaine-quand{font-weight:600}
.topcal-front .tcf-semaine-combien{
  font-family:var(--tcf-mono);font-size:.78rem;color:var(--tcf-ink-3);
  margin-inline-start:auto;
}
/* Une semaine depliee ne colle pas a son propre titre. */
.topcal-front .tcf-semaine[open] > summary{padding-bottom:.4rem}
.topcal-front .tcf-semaine .tcf-mois:first-of-type{margin-top:.6rem}

.topcal-front .tcf-empty{text-align:center;padding:3rem 1.4rem;color:var(--tcf-ink-2)}
.topcal-front .tcf-empty b{display:block;font-size:1.1rem;color:var(--tcf-ink);margin-bottom:.4rem}
.topcal-front .tcf-empty p{max-width:44ch;margin:0 auto;font-size:.92rem}
/* L'ecran de reservation est le SEUL sans barre de vues : sorti par un etat
   vide, le visiteur n'avait aucune sortie, et la phrase « d'autres dates sont
   peut-etre libres » ne liait rien. */
.topcal-front .tcf-empty-geste{margin-top:1.6rem}
/* « Prevenez-moi » — le formulaire de l'etat vide.
   Le filet du haut le SEPARE de la phrase qui precede : sans lui, le champ se
   lit comme la suite du texte, et on ne voit pas qu'il y a un geste a faire.
   Largeur bornee : un champ de courriel etire sur 900 px n'est pas plus facile
   a remplir, il est plus difficile a VOIR. */
/* ── LE RAIL HORAIRE DE LA VUE JOUR ─────────────────────────────────────
   Une rangee par heure, et chaque seance posee sur les rangees qu'elle
   occupe : le creux de l'apres-midi se VOIT, au lieu de se compter.
   `--tcf-heures` porte le nombre de rangees, `--tcf-rang` et `--tcf-duree`
   la place de chaque piece. Les replis les rendent inoffensifs si un rendu
   les perdait : le rail redeviendrait une pile, jamais un tas. */
/* `minmax` et pas une hauteur fixe : une heure qui porte trois seances
   GRANDIT. Un rail qui cacherait pour rester regulier aurait inverse ses
   priorites — la regularite est une commodite, la seance est la vente. */
.topcal-front .tcf-agenda{display:grid;grid-template-columns:4.6rem repeat(var(--tcf-voies,1),minmax(0,1fr));grid-template-rows:repeat(var(--tcf-heures,12),minmax(var(--tcf-h-rang,68px),auto));position:relative}
.topcal-front .tcf-ln{grid-row:var(--tcf-rang,1);grid-column:1/-1;align-self:start;height:0;display:grid;grid-template-columns:4.6rem minmax(0,1fr);align-items:center}
.topcal-front .tcf-hl{text-align:end;padding-inline-end:.7rem;font-size:.78rem;line-height:1;color:var(--tcf-ink);opacity:.62;font-variant-numeric:tabular-nums}
.topcal-front .tcf-tr{border-top:1px solid var(--tcf-line)}
.topcal-front .tcf-pose{grid-column:calc(2 + var(--tcf-voie,0));grid-row:var(--tcf-rang,1)/span var(--tcf-duree,1);min-width:0;padding:3px 0 3px .2rem;display:flex;flex-direction:column}
.topcal-front .tcf-pose>*{flex:1;min-height:0}
/* Au telephone, la gouttiere d'heures se retracte : 4,6 rem sur 390 px, c'est
   un huitieme de l'ecran pris par cinq caracteres. Les rangees se resserrent
   aussi — une journee de douze heures ne doit pas demander douze ecrans. */
@media (max-width:560px){
  .topcal-front .tcf-agenda{--tcf-h-rang:58px}
  .topcal-front .tcf-agenda,
  .topcal-front .tcf-ln{grid-template-columns:3.1rem minmax(0,1fr)}
  .topcal-front .tcf-hl{font-size:.72rem;padding-inline-end:.4rem}
  /* Une voie de 110 px n'est pas une voie, c'est un couloir. Au telephone on
     renonce a l'etalement de la duree : chaque seance tient sa rangee de
     DEPART, sur toute la largeur. Rien ne se chevauche donc plus — les
     groupes sont uniques par rangee — et rien n'est cache. Le rail dit
     encore QUAND, il cesse seulement de dire COMBIEN DE TEMPS. */
  .topcal-front .tcf-pose{grid-column:2/-1;grid-row:var(--tcf-rang,1)}
}
.topcal-front .tcf-attente{margin-top:1.8rem;padding-top:1.6rem;border-top:1px solid var(--tcf-line);max-width:26rem;margin-left:auto;margin-right:auto;text-align:left}
.topcal-front .tcf-attente .tcf-empty-geste{margin-top:1rem}
/* « Deux personnes attendent deja » — le seul argument de cet ecran. Il se
   pose AVANT le champ, parce qu'il est la raison de le remplir. */
.topcal-front .tcf-attente-rang{
  margin:0 0 .9rem;padding:9px 12px;border-radius:10px;
  background:var(--tcf-tight-soft);color:var(--tcf-ink-2);font-size:.9rem;
}

/* ── LA SUITE DES DATES ──────────────────────────────────────────────────
   La vue Liste mesurait 26 179 px de haut sur un telephone avec 138 creneaux,
   la vue Cartes 41 568 — trente et un ecrans de defilement pour trouver une
   date. Chaque tranche garde son adresse, donc son indexation : c'est la
   promesse du produit, et un « voir plus » en JavaScript l'aurait perdue. */
.topcal-front .tcf-suite{margin:2.4rem 0 1rem;text-align:center}

/* ── « LA PROCHAINE EST LE 12 AVRIL », ET LE MOYEN D'Y ALLER ─────────────
 *
 * ⚠ CE QUE CETTE LIGNE FERME. Un evenement publie dont la periode s'ouvrait
 * dans sept mois n'apparaissait sur AUCUNE vue : la liste et les cartes ne
 * regardent que les quatre-vingt-dix prochains jours, et la vue Mois etait
 * verrouillee sur le mois courant, sans une seule fleche. La console, elle,
 * annonçait « en ligne sur le calendrier public ».
 *
 * Une vue vide ne se contente plus de se taire : elle dit ou est la suite. */
.topcal-front .tcf-ailleurs{
  max-width:44ch;margin:1.4rem auto 0;font-size:.92rem;color:var(--tcf-ink-2);
  display:flex;flex-direction:column;align-items:center;gap:.9rem;
}
/* Hors de l'etat vide, elle ferme un mois vide : elle garde alors sa place
   sous la grille plutot que d'etre centree dans du blanc. */
.topcal-front .tcf-cal + .tcf-ailleurs{margin-top:1.8rem}

/* ── LES DEUX PAS DE MOIS ────────────────────────────────────────────────
 *
 * Le pas indisponible est un `<span>`, pas un `<a>` grise : un lien qu'on
 * peut suivre et qui ne mene nulle part coute un clic et de la confiance.
 * Il garde sa place pour que le titre du mois ne se decale pas au passage
 * de septembre a octobre. */
/* ⚠ FUSION DU 15/09 — DEUX NAVIGATIONS DE MOIS PORTENT LA MEME CLASSE.
 *
 * `.tcf-mois-nav` est ecrite DEUX FOIS dans cette feuille, par deux branches
 * qui ne se sont pas vues, et les deux balisages sont rendus :
 *   · plus haut (« ALLER A UN AUTRE MOIS ») : une rangee de liens en toutes
 *     lettres, posee SOUS la grille, enfants `<a>` sans classe ;
 *   · ici : deux pas en fleches poses A COTE du titre du mois, enfants
 *     `.tcf-mois-pas`.
 * `class-topcal-front.php` rend les deux — `<nav class="tcf-mois-nav">` pour
 * la navigation d'annee, pour celle de mois en toutes lettres, et pour les
 * deux pas.
 *
 * Telle quelle, la seconde ecriture gagnait EN SILENCE sur la premiere : meme
 * selecteur, plus bas dans le fichier. La rangee de liens perdait son
 * `margin-top` et devenait `inline-flex` — collee sous la grille, decalee d'un
 * cadratin a gauche, sans que rien ne proteste. C'est le defaut que le CSS ne
 * signale jamais.
 *
 * On distingue donc les deux par ce qui les distingue VRAIMENT : leurs
 * enfants. `:has()` est deja employe ailleurs dans cette feuille. Si un
 * navigateur ne le comprend pas, la regle est ignoree et les deux pas
 * retombent sur la rangee en toutes lettres : degrade, pas casse.
 *
 * ⚠ LA VRAIE REPARATION EST DANS LE BALISAGE, PAS ICI : deux composants
 * differents ne devraient pas porter la meme classe. Renommer celui-ci
 * (`.tcf-mois-pas-nav`, par exemple) est un changement PHP, il n'appartient
 * pas a une fusion de feuilles de style. */
.topcal-front .tcf-mois-nav:has(.tcf-mois-pas){display:inline-flex;flex-wrap:nowrap;gap:8px;margin-top:0;margin-inline-start:1rem;vertical-align:middle}
.topcal-front .tcf-mois-pas{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--tcf-touch);height:var(--tcf-touch);
  border:1px solid var(--tcf-line);border-radius:12px;
  font-size:1.15rem;line-height:1;text-decoration:none;
  color:var(--tcf-ink);background:var(--tcf-surface);
  transition:border-color .15s,color .15s;
}
.topcal-front a.tcf-mois-pas:hover{border-color:var(--tcf-ac);color:var(--tcf-ac)}
.topcal-front .tcf-mois-pas.is-off{color:var(--tcf-ink-3);opacity:.45}

.topcal-front .tcf-errors{
  border:1px solid var(--tcf-full);background:var(--tcf-full-soft);color:var(--tcf-full);
  border-radius:var(--tcf-r-sm);padding:14px 16px;margin-bottom:1.6rem;
}
.topcal-front .tcf-errors ul{margin:.4rem 0 0;padding-inline-start:1.2rem}
.topcal-front .tcf-errors li{margin-top:.2rem}
.topcal-front .tcf-ok{
  border:1px solid var(--tcf-free);background:var(--tcf-free-soft);color:var(--tcf-free);
  border-radius:var(--tcf-r-sm);padding:14px 16px;margin-bottom:1.6rem;
}

/* ── CE QU'ON VOIT APRES AVOIR RESERVE ───────────────────────────────────
   Ce panneau remplace un bandeau d'une ligne — 128 octets, quinze mots —
   pose en haut d'une page de 102 066. Il ne peut donc PAS reutiliser
   `.tcf-panel` : celui-la est `position:sticky`, fait pour suivre une saisie
   qui defile, et une confirmation n'a rien a suivre.

   Il emprunte en revanche tout le reste : `.tcf-recap` pour ses rangees,
   `.tcf-panel-titre`, `.tcf-panel-quand` et `.tcf-panel-note` pour ses trois
   niveaux de texte. Trois classes de plus auraient diverge du panneau de
   reservation a la premiere retouche. */
.topcal-front .tcf-fait{
  color:var(--tcf-ink);
  background:var(--tcf-surface);border:1px solid var(--tcf-line);
  border-radius:16px;padding:26px;margin-bottom:1.8rem;max-width:46rem;
}
.topcal-front .tcf-fait .tcf-panel-titre{margin-top:.3rem}
.topcal-front .tcf-fait .tcf-recap{border-top:1px solid var(--tcf-line);margin-top:0}
.topcal-front .tcf-fait .tcf-recap:first-of-type{border-top:0}
/* Les gestes s'enroulent : sous 400 px, « Ajouter a mon agenda » et
   « Annuler cette reservation » cote a cote deborderaient l'ecran. */
.topcal-front .tcf-fait-gestes{
  display:flex;flex-wrap:wrap;gap:10px;margin-top:1.4rem;align-items:center;
}

/* ── LA GRILLE HORAIRE DE LA JOURNEE ─────────────────────────────────────
 *
 * Demande du proprietaire, 08/09 : « un format creneau horaire comme le
 * calendrier de son telephone ». La position dit l'heure, la hauteur dit la duree.
 *
 * ⚠ LES TRAITS D'HEURE SONT UN DEGRADE, PAS DES ELEMENTS.
 *
 * `repeating-linear-gradient` dessine une ligne par heure sans un seul noeud
 * dans le document. Une journee de 6 h a 22 h aurait sinon seize `<div>` vides
 * dans la colonne, que le lecteur d'ecran traverse et que le robot d'indexation
 * lit — pour du mobilier. Le degrade se cale sur `--tcf-g-heure`, la meme
 * variable qui donne sa hauteur a la colonne : les traits et les paves ne
 * peuvent donc pas se desynchroniser.
 *
 * ⚠ ET LA GEOMETRIE ARRIVE EN VARIABLES, PAS EN `top:` NI EN `left:`.
 *
 * Le serveur pose `--g-haut`, `--g-duree`, `--g-gauche`, `--g-largeur` dans
 * l'attribut `style` du pave ; c'est CETTE feuille qui decide d'en faire une
 * position absolue. Sous 680 px elle n'en fait plus rien et la meme liste
 * redevient une pile — sans un seul `!important`, qui serait la dette qu'on
 * paie au defaut suivant. */
.topcal-front .tcf-grille{
  /* ⚠ 68 PX L'HEURE, ET CE NOMBRE VA PAR PAIRE AVEC UN SEUIL EN PHP.
   *
   * Un creneau d'une demi-heure fait donc 34 px. C'est la hauteur ou une
   * ligne de texte et ses marges tiennent — pas deux : c'est pourquoi
   * `grille()` marque `is-court` les creneaux de 40 minutes ou moins, et
   * pourquoi ce seuil (40 min = 45 px ici) suit cette valeur. Baisser la
   * hauteur d'heure sans revenir au seuil remet les bardeaux mesures le
   * 08/09 : onze consultations de trente minutes chevauchees de quatre
   * pixels chacune, et un apres-midi entier illisible. */
  --tcf-g-heure:68px;
  --tcf-g-min:calc(var(--tcf-g-heure) / 60);
  /* ⚠ LE DEFAUT EST ICI PARCE QUE LE SERVEUR POSE LA VRAIE VALEUR.
   *
   * `--tcf-g-n` — le nombre d'heures de la fenetre — arrive dans l'attribut
   * `style` de la grille. Le cliquet des jetons orphelins a eu raison de le
   * refuser sans defaut : un `var()` non defini ne vaut pas zero, il rend la
   * propriete INVALIDE AU CALCUL, et `height` reprend alors sa valeur initiale
   * — `auto`. La colonne s'effondrerait a la hauteur de ses paves, tous les
   * traits d'heure disparaitraient, et rien dans la page ne le dirait.
   *
   * Le defaut ne rend pas la grille juste : il la rend LISIBLE le jour ou le
   * serveur oublie. Ce qui garde la justesse de la position est un instrument
   * qui mesure le rendu — voir `bin/grille-horaire.mjs`. */
  --tcf-g-n:12;
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  gap:0 12px;
  margin-top:1.5rem;
  /* L'etiquette de la premiere heure est remontee d'un demi-cadratin pour se
     poser SUR son trait : sans ce retrait, elle depasserait de la boite de la
     grille et se ferait rogner par tout ce qui la recadre — un `overflow`
     hérité, une capture d'element. Le retrait est ici et pas sur l'etiquette :
     il decale la regle ET la colonne du meme nombre de pixels, donc il ne peut
     pas les desynchroniser. */
  padding-top:.45em;
}
.topcal-front .tcf-g-regle{
  display:grid;
  grid-template-rows:repeat(var(--tcf-g-n),var(--tcf-g-heure));
}
.topcal-front .tcf-g-h{
  font:600 .76rem/1 var(--tcf-mono);
  color:var(--tcf-ink-3);
  text-align:end;
  white-space:nowrap;
  /* L'etiquette se pose SUR son trait, pas sous lui : c'est ce que fait le
     calendrier du telephone, et c'est ce qui permet de lire « 9 h » comme le
     debut de la bande et non comme sa fin. */
  transform:translateY(-.4em);
}
.topcal-front .tcf-g-col{
  position:relative;
  height:calc(var(--tcf-g-n) * var(--tcf-g-heure));
  margin:0;
  padding:0;
  list-style:none;
  border-bottom:1px solid var(--tcf-line);
  background:repeating-linear-gradient(to bottom,
    var(--tcf-line) 0 1px,
    transparent 1px var(--tcf-g-heure));
}
.topcal-front .tcf-g-pave{
  /* Meme raison qu'au-dessus : ces quatre valeurs viennent du serveur, et un
     `var()` non defini rendrait `top`, `height` et `width` invalides d'un coup
     — le pave se poserait en haut de la colonne, a une heure fausse, sans que
     rien ne proteste. Le defaut est neutre et documente : en haut, une heure,
     toute la largeur. */
  --g-haut:0;
  --g-duree:60;
  --g-gauche:0;
  --g-largeur:100%;
  position:absolute;
  top:calc(var(--g-haut) * var(--tcf-g-min));
  height:calc(var(--g-duree) * var(--tcf-g-min));
  inset-inline-start:var(--g-gauche);
  width:var(--g-largeur);
  /* ⚠ ET ELLE NE DEPASSE PAS LA HAUTEUR D'UNE DEMI-HEURE (34 px).
   *
   * Premiere version : 38 px. Une demi-heure en faisant 34, chaque creneau
   * mordait de quatre pixels sur le suivant — invisible sur un creneau isole,
   * ruineux sur une serie : onze consultations d'affilee formaient une masse
   * unique aux bords en dents de scie. Une hauteur minimale doit rendre un
   * creneau court PRENABLE, pas le faire deborder sur son voisin.
   *
   * Un quart d'heure fait donc 17 px et garde ses 17 px : c'est petit, c'est
   * cliquable, et sur telephone le repli en pile lui rend une pleine rangee. */
  min-height:30px;
  padding:0 3px 3px 0;
}
.topcal-front .tcf-g-lien{
  display:flex;
  flex-direction:column;
  height:100%;
  overflow:hidden;
  padding:5px 9px;
  border-radius:var(--tcf-r-sm);
  text-decoration:none;
  color:var(--tcf-ink);
  background:var(--tcf-ev-0-doux);
  box-shadow:inset 3px 0 0 var(--tcf-ev-0);
  transition:transform .12s ease,box-shadow .12s ease;
}
.topcal-front a.tcf-g-lien:hover{transform:translateY(-1px);box-shadow:inset 3px 0 0 var(--tcf-ev-0),0 4px 12px -6px rgba(23,19,16,.28)}
.topcal-front .tcf-g-heure{font:600 .74rem/1.3 var(--tcf-mono);color:var(--tcf-ink-2)}
.topcal-front .tcf-g-titre{
  font-weight:650;
  font-size:.94rem;
  line-height:1.25;
  /* Le nom passe a la ligne s'il le faut, et se coupe s'il n'y a plus de
     place : un nom long ne doit pas pousser l'etat hors du pave. */
  overflow:hidden;
}
.topcal-front .tcf-g-etat{
  /* Les trois lignes se groupent EN HAUT du pave, comme sur le calendrier du
     telephone. Un `margin-top:auto` collait l'etat au bas de la boite : sur un
     creneau de trois heures, « 6 places restantes » se retrouvait a 190 px de
     son propre titre, et se lisait comme appartenant au creneau du dessous. */
  font-size:.76rem;
  color:var(--tcf-ink-3);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
/* Le pave prend la teinte de sa seance — meme rang de couleur que la fiche et
   que la nomenclature, sinon la legende ne nomme plus rien. */
.topcal-front .tcf-g-lien.tcf-ev-1{background:var(--tcf-ev-1-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-1)}
.topcal-front .tcf-g-lien.tcf-ev-2{background:var(--tcf-ev-2-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-2)}
.topcal-front .tcf-g-lien.tcf-ev-3{background:var(--tcf-ev-3-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-3)}
.topcal-front .tcf-g-lien.tcf-ev-4{background:var(--tcf-ev-4-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-4)}
.topcal-front .tcf-g-lien.tcf-ev-5{background:var(--tcf-ev-5-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-5)}
.topcal-front .tcf-g-lien.tcf-ev-6{background:var(--tcf-ev-6-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-6)}
.topcal-front .tcf-g-lien.tcf-ev-7{background:var(--tcf-ev-7-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-7)}
.topcal-front .tcf-g-lien.tcf-ev-8{background:var(--tcf-ev-8-doux);box-shadow:inset 3px 0 0 var(--tcf-ev-8)}
/* Complet : il reste VISIBLE — « ce jour-la c'est plein » est une information
   — mais il ne se clique pas, et son trait de couleur tombe. */
.topcal-front .tcf-g-lien.is-full{
  background:var(--tcf-full-soft);
  box-shadow:inset 3px 0 0 var(--tcf-full);
  color:var(--tcf-ink-3);
}
.topcal-front .tcf-g-lien.is-closed{background:var(--tcf-closed-soft);box-shadow:inset 3px 0 0 var(--tcf-closed)}
/* ── LE CRENEAU COURT : UNE SEULE LIGNE ──────────────────────────────────
 *
 * L'heure et le nom cote a cote, l'etat retire. Ce n'est pas une perte : la
 * meme information est sur la fiche du creneau, et un pave de 34 px qui
 * essaie de porter trois lignes n'en montre aucune — mesure du 08/09. */
.topcal-front .tcf-g-lien.is-court{
  flex-direction:row;
  align-items:center;
  gap:7px;
  padding:0 9px;
}
.topcal-front .tcf-g-lien.is-court .tcf-g-heure{flex:none;font-size:.7rem}
.topcal-front .tcf-g-lien.is-court .tcf-g-titre{
  font-size:.84rem;
  font-weight:600;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.topcal-front .tcf-g-lien.is-court .tcf-g-etat{display:none}

/* ── RESPONSIVE ─────────────────────────────────────────────────────────── */
@media (max-width:860px){
  .topcal-front .tcf-book{grid-template-columns:1fr;gap:32px}

  /* ── LE PRIX NE PART PLUS EN BAS DE PAGE ────────────────────────────────
     ⚠ MESURE DU 11/09 : `position:static` REJETAIT LE PRIX A y=1400 px sur un
     telephone — les quinze derniers pour cent d'une page de 1657. La colonne
     de droite passe derriere TOUTE la colonne de gauche : image, titre,
     description entiere, etat, nombre de personnes, options, quatre champs
     d'identite. Le client decidait d'acheter avant d'avoir vu le total.

     On ne duplique pas le recapitulatif en haut — deux totaux dans une page
     sont deux verites qui divergent des que l'une se met a jour. On EPINGLE
     celui qui existe au bas de l'ecran : le total et le bouton restent sous
     l'oeil pendant toute la saisie. C'est ce que fait une caisse, et pour la
     meme raison.

     `position:sticky` et non `fixed` : la barre se repose naturellement a sa
     place quand on atteint le bas de page, sans masquer la derniere ligne du
     formulaire ni demander une marge de compensation. */
  .topcal-front .tcf-panel{
    position:sticky;top:auto;bottom:0;z-index:5;
    padding:16px 18px;border-radius:16px 16px 0 0;
    /* L'ombre remplace la bordure basse : elle dit « il y a du contenu dessous »
       sans ajouter un trait de plus a une hauteur deja comptee. */
    border-bottom:0;box-shadow:0 -6px 24px rgba(0,0,0,.10);
  }
  /* Le rappel du titre et de la date vit deja en haut de la colonne gauche :
     repete dans une barre epinglee, il coute la moitie de sa hauteur pour ne
     rien apprendre. Le total et le bouton restent.

     ⚠ LES CINQ SELECTEURS SONT PORTES PAR `.tcf-panel`, ET TROIS NE L'ETAIENT
     PAS. C'est ce qui rendait cette regle fausse hors de la barre epinglee :
     `tcf-panel-titre`, `tcf-panel-quand` et `tcf-panel-note` s'appliquaient a
     TOUTE la page, alors que leurs deux voisines etaient deja cantonnees.

     Mesure du 14/09 sous Chromium, a 390 px : cinq elements passaient a
     `display:none` et AUCUN n'etait dans un `.tcf-panel`. Le plus couteux
     existait avant ce lot — « Your address is passed on to the organiser for
     this request only. », la mention de confidentialite du formulaire
     « prevenez-moi » (`formulaire_dattente()`), invisible sur tout telephone.
     Une mention qui protege le visiteur ne peut pas etre masquee par une
     regle ecrite pour economiser de la hauteur ailleurs.

     La barre epinglee ne perd rien : a l'interieur de `.tcf-panel`, les cinq
     selecteurs designent exactement ce qu'ils designaient. */
  .topcal-front .tcf-panel .tcf-eyebrow,
  .topcal-front .tcf-panel .tcf-panel-titre,
  .topcal-front .tcf-panel .tcf-panel-quand,
  .topcal-front .tcf-panel .tcf-panel-note,
  .topcal-front .tcf-panel .tcf-recap{display:none}
  .topcal-front .tcf-total{margin-top:0;padding-top:0;border-top:0}
  .topcal-front .tcf-total .amount{font-size:1.5rem}
  .topcal-front .tcf-panel-geste{margin-top:10px}
}
@media (max-width:680px){
  /* Sous 680 px, sept colonnes donnent des cases de moins de 60 px : le numero
     du jour et son point ne tiennent plus ensemble. On garde la grille — un
     calendrier reste un calendrier — mais on relache le carre et on retire la
     bordure, qui devient du bruit a cette taille. */
  /* ⚠ SOUS 680 PX, LA GRILLE REDEVIENT UNE PILE — ET C'EST VOULU.
   *
   * Une echelle verticale de 64 px l'heure demande 1000 px de hauteur pour une
   * journee de 6 h a 22 h. Sur un telephone tenu a la main, on ne voit alors
   * jamais plus de trois heures a la fois : la grille perd exactement ce
   * qu'elle apporte — la journee d'un coup d'oeil — et garde tous ses defauts,
   * dont des paves de la largeur d'un pouce quand deux seances se chevauchent.
   *
   * La feuille cesse donc d'utiliser `--g-haut` et compagnie. Le serveur les
   * pose toujours, personne ne les lit, et le meme balisage redevient la liste
   * verticale qui etait la bonne reponse sur un petit ecran depuis le debut.
   * C'est pour ça que la geometrie arrive en variables et pas en `top:`. */
  .topcal-front .tcf-grille{display:block}
  .topcal-front .tcf-g-regle{display:none}
  .topcal-front .tcf-g-col{
    position:static;
    height:auto;
    background:none;
    border-bottom:0;
    display:flex;
    flex-direction:column;
    gap:8px;
  }
  .topcal-front .tcf-g-pave{
    position:static;
    width:auto;
    height:auto;
    min-height:0;
    padding:0;
  }
  .topcal-front .tcf-g-lien{padding:11px 13px;gap:2px}
  /* En pile, la place ne manque plus : le creneau court reprend ses trois
     lignes et son etat. Le `is-court` ne decrivait qu'une contrainte de
     hauteur, et cette contrainte n'existe pas ici. */
  .topcal-front .tcf-g-lien.is-court{flex-direction:column;align-items:stretch;padding:11px 13px}
  .topcal-front .tcf-g-lien.is-court .tcf-g-titre{white-space:normal;font-size:1rem}
  .topcal-front .tcf-g-lien.is-court .tcf-g-etat{display:block}
  .topcal-front .tcf-g-titre{font-size:1rem}
  .topcal-front .tcf-g-etat{margin-top:2px}

  /* ── LA GRILLE AU TELEPHONE : LE POINT PARLE, LE MOT SE TAIT ───────────
     ⚠ MESURE DU 14/09, A 390 px, SUR LA GRILLE DE SEPTEMBRE EN FRANCAIS :
     30 des 31 cases debordaient leur boite, et « 13 créneaux » — 11 caracteres
     en `white-space:nowrap` dans un carre de 40 px — sortait HORIZONTALEMENT
     par-dessus les cases voisines. Sur la capture, le mot passe sur les
     numeros 22 a 30 : la moitie basse du mois n'est plus lisible du tout.

     Trois causes, et il faut les trois :
       · `height:40px` — une hauteur FIXE, alors que la case porte un numero
         de 1.05rem PLUS une pastille d'etat. Elle devient `min-height`.
       · `padding:0` — le contenu collait aux bords, ce qui aggravait tout.
       · le MOT lui-meme, qui ne peut tenir dans aucune case a sept colonnes :
         390 px / 7 font 50 px, et « 13 créneaux » en demande 75.

     On garde donc le POINT, qui porte l'etat, et l'on masque le mot A L'OEIL
     SEULEMENT (`clip`, comme `.tcf-sr`) : les lecteurs d'ecran l'enoncent
     toujours, l'attribut `title` de la case le porte au survol, et la legende
     juste sous la grille nomme les quatre points. C'est exactement la forme
     qu'ont tous les calendriers de telephone, et pour la meme raison.

     ⚠ AUCUNE COULEUR N'EST INTRODUITE ICI. Le front herite du theme du client,
     c'est voulu, et ce defaut est une mise en page — pas une palette. */
  .topcal-front .tcf-cal{gap:4px}
  .topcal-front .tcf-day{width:auto;min-height:44px;height:auto;padding:5px 3px}
  .topcal-front a.tcf-day{border-radius:10px}
  .topcal-front .tcf-day .n{font-size:1.05rem;align-self:center}
  .topcal-front .tcf-day .et{display:flex;justify-content:center}
  .topcal-front .tcf-day .et .tcf-state{gap:0;padding:0}
  .topcal-front .tcf-day .et .tcf-mot{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
  }

  /* Les lignes passent en deux temps : la date et le titre d'abord, le prix et
     l'action ensuite, pleine largeur. Une troisieme colonne de 90 px ecrase le
     titre sur trois lignes et le prix sur deux. */
  /* ── SOUS 680 px, LE CRENEAU S'EMPILE — IL NE SE RESSERRE PAS ────────
   *
   * J'avais d'abord garde deux colonnes en retrecissant celle de l'heure a
   * 74 px. L'heure porte `white-space:nowrap` — pour qu'une plage horaire ne
   * se coupe jamais au milieu — et « 09:00 — 12:00 » demande 110 px : elle
   * DEBORDAIT donc sa colonne et se dessinait PAR-DESSUS le titre. Mesure sur
   * l'apercu telephone du 02/09 : « 09:00 — 12:0Seance decouverte ».
   *
   * Deux regles justes chacune de leur cote — ne jamais couper un horaire, et
   * gagner de la place sur un telephone — se contredisaient une fois posees
   * ensemble. On ne resserre donc pas : on empile. Un ecran de 390 px n'a pas
   * trois colonnes a donner, et pretendre le contraire est ce qui produit un
   * chevauchement.
   */
  .topcal-front .tcf-creneau{grid-template-columns:minmax(0,1fr);gap:8px;padding:1.15rem 0}
  .topcal-front .tcf-heure{padding-top:0;font-size:.8rem;color:var(--tcf-ink-2)}
  .topcal-front .tcf-action{
    flex-direction:row;align-items:center;justify-content:flex-start;
    gap:16px;flex-wrap:wrap;text-align:start;padding-top:.35rem;
  }
  .topcal-front .tcf-jour{padding:.9rem .9rem 1rem}
  /* Le compte de seances DISPARAIT plutot que de se tronquer.
   *
   * « 3 SÉA… » se lit comme une panne, pas comme une abreviation. Et
   * l'information est deja la : les seances sont juste dessous, on les compte
   * en les regardant. Une troncature n'a de sens que quand ce qui reste
   * garde un sens. */
  .topcal-front .tcf-jour-h .tcf-eyebrow{display:none}
  /* La croix redevient une cible de doigt sur telephone. */
  .topcal-front .tcf-fermer{width:var(--tcf-touch);height:var(--tcf-touch);margin-block:-6px}
  .topcal-front .tcf-jauge-barre{width:96px}
  .topcal-front .tcf-lead h2{font-size:1.7rem}
  .topcal-front .tcf-views{width:100%}
}
@media (prefers-reduced-motion:reduce){
  .topcal-front *{transition-duration:.01ms !important;animation-duration:.01ms !important}
}

/* ── LE GABARIT ANNEE ─────────────────────────────────────────────────────
   Douze mois d'un coup d'oeil : le gabarit d'une activite SAISONNIERE, qui
   ferme cinq mois par an et dont le visiteur veut d'abord savoir s'il regarde
   la bonne periode. Une liste de quinze jours ne le lui dit pas. */
.topcal-front .tcf-annee{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:30px 22px;margin-bottom:2rem;
}
.topcal-front .tcf-mini{
  display:block;padding:14px;border:1px solid transparent;border-radius:10px;
  color:inherit;text-decoration:none;
}
.topcal-front a.tcf-mini:hover{border-color:var(--tcf-line)}
.topcal-front .tcf-mini.is-on{border-color:var(--tcf-line);background:var(--tcf-fill)}
/* Un mois sans rien n'est pas cliquable — et il ne doit pas en avoir l'air.
   Il garde sa grille grise, qui EST l'information : « rien ce mois-la ». */
.topcal-front .tcf-mini.is-vide{cursor:default}
.topcal-front .tcf-mini.is-vide .tcf-mini-t{color:var(--tcf-ink-3)}
.topcal-front .tcf-mini-t{display:block;font-size:.92rem;font-weight:600;margin-bottom:10px}
.topcal-front .tcf-mini-d{display:block;font-size:.78rem;color:var(--tcf-ink-3)}

/* ⚠ DES CARRES DECLARES, ET NON `1fr` — LA NOTE DU DESSIN EST FORMELLE :
   « avec 1fr, un mois de cinq semaines et un mois de six n'ont pas la meme
   largeur de case, et les douze grilles cessent de se repondre. »

   ⚠ ET SIX RANGEES TOUJOURS, MEME QUAND LE MOIS N'EN REMPLIT QUE CINQ. C'est
   `grid-template-rows` qui le tient, pas des cases vides en PHP : sans lui,
   « ferme » sous Mars tombe vingt pixels plus bas que sous Janvier — le
   desalignement le plus visible d'une grille de grilles. */
.topcal-front .tcf-mini-g{
  display:grid;grid-template-columns:repeat(7,14px);grid-template-rows:repeat(6,14px);
  gap:3px;margin-bottom:10px;height:99px;
}
.topcal-front .tcf-mini-c{width:14px;height:14px;border-radius:3px;display:block}
.topcal-front .tcf-mini-c.is-hors{background:transparent}
.topcal-front .tcf-mini-c.is-free{background:var(--tcf-free)}
.topcal-front .tcf-mini-c.is-tight{background:var(--tcf-tight)}
.topcal-front .tcf-mini-c.is-full{background:var(--tcf-full)}
.topcal-front .tcf-mini-c.is-closed{background:var(--tcf-line)}

/* La legende : le point porte la couleur, le mot porte l'encre du theme.
   Les deux ensemble — jamais la couleur seule (WCAG 1.4.1), et un daltonien
   lit exactement la meme chose que les autres. */
.topcal-front .tcf-legende{
  display:flex;flex-wrap:wrap;gap:20px;padding:14px 0;margin:0 0 2rem;
  border-top:1px solid var(--tcf-line);border-bottom:1px solid var(--tcf-line);
  font-size:.82rem;
}
.topcal-front .tcf-leg{display:inline-flex;align-items:center;gap:8px;color:var(--tcf-ink)}
.topcal-front .tcf-leg i{width:7px;height:7px;border-radius:50%;flex:none}
.topcal-front .tcf-leg.is-free i{background:var(--tcf-free)}
.topcal-front .tcf-leg.is-tight i{background:var(--tcf-tight)}
.topcal-front .tcf-leg.is-full i{background:var(--tcf-full)}
.topcal-front .tcf-leg.is-closed i{background:var(--tcf-closed)}

/* Le pied : ce qui est ouvert, et jusqu'ou on peut reserver. L'horizon se dit
   AVANT — une phrase de dix mots plutot qu'un formulaire rempli pour rien. */
.topcal-front .tcf-pied{
  margin-top:2.4rem;padding-top:14px;border-top:1px solid var(--tcf-line);
  font-size:.82rem;color:var(--tcf-ink-3);
}

/* Le texte que seul un lecteur d'ecran lit : une case de quatorze pixels ne
   peut pas ecrire « 4 creneaux », mais elle doit le DIRE. */
.topcal-front .tcf-hors-ecran{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

@media (max-width:860px){
  /* Quatre colonnes de mini-mois demandent 4 x 119 px de grille plus les
     gouttieres : sous 860 px, on passe a deux, et sous 560 px les douze mois
     se lisent en colonne simple — la grille de 14 px, elle, ne bouge jamais :
     c'est elle qui fait que les mois se repondent. */
  .topcal-front .tcf-annee{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px 16px}
}
@media (max-width:420px){
  .topcal-front .tcf-annee{grid-template-columns:1fr}
}

/* ── LA CARTE D'UNE ACTIVITE ──────────────────────────────────────────────
   Une carte est une ACTIVITE, pas un creneau : son nom, ce qu'on y fait, sa
   duree, son prix, et sa PROCHAINE date. Le visiteur ne choisit pas un
   creneau parmi quarante-deux, il choisit un atelier puis une date. */
.topcal-front .tcf-card-desc{
  /* Deux lignes, coupees par le NAVIGATEUR. Un « … » pose en PHP se verrait
     en plus de celui-ci, et couperait au mauvais endroit dans la moitie des
     langues. */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;margin:.5rem 0 0;color:var(--tcf-ink-2);font-size:.9rem;line-height:1.5;
  /* ── ⚠ ET LES DEUX LIGNES SONT RESERVEES, PAS SEULEMENT PLAFONNEES ────
     `-webkit-line-clamp:2` PLAFONNE a deux lignes ; il n'en RESERVE pas deux.
     Mesure du 21/09 sur les trois cartes de la vitrine, a 1 440 px :

         hauteurs de `.tcf-card-desc`   [22, 43, 43] px

     La premiere activite — « Un rendez-vous de trente minutes. » — tient sur
     UNE ligne. Tout ce qui est en dessous remonte donc de 22 px dans cette
     carte-la, et ce qui remonte porte un FILET VISIBLE : le `border-top` de
     `.tcf-card-quand`, un trait de separation qui ne se rejoint plus d'une
     carte a l'autre. La pastille d'etat suit, decalee d'autant.

     ⚠ CE DEPOT A DEJA CORRIGE CE DEFAUT-LA, NEUF LIGNES PLUS HAUT, LE 10/09,
     sur le TITRE des memes cartes (`.tcf-card h3{min-height:2.3em}`), et son
     commentaire porte l'argument qui decide ici aussi : « Reserver la place
     coute du blanc sous les titres courts ; ne pas la reserver coute
     l'alignement de toute la rangee, et il suffit d'UNE traduction plus longue
     pour le perdre dans une langue qu'on ne regarde pas. »

     `.tcf-card-desc` est arrive apres, avec le lot front du 16/09, et n'a pas
     recu la meme reserve. 3em = 2 lignes x 1,5 de hauteur de ligne.

     ⚠ ET LA CARTE NE GRANDIT PAS D'UN PIXEL : les 21 px reserves sont absorbes
     par `.tcf-card .act{margin-top:auto}`. Mesure : hauteurs des cartes
     [323, 323, 323] avant comme apres, et l'ecart des filets passe de 22 a 0.
     A 980 px l'ecart etait deja nul — aucune regression. */
  min-height:3em;
}
.topcal-front .tcf-card-meta{
  margin:.7rem 0 0;font-family:var(--tcf-mono);font-size:.74rem;color:var(--tcf-ink-3);
}

/* ⚠ EN COLONNE, ET C'EST UNE QUESTION DE CONSTANCE, PAS DE PLACE. La note du
   dessin le mesure : « En flex-wrap, l'etat passe sous la date quand la date
   est longue et reste a cote quand elle est courte : cinq cartes sur six
   l'avaient dessous, la sixieme a cote — pour la seule raison que "Saison
   terminee le 31 aout" est plus court. Une mise en page qui depend de la
   longueur du texte n'est pas une mise en page. » */
.topcal-front .tcf-card-quand{
  display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  margin:.9rem 0 0;padding-top:.9rem;border-top:1px solid var(--tcf-line);
}
.topcal-front .tcf-card-quand .q{font-size:.86rem;color:var(--tcf-ink-2)}
/* L'etat sous la date, jamais a cote : voir la note de mise en page ci-dessus.
   Le bloc est la pour que la pastille ne s'etire pas sur toute la largeur. */
.topcal-front .tcf-card-quand .e{display:inline-flex}

/* ── LA BANDE DE LA SEMAINE, SUR LA VUE JOUR ──────────────────────────────
   Cette vue etait un cul-de-sac : on ne pouvait changer de jour que par la
   grille du Mois, ou en fabriquant une adresse a la main. Choisie comme vue
   d'accueil — ce que fait le metier « praticien » — le visiteur voyait UNE
   journee et n'avait aucun moyen d'en voir une autre.

   La bande DIT ce que chaque jour porte avant qu'on y aille. Deux fleches
   feraient changer de jour a l'aveugle : on clique, on regarde, on reclique. */
.topcal-front .tcf-bande{
  display:grid;grid-template-columns:var(--tcf-touch) repeat(7,minmax(0,1fr)) var(--tcf-touch);
  gap:6px;align-items:stretch;margin-bottom:2rem;
}
.topcal-front .tcf-jsem{
  min-width:0;min-height:var(--tcf-touch);padding:8px 6px;border-radius:10px;
  display:flex;flex-direction:column;align-items:center;gap:3px;
  text-decoration:none;color:inherit;
}
.topcal-front a.tcf-jsem{background:var(--tcf-surface);border:1px solid var(--tcf-line)}
.topcal-front a.tcf-jsem:hover{border-color:var(--tcf-ac)}
.topcal-front .tcf-jsem .jw{
  font-family:var(--tcf-mono);font-size:.62rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--tcf-ink-3);
}
.topcal-front .tcf-jsem .jd{font-size:1.05rem;font-weight:600;line-height:1.2}
.topcal-front .tcf-jsem .je{max-width:100%;min-width:0}
/* ⚠ ON NE TRONQUE PAS UNE INFORMATION QUI TIENT EN DEUX MOTS.
   La pastille portait `white-space:nowrap` et `overflow:hidden` : sur une
   tuile de soixante-dix pixels, « 5 creneaux » devenait « 5 crene » et
   « Complet » devenait « Compl ». Vu a l'oeil sur un vrai WordPress le
   12/09. Une bande dont on ne peut pas lire l'etat ne fait pas gagner le
   clic qu'elle existe pour economiser — elle le fait perdre deux fois.
   Le texte passe donc a la ligne, et les sept tuiles s'alignent sur la plus
   haute (`align-items:stretch` sur la bande). */
.topcal-front .tcf-jsem .je .tcf-state{
  background:none;color:var(--tcf-ink);font-size:.64rem;padding:0;
  max-width:100%;white-space:normal;text-align:center;line-height:1.15;
  justify-content:center;
}
/* Un jour passe ou ferme reste AFFICHE — savoir que mardi est ferme fait
   partie de la reponse — mais il n'est pas un lien : il menerait au vide. */
.topcal-front .tcf-jsem.is-off{opacity:.55}
/* ⚠ LE JOUR CHOISI RETOURNE SON COUPLE, DONC TOUT CE QU'IL CONTIENT AUSSI.
   Le mot prend `--tcf-ink` partout — juste partout, sauf ICI, ou le fond EST
   `--tcf-ink` : encre sur encre, rapport 1,00, mot invisible. Un mot blanc
   sur blanc ne se remarque pas, il se confond avec une case vide. */
.topcal-front .tcf-jsem.is-on{background:var(--tcf-inverse-fond);color:var(--tcf-inverse-encre);border-color:var(--tcf-inverse-fond)}
.topcal-front .tcf-jsem.is-on .jw{color:var(--tcf-inverse-encre);opacity:.78}
.topcal-front .tcf-jsem.is-on .je .tcf-state{color:var(--tcf-inverse-encre)}
/* Aujourd'hui, quand ce n'est pas le jour regarde : un filet, pas un aplat —
   deux aplats sur la meme bande se disputeraient l'oeil. */
.topcal-front .tcf-jsem.is-today:not(.is-on){border-color:var(--tcf-ink)}

/* Les fleches sont DESSINEES, pas des glyphes : « ‹ » n'existe pas dans toutes
   les polices, et un caractere de ponctuation se lit mal a un lecteur d'ecran
   (le nom accessible vit dans `aria-label`). */
.topcal-front .tcf-bande-fl{
  display:grid;place-items:center;min-height:var(--tcf-touch);
  border:1px solid var(--tcf-line);border-radius:10px;
  background:var(--tcf-surface);color:var(--tcf-ink);text-decoration:none;
}
.topcal-front .tcf-bande-fl:hover{border-color:var(--tcf-ac)}
.topcal-front .tcf-bande-fl i{
  width:9px;height:9px;
  border-block-start:1.5px solid currentColor;border-inline-end:1.5px solid currentColor;
}
.topcal-front .tcf-bande-fl[rel="prev"] i{transform:rotate(-135deg);margin-inline-start:4px}
.topcal-front .tcf-bande-fl[rel="next"] i{transform:rotate(45deg);margin-inline-end:4px}

@media (max-width:560px){
  /* Sept colonnes plus deux fleches sous 560 px donnent des cases de moins de
     40 px : le mot d'etat n'y tient plus. Les fleches passent en dessous, et
     la semaine garde ses sept colonnes — c'est elle l'information. */
  .topcal-front .tcf-bande{grid-template-columns:repeat(7,minmax(0,1fr));gap:4px}
  /* ⚠ MESURE DU 21/09 — CETTE LIGNE ABAISSAIT LA FLECHE DE 44 A 38 PX
     EXACTEMENT SOUS 560 PX, c'est-a-dire precisement la ou c'est un doigt qui
     touche et plus une souris. Le `38px` datait du temps ou les fleches
     tenaient dans la grille des sept jours, serrees entre les colonnes. Depuis
     ce meme bloc elles passent EN DESSOUS, sur leur propre rangee, `span 3` :
     mesure faite, 144 px de large. Rien ne les contraint plus en hauteur, et
     rien ne justifiait de les raccourcir. */
  .topcal-front .tcf-bande-fl{grid-column:span 3;min-height:var(--tcf-touch)}
  .topcal-front .tcf-bande-fl[rel="next"]{grid-column:5 / span 3}
  .topcal-front .tcf-jsem .je{display:none}
}

/* ══════════════════ LE TRI PAR TYPE — DEMANDE DU 07/09 ══════════════════
 *
 * Les memes pastilles que la barre de vues, et volontairement : ce sont deux
 * facons de choisir ce qu'on regarde, elles doivent se lire comme une paire.
 *
 * Elles s'enroulent. Le nombre de types n'est pas borne par un ecran, et une
 * barre qui deborde cache justement les types du bas de l'alphabet — ceux
 * qu'on ne pense jamais a aller chercher.
 *
 * Aucune couleur de marque : l'actif se distingue par l'inversion encre/papier,
 * ce qui reste lisible dans le theme du client quel qu'il soit.
 */
.topcal-front .tcf-types{
  display:flex;flex-wrap:wrap;gap:6px;margin:-1.6rem 0 2.4rem;
}
/* ⚠ MESURE DU 21/09 — 34,94 px, LA PLUS PETITE DES DEUX BARRES JUMELLES.
   L'en-tete ci-dessus promet « les memes pastilles que la barre de vues, et
   volontairement : elles doivent se lire comme une paire ». Elles ne l'etaient
   pas : 34 ici contre 38 la-bas. Les deux passent a `--tcf-touch`, et la paire
   devient vraie pour la premiere fois. */
.topcal-front .tcf-types a{
  font-family:var(--tcf-mono);font-size:.74rem;padding:7px 14px;
  border:1px solid var(--tcf-line);border-radius:999px;
  color:var(--tcf-ink-2);text-decoration:none;background:var(--tcf-bg);
  min-height:var(--tcf-touch);display:inline-flex;align-items:center;
}
.topcal-front .tcf-types a:hover,
.topcal-front .tcf-types a:focus-visible{color:var(--tcf-ink);border-color:var(--tcf-ink-3)}
/* ⚠ FUSION DU 15/09 — LA PASTILLE ACTIVE DEVENAIT INVISIBLE, ET NI L'UNE NI
   L'AUTRE BRANCHE N'AVAIT TORT.

   Elle s'ecrivait `background:var(--tcf-ink);color:var(--tcf-bg)` — l'inversion
   encre/papier, et c'etait JUSTE dans le fichier ou elle a ete ecrite : les
   deux jetons y valaient des couleurs opaques, `#171310` et `#FCFBF9`.

   L'autre branche a, pendant ce temps, branche ces deux jetons sur la palette
   du theme WordPress, avec un dernier repli qui vaut `currentColor` pour
   l'encre et `transparent` pour le papier. C'est le bon choix — c'est tout
   l'objet du socle — mais il change ce que la pastille veut dire : sur un
   theme qui ne declare pas de palette, elle devient du texte TRANSPARENT sur
   un fond `currentColor`, lequel prend la couleur de texte de l'element, donc
   transparent aussi. Une pastille vide, sans un mot dessus. C'est exactement
   la mesure du 12/09 citee plus haut : 1,00 de contraste sur les quarante-deux
   boutons « Book ».

   Aucun des deux commentaires ne pouvait le voir : le defaut n'existe que
   depuis que les deux moities sont dans le meme fichier.

   On garde l'intention — l'actif se distingue par l'inversion, pas par une
   couleur de marque — en la disant avec le couple qui est garanti OPAQUE et
   qui sert deja a ca partout ailleurs dans cette feuille (jour selectionne,
   filtre actif, bouton principal). Meme rendu quand le theme declare sa
   palette, lisible quand il n'en declare pas. */
.topcal-front .tcf-types a[aria-current]{
  background:var(--tcf-inverse-fond);border-color:var(--tcf-inverse-fond);color:var(--tcf-inverse-encre);
}
/* Sur la fiche, le type est un lien : il garde la couleur de la ligne qui le
   porte plutot que celle des liens, sinon trois mots colores sautent aux yeux
   avant l'adresse et le nom de l'organisateur. */
.topcal-front .tcf-lieu-type a{color:inherit}
