/*
 * 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.
 */

/* Deux mesures, déclarées une seule fois : la boîte du fil et la gouttière
   que le contenu lui réserve. Les séparer en deux valeurs en dur, c'était
   la porte ouverte à ce qu'elles divergent — c'est exactement ce qui s'est
   produit sous 861px, où le fil rétrécissait sans que la gouttière suive.
   (Ce sont des variables propres au fil : le fichier reste autonome, il ne
   redéclare toujours rien qui appartienne à footer.css ou à
   home-redesign.css.)

   La gouttière vaut la largeur du fil, plus sur petit écran le débord des
   repères : le tracé est inscrit entre x=12 et x=62 sur 74 unités de
   viewBox, marge qui rétrécit avec la boîte (6px seulement à 40px de
   large) — moins que le rayon d'un point en état courant, halo compris.
   Les 8px supplémentaires rendent cette marge au contenu. */
:root {
    --vd-rope-width: 74px;
    --vd-rope-gutter: 74px;
}

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

/* 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: var(--vd-rope-width);
    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; }

/* --------------------------------------------------------------------
   Matière : corde polyester tressée

   La corde est la matière du produit — autant qu'elle en ait l'air. Trois
   couches posées sur le MÊME tracé suffisent à faire lire un cylindre
   tressé là où un trait plat reste un trait :

   - le CORPS donne l'épaisseur ;
   - la TRESSE est une série de brins diagonaux qui traversent la corde et
     se croisent en losanges. Sa géométrie dépend de la tangente au tracé,
     donc elle est calculée par rope_controller.js (buildBraid) et non
     écrite ici : un stroke-dasharray ne sait faire que des creux
     perpendiculaires — une échelle, pas une tresse ;
   - le REFLET est un filet clair, deux fois moins large, qui donne le
     satiné un peu synthétique du polyester et la rondeur.
   -------------------------------------------------------------------- */

.vd-rope__strand path {
    fill: none;
}

.vd-rope__body {
    stroke-width: 6;
    stroke-linecap: round;
}

/* Les brins sont fins et à bouts francs : arrondis, ils déborderaient du
   corps et la corde paraîtrait duveteuse au lieu de tressée. Leur pas et
   leur inclinaison se règlent dans le contrôleur (BRAID_PITCH,
   BRAID_HALF_WIDTH), pas ici — c'est de la géométrie, pas du style. */
.vd-rope__braid {
    stroke-width: 1.5;
    stroke-linecap: butt;
}

.vd-rope__sheen {
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-dasharray: 2.6 6.4;
    stroke-dashoffset: 3.5;
}

/* Brin non parcouru : 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. La tresse y est à
   peine plus marquée que le corps — assez pour la matière, pas assez pour
   attirer l'œil sur ce qui reste à parcourir. */
.vd-rope__strand--guide .vd-rope__body { stroke: rgba(128, 128, 128, 0.20); }
.vd-rope__strand--guide .vd-rope__braid { stroke: rgba(96, 96, 96, 0.30); }

/* Brin parcouru. Le creux entre deux brins est un ambre sombre plutôt qu'un
   noir : une corde teintée garde sa couleur jusque dans ses creux. */
.vd-rope__strand--cord .vd-rope__body { stroke: var(--vd-accent, var(--ts-primary, #E9A23B)); }
.vd-rope__strand--cord .vd-rope__braid { stroke: rgba(103, 61, 10, 0.45); }
.vd-rope__strand--cord .vd-rope__sheen { stroke: rgba(255, 238, 205, 0.55); }

/* 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; }
}

/* 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é.

   Sans borne de largeur : la gouttière était réservée au-dessus de 861px
   seulement, alors que c'est en dessous qu'elle manque le plus. Sur grand
   écran le fil pouvait à la rigueur se loger dans la marge de la page ;
   sur téléphone il n'y a plus de marge du tout, et le tracé traversait le
   texte, les prix et les boutons sur toute la descente. */
body:has(.vd-rope:not([hidden])) main .container {
    padding-right: var(--vd-rope-gutter);
}

/* Sur téléphone, la même gouttière pour les deux blocs pleine largeur posés
   hors de <main> et que le fil recouvrait aussi : les bandeaux flash (leur
   croix de fermeture, calée en haut à droite, tombait pile sous un repère —
   le tap partait sur le fil) et le pied de page, que le nœud final du tracé
   traverse dès qu'on arrive en bas. Au-dessus de 861px ils gardent leurs
   marges de page, assez larges pour laisser passer le fil. */
@media (max-width: 860px) {
    body:has(.vd-rope:not([hidden])) > .alert {
        margin-right: var(--vd-rope-gutter);
    }

    body:has(.vd-rope:not([hidden])) .site-footer .container {
        padding-right: var(--vd-rope-gutter);
    }
}

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