/*
 * Fil d'Ariane ondulé — repère de progression et navigation.
 *
 * Extrait de home-redesign.css pour être réutilisable page par page : le fil
 * n'a rien de propre à l'accueil, alors que le reste de home-redesign.css
 * (30 ko de sections pleine hauteur) n'a de sens que là. Même raisonnement que
 * pour footer.css.
 *
 * Une page a le fil dès qu'elle inclut templates/partials/_rope.html.twig et
 * pose des ancres `id` + `data-rope-label` sur ses régions. Tout le reste —
 * placement des repères, remplissage de la corde, masquage de la barre de
 * défilement native — est piloté par assets/controllers/rope_controller.js.
 *
 * La corde est la matière du produit : le repère de progression dit quelque
 * chose de vrai sur ce qui est vendu.
 *
 * Ce fichier est autonome : il passe par des valeurs de repli dans chaque
 * var() plutôt que de redéclarer un :root, pour ne dépendre ni de footer.css
 * ni de home-redesign.css tout en restant impossible à désynchroniser d'eux.
 */

/* Le fil démarre sous la navbar, comme le contenu : sinon son point
   d'ancrage et le début de sa première courbe passent derrière la barre
   opaque, et le fil paraît coupé net au lieu de naître avec la page.
   Les 16px supplémentaires en haut et en bas font la place des repères
   posés aux deux extrémités du tracé : sans eux le premier repasserait
   sous la navbar et le dernier sortirait par le bas de l'écran. 16px = le
   rayon du plus gros point, agrandi en état courant, halo compris. */
.vd-rope {
    position: fixed;
    top: calc(var(--navbar-height, 76px) + 16px); right: 0;
    width: 74px;
    height: calc(100vh - var(--navbar-height, 76px) - 32px);
    height: calc(100svh - var(--navbar-height, 76px) - 32px);
    z-index: 5;              /* sous la navbar sticky, au-dessus du contenu */
    pointer-events: none;
}

/* Le tracé et les repères doivent partager exactement la même boîte,
   sinon les points ne tombent plus sur la corde. D'où la marge portée
   par .vd-rope lui-même plutôt que par ces deux-là : un <svg> en
   position absolue avec height:auto est un élément remplacé, il prend sa
   taille intrinsèque (le ratio 74:860 du viewBox) au lieu de s'étirer
   entre ses insets — le bas était ignoré et les points dérivaient. */
.vd-rope svg {
    display: block;
    width: 100%; height: 100%;
}

.vd-rope__marks { position: absolute; inset: 0; }

/* Le tracé de fond : gris neutre semi-transparent, seule teinte lisible
   à la fois sur fond sombre (l'accueil) et sur fond clair (le catalogue et
   les pages Bootstrap), sans avoir à se décliner par page. */
.vd-rope__guide {
    fill: none; stroke-width: 5; stroke-linecap: round;
    stroke: rgba(128, 128, 128, 0.22);
}

.vd-rope__cord {
    fill: none; stroke-width: 5; stroke-linecap: round;
    stroke: var(--vd-accent, var(--ts-primary, #E9A23B));
    transition: stroke-dashoffset 0.08s linear;  /* lissage discret */
}

/* Le fil remplace la barre de défilement native — mais seulement une fois
   qu'il est effectivement en place (classe posée par rope_controller.js).
   Sans JS, la barre du navigateur reste : mieux vaut un repère ordinaire
   que pas de repère du tout. */
html.vd-rope-ready { scrollbar-width: none; }
html.vd-rope-ready::-webkit-scrollbar { width: 0; height: 0; }

/* --------------------------------------------------------------------
   Repères de section
   Le fil ne fait pas que dire où l'on en est : puisqu'il remplace la
   barre de défilement, il doit aussi permettre de se déplacer. Un repère
   par région, posé par le contrôleur à la fraction de défilement exacte
   où la région commence — un repère s'allume donc pile quand la corde
   le rejoint.
   -------------------------------------------------------------------- */

.vd-rope__mark {
    position: absolute;                      /* left/top posés par le contrôleur */
    transform: translate(-50%, -50%);        /* recentré sur le tracé */
    display: grid;
    place-items: center;
    width: 34px; height: 34px;               /* cible confortable autour d'un point de 9px */
    pointer-events: auto;                    /* seuls les repères captent le pointeur */
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}

.vd-rope__dot {
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--hr-ink, #0A0907);
    border: 2px solid rgba(128, 128, 128, 0.5);   /* même gris que le tracé de fond */
    transition: background-color 0.25s ease, border-color 0.25s ease,
                transform 0.25s ease, box-shadow 0.25s ease;
}

/* Atteint mais pas courant : anneau doré, cœur sombre. Un disque plein
   doré se fondrait dans la corde dorée qui le traverse — on ne verrait
   plus du tout les repères déjà passés. En perle, ils se détachent. */
.vd-rope__mark.is-reached .vd-rope__dot {
    border-color: var(--hr-gold, #E9A23B);
}

.vd-rope__mark.is-current .vd-rope__dot {
    background: var(--hr-gold, #E9A23B);
    border-color: var(--hr-gold, #E9A23B);
    transform: scale(1.5);
    box-shadow: 0 0 0 4px rgba(233, 162, 59, 0.22);
}

.vd-rope__mark:hover .vd-rope__dot {
    transform: scale(1.5);
    border-color: var(--hr-gold, #E9A23B);
}

/* Le dernier repère — le pied de page — tombe à 100 % du défilement,
   donc exactement au bout du tracé : c'est le nœud qui termine la corde.
   Un peu plus gros et plus épais, pour qu'on lise une fin de fil et pas
   un point de plus. */
.vd-rope__mark:last-child .vd-rope__dot {
    width: 13px; height: 13px;
    border-width: 3px;
}

.vd-rope__mark:focus-visible {
    outline: 2px solid var(--hr-gold, #E9A23B);
    outline-offset: 2px;
    border-radius: 50%;
}

/* Le libellé n'apparaît qu'à la demande : au repos le fil doit rester une
   ligne, pas un sommaire. */
.vd-rope__label {
    position: absolute;
    right: calc(100% - 2px);
    padding: 0.35rem 0.6rem;
    white-space: nowrap;
    font-family: var(--font-mono, 'Inter', sans-serif);
    font-size: 0.62rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--hr-cream, #E8D9B8);
    background: rgba(10, 9, 7, 0.92);
    border: 1px solid var(--hr-line-on-dark-strong, rgba(233, 162, 59, 0.4));
    opacity: 0;
    transform: translateX(6px);
    transition: opacity 0.2s ease, transform 0.2s ease;
    pointer-events: none;
}

.vd-rope__mark:hover .vd-rope__label,
.vd-rope__mark:focus-visible .vd-rope__label {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .vd-rope__dot, .vd-rope__label { transition: none; }
}

@media (max-width: 860px) { .vd-rope { width: 40px; } }

/* Le contrôleur efface le fil sur une page qui ne défile pas (panier vide,
   page courte) : sans défilement il n'y a rien à repérer. */
.vd-rope[hidden] { display: none; }

/* Le fil ne doit jamais passer sous le contenu : on lui réserve sa
   gouttière. Visé par :has() plutôt que par une classe sur <body>, pour
   qu'une page hérite de la gouttière du seul fait d'inclure le partial —
   rien à penser en plus au moment de l'ajouter à une nouvelle page. Et
   pas de gouttière réservée quand le fil est effacé. */
@media (min-width: 861px) {
    body:has(.vd-rope:not([hidden])) main .container { padding-right: 74px; }
}

/* Élément purement décoratif : inutile à l'impression. */
@media print { .vd-rope { display: none; } }
