body {
    font-family: var(--font-family);
    background: #f8f9fa;
}

/* Date slider wrapper with reset button */
.date-slider-wrapper {
    display: flex;
    align-items: flex-end;
    gap: 15px;
    margin-bottom: 10px;
}

.date-slider-container {
    flex: 1;
}

.date-slider {
    width: 100%;
}

.date-slider-reset-btn {
    padding: 4px 8px;
    min-width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.date-slider-reset-btn i {
    margin: 0;
    padding: 0;
    font-size: 14px;
}

/* ------------------------------------------------------------------ */
/* En-tête de la frise publiée                                          */
/*                                                                      */
/* Palette et formes reprises des pages de présentation : c'est la page  */
/* qu'un enseignant envoie au dehors, elle doit ressembler au reste de   */
/* la maison. Le violet d'origine venait de Chronos, et son aplat        */
/* saturé écrasait la frise bleue qui le suit.                           */
/* ------------------------------------------------------------------ */

/* Le chat constructeur montre la même frise : il en reprend la palette. */
.frise-page,
.frise-chat-page {
    --pub-bleu: #0271E8;
    --pub-violet: #5856d6;
    --pub-degrade: linear-gradient(135deg, #0271E8 0%, #5856d6 100%);
    --pub-encre: #1a1a1a;
    --pub-gris: #6b7280;
    --pub-gris-clair: #e5e7eb;
}

/* Le titre, les compteurs et les boutons ne font qu'un seul bloc, sur un
   seul fond : découpés en bandes, ils dessinaient trois aplats successifs
   dont les coutures se voyaient. Le gris du corps prend la suite, franc,
   et fait ressortir les cartes de la frise. */
.public-hero {
    width: 100%;
    background: radial-gradient(ellipse at top left, rgba(2, 113, 232, 0.08), transparent 55%),
                radial-gradient(ellipse at bottom right, rgba(88, 86, 214, 0.10), transparent 55%),
                #fff;
    padding-bottom: 2rem;
    margin-bottom: 2rem;
}

.public-header {
    background: none;
    color: var(--pub-encre);
    padding: 2.5rem 1.5rem 0.75rem;
    text-align: center;
    margin: 0;
}

.public-titre {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
}

/* Cette page est la seule que l'on envoie au dehors, et elle n'a pas de
   barre de navigation : la marque y tient lieu de retour à la maison. */
.public-marque {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--pub-encre);
    text-decoration: none;
    white-space: nowrap;
}

.public-marque:hover {
    color: var(--pub-bleu);
}

.public-marque i {
    color: var(--pub-bleu);
}

.public-header h1 {
    font-size: clamp(1.8rem, 3.6vw, 2.8rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    line-height: 1.15;
    margin: 0 0 0.5rem;
}

/* Le titre d'une frise : le dégradé des pages de présentation, découpé sur le
   texte. Sur la vue publique comme en tête du chat constructeur. La couleur qui
   suit n'est pas décorative : c'est elle qui s'affiche partout où le découpage ne
   prend pas — impression sans les fonds, navigateur qui l'ignore. */
.public-header h1,
.titre-de-frise {
    background: var(--pub-degrade);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--pub-bleu);
}

.public-header p {
    font-size: 1.1rem;
    color: var(--pub-gris);
    max-width: 640px;
    margin: 0 auto;
}

.timeline-wrapper {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}

.timeline {
}

.empty-state {
    text-align: center;
    padding: 3rem;
    color: #6c757d;
}

.empty-state i {
    font-size: 3rem;
    margin-bottom: 1rem;
}

.footer {
    margin-top: 3rem;
    padding: 2rem 0;
    text-align: center;
    color: #6c757d;
    font-size: 0.9rem;
}

/* Les compteurs se tiennent seuls : le cadre translucide qui les
   entourait était une barre pleine largeur pour deux pastilles. */
.stats-info {
    background: none;
    padding: 0;
    margin-top: 1.25rem;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.6rem;
}

.stats-info .badge {
    background: #fff !important;
    color: var(--pub-gris) !important;
    border: 1px solid var(--pub-gris-clair);
    border-radius: 9999px;
    padding: 0.4rem 0.9rem;
    font-weight: 600;
    font-size: 0.85rem;
    margin: 0;
}
/* ------------------------------------------------------------------ */
/* Adaptation mobile                                                    */
/*                                                                      */
/* C'est la page qu'un enseignant projette ou envoie à ses élèves :     */
/* elle est souvent ouverte sur un téléphone, et n'avait pourtant       */
/* aucune règle d'adaptation. Les points de rupture reprennent ceux de  */
/* timeline.css, qui régit le contenu affiché en dessous.               */
/* ------------------------------------------------------------------ */

@media (max-width: 768px) {
    .public-header {
        padding: 1.5rem 1rem;
        margin-bottom: 1.5rem;
    }

    .public-header h1 {
        font-size: 1.6rem;
        /* Un titre de frise peut être long et sans espace sécable. */
        overflow-wrap: break-word;
    }

    .public-header p {
        font-size: 1rem;
    }

    .timeline-wrapper {
        padding: 0 0.75rem;
    }

    .stats-info {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: 0.5rem;
        padding: 0.75rem;
        font-size: 0.9rem;
    }

    .empty-state {
        padding: 2rem 1rem;
    }

    .footer {
        margin-top: 2rem;
        padding: 1.5rem 1rem;
    }
}

/* Sur un téléphone, l'en-tête ne doit pas coûter un écran entier avant la
   frise : tout y est resserré d'un cran. */
@media (max-width: 768px) {
    .public-hero {
        padding-bottom: 1.5rem;
        margin-bottom: 1rem;
    }

    .public-header {
        padding: 1.25rem 1rem 0.35rem;
    }

    .stats-info {
        margin-top: 0.75rem;
    }

    .frise-bascule {
        padding: 0 0.75rem;
    }

    /* On n'imprime pas depuis un téléphone : le rappel du format n'y a
       rien à faire, et il coûtait deux lignes avant la frise. */
    .frise-bascule-avis {
        display: none;
    }

    .pub-btn {
        padding: 0.55rem 1.1rem;
        font-size: 0.9rem;
        border-radius: 10px;
    }

    .frise-reglages {
        margin-top: 0.85rem;
        gap: 0.4rem;
    }

    .frise-pilule {
        padding: 0.28rem 0.7rem;
        font-size: 0.78rem;
    }
}

@media (max-width: 480px) {
    .public-header {
        padding: 1rem 0.75rem 0.3rem;
    }

    .public-hero {
        padding-bottom: 1.25rem;
        margin-bottom: 0.75rem;
    }

    .frise-bascule-actions {
        gap: 0.5rem;
    }

    .pub-btn {
        padding: 0.5rem 0.9rem;
        font-size: 0.85rem;
    }

    .frise-pilule {
        padding: 0.25rem 0.6rem;
        font-size: 0.74rem;
        gap: 0.3rem;
    }

    .public-header h1 {
        font-size: 1.35rem;
    }

    .public-header p {
        font-size: 0.95rem;
    }

    .timeline-wrapper {
        padding: 0 0.5rem;
    }

    .empty-state i {
        font-size: 2.25rem;
    }
}

/* ------------------------------------------------------------------ */
/* Bascule entre la frise verticale et la frise murale                  */
/*                                                                      */
/* Discrète : cette page est d'abord une frise, pas une barre d'outils. */
/* Le message étroit ne paraît que sous 1100 px, là où la mise en page   */
/* horizontale ne s'applique pas.                                       */
/* ------------------------------------------------------------------ */

.frise-bascule {
    text-align: center;
    margin: 0;
    padding: 0 1rem;
    font-size: 0.9rem;
}

.frise-bascule-avis {
    margin: 0 0 1rem;
    color: var(--pub-gris);
}

.frise-bascule-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
}

/* Boutons des pages de présentation : arrondis larges, dégradé de la
   maison pour l'action qu'on met en avant, blanc cerné pour l'autre. */
.pub-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 1.5rem;
    border: none;
    border-radius: 12px;
    font-weight: 600;
    font-size: 1rem;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.25s ease;
}

.pub-btn:hover {
    transform: translateY(-2px);
    text-decoration: none;
}

.pub-btn-primaire {
    background: var(--pub-degrade);
    color: #fff;
    box-shadow: 0 4px 14px rgba(2, 113, 232, 0.3);
}

.pub-btn-primaire:hover {
    color: #fff;
    box-shadow: 0 8px 24px rgba(2, 113, 232, 0.35);
}

.pub-btn-secondaire {
    background: #fff;
    color: var(--pub-bleu);
    border: 2px solid var(--pub-gris-clair);
}

.pub-btn-secondaire:hover {
    color: var(--pub-bleu);
    border-color: var(--pub-bleu);
}

/* Troisième degré, pour la bascule : ni le plein du jeu, ni le cadre de
   l'impression, mais un aplat bleu très pâle. Les trois boutons se lisent
   alors dans l'ordre de ce qu'ils engagent. */
/* Un bouton réduit à son icône reste carré plutôt que de garder la largeur
   d'un bouton à texte. */
.pub-btn-icone {
    padding: 0.7rem;
    aspect-ratio: 1;
    justify-content: center;
}

.pub-btn-fantome {
    background: rgba(2, 113, 232, 0.07);
    color: var(--pub-bleu);
    border: none;
}

.pub-btn-fantome:hover {
    background: rgba(2, 113, 232, 0.13);
    color: var(--pub-bleu);
}

/* ------------------------------------------------------------------ */
/* Ce que la frise montre, et donc ce qui s'imprimera                   */
/*                                                                      */
/* Des pilules que l'on éteint et rallume, plutôt que des cases à       */
/* cocher : c'est la même famille que les compteurs du titre et les     */
/* boutons, et l'état se lit de loin. La case reste dans le document,   */
/* invisible mais atteignable au clavier — c'est elle qui porte l'état  */
/* et qui déclenche.                                                    */
/* ------------------------------------------------------------------ */

.frise-reglages {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 1.5rem;
}

.frise-pilule {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding: 0.35rem 0.9rem;
    border: 1px solid var(--pub-gris-clair);
    border-radius: 9999px;
    background: #fff;
    color: var(--pub-gris);
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    user-select: none;
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.frise-pilule i {
    font-size: 0.8em;
    opacity: 0.75;
}

/* La case pilote tout, mais ne se montre pas : la pilule est sa surface. */
.frise-pilule input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.frise-pilule:hover {
    border-color: var(--pub-bleu);
    color: var(--pub-bleu);
}

/* Allumée : ce que la frise montre en ce moment. */
.frise-pilule:has(input:checked) {
    background: rgba(2, 113, 232, 0.08);
    border-color: rgba(2, 113, 232, 0.35);
    color: var(--pub-bleu);
}

.frise-pilule:has(input:checked) i {
    opacity: 1;
}

/* Éteinte : le texte se barre, l'œil n'a pas à relire l'étiquette. */
.frise-pilule:not(:has(input:checked)) {
    text-decoration: line-through;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--pub-gris-clair);
}

/* Le clavier doit voir où il est, puisque la case ne se montre plus. */
.frise-pilule:has(input:focus-visible) {
    outline: 2px solid var(--pub-bleu);
    outline-offset: 2px;
}

/* ------------------------------------------------------------------ */
/* Ce que les réglages font disparaître                                 */
/*                                                                      */
/* Ici, et non dans la feuille de la frise horizontale : ces cases       */
/* valent pour les deux mises en page. Les sélecteurs nomment l'un et    */
/* l'autre des deux rangs, parce que la frise horizontale repositionne   */
/* certains de ces éléments en les visant de la même façon — une règle   */
/* plus simple se ferait battre, et la case resterait sans effet.        */
/* ------------------------------------------------------------------ */

.fp-sans-dates .timeline-item .timeline-date-badge,
.fp-sans-dates .timeline-item.timeline-left .timeline-date-badge,
.fp-sans-dates .timeline-item.timeline-right .timeline-date-badge { display: none; }

.fp-sans-descriptions .timeline-item .event-description-container { display: none; }
.fp-sans-themes .timeline-item .timeline-content .mt-2 { display: none; }
.fp-sans-images .timeline-item .event-images { display: none !important; }

/* À l'impression, l'en-tête en dégradé mange une page entière et vide
   les cartouches d'encre pour rien. */
/* ------------------------------------------------------------------ */
/* Intégrée au site d'un autre (FriseIntegration)                       */
/*                                                                      */
/* Le cadre est petit, et c'est la frise qu'on y vient voir : l'en-tête  */
/* se resserre, et la marque, qui mène à Fraisk, se pose en bas au       */
/* milieu.                                                              */
/* ------------------------------------------------------------------ */

.frise-integree .public-hero {
    padding-bottom: 0.75rem;
    margin-bottom: 0.75rem;
}

.frise-integree .public-header {
    padding-top: 1rem;
}

.frise-integree .public-header h1 {
    font-size: clamp(1.2rem, 2.4vw, 1.6rem);
}

/* Posée au bas du cadre : la frise y est souvent plus haute que lui, et la
   marque ne doit pas attendre la fin du défilement pour paraître. La page lui
   réserve sa hauteur, pour qu'elle ne couvre jamais la fin de la frise. */
.frise-integree {
    padding-bottom: 2.6rem;
}

.frise-integration-pied {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 5;
    display: flex;
    justify-content: center;
    padding: 0.4rem 1rem;
    background: rgba(255, 255, 255, 0.92);
    box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.06);
}

.frise-integration-pied .public-marque {
    font-size: 1rem;
}

@media print {
    /* La bascule prépare l'impression, elle n'y figure pas. Le pied de
       page du site non plus : mentions légales et liens de navigation
       n'ont rien à faire sur une frise affichée au mur. */
    .frise-bascule,
    .frise-reglages,
    .footer-fixed {
        display: none !important;
    }

    .public-hero {
        background: none !important;
        padding: 0;
        margin: 0;
    }

    .public-header {
        background: none !important;
        color: #000 !important;
        padding: 0 0 1rem;
        margin-bottom: 1rem;
        /* Pas de filet sous le titre : deux points de noir sur toute la
           largeur de la feuille pèsent plus lourd que ce qu'ils séparent. */
        border-bottom: none;
    }

    /* Sans impression des fonds — le réglage par défaut — le dégradé
       disparaît et un texte « transparent » sortirait blanc sur blanc. Le
       titre reprend donc une couleur pleine. */
    .public-header h1 {
        font-size: 1.5rem;
        background: none;
        -webkit-background-clip: border-box;
        background-clip: border-box;
        -webkit-text-fill-color: currentColor;
        color: var(--pub-bleu);
    }

    /* La marque reste à gauche du titre, comme à l'écran, à sa taille. */
    .public-marque {
        font-size: 1.1rem;
    }

    /* La marque, à gauche du titre, dit d'où vient la frise : le pied de page du
       site ne s'imprime pas. Elle remplace l'ancien sous-titre « fraisk.com ». */

    .timeline-wrapper {
        max-width: none;
        padding: 0;
    }
}
