1822 lines
56 KiB
Plaintext
1822 lines
56 KiB
Plaintext
---
|
||
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
||
import GlossaryPortalAside from "../../components/GlossaryPortalAside.astro";
|
||
import GlossaryPortalHero from "../../components/GlossaryPortalHero.astro";
|
||
import GlossaryPortalSection from "../../components/GlossaryPortalSection.astro";
|
||
import GlossaryPortalStickySync from "../../components/GlossaryPortalStickySync.astro";
|
||
import { getCollection } from "astro:content";
|
||
import { hrefOfGlossaryEntry } from "../../lib/glossary";
|
||
|
||
const entries = await getCollection("glossaire");
|
||
|
||
const collator = new Intl.Collator("fr", { sensitivity: "base", numeric: true });
|
||
|
||
const kindLabels = {
|
||
concept: "Concept",
|
||
diagnostic: "Diagnostic",
|
||
topologie: "Topologie",
|
||
verbe: "Verbe",
|
||
paradigme: "Paradigme",
|
||
doctrine: "Doctrine",
|
||
dispositif: "Dispositif",
|
||
figure: "Figure",
|
||
qualification: "Qualification",
|
||
epistemologie: "Épistémologie",
|
||
};
|
||
|
||
const domainLabels = {
|
||
transversal: "Transversal",
|
||
theorie: "Théorie",
|
||
"cas-ia": "Cas IA",
|
||
};
|
||
|
||
const levelLabels = {
|
||
fondamental: "Fondamental",
|
||
intermediaire: "Intermédiaire",
|
||
avance: "Avancé",
|
||
};
|
||
|
||
const sorted = [...entries].sort((a, b) => collator.compare(a.data.term, b.data.term));
|
||
|
||
function groupByInitial(list) {
|
||
const map = new Map();
|
||
|
||
for (const entry of list) {
|
||
const letter = (entry.data.term || "").trim().charAt(0).toUpperCase() || "#";
|
||
if (!map.has(letter)) map.set(letter, []);
|
||
map.get(letter).push(entry);
|
||
}
|
||
|
||
return [...map.entries()].sort((a, b) => collator.compare(a[0], b[0]));
|
||
}
|
||
|
||
const groupedAlpha = groupByInitial(sorted);
|
||
const totalEntries = sorted.length;
|
||
const totalLetters = groupedAlpha.length;
|
||
const paradigmesCount = entries.filter((entry) => entry.data.kind === "paradigme").length;
|
||
const doctrinesCount = entries.filter((entry) => entry.data.kind === "doctrine").length;
|
||
const verbesCount = entries.filter((entry) => entry.data.kind === "verbe").length;
|
||
const casIaCount = entries.filter((entry) => entry.data.domain === "cas-ia").length;
|
||
|
||
const pageItems = [
|
||
{ href: "#index-alphabetique", label: "Index alphabétique" },
|
||
{ href: "#prolonger-la-lecture", label: "Prolonger la lecture" },
|
||
];
|
||
|
||
const usefulLinks = [
|
||
{ href: "/glossaire/", label: "Accueil du glossaire" },
|
||
{ href: "/glossaire/concepts-fondamentaux/", label: "Concepts fondamentaux" },
|
||
{ href: "/glossaire/paradigme-archicratique/", label: "Paradigme archicratique" },
|
||
{ href: "/glossaire/scenes-archicratiques/", label: "Scènes archicratiques" },
|
||
{ href: "/glossaire/dynamiques-archicratiques/", label: "Dynamiques archicratiques" },
|
||
{ href: "/glossaire/tensions-irreductibles/", label: "Tensions irréductibles" },
|
||
{ href: "/glossaire/paradigmes/", label: "Paradigmes et doctrines" },
|
||
{ href: "/glossaire/archicrations/", label: "Méta-régimes archicratiques" },
|
||
];
|
||
|
||
const prolongerLinks = [
|
||
{
|
||
href: "/glossaire/",
|
||
title: "Accueil du glossaire",
|
||
text: "Revenir à la cartographie générale du système archicratique.",
|
||
},
|
||
{
|
||
href: "/glossaire/concepts-fondamentaux/",
|
||
title: "Concepts fondamentaux",
|
||
text:
|
||
"Repartir du noyau minimal : arcalité, cratialité, tension, archicration, co-viabilité, archicratie.",
|
||
},
|
||
{
|
||
href: "/glossaire/paradigmes/",
|
||
title: "Paradigmes et doctrines",
|
||
text:
|
||
"Retrouver le paysage théorique au sein duquel l’archicratie se situe et se distingue.",
|
||
},
|
||
{
|
||
href: "/glossaire/archicrations/",
|
||
title: "Méta-régimes archicratiques",
|
||
text:
|
||
"Parcourir les grandes formes de co-viabilité et leurs modulations historiques.",
|
||
},
|
||
];
|
||
---
|
||
|
||
<GlossaryLayout
|
||
title="Index complet du glossaire"
|
||
version="1.0"
|
||
stickyMode="glossary-portal"
|
||
>
|
||
<Fragment slot="aside">
|
||
<div class="gic-aside-stack">
|
||
<GlossaryPortalAside
|
||
ariaLabel="Navigation de l’index complet du glossaire"
|
||
title="Index complet"
|
||
meta={`${totalEntries} entrée${totalEntries > 1 ? "s" : ""} · ${totalLetters} lettre${totalLetters > 1 ? "s" : ""}`}
|
||
pageItems={pageItems}
|
||
usefulLinks={usefulLinks}
|
||
/>
|
||
|
||
<div class="gic-aside__block">
|
||
<h2 class="gic-aside__heading">Repères de lecture</h2>
|
||
|
||
<div class="gic-aside__pills" aria-label="Repères de l’index">
|
||
<span class="gic-aside__pill">
|
||
{paradigmesCount} paradigme{paradigmesCount > 1 ? "s" : ""}
|
||
</span>
|
||
<span class="gic-aside__pill">
|
||
{doctrinesCount} doctrine{doctrinesCount > 1 ? "s" : ""}
|
||
</span>
|
||
</div>
|
||
|
||
<p class="gic-aside__note">
|
||
Cet index complète les portails thématiques : il permet de retrouver
|
||
rapidement une fiche, puis de repartir vers les grandes cartographies du glossaire.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</Fragment>
|
||
|
||
<section class="gic-page">
|
||
<GlossaryPortalHero
|
||
prefix="gic"
|
||
kicker="Référentiel terminologique"
|
||
title="Index complet du glossaire"
|
||
intro="Cette page rassemble l’ensemble des entrées du glossaire dans un ordre alphabétique intégral."
|
||
moreParagraphs={[
|
||
"Elle complète l’accueil conceptuel du glossaire par une navigation plus encyclopédique, plus directe et plus exhaustive.",
|
||
]}
|
||
introMaxWidth="72ch"
|
||
followIntroMaxWidth="68ch"
|
||
moreMaxHeight="12rem"
|
||
/>
|
||
|
||
<GlossaryPortalSection
|
||
id="index-alphabetique"
|
||
title="Index alphabétique"
|
||
count={`${totalEntries} entrée${totalEntries > 1 ? "s" : ""}`}
|
||
intro="Naviguer par lettre permet de retrouver rapidement chaque fiche du glossaire, tout en conservant ses principaux marqueurs de lecture."
|
||
>
|
||
<nav class="gic-letters" id="gic-letters-source" aria-label="Lettres de l’index">
|
||
{groupedAlpha.map(([letter]) => (
|
||
<a href={`#letter-${letter}`}>{letter}</a>
|
||
))}
|
||
</nav>
|
||
|
||
<nav
|
||
class="gic-follow-letters"
|
||
id="gic-follow-letters"
|
||
aria-label="Lettres de l’index flottant"
|
||
aria-hidden="true"
|
||
hidden
|
||
>
|
||
{groupedAlpha.map(([letter]) => (
|
||
<a href={`#letter-${letter}`}>{letter}</a>
|
||
))}
|
||
</nav>
|
||
</GlossaryPortalSection>
|
||
|
||
<div class="gic-groups">
|
||
{groupedAlpha.map(([letter, items]) => (
|
||
<section class="gic-section gic-group" id={`letter-${letter}`}>
|
||
<div class="gic-section__head">
|
||
<h2>{letter}</h2>
|
||
<span class="gic-section__count">
|
||
{items.length} entrée{items.length > 1 ? "s" : ""}
|
||
</span>
|
||
</div>
|
||
|
||
<div class="gic-list">
|
||
{items.map((entry) => (
|
||
<article class="gic-item">
|
||
<a class="gic-term" href={hrefOfGlossaryEntry(entry)}>
|
||
{entry.data.term}
|
||
</a>
|
||
|
||
<p class="gic-def">{entry.data.definitionShort}</p>
|
||
|
||
<p class="gic-meta">
|
||
<span>{kindLabels[entry.data.kind] ?? entry.data.kind}</span>
|
||
<span>{domainLabels[entry.data.domain] ?? entry.data.domain}</span>
|
||
<span>{levelLabels[entry.data.level] ?? entry.data.level}</span>
|
||
</p>
|
||
</article>
|
||
))}
|
||
</div>
|
||
</section>
|
||
))}
|
||
</div>
|
||
|
||
<GlossaryPortalSection
|
||
id="prolonger-la-lecture"
|
||
title="Prolonger la lecture"
|
||
intro="Cet index intégral complète les portails thématiques sans s’y substituer. Il permet de repartir ensuite vers les grandes cartographies déjà stabilisées du glossaire."
|
||
final={true}
|
||
>
|
||
<div class="gic-cards">
|
||
{prolongerLinks.map((item) => (
|
||
<a class="gic-card" href={item.href}>
|
||
<strong>{item.title}</strong>
|
||
<span>{item.text}</span>
|
||
</a>
|
||
))}
|
||
</div>
|
||
</GlossaryPortalSection>
|
||
</section>
|
||
|
||
<GlossaryPortalStickySync
|
||
heroMoreId="gic-hero-more"
|
||
heroToggleId="gic-hero-toggle"
|
||
mobileBreakpoint={980}
|
||
compactSticky={true}
|
||
/>
|
||
|
||
<script is:inline>
|
||
(() => {
|
||
const boot = () => {
|
||
const body = document.body;
|
||
const root = document.documentElement;
|
||
const follow = document.getElementById("reading-follow");
|
||
const lettersSource = document.getElementById("gic-letters-source");
|
||
const lettersFollow = document.getElementById("gic-follow-letters");
|
||
const groupSections = Array.from(document.querySelectorAll(".gic-group"));
|
||
|
||
if (!body || !root || !follow || !lettersSource || !lettersFollow || groupSections.length === 0) {
|
||
return;
|
||
}
|
||
|
||
const BODY_CLASS = "is-index-complet-page";
|
||
const LETTERS_DOCKED_CLASS = "gic-letters-docked";
|
||
const ACTIVE_CLASS = "is-active";
|
||
const mqMobile = window.matchMedia("(max-width: 860px)");
|
||
const mqSmallLandscape = window.matchMedia(
|
||
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||
);
|
||
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
||
const EXTRA_GAP = 12;
|
||
const MAX_CORRECTION_PASSES = 8;
|
||
|
||
const sourceLinks = Array.from(lettersSource.querySelectorAll("a"));
|
||
const followLinks = Array.from(lettersFollow.querySelectorAll("a"));
|
||
const allLetterLinks = [...sourceLinks, ...followLinks];
|
||
|
||
body.classList.add(BODY_CLASS);
|
||
|
||
const syncPremiumStickyMetrics = () => {
|
||
const hero = document.querySelector("[data-glossary-portal-hero]");
|
||
const followInner = follow.querySelector(".reading-follow__inner");
|
||
|
||
const heroH = hero ? Math.round(hero.getBoundingClientRect().height || 0) : 0;
|
||
const followOn =
|
||
follow.classList.contains("is-on") &&
|
||
follow.style.display !== "none" &&
|
||
follow.getAttribute("aria-hidden") !== "true";
|
||
|
||
const followH = followOn && followInner
|
||
? Math.round(followInner.getBoundingClientRect().height || 0)
|
||
: 0;
|
||
|
||
const lettersH =
|
||
!lettersFollow.hidden && lettersFollow.getAttribute("aria-hidden") === "false"
|
||
? Math.round(lettersFollow.getBoundingClientRect().height || 0)
|
||
: 0;
|
||
|
||
root.style.setProperty("--gic-premium-hero-h", `${heroH}px`);
|
||
root.style.setProperty("--gic-premium-follow-h", `${followH}px`);
|
||
root.style.setProperty("--gic-premium-letters-h", `${lettersH}px`);
|
||
};
|
||
|
||
const forceHideGlobalFollowOnCompactViewport = () => {
|
||
follow.style.display = "";
|
||
syncPremiumStickyMetrics();
|
||
};
|
||
|
||
const isCompactViewport = () =>
|
||
mqMobile.matches || mqSmallLandscape.matches;
|
||
|
||
const computeFollowOn = () =>
|
||
follow.classList.contains("is-on") &&
|
||
follow.style.display !== "none" &&
|
||
follow.getAttribute("aria-hidden") !== "true";
|
||
|
||
const setAnchorOffset = (value) => {
|
||
root.style.setProperty(
|
||
"--gic-follow-letters-offset",
|
||
`${Math.max(0, Math.round(value))}px`
|
||
);
|
||
};
|
||
|
||
const syncFollowLettersTop = () => {
|
||
const inner = follow.querySelector(".reading-follow__inner");
|
||
const followIsOn =
|
||
follow.classList.contains("is-on") &&
|
||
follow.style.display !== "none" &&
|
||
follow.getAttribute("aria-hidden") !== "true";
|
||
|
||
if (!followIsOn || !inner) {
|
||
lettersFollow.style.top = "";
|
||
return;
|
||
}
|
||
|
||
const followRect = follow.getBoundingClientRect();
|
||
const innerRect = inner.getBoundingClientRect();
|
||
const top = followRect.top + innerRect.height;
|
||
|
||
lettersFollow.style.top = `${Math.round(top)}px`;
|
||
};
|
||
|
||
const syncLettersDockState = () => {
|
||
if (!computeFollowOn()) {
|
||
body.classList.remove(LETTERS_DOCKED_CLASS);
|
||
lettersFollow.hidden = true;
|
||
lettersFollow.setAttribute("aria-hidden", "true");
|
||
setAnchorOffset(0);
|
||
return;
|
||
}
|
||
|
||
const inner = follow.querySelector(".reading-follow__inner");
|
||
if (!inner) {
|
||
body.classList.remove(LETTERS_DOCKED_CLASS);
|
||
lettersFollow.hidden = true;
|
||
lettersFollow.setAttribute("aria-hidden", "true");
|
||
setAnchorOffset(0);
|
||
return;
|
||
}
|
||
|
||
const sourceRect = lettersSource.getBoundingClientRect();
|
||
const innerRect = inner.getBoundingClientRect();
|
||
const shouldDock = sourceRect.top <= (innerRect.bottom + 6);
|
||
|
||
body.classList.toggle(LETTERS_DOCKED_CLASS, shouldDock);
|
||
lettersFollow.hidden = !shouldDock;
|
||
lettersFollow.setAttribute("aria-hidden", shouldDock ? "false" : "true");
|
||
|
||
if (shouldDock) {
|
||
const dockedHeight = lettersFollow.getBoundingClientRect().height || 0;
|
||
setAnchorOffset(dockedHeight + EXTRA_GAP);
|
||
} else {
|
||
setAnchorOffset(0);
|
||
}
|
||
};
|
||
|
||
const getAnchorViewportTop = () => {
|
||
const inner = follow.querySelector(".reading-follow__inner");
|
||
const followOn = computeFollowOn();
|
||
|
||
if (!followOn || !inner) {
|
||
return 12;
|
||
}
|
||
|
||
const followLettersVisible =
|
||
!lettersFollow.hidden &&
|
||
lettersFollow.getAttribute("aria-hidden") === "false";
|
||
|
||
if (followLettersVisible) {
|
||
return Math.round(lettersFollow.getBoundingClientRect().bottom + EXTRA_GAP);
|
||
}
|
||
|
||
return Math.round(inner.getBoundingClientRect().bottom + EXTRA_GAP);
|
||
};
|
||
|
||
const getTargetHead = (section) =>
|
||
section?.querySelector(".gic-section__head") || section;
|
||
|
||
const correctAnchorAlignment = (section, pass = 0) => {
|
||
if (!section || pass >= MAX_CORRECTION_PASSES) return;
|
||
|
||
requestAnimationFrame(() => {
|
||
syncFollowLettersTop();
|
||
syncLettersDockState();
|
||
|
||
const head = getTargetHead(section);
|
||
if (!head) return;
|
||
|
||
const wantedTop = getAnchorViewportTop();
|
||
const headTop = head.getBoundingClientRect().top;
|
||
const delta = headTop - wantedTop;
|
||
|
||
if (Math.abs(delta) <= 1) return;
|
||
|
||
window.scrollBy({
|
||
top: delta,
|
||
behavior: "auto",
|
||
});
|
||
|
||
correctAnchorAlignment(section, pass + 1);
|
||
});
|
||
};
|
||
|
||
const scrollToLetterTarget = (targetId) => {
|
||
const section = document.getElementById(targetId);
|
||
if (!section) return;
|
||
|
||
const head = getTargetHead(section);
|
||
if (!head) return;
|
||
|
||
syncFollowLettersTop();
|
||
syncLettersDockState();
|
||
|
||
const targetTop = getAnchorViewportTop();
|
||
const rect = head.getBoundingClientRect();
|
||
const absoluteTop = window.scrollY + rect.top - targetTop;
|
||
|
||
if (window.location.hash !== `#${targetId}`) {
|
||
history.pushState(null, "", `#${targetId}`);
|
||
}
|
||
|
||
window.scrollTo({
|
||
top: Math.max(0, Math.round(absoluteTop)),
|
||
behavior: reducedMotion.matches ? "auto" : "smooth",
|
||
});
|
||
|
||
requestAnimationFrame(() => {
|
||
requestAnimationFrame(() => {
|
||
correctAnchorAlignment(section, 0);
|
||
});
|
||
});
|
||
|
||
window.setTimeout(() => correctAnchorAlignment(section, 0), 120);
|
||
window.setTimeout(() => correctAnchorAlignment(section, 0), 260);
|
||
};
|
||
|
||
const syncActiveLetter = () => {
|
||
let activeId = null;
|
||
|
||
const inner = follow.querySelector(".reading-follow__inner");
|
||
const followOn = computeFollowOn();
|
||
const followBottom = followOn && inner
|
||
? inner.getBoundingClientRect().bottom
|
||
: 0;
|
||
|
||
const dockedHeight =
|
||
!lettersFollow.hidden && lettersFollow.getAttribute("aria-hidden") === "false"
|
||
? lettersFollow.getBoundingClientRect().height
|
||
: 0;
|
||
|
||
const threshold = followBottom > 0
|
||
? followBottom + dockedHeight + 12
|
||
: 140;
|
||
|
||
for (const section of groupSections) {
|
||
const rect = section.getBoundingClientRect();
|
||
if (rect.top <= threshold) {
|
||
activeId = section.id;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!activeId && groupSections[0]) {
|
||
activeId = groupSections[0].id;
|
||
}
|
||
|
||
const applyState = (links) => {
|
||
links.forEach((link) => {
|
||
const isActive = link.getAttribute("href") === `#${activeId}`;
|
||
link.classList.toggle(ACTIVE_CLASS, isActive);
|
||
|
||
if (isActive) {
|
||
link.setAttribute("aria-current", "true");
|
||
} else {
|
||
link.removeAttribute("aria-current");
|
||
}
|
||
});
|
||
};
|
||
|
||
applyState(sourceLinks);
|
||
applyState(followLinks);
|
||
};
|
||
|
||
const handleLetterClick = (event) => {
|
||
const link = event.currentTarget;
|
||
const href = link?.getAttribute("href") || "";
|
||
|
||
if (!href.startsWith("#letter-")) return;
|
||
|
||
event.preventDefault();
|
||
scrollToLetterTarget(href.slice(1));
|
||
};
|
||
|
||
allLetterLinks.forEach((link) => {
|
||
link.addEventListener("click", handleLetterClick);
|
||
});
|
||
|
||
let raf = 0;
|
||
const schedule = () => {
|
||
if (raf) return;
|
||
raf = requestAnimationFrame(() => {
|
||
raf = 0;
|
||
forceHideGlobalFollowOnCompactViewport();
|
||
syncFollowLettersTop();
|
||
syncLettersDockState();
|
||
syncPremiumStickyMetrics();
|
||
syncActiveLetter();
|
||
});
|
||
};
|
||
|
||
const onScroll = () => {
|
||
schedule();
|
||
};
|
||
|
||
const onHashChange = () => {
|
||
const id = window.location.hash.replace(/^#/, "");
|
||
if (!id.startsWith("letter-")) return;
|
||
scrollToLetterTarget(id);
|
||
};
|
||
|
||
const followObserver = new MutationObserver(schedule);
|
||
followObserver.observe(follow, {
|
||
attributes: true,
|
||
attributeFilter: ["class", "style", "aria-hidden"],
|
||
subtree: false,
|
||
});
|
||
|
||
window.addEventListener("scroll", onScroll, { passive: true });
|
||
window.addEventListener("resize", schedule);
|
||
window.addEventListener("pageshow", schedule);
|
||
window.addEventListener("hashchange", onHashChange);
|
||
|
||
if (document.fonts?.ready) {
|
||
document.fonts.ready.then(schedule).catch(() => {});
|
||
}
|
||
|
||
if (mqSmallLandscape.addEventListener) {
|
||
mqSmallLandscape.addEventListener("change", schedule);
|
||
} else if (mqSmallLandscape.addListener) {
|
||
mqSmallLandscape.addListener(schedule);
|
||
}
|
||
|
||
if (reducedMotion.addEventListener) {
|
||
reducedMotion.addEventListener("change", schedule);
|
||
} else if (reducedMotion.addListener) {
|
||
reducedMotion.addListener(schedule);
|
||
}
|
||
|
||
setAnchorOffset(0);
|
||
forceHideGlobalFollowOnCompactViewport();
|
||
schedule();
|
||
|
||
if (window.location.hash.startsWith("#letter-")) {
|
||
requestAnimationFrame(() => {
|
||
requestAnimationFrame(() => {
|
||
scrollToLetterTarget(window.location.hash.slice(1));
|
||
});
|
||
});
|
||
}
|
||
};
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
||
} else {
|
||
boot();
|
||
}
|
||
})();
|
||
</script>
|
||
<script is:inline>
|
||
/*
|
||
INDEX COMPLET — STACK PREMIUM MOBILE/TABLETTE V2
|
||
|
||
Principe :
|
||
- uniquement sur /glossaire/index-complet/ ;
|
||
- rail vertical calculé en pixels réels ;
|
||
- cockpit compact :
|
||
header → hero condensé → follow H2 compact → lettres horizontales.
|
||
*/
|
||
(() => {
|
||
const boot = () => {
|
||
const body = document.body;
|
||
const root = document.documentElement;
|
||
const hero = document.querySelector("[data-glossary-portal-hero]");
|
||
const follow = document.getElementById("reading-follow");
|
||
const inner = follow?.querySelector(".reading-follow__inner");
|
||
const lettersSource = document.getElementById("gic-letters-source");
|
||
const lettersFollow = document.getElementById("gic-follow-letters");
|
||
|
||
if (!body || !root || !hero || !follow || !inner || !lettersSource || !lettersFollow) return;
|
||
|
||
const mqCompact = window.matchMedia("(max-width: 980px)");
|
||
const mqSmallLandscape = window.matchMedia(
|
||
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||
);
|
||
|
||
const isCompact = () => mqCompact.matches || mqSmallLandscape.matches;
|
||
|
||
const pxVar = (name, fallback = 0) => {
|
||
const raw = getComputedStyle(root).getPropertyValue(name).trim();
|
||
const n = Number.parseFloat(raw);
|
||
return Number.isFinite(n) ? n : fallback;
|
||
};
|
||
|
||
const stackTop = () => {
|
||
const glossaryTop = pxVar("--glossary-sticky-top", NaN);
|
||
if (Number.isFinite(glossaryTop) && glossaryTop > 0) return glossaryTop;
|
||
|
||
const headerH = pxVar("--sticky-header-h", 0);
|
||
const gap = pxVar("--page-gap", 12);
|
||
return Math.max(0, Math.round(headerH + gap));
|
||
};
|
||
|
||
const heads = Array.from(
|
||
document.querySelectorAll(".glossary-portal-section__head, .gic-section__head")
|
||
);
|
||
|
||
const titleOf = (head) => {
|
||
const h = head?.querySelector("h2, h3");
|
||
return (h?.textContent || head?.textContent || "")
|
||
.replace(/\s+/g, " ")
|
||
.trim();
|
||
};
|
||
|
||
const writeFollow = (title) => {
|
||
const h1 = inner.querySelector(".rf-h1");
|
||
const h2 = inner.querySelector(".rf-h2");
|
||
const h3 = inner.querySelector(".rf-h3");
|
||
|
||
if (h1) h1.textContent = "Index complet";
|
||
if (h2) h2.textContent = title || "Index alphabétique";
|
||
if (h3) h3.textContent = "";
|
||
|
||
follow.classList.add("is-on");
|
||
follow.setAttribute("aria-hidden", "false");
|
||
follow.style.setProperty("display", "block", "important");
|
||
|
||
inner.style.setProperty("display", "block", "important");
|
||
inner.style.setProperty("visibility", "visible", "important");
|
||
inner.style.setProperty("opacity", "1", "important");
|
||
|
||
body.classList.add("glossary-portal-follow-on", "gic-premium-follow-on");
|
||
};
|
||
|
||
const clearFollow = () => {
|
||
follow.classList.remove("is-on");
|
||
follow.setAttribute("aria-hidden", "true");
|
||
|
||
body.classList.remove(
|
||
"glossary-portal-follow-on",
|
||
"gic-premium-follow-on",
|
||
"gic-letters-docked",
|
||
"gic-premium-letters-on"
|
||
);
|
||
|
||
lettersFollow.hidden = true;
|
||
lettersFollow.setAttribute("aria-hidden", "true");
|
||
|
||
root.style.setProperty("--gic-premium-follow-h", "0px");
|
||
root.style.setProperty("--gic-premium-letters-h", "0px");
|
||
root.style.setProperty("--gic-stack-h", "0px");
|
||
root.style.setProperty("--gic-follow-letters-offset", "0px");
|
||
};
|
||
|
||
const currentHead = () => {
|
||
const top = stackTop();
|
||
const heroH = pxVar("--gic-premium-hero-h", 0);
|
||
const followH = pxVar("--gic-premium-follow-h", 0);
|
||
const lettersH = pxVar("--gic-premium-letters-h", 0);
|
||
const threshold = top + heroH + followH + lettersH + 18;
|
||
|
||
let current = null;
|
||
for (const head of heads) {
|
||
const r = head.getBoundingClientRect();
|
||
if (r.top <= threshold) current = head;
|
||
else break;
|
||
}
|
||
return current;
|
||
};
|
||
|
||
const measure = () => {
|
||
const heroH = body.classList.contains("glossary-portal-hero-condensed")
|
||
? Math.max(0, Math.round(hero.getBoundingClientRect().height || 0))
|
||
: 0;
|
||
|
||
const followH = body.classList.contains("gic-premium-follow-on")
|
||
? Math.max(0, Math.round(inner.getBoundingClientRect().height || 0))
|
||
: 0;
|
||
|
||
const lettersH = body.classList.contains("gic-premium-letters-on")
|
||
? Math.max(0, Math.round(lettersFollow.getBoundingClientRect().height || 0))
|
||
: 0;
|
||
|
||
const stackH = heroH + followH + lettersH;
|
||
|
||
root.style.setProperty("--gic-premium-top", `${stackTop()}px`);
|
||
root.style.setProperty("--gic-premium-hero-h", `${heroH}px`);
|
||
root.style.setProperty("--gic-premium-follow-h", `${followH}px`);
|
||
root.style.setProperty("--gic-premium-letters-h", `${lettersH}px`);
|
||
root.style.setProperty("--gic-stack-h", `${stackH}px`);
|
||
root.style.setProperty("--glossary-local-sticky-h", `${stackH}px`);
|
||
root.style.setProperty("--followbar-h", `${followH}px`);
|
||
root.style.setProperty("--sticky-offset-px", `${stackTop() + stackH + 12}px`);
|
||
};
|
||
|
||
const syncLetters = () => {
|
||
if (!body.classList.contains("gic-premium-follow-on")) {
|
||
body.classList.remove("gic-letters-docked", "gic-premium-letters-on");
|
||
lettersFollow.hidden = true;
|
||
lettersFollow.setAttribute("aria-hidden", "true");
|
||
root.style.setProperty("--gic-follow-letters-offset", "0px");
|
||
return;
|
||
}
|
||
|
||
const sourceRect = lettersSource.getBoundingClientRect();
|
||
const followBottom = stackTop() + pxVar("--gic-premium-hero-h", 0) + pxVar("--gic-premium-follow-h", 0);
|
||
const shouldDock = sourceRect.top <= followBottom + 8;
|
||
|
||
body.classList.toggle("gic-letters-docked", shouldDock);
|
||
body.classList.toggle("gic-premium-letters-on", shouldDock);
|
||
|
||
lettersFollow.hidden = !shouldDock;
|
||
lettersFollow.setAttribute("aria-hidden", shouldDock ? "false" : "true");
|
||
|
||
if (shouldDock) {
|
||
lettersFollow.style.setProperty("display", "flex", "important");
|
||
root.style.setProperty(
|
||
"--gic-follow-letters-offset",
|
||
`${Math.max(0, Math.round(lettersFollow.getBoundingClientRect().height || 0)) + 12}px`
|
||
);
|
||
} else {
|
||
root.style.setProperty("--gic-follow-letters-offset", "0px");
|
||
}
|
||
};
|
||
|
||
let raf = 0;
|
||
|
||
const sync = () => {
|
||
raf = 0;
|
||
|
||
body.classList.add("is-index-complet-page", "is-glossary-portal-page");
|
||
|
||
if (!isCompact()) {
|
||
body.classList.remove(
|
||
"gic-premium-compact",
|
||
"gic-premium-follow-on",
|
||
"gic-premium-letters-on"
|
||
);
|
||
|
||
hero.style.removeProperty("position");
|
||
hero.style.removeProperty("top");
|
||
hero.style.removeProperty("z-index");
|
||
|
||
follow.style.removeProperty("display");
|
||
follow.style.removeProperty("top");
|
||
follow.style.removeProperty("left");
|
||
follow.style.removeProperty("width");
|
||
|
||
lettersFollow.style.removeProperty("display");
|
||
lettersFollow.style.removeProperty("top");
|
||
lettersFollow.style.removeProperty("left");
|
||
lettersFollow.style.removeProperty("width");
|
||
|
||
return;
|
||
}
|
||
|
||
body.classList.add("gic-premium-compact");
|
||
|
||
const top = stackTop();
|
||
const scrollY = window.scrollY || window.pageYOffset || 0;
|
||
const heroRect = hero.getBoundingClientRect();
|
||
|
||
const condensed = scrollY > 8 && heroRect.top <= top + 8;
|
||
body.classList.toggle("glossary-portal-hero-condensed", condensed);
|
||
|
||
hero.style.setProperty("position", "sticky", "important");
|
||
hero.style.setProperty("top", `${top}px`, "important");
|
||
hero.style.setProperty("z-index", "72", "important");
|
||
|
||
if (!condensed) {
|
||
clearFollow();
|
||
measure();
|
||
return;
|
||
}
|
||
|
||
measure();
|
||
|
||
const head = currentHead();
|
||
const rawTitle = titleOf(head) || "Index alphabétique";
|
||
const title = /^[A-ZÀÂÄÇÉÈÊËÎÏÔÖÙÛÜŸ]$/i.test(rawTitle)
|
||
? "Index alphabétique"
|
||
: rawTitle;
|
||
|
||
writeFollow(title);
|
||
|
||
measure();
|
||
syncLetters();
|
||
measure();
|
||
};
|
||
|
||
const schedule = () => {
|
||
if (raf) return;
|
||
raf = requestAnimationFrame(sync);
|
||
};
|
||
|
||
window.addEventListener("scroll", schedule, { passive: true });
|
||
window.addEventListener("resize", schedule);
|
||
window.addEventListener("pageshow", schedule);
|
||
|
||
if (document.fonts?.ready) {
|
||
document.fonts.ready.then(schedule).catch(() => {});
|
||
}
|
||
|
||
if (mqCompact.addEventListener) mqCompact.addEventListener("change", schedule);
|
||
else if (mqCompact.addListener) mqCompact.addListener(schedule);
|
||
|
||
if (mqSmallLandscape.addEventListener) mqSmallLandscape.addEventListener("change", schedule);
|
||
else if (mqSmallLandscape.addListener) mqSmallLandscape.addListener(schedule);
|
||
|
||
schedule();
|
||
};
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
||
} else {
|
||
boot();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<style is:global>
|
||
/* INDEX COMPLET — STACK PREMIUM MOBILE/TABLETTE V2 */
|
||
|
||
@media (max-width: 980px){
|
||
body.is-index-complet-page.gic-premium-compact{
|
||
scroll-padding-top: calc(var(--gic-premium-top, 0px) + var(--gic-stack-h, 0px) + 16px);
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact .glossary-portal-hero,
|
||
body.is-index-complet-page.gic-premium-compact .glossary-page-hero{
|
||
position: sticky !important;
|
||
top: var(--gic-premium-top, var(--glossary-sticky-top, 0px)) !important;
|
||
z-index: 72 !important;
|
||
overflow: hidden !important;
|
||
margin-bottom: 12px !important;
|
||
transform: translateZ(0) !important;
|
||
backface-visibility: hidden !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero,
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-page-hero{
|
||
padding: 7px 10px 7px !important;
|
||
row-gap: 3px !important;
|
||
border-radius: 14px 14px 0 0 !important;
|
||
margin-bottom: 0 !important;
|
||
box-shadow: 0 12px 30px rgba(0,0,0,.24) !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero__kicker{
|
||
font-size: 8px !important;
|
||
line-height: 1 !important;
|
||
letter-spacing: .105em !important;
|
||
opacity: .66 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero h1{
|
||
font-size: clamp(1.18rem, 4.8vw, 1.48rem) !important;
|
||
line-height: 1 !important;
|
||
letter-spacing: -.028em !important;
|
||
margin: 0 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed:not(.glossary-portal-hero-expanded) .glossary-portal-hero__intro{
|
||
display: -webkit-box !important;
|
||
-webkit-box-orient: vertical !important;
|
||
-webkit-line-clamp: 1 !important;
|
||
line-clamp: 1 !important;
|
||
max-height: 1.12em !important;
|
||
overflow: hidden !important;
|
||
font-size: .66rem !important;
|
||
line-height: 1.12 !important;
|
||
opacity: .72 !important;
|
||
margin: 0 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed:not(.glossary-portal-hero-expanded) .glossary-portal-hero__more{
|
||
max-height: 0 !important;
|
||
opacity: 0 !important;
|
||
overflow: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero__toggle{
|
||
display: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow{
|
||
display: block !important;
|
||
position: fixed !important;
|
||
left: var(--reading-left) !important;
|
||
width: var(--reading-width) !important;
|
||
top: calc(var(--gic-premium-top, 0px) + var(--gic-premium-hero-h, 0px) - 1px) !important;
|
||
z-index: 71 !important;
|
||
opacity: 0 !important;
|
||
visibility: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.gic-premium-follow-on #reading-follow{
|
||
opacity: 1 !important;
|
||
visibility: visible !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .reading-follow__inner{
|
||
display: block !important;
|
||
visibility: visible !important;
|
||
opacity: 1 !important;
|
||
max-height: none !important;
|
||
min-height: 0 !important;
|
||
margin-top: 0 !important;
|
||
padding: 5px 56px 5px 9px !important;
|
||
border-top-left-radius: 0 !important;
|
||
border-top-right-radius: 0 !important;
|
||
border-bottom-left-radius: 0 !important;
|
||
border-bottom-right-radius: 0 !important;
|
||
box-shadow: 0 8px 18px rgba(0,0,0,.16) !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .rf-h1,
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .rf-h3,
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .rf-actions{
|
||
display: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .rf-h2{
|
||
display: block !important;
|
||
font-size: .78rem !important;
|
||
line-height: 1.08 !important;
|
||
white-space: nowrap !important;
|
||
overflow: hidden !important;
|
||
text-overflow: ellipsis !important;
|
||
letter-spacing: -.012em !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #gic-follow-letters{
|
||
position: fixed !important;
|
||
left: var(--reading-left) !important;
|
||
width: var(--reading-width) !important;
|
||
top: calc(
|
||
var(--gic-premium-top, 0px)
|
||
+ var(--gic-premium-hero-h, 0px)
|
||
+ var(--gic-premium-follow-h, 0px)
|
||
- 1px
|
||
) !important;
|
||
z-index: 70 !important;
|
||
display: none !important;
|
||
flex-wrap: nowrap !important;
|
||
gap: 6px !important;
|
||
overflow-x: auto !important;
|
||
overflow-y: hidden !important;
|
||
scrollbar-width: none !important;
|
||
-webkit-overflow-scrolling: touch !important;
|
||
margin: 0 !important;
|
||
padding: 6px 8px 7px !important;
|
||
border-radius: 0 0 12px 12px !important;
|
||
opacity: 0 !important;
|
||
visibility: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #gic-follow-letters::-webkit-scrollbar{
|
||
display: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #gic-follow-letters a{
|
||
flex: 0 0 auto !important;
|
||
min-width: 28px !important;
|
||
height: 28px !important;
|
||
padding: 0 9px !important;
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.gic-premium-letters-on #gic-follow-letters{
|
||
display: flex !important;
|
||
opacity: 1 !important;
|
||
visibility: visible !important;
|
||
pointer-events: auto !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact .gic-section,
|
||
body.is-index-complet-page.gic-premium-compact .gic-group,
|
||
body.is-index-complet-page.gic-premium-compact .glossary-portal-section{
|
||
scroll-margin-top: calc(var(--gic-premium-top, 0px) + var(--gic-stack-h, 0px) + 18px) !important;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 761px) and (max-width: 980px){
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero,
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-page-hero{
|
||
padding: 8px 12px 8px !important;
|
||
border-radius: 16px 16px 0 0 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero h1{
|
||
font-size: clamp(1.48rem, 3vw, 1.82rem) !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed:not(.glossary-portal-hero-expanded) .glossary-portal-hero__intro{
|
||
font-size: .76rem !important;
|
||
line-height: 1.14 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .rf-h2{
|
||
font-size: .86rem !important;
|
||
}
|
||
}
|
||
|
||
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero,
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-page-hero{
|
||
padding: 5px 8px 5px !important;
|
||
row-gap: 2px !important;
|
||
border-radius: 12px 12px 0 0 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed .glossary-portal-hero h1{
|
||
font-size: clamp(1rem, 3vw, 1.22rem) !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact.glossary-portal-hero-condensed:not(.glossary-portal-hero-expanded) .glossary-portal-hero__intro{
|
||
display: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #reading-follow .reading-follow__inner{
|
||
padding-top: 4px !important;
|
||
padding-bottom: 4px !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #gic-follow-letters{
|
||
padding-top: 4px !important;
|
||
padding-bottom: 5px !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-premium-compact #gic-follow-letters a{
|
||
min-width: 24px !important;
|
||
height: 24px !important;
|
||
padding: 0 7px !important;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<script is:inline>
|
||
/*
|
||
INDEX COMPLET — FOLLOW LABEL ET STABILITÉ DESKTOP
|
||
|
||
Sur cette page, les sections alphabétiques A/B/C… ne doivent pas
|
||
devenir le titre du reading-follow : la lettre active est déjà
|
||
portée par la barre alphabétique.
|
||
*/
|
||
(() => {
|
||
const boot = () => {
|
||
const body = document.body;
|
||
const follow = document.getElementById("reading-follow");
|
||
const inner = follow?.querySelector(".reading-follow__inner");
|
||
|
||
if (!body || !follow || !inner) return;
|
||
|
||
const LETTER_RE = /^[A-ZÀÂÄÇÉÈÊËÎÏÔÖÙÛÜŸ]$/i;
|
||
|
||
const normalize = () => {
|
||
if (!body.classList.contains("is-index-complet-page")) return;
|
||
|
||
const h1 = inner.querySelector(".rf-h1");
|
||
const h2 = inner.querySelector(".rf-h2");
|
||
const h3 = inner.querySelector(".rf-h3");
|
||
|
||
const txt = (h2?.textContent || "").replace(/\s+/g, " ").trim();
|
||
|
||
if (
|
||
h2 &&
|
||
(
|
||
LETTER_RE.test(txt) ||
|
||
body.classList.contains("gic-letters-docked") ||
|
||
body.classList.contains("gic-premium-letters-on")
|
||
)
|
||
) {
|
||
if (h1) h1.textContent = "Index complet du glossaire";
|
||
h2.textContent = "Index alphabétique";
|
||
if (h3) h3.textContent = "";
|
||
}
|
||
};
|
||
|
||
let raf = 0;
|
||
const schedule = () => {
|
||
if (raf) return;
|
||
raf = requestAnimationFrame(() => {
|
||
raf = 0;
|
||
normalize();
|
||
});
|
||
};
|
||
|
||
const observer = new MutationObserver(schedule);
|
||
|
||
observer.observe(body, {
|
||
attributes: true,
|
||
attributeFilter: ["class"],
|
||
});
|
||
|
||
observer.observe(inner, {
|
||
childList: true,
|
||
subtree: true,
|
||
characterData: true,
|
||
});
|
||
|
||
window.addEventListener("scroll", schedule, { passive: true });
|
||
window.addEventListener("resize", schedule);
|
||
window.addEventListener("pageshow", schedule);
|
||
|
||
schedule();
|
||
};
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
||
} else {
|
||
boot();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<style is:global>
|
||
/* INDEX COMPLET — FOLLOW LABEL ET STABILITÉ DESKTOP */
|
||
|
||
@media (min-width: 981px){
|
||
body.is-index-complet-page.glossary-portal-follow-on #reading-follow{
|
||
top: calc(
|
||
var(--glossary-sticky-top, var(--sticky-header-h, 0px))
|
||
+ var(--glossary-local-sticky-h, 0px)
|
||
- 1px
|
||
) !important;
|
||
z-index: 71 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-letters-docked #gic-follow-letters{
|
||
top: calc(
|
||
var(--glossary-sticky-top, var(--sticky-header-h, 0px))
|
||
+ var(--glossary-local-sticky-h, 0px)
|
||
+ var(--followbar-h, 0px)
|
||
- 1px
|
||
) !important;
|
||
z-index: 70 !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-letters-docked #reading-follow .rf-h2{
|
||
white-space: nowrap !important;
|
||
overflow: hidden !important;
|
||
text-overflow: ellipsis !important;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<script is:inline>
|
||
/*
|
||
INDEX COMPLET — DESKTOP FOLLOW GATE
|
||
|
||
Le reading-follow ne doit pas apparaître en haut de page.
|
||
Il devient visible seulement lorsque le hero est effectivement condensé.
|
||
*/
|
||
(() => {
|
||
const boot = () => {
|
||
const body = document.body;
|
||
const hero = document.querySelector("[data-glossary-portal-hero]");
|
||
const follow = document.getElementById("reading-follow");
|
||
|
||
if (!body || !hero || !follow) return;
|
||
|
||
const mqDesktop = window.matchMedia("(min-width: 981px)");
|
||
|
||
const sync = () => {
|
||
if (!mqDesktop.matches) {
|
||
body.classList.remove("gic-desktop-follow-gated");
|
||
return;
|
||
}
|
||
|
||
const condensed = body.classList.contains("glossary-portal-hero-condensed");
|
||
body.classList.toggle("gic-desktop-follow-gated", !condensed);
|
||
|
||
if (!condensed) {
|
||
follow.classList.remove("is-on");
|
||
follow.setAttribute("aria-hidden", "true");
|
||
}
|
||
};
|
||
|
||
let raf = 0;
|
||
const schedule = () => {
|
||
if (raf) return;
|
||
raf = requestAnimationFrame(() => {
|
||
raf = 0;
|
||
sync();
|
||
});
|
||
};
|
||
|
||
const observer = new MutationObserver(schedule);
|
||
observer.observe(body, {
|
||
attributes: true,
|
||
attributeFilter: ["class"],
|
||
});
|
||
|
||
window.addEventListener("scroll", schedule, { passive: true });
|
||
window.addEventListener("resize", schedule);
|
||
window.addEventListener("pageshow", schedule);
|
||
|
||
if (mqDesktop.addEventListener) mqDesktop.addEventListener("change", schedule);
|
||
else if (mqDesktop.addListener) mqDesktop.addListener(schedule);
|
||
|
||
schedule();
|
||
};
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
||
} else {
|
||
boot();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<style is:global>
|
||
/* INDEX COMPLET — DESKTOP FOLLOW GATE */
|
||
|
||
@media (min-width: 981px){
|
||
body.is-index-complet-page.gic-desktop-follow-gated #reading-follow,
|
||
body.is-index-complet-page.gic-desktop-follow-gated #reading-follow .reading-follow__inner{
|
||
opacity: 0 !important;
|
||
visibility: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
|
||
body.is-index-complet-page.gic-desktop-follow-gated #gic-follow-letters{
|
||
opacity: 0 !important;
|
||
visibility: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<script is:inline>
|
||
/*
|
||
INDEX COMPLET — AUTO-CENTER ACTIVE LETTER
|
||
|
||
Sur mobile, la barre alphabétique horizontale doit suivre le lecteur :
|
||
la lettre active est automatiquement recentrée dans gic-follow-letters.
|
||
*/
|
||
(() => {
|
||
const boot = () => {
|
||
const body = document.body;
|
||
const lettersFollow = document.getElementById("gic-follow-letters");
|
||
|
||
if (!body || !lettersFollow) return;
|
||
|
||
const mqCompact = window.matchMedia("(max-width: 760px)");
|
||
|
||
let lastHref = "";
|
||
let raf = 0;
|
||
|
||
const centerActiveLetter = () => {
|
||
raf = 0;
|
||
|
||
if (!mqCompact.matches) return;
|
||
if (!body.classList.contains("is-index-complet-page")) return;
|
||
if (!body.classList.contains("gic-premium-letters-on")) return;
|
||
|
||
const active =
|
||
lettersFollow.querySelector('a[aria-current="true"]') ||
|
||
lettersFollow.querySelector("a.is-active");
|
||
|
||
if (!active) return;
|
||
|
||
const href = active.getAttribute("href") || "";
|
||
const force = href !== lastHref;
|
||
lastHref = href;
|
||
|
||
const containerRect = lettersFollow.getBoundingClientRect();
|
||
const activeRect = active.getBoundingClientRect();
|
||
|
||
const activeCenter =
|
||
activeRect.left - containerRect.left + lettersFollow.scrollLeft + activeRect.width / 2;
|
||
|
||
const target =
|
||
activeCenter - lettersFollow.clientWidth / 2;
|
||
|
||
const max =
|
||
lettersFollow.scrollWidth - lettersFollow.clientWidth;
|
||
|
||
const next = Math.max(0, Math.min(max, Math.round(target)));
|
||
|
||
if (force || Math.abs(lettersFollow.scrollLeft - next) > 6) {
|
||
lettersFollow.scrollTo({
|
||
left: next,
|
||
behavior: "smooth",
|
||
});
|
||
}
|
||
};
|
||
|
||
const schedule = () => {
|
||
if (raf) return;
|
||
raf = requestAnimationFrame(centerActiveLetter);
|
||
};
|
||
|
||
const observer = new MutationObserver(schedule);
|
||
|
||
observer.observe(lettersFollow, {
|
||
subtree: true,
|
||
attributes: true,
|
||
attributeFilter: ["class", "aria-current"],
|
||
});
|
||
|
||
observer.observe(body, {
|
||
attributes: true,
|
||
attributeFilter: ["class"],
|
||
});
|
||
|
||
window.addEventListener("scroll", schedule, { passive: true });
|
||
window.addEventListener("resize", schedule);
|
||
window.addEventListener("pageshow", schedule);
|
||
|
||
if (mqCompact.addEventListener) mqCompact.addEventListener("change", schedule);
|
||
else if (mqCompact.addListener) mqCompact.addListener(schedule);
|
||
|
||
schedule();
|
||
};
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
||
} else {
|
||
boot();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
</GlossaryLayout>
|
||
|
||
<style>
|
||
.gic-page{
|
||
--gic-follow-letters-offset: 0px;
|
||
padding: var(--portal-page-pad-top, 8px) 0 var(--portal-page-pad-bottom, 24px);
|
||
}
|
||
|
||
.gic-aside-stack{
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.gic-aside__block{
|
||
border: 1px solid rgba(127,127,127,0.22);
|
||
border-radius: 15px;
|
||
padding: 11px 12px;
|
||
background: rgba(127,127,127,0.05);
|
||
}
|
||
|
||
.gic-aside__heading{
|
||
margin: 0 0 8px;
|
||
font-size: 13.5px;
|
||
line-height: 1.25;
|
||
font-weight: 800;
|
||
opacity: .92;
|
||
}
|
||
|
||
.gic-aside__pills{
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
}
|
||
|
||
.gic-aside__pill{
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 3px 8px;
|
||
border: 1px solid rgba(127,127,127,0.24);
|
||
border-radius: 999px;
|
||
background: rgba(127,127,127,0.04);
|
||
font-size: 11.5px;
|
||
line-height: 1.25;
|
||
opacity: .9;
|
||
}
|
||
|
||
.gic-aside__note{
|
||
margin: 8px 0 0;
|
||
font-size: 11.5px;
|
||
line-height: 1.4;
|
||
opacity: .8;
|
||
}
|
||
|
||
.gic-letters{
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 7px;
|
||
margin-top: 12px;
|
||
}
|
||
|
||
.gic-letters a,
|
||
.gic-follow-letters a{
|
||
min-width: 32px;
|
||
text-align: center;
|
||
border: 1px solid rgba(127,127,127,0.24);
|
||
border-radius: 9px;
|
||
padding: 4px 7px;
|
||
text-decoration: none;
|
||
transition:
|
||
transform 120ms ease,
|
||
background 120ms ease,
|
||
border-color 120ms ease,
|
||
box-shadow 120ms ease,
|
||
color 120ms ease;
|
||
}
|
||
|
||
.gic-letters a:hover,
|
||
.gic-follow-letters a:hover{
|
||
transform: translateY(-1px);
|
||
background: rgba(127,127,127,0.08);
|
||
border-color: rgba(0,217,255,0.16);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.gic-letters a.is-active,
|
||
.gic-follow-letters a.is-active,
|
||
.gic-letters a[aria-current="true"],
|
||
.gic-follow-letters a[aria-current="true"]{
|
||
border-color: rgba(0,217,255,0.34);
|
||
background:
|
||
linear-gradient(180deg, rgba(0,217,255,0.14), rgba(0,217,255,0.06)),
|
||
rgba(127,127,127,0.10);
|
||
color: var(--glossary-accent, #00d9ff);
|
||
box-shadow:
|
||
inset 0 1px 0 rgba(255,255,255,0.05),
|
||
0 0 0 1px rgba(0,217,255,0.06);
|
||
}
|
||
|
||
.gic-follow-letters{
|
||
position: fixed;
|
||
left: var(--reading-left);
|
||
width: var(--reading-width);
|
||
box-sizing: border-box;
|
||
z-index: 59;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 7px;
|
||
padding: 7px 10px 9px;
|
||
border: 1px solid rgba(127,127,127,.20);
|
||
border-top: 0;
|
||
border-radius: 0 0 12px 12px;
|
||
background: rgba(255,255,255,.86);
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
box-shadow: 0 8px 18px rgba(0,0,0,.06);
|
||
opacity: 0;
|
||
transform: translateY(-6px);
|
||
pointer-events: none;
|
||
transition: opacity 160ms ease, transform 160ms ease;
|
||
}
|
||
|
||
:global(body.is-index-complet-page.gic-letters-docked .gic-follow-letters){
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
pointer-events: auto;
|
||
}
|
||
|
||
:global(body.is-index-complet-page.gic-letters-docked #reading-follow .reading-follow__inner){
|
||
border-bottom-left-radius: 0;
|
||
border-bottom-right-radius: 0;
|
||
}
|
||
|
||
.gic-groups{
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 22px;
|
||
}
|
||
|
||
.gic-group{
|
||
scroll-margin-top: calc(
|
||
var(--sticky-offset-px, 96px) + 28px + var(--gic-follow-letters-offset, 0px)
|
||
);
|
||
}
|
||
|
||
.gic-section{
|
||
margin-top: 28px;
|
||
}
|
||
|
||
.gic-section__head{
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
gap: 10px;
|
||
flex-wrap: wrap;
|
||
margin-bottom: 8px;
|
||
scroll-margin-top: calc(
|
||
var(--sticky-offset-px, 96px) + 24px + var(--gic-follow-letters-offset, 0px)
|
||
);
|
||
}
|
||
|
||
.gic-section__head h2{
|
||
margin: 0;
|
||
scroll-margin-top: calc(
|
||
var(--sticky-offset-px, 96px) + 28px + var(--gic-follow-letters-offset, 0px)
|
||
);
|
||
}
|
||
|
||
.gic-section__count{
|
||
font-size: 13px;
|
||
opacity: .72;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.gic-list{
|
||
display: grid;
|
||
gap: 10px;
|
||
}
|
||
|
||
.gic-item{
|
||
border: 1px solid rgba(127,127,127,0.20);
|
||
border-radius: 15px;
|
||
padding: 13px 14px;
|
||
background: rgba(127,127,127,0.04);
|
||
}
|
||
|
||
.gic-term{
|
||
display: inline-block;
|
||
font-weight: 800;
|
||
font-size: 1rem;
|
||
line-height: 1.28;
|
||
text-decoration: none;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.gic-def{
|
||
margin: 0 0 7px;
|
||
font-size: 13.5px;
|
||
line-height: 1.46;
|
||
opacity: .94;
|
||
}
|
||
|
||
.gic-meta{
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
margin: 0;
|
||
font-size: 11.5px;
|
||
opacity: .78;
|
||
}
|
||
|
||
.gic-meta span{
|
||
border: 1px solid rgba(127,127,127,0.20);
|
||
border-radius: 999px;
|
||
padding: 2px 7px;
|
||
}
|
||
|
||
.gic-cards{
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||
gap: var(--portal-grid-gap, 12px);
|
||
margin-top: 12px;
|
||
}
|
||
|
||
.gic-card{
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
padding: var(--portal-card-pad-y, 14px) var(--portal-card-pad-x, 16px);
|
||
border: 1px solid rgba(127,127,127,0.22);
|
||
border-radius: var(--portal-card-radius, 16px);
|
||
background: rgba(127,127,127,0.05);
|
||
text-decoration: none;
|
||
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
|
||
}
|
||
|
||
.gic-card:hover{
|
||
transform: translateY(-1px);
|
||
background: rgba(127,127,127,0.08);
|
||
border-color: rgba(0,217,255,0.16);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.gic-card strong{
|
||
font-size: var(--portal-card-title-size, 15px);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.gic-card span{
|
||
font-size: var(--portal-card-text-size, 14px);
|
||
line-height: var(--portal-card-text-lh, 1.45);
|
||
opacity: .92;
|
||
}
|
||
|
||
@media (max-width: 860px){
|
||
.gic-follow-letters{
|
||
display: none !important;
|
||
}
|
||
|
||
.gic-aside-stack{
|
||
gap: 10px;
|
||
}
|
||
|
||
.gic-aside__block{
|
||
border-radius: 14px;
|
||
padding: 10px 11px;
|
||
}
|
||
|
||
.gic-aside__heading{
|
||
margin-bottom: 7px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.gic-aside__pill{
|
||
padding: 3px 7px;
|
||
font-size: 11px;
|
||
}
|
||
|
||
.gic-aside__note{
|
||
font-size: 11px;
|
||
line-height: 1.34;
|
||
}
|
||
|
||
.gic-letters{
|
||
gap: 6px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.gic-letters a{
|
||
min-width: 30px;
|
||
padding: 4px 6px;
|
||
border-radius: 8px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.gic-groups{
|
||
gap: 18px;
|
||
}
|
||
|
||
.gic-section{
|
||
margin-top: 22px;
|
||
}
|
||
|
||
.gic-item{
|
||
border-radius: 14px;
|
||
padding: 12px 12px;
|
||
}
|
||
|
||
.gic-term{
|
||
font-size: .96rem;
|
||
}
|
||
|
||
.gic-def{
|
||
font-size: 13px;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.gic-meta{
|
||
gap: 5px;
|
||
font-size: 11px;
|
||
}
|
||
|
||
.gic-meta span{
|
||
padding: 2px 6px;
|
||
}
|
||
|
||
.gic-cards{
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||
.gic-follow-letters{
|
||
display: none !important;
|
||
}
|
||
|
||
.gic-aside-stack{
|
||
gap: 8px;
|
||
}
|
||
|
||
.gic-aside__block{
|
||
border-radius: 13px;
|
||
padding: 9px 10px;
|
||
}
|
||
|
||
.gic-aside__heading{
|
||
margin-bottom: 6px;
|
||
font-size: 12.5px;
|
||
}
|
||
|
||
.gic-aside__pill{
|
||
padding: 2px 7px;
|
||
font-size: 10.5px;
|
||
}
|
||
|
||
.gic-aside__note{
|
||
font-size: 10.5px;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.gic-letters{
|
||
gap: 5px;
|
||
margin-top: 9px;
|
||
}
|
||
|
||
.gic-letters a{
|
||
min-width: 28px;
|
||
padding: 3px 6px;
|
||
border-radius: 8px;
|
||
font-size: 11.5px;
|
||
}
|
||
|
||
.gic-groups{
|
||
gap: 16px;
|
||
}
|
||
|
||
.gic-section{
|
||
margin-top: 18px;
|
||
}
|
||
|
||
.gic-section__head{
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.gic-item{
|
||
border-radius: 13px;
|
||
padding: 10px 11px;
|
||
}
|
||
|
||
.gic-term{
|
||
font-size: .93rem;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.gic-def{
|
||
margin-bottom: 6px;
|
||
font-size: 12.5px;
|
||
line-height: 1.34;
|
||
}
|
||
|
||
.gic-meta{
|
||
gap: 4px;
|
||
font-size: 10.5px;
|
||
}
|
||
|
||
.gic-meta span{
|
||
padding: 1px 6px;
|
||
}
|
||
|
||
.gic-cards{
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark){
|
||
.gic-aside__block,
|
||
.gic-aside__pill,
|
||
.gic-item,
|
||
.gic-card{
|
||
background: rgba(255,255,255,0.04);
|
||
}
|
||
|
||
.gic-follow-letters{
|
||
background: rgba(0,0,0,.58);
|
||
box-shadow: 0 10px 22px rgba(0,0,0,.18);
|
||
}
|
||
|
||
.gic-letters a:hover,
|
||
.gic-follow-letters a:hover,
|
||
.gic-card:hover{
|
||
background: rgba(255,255,255,0.07);
|
||
}
|
||
|
||
.gic-letters a.is-active,
|
||
.gic-follow-letters a.is-active,
|
||
.gic-letters a[aria-current="true"],
|
||
.gic-follow-letters a[aria-current="true"]{
|
||
background:
|
||
linear-gradient(180deg, rgba(0,217,255,0.18), rgba(0,217,255,0.08)),
|
||
rgba(255,255,255,0.06);
|
||
}
|
||
}
|
||
|
||
:global(body.is-index-complet-page #reading-follow){
|
||
z-index: 10;
|
||
}
|
||
|
||
@media (max-width: 860px){
|
||
:global(body.is-index-complet-page #reading-follow),
|
||
:global(body.is-index-complet-page #reading-follow .reading-follow__inner){
|
||
display: none !important;
|
||
opacity: 0 !important;
|
||
visibility: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
|
||
:global(body.is-index-complet-page){
|
||
--followbar-h: 0px !important;
|
||
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||
}
|
||
}
|
||
|
||
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||
:global(body.is-index-complet-page #reading-follow),
|
||
:global(body.is-index-complet-page #reading-follow .reading-follow__inner){
|
||
display: none !important;
|
||
opacity: 0 !important;
|
||
visibility: hidden !important;
|
||
pointer-events: none !important;
|
||
}
|
||
|
||
:global(body.is-index-complet-page){
|
||
--followbar-h: 0px !important;
|
||
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||
}
|
||
}
|
||
|
||
</style> |