Merge pull request 'feat(glossaire): harmonize portal pages and sticky reading ux' (#298) from feat/glossaire-portal-polish-final into main
All checks were successful
Proposer Apply (Queue) / apply-proposer (push) Successful in 27s
Deploy staging+live (annotations) / deploy (push) Successful in 10m51s
SMOKE / smoke (push) Successful in 7s
CI / build-and-anchors (push) Successful in 43s

Reviewed-on: #298
This commit was merged in pull request #298.
This commit is contained in:
2026-03-26 13:01:46 +01:00
9 changed files with 714 additions and 625 deletions

View File

@@ -0,0 +1,87 @@
---
export interface Props {
href: string;
label: string;
icon?: string;
className?: string;
}
const {
href,
label,
icon = "↗",
className,
} = Astro.props;
---
<a class:list={["glossary-portal-cta", className]} href={href}>
<span>{label}</span>
<span aria-hidden="true">{icon}</span>
</a>
<style>
.glossary-portal-cta{
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
min-height: 40px;
padding: 0 14px;
border: 1px solid rgba(0,217,255,0.24);
border-radius: 999px;
background:
linear-gradient(180deg, rgba(0,217,255,0.10), rgba(0,217,255,0.04)),
rgba(127,127,127,0.06);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.05),
0 0 0 1px rgba(0,217,255,0.04);
text-decoration: none;
font-size: 12px;
font-weight: 800;
letter-spacing: .01em;
white-space: nowrap;
transition:
transform 120ms ease,
background 120ms ease,
border-color 120ms ease,
box-shadow 120ms ease;
}
.glossary-portal-cta:hover{
transform: translateY(-1px);
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.08);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.06),
0 0 0 1px rgba(0,217,255,0.08),
0 10px 28px rgba(0,0,0,0.18);
text-decoration: none;
}
.glossary-portal-cta:focus-visible{
outline: 2px solid rgba(0,217,255,0.28);
outline-offset: 4px;
}
@media (max-width: 720px){
.glossary-portal-cta{
width: 100%;
}
}
@media (prefers-color-scheme: dark){
.glossary-portal-cta{
background:
linear-gradient(180deg, rgba(0,217,255,0.12), rgba(0,217,255,0.05)),
rgba(255,255,255,0.04);
}
.glossary-portal-cta:hover{
background:
linear-gradient(180deg, rgba(0,217,255,0.16), rgba(0,217,255,0.07)),
rgba(255,255,255,0.06);
}
}
</style>

View File

@@ -0,0 +1,96 @@
---
export interface Props {
id?: string;
title: string;
count?: string;
intro?: string;
surface?: boolean;
className?: string;
}
const {
id,
title,
count,
intro,
surface = false,
className,
} = Astro.props;
---
<div
class:list={[
"glossary-portal-panel",
surface && "glossary-portal-panel--surface",
className,
]}
>
<div class="glossary-portal-panel__head">
<h3 id={id}>{title}</h3>
{count && <span class="glossary-portal-panel__count">{count}</span>}
</div>
{intro && <p class="glossary-portal-panel__intro">{intro}</p>}
<slot />
</div>
<style>
.glossary-portal-panel{
display: grid;
gap: 12px;
}
.glossary-portal-panel--surface{
padding: 18px 18px 16px;
border: 1px solid var(--glossary-border, rgba(127,127,127,0.18));
border-radius: 18px;
background:
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)),
var(--glossary-bg-soft, rgba(127,127,127,0.035));
}
.glossary-portal-panel__head{
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
.glossary-portal-panel__head h3{
margin: 0;
font-size: 15px;
line-height: 1.3;
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 36px);
}
.glossary-portal-panel__count{
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 10px;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 999px;
font-size: 12px;
line-height: 1.2;
opacity: .78;
white-space: nowrap;
}
.glossary-portal-panel__intro{
max-width: 78ch;
margin: 0;
font-size: 14px;
line-height: 1.5;
opacity: .9;
}
@media (prefers-color-scheme: dark){
.glossary-portal-panel--surface{
background:
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)),
rgba(255,255,255,0.04);
}
}
</style>

View File

@@ -4,6 +4,7 @@ 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 GlossaryPortalPanel from "../../components/GlossaryPortalPanel.astro";
import { getCollection } from "astro:content";
import {
buildGlossaryBySlug,
@@ -246,20 +247,14 @@ const prolongerLinks = [
intro="Ces diagnostics entrent en résonance avec dautres notions et paradigmes qui permettent de préciser les mécanismes de fermeture, de capture, dopacification ou de désajustement de la régulation."
>
{otherEntries.length > 0 && (
<div class="dyna-block dyna-block--panel">
<div class="dyna-block__head">
<h3 id="notions-et-diagnostics-lies">Notions et diagnostics liés</h3>
<span class="dyna-block__count">
{otherCount} entrée{otherCount > 1 ? "s" : ""}
</span>
</div>
<p class="dyna-block__intro">
Ces entrées prolongent lanalyse des dérives archicratiques vers
des questions dempêchement, dinvisibilisation, de fermeture ou
de capture de la scène régulatrice.
</p>
<GlossaryPortalPanel
id="notions-et-diagnostics-lies"
title="Notions et diagnostics liés"
count={`${otherCount} entrée${otherCount > 1 ? "s" : ""}`}
intro="Ces entrées prolongent lanalyse des dérives archicratiques vers des questions dempêchement, dinvisibilisation, de fermeture ou de capture de la scène régulatrice."
surface={true}
className="dyna-block"
>
<div class="dyna-cards">
{otherEntries.map((entry) => (
<a class="dyna-card" href={hrefOf(entry)}>
@@ -274,24 +269,18 @@ const prolongerLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{paradigmEntries.length > 0 && (
<div class="dyna-block dyna-block--panel">
<div class="dyna-block__head">
<h3 id="paradigmes-mobilises">Paradigmes mobilisés</h3>
<span class="dyna-block__count">
{paradigmCount} paradigme{paradigmCount > 1 ? "s" : ""}
</span>
</div>
<p class="dyna-block__intro">
Ces paradigmes servent de ressources comparatives pour penser les
processus de rigidification, dautonomisation et dopacification
des régimes de régulation.
</p>
<GlossaryPortalPanel
id="paradigmes-mobilises"
title="Paradigmes mobilisés"
count={`${paradigmCount} paradigme${paradigmCount > 1 ? "s" : ""}`}
intro="Ces paradigmes servent de ressources comparatives pour penser les processus de rigidification, dautonomisation et dopacification des régimes de régulation."
surface={true}
className="dyna-block"
>
<div class="dyna-cards">
{paradigmEntries.map((entry) => (
<a class="dyna-card" href={hrefOf(entry)}>
@@ -306,7 +295,7 @@ const prolongerLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
</GlossaryPortalSection>
)}
@@ -419,52 +408,6 @@ const prolongerLinks = [
margin-top: 22px;
}
.dyna-block--panel{
padding: 18px 18px 16px;
border: 1px solid rgba(127,127,127,0.18);
border-radius: 18px;
background:
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)),
rgba(127,127,127,0.035);
}
.dyna-block__head{
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 8px;
}
.dyna-block h3{
margin: 0;
font-size: 15px;
line-height: 1.3;
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 36px);
}
.dyna-block__count{
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 10px;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 999px;
font-size: 12px;
line-height: 1.2;
opacity: .78;
white-space: nowrap;
}
.dyna-block__intro{
max-width: 78ch;
margin: 0 0 12px;
font-size: 14px;
line-height: 1.5;
opacity: .9;
}
.dyna-cards{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));

View File

@@ -8,7 +8,6 @@ import { getCollection } from "astro:content";
import { hrefOfGlossaryEntry } from "../../lib/glossary";
const entries = await getCollection("glossaire");
const hrefOf = hrefOfGlossaryEntry;
const collator = new Intl.Collator("fr", { sensitivity: "base", numeric: true });
@@ -79,8 +78,7 @@ const prolongerLinks = [
{
href: "/glossaire/",
title: "Accueil du glossaire",
text:
"Revenir à la cartographie générale du système archicratique.",
text: "Revenir à la cartographie générale du système archicratique.",
},
{
href: "/glossaire/concepts-fondamentaux/",
@@ -109,13 +107,39 @@ const prolongerLinks = [
stickyMode="glossary-portal"
>
<Fragment slot="aside">
<GlossaryPortalAside
ariaLabel="Navigation de lindex 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-stack">
<GlossaryPortalAside
ariaLabel="Navigation de lindex 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 lindex">
<span class="gic-aside__pill">
{paradigmesCount} paradigme{paradigmesCount > 1 ? "s" : ""}
</span>
<span class="gic-aside__pill">
{doctrinesCount} doctrine{doctrinesCount > 1 ? "s" : ""}
</span>
<span class="gic-aside__pill">
{verbesCount} verbe{verbesCount > 1 ? "s" : ""}
</span>
<span class="gic-aside__pill">
{casIaCount} entrée{casIaCount > 1 ? "s" : ""} cas IA
</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">
@@ -138,21 +162,6 @@ const prolongerLinks = [
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."
>
<div class="gic-stats" aria-label="Repères de lindex">
<span class="gic-stat-pill">
{paradigmesCount} paradigme{paradigmesCount > 1 ? "s" : ""}
</span>
<span class="gic-stat-pill">
{doctrinesCount} doctrine{doctrinesCount > 1 ? "s" : ""}
</span>
<span class="gic-stat-pill">
{verbesCount} verbe{verbesCount > 1 ? "s" : ""}
</span>
<span class="gic-stat-pill">
{casIaCount} entrée{casIaCount > 1 ? "s" : ""} cas IA
</span>
</div>
<nav class="gic-letters" id="gic-letters-source" aria-label="Lettres de lindex">
{groupedAlpha.map(([letter]) => (
<a href={`#letter-${letter}`}>{letter}</a>
@@ -174,10 +183,10 @@ const prolongerLinks = [
<div class="gic-groups">
{groupedAlpha.map(([letter, items]) => (
<section class="gic-group" id={`letter-${letter}`}>
<div class="gic-group__head">
<h3>{letter}</h3>
<span class="gic-group__count">
<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>
@@ -185,7 +194,7 @@ const prolongerLinks = [
<div class="gic-list">
{items.map((entry) => (
<article class="gic-item">
<a class="gic-term" href={hrefOf(entry)}>
<a class="gic-term" href={hrefOfGlossaryEntry(entry)}>
{entry.data.term}
</a>
@@ -207,6 +216,7 @@ const prolongerLinks = [
id="prolonger-la-lecture"
title="Prolonger la lecture"
intro="Cet index intégral complète les portails thématiques sans sy 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) => (
@@ -217,90 +227,270 @@ const prolongerLinks = [
))}
</div>
</GlossaryPortalSection>
<GlossaryPortalSection
id="portee-densemble"
title="Portée densemble"
final={true}
>
<p>
Lindex complet ne remplace pas les parcours thématiques : il les complète.
Il offre une entrée alphabétique stable dans le lexique archicratique, afin
de retrouver rapidement une fiche, puis de repartir vers les grands portails
conceptuels, topologiques, dynamiques ou théoriques du glossaire.
</p>
</GlossaryPortalSection>
</section>
<GlossaryPortalStickySync
heroMoreId="gic-hero-more"
heroToggleId="gic-hero-toggle"
sectionHeadSelector=".glossary-portal-section__head, .gic-group__head"
/>
<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) return;
body.classList.add("is-index-complet-page");
if (!body || !root || !follow || !lettersSource || !lettersFollow || groupSections.length === 0) {
return;
}
if (!follow || !lettersSource || !lettersFollow) return;
const DOCKED_CLASS = "gic-letters-docked";
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)");
let raf = 0;
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
const EXTRA_GAP = 12;
const MAX_CORRECTION_PASSES = 8;
const hideFollowLetters = () => {
body.classList.remove(DOCKED_CLASS);
lettersFollow.hidden = true;
lettersFollow.setAttribute("aria-hidden", "true");
lettersFollow.style.top = "";
const sourceLinks = Array.from(lettersSource.querySelectorAll("a"));
const followLinks = Array.from(lettersFollow.querySelectorAll("a"));
const allLetterLinks = [...sourceLinks, ...followLinks];
body.classList.add(BODY_CLASS);
const computeFollowOn = () =>
!mqMobile.matches &&
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 sync = () => {
const syncFollowLettersTop = () => {
const inner = follow.querySelector(".reading-follow__inner");
const followIsOn =
!mqMobile.matches &&
follow.classList.contains("is-on") &&
follow.style.display !== "none" &&
follow.getAttribute("aria-hidden") !== "true";
if (!followIsOn) {
hideFollowLetters();
return;
}
const inner = follow.querySelector(".reading-follow__inner");
if (!inner) {
hideFollowLetters();
if (!followIsOn || !inner) {
lettersFollow.style.top = "";
return;
}
const followRect = follow.getBoundingClientRect();
const innerRect = inner.getBoundingClientRect();
const sourceRect = lettersSource.getBoundingClientRect();
const top = followRect.top + innerRect.height;
lettersFollow.style.top = `${Math.round(followRect.top + innerRect.height)}px`;
const shouldDock = sourceRect.top <= innerRect.bottom + 6;
body.classList.toggle(DOCKED_CLASS, shouldDock);
lettersFollow.hidden = !shouldDock;
lettersFollow.setAttribute("aria-hidden", shouldDock ? "false" : "true");
lettersFollow.style.top = `${Math.round(top)}px`;
};
const syncLettersDockState = () => {
if (mqMobile.matches || !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;
sync();
syncFollowLettersTop();
syncLettersDockState();
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,
@@ -308,9 +498,10 @@ const prolongerLinks = [
subtree: false,
});
window.addEventListener("scroll", schedule, { passive: true });
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(() => {});
@@ -322,7 +513,22 @@ const prolongerLinks = [
mqMobile.addListener(schedule);
}
if (reducedMotion.addEventListener) {
reducedMotion.addEventListener("change", schedule);
} else if (reducedMotion.addListener) {
reducedMotion.addListener(schedule);
}
setAnchorOffset(0);
schedule();
if (window.location.hash.startsWith("#letter-")) {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
scrollToLetterTarget(window.location.hash.slice(1));
});
});
}
};
if (document.readyState === "loading") {
@@ -336,28 +542,53 @@ const prolongerLinks = [
<style>
.gic-page{
--gic-follow-letters-offset: 0px;
padding: 8px 0 24px;
}
.gic-stats{
.gic-aside-stack{
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 14px;
flex-direction: column;
gap: 14px;
}
.gic-stat-pill{
.gic-aside__block{
border: 1px solid rgba(127,127,127,0.22);
border-radius: 16px;
padding: 12px;
background: rgba(127,127,127,0.05);
}
.gic-aside__heading{
margin: 0 0 10px;
font-size: 13px;
font-weight: 800;
opacity: .9;
}
.gic-aside__pills{
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.gic-aside__pill{
display: inline-flex;
align-items: center;
min-height: 30px;
padding: 0 11px;
border: 1px solid rgba(127,127,127,0.22);
padding: 4px 9px;
border: 1px solid rgba(127,127,127,0.24);
border-radius: 999px;
background: rgba(127,127,127,0.04);
font-size: 12px;
line-height: 1.2;
line-height: 1.3;
opacity: .9;
white-space: nowrap;
}
.gic-aside__note{
margin: 10px 0 0;
font-size: 12px;
line-height: 1.45;
opacity: .78;
}
.gic-letters{
@@ -378,7 +609,9 @@ const prolongerLinks = [
transition:
transform 120ms ease,
background 120ms ease,
border-color 120ms ease;
border-color 120ms ease,
box-shadow 120ms ease,
color 120ms ease;
}
.gic-letters a:hover,
@@ -389,28 +622,37 @@ const prolongerLinks = [
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: 8px;
padding: 8px 12px 10px;
border: 1px solid rgba(127,127,127,.20);
border-top: 0;
border-radius: 0 0 14px 14px;
background: rgba(255,255,255,.86);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: 0 10px 22px rgba(0,0,0,.06);
opacity: 0;
transform: translateY(-6px);
pointer-events: none;
@@ -423,7 +665,7 @@ const prolongerLinks = [
pointer-events: auto;
}
:global(body.is-index-complet-page.is-glossary-portal-page.glossary-portal-follow-on.gic-letters-docked #reading-follow .reading-follow__inner){
:global(body.is-index-complet-page.gic-letters-docked #reading-follow .reading-follow__inner){
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
@@ -432,33 +674,38 @@ const prolongerLinks = [
display: flex;
flex-direction: column;
gap: 28px;
margin-top: 28px;
}
.gic-group{
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 28px);
scroll-margin-top: calc(
var(--sticky-offset-px, 96px) + 28px + var(--gic-follow-letters-offset, 0px)
);
}
.gic-group h3{
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 28px);
.gic-section{
margin-top: 34px;
}
.gic-group__head{
.gic-section__head{
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 10px;
scroll-margin-top: calc(
var(--sticky-offset-px, 96px) + 28px + var(--gic-follow-letters-offset, 0px)
);
}
.gic-group__head h3{
.gic-section__head h2{
margin: 0;
font-size: clamp(1.15rem, 1.8vw, 1.35rem);
line-height: 1.2;
scroll-margin-top: calc(
var(--sticky-offset-px, 96px) + 28px + var(--gic-follow-letters-offset, 0px)
);
}
.gic-group__count{
.gic-section__count{
font-size: 13px;
opacity: .72;
white-space: nowrap;
@@ -478,11 +725,11 @@ const prolongerLinks = [
.gic-term{
display: inline-block;
margin-bottom: 6px;
font-weight: 800;
font-size: 1.04rem;
line-height: 1.3;
text-decoration: none;
margin-bottom: 6px;
}
.gic-def{
@@ -522,10 +769,7 @@ const prolongerLinks = [
border-radius: 16px;
background: rgba(127,127,127,0.05);
text-decoration: none;
transition:
transform 120ms ease,
background 120ms ease,
border-color 120ms ease;
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
}
.gic-card:hover{
@@ -553,21 +797,31 @@ const prolongerLinks = [
}
@media (prefers-color-scheme: dark){
.gic-stat-pill,
.gic-aside__block,
.gic-aside__pill,
.gic-item,
.gic-card,
.gic-follow-letters{
.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-follow-letters{
box-shadow: 0 10px 22px rgba(0,0,0,.18);
.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);
}
}
</style>

View File

@@ -274,6 +274,7 @@ const approfondirPortalItems = [
>
<GlossaryPortalGrid items={approfondirPortalItems} secondary={true} />
</GlossaryHomeSection>
</section>
<script is:inline>
(() => {

View File

@@ -4,6 +4,8 @@ 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 GlossaryPortalPanel from "../../components/GlossaryPortalPanel.astro";
import GlossaryPortalCta from "../../components/GlossaryPortalCta.astro";
import { getCollection } from "astro:content";
import {
buildGlossaryBySlug,
@@ -133,15 +135,15 @@ const doctrineEntries = resolveOrderedEntries([
const tensionEntries = resolveOrderedEntries([
"subsistance-vivante-et-captation-capitalistique",
"regulation-technique-et-legitimation-democratique",
"souverainetes-territoriales-et-interdependances-globales",
"memoire-symbolique-et-instantaneite-computationnelle",
"coexistence-ontologique-et-necessite-regulatrice",
"travail-vivant-et-abstraction-de-la-valeur",
"egalisation-normative-et-differenciation-singuliere",
"liberte-daction-et-regimes-de-securite-algorithmique",
"visibilite-mediatique-et-reconnaissance-symbolique",
"egalisation-normative-et-differenciation-singuliere",
"pluralite-natalite-action",
"technodiversite-et-cosmotechnie",
"regulation-technique-et-legitimation-democratique",
"souverainetes-territoriales-et-interdependances-globales",
"formes-de-vie-et-cadres-dhabitabilite",
"memoire-symbolique-et-instantaneite-computationnelle",
"coexistence-ontologique-et-necessite-regulatrice",
]);
const casIaEntries = resolveOrderedEntries([
@@ -366,20 +368,14 @@ const usefulLinks = [
intro="Le paradigme ne se réduit pas à un noyau abstrait. Il déploie une architecture interne faite de scènes, de topologies, de dynamiques, de pathologies, de figures et dopérateurs méthodologiques."
>
{sceneEntries.length > 0 && (
<div class="pa-block">
<div class="pa-block__head">
<h3 id="scenes-topologies-et-instituabilite">Scènes, topologies et instituabilité</h3>
<span class="pa-block__count">
{sceneEntries.length} entrée{sceneEntries.length > 1 ? "s" : ""}
</span>
</div>
<p class="pa-block__intro">
Le paradigme archicratique ne pense pas seulement ce qui régule,
mais aussi les lieux, les formats et les conditions par lesquels
cette régulation peut comparaître ou se dérober.
</p>
<GlossaryPortalPanel
id="scenes-topologies-et-instituabilite"
title="Scènes, topologies et instituabilité"
count={`${sceneEntries.length} entrée${sceneEntries.length > 1 ? "s" : ""}`}
intro="Le paradigme archicratique ne pense pas seulement ce qui régule, mais aussi les lieux, les formats et les conditions par lesquels cette régulation peut comparaître ou se dérober."
surface={true}
className="pa-block"
>
<div class="pa-cards">
{sceneEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -394,24 +390,18 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{dynamicEntries.length > 0 && (
<div class="pa-block">
<div class="pa-block__head">
<h3 id="dynamiques-et-pathologies">Dynamiques et pathologies</h3>
<span class="pa-block__count">
{dynamicEntries.length} entrée{dynamicEntries.length > 1 ? "s" : ""}
</span>
</div>
<p class="pa-block__intro">
Toute architecture de régulation se transforme, se ferme, se
dégrade ou se réouvre. Le paradigme ne décrit donc pas seulement
des formes, mais aussi leurs trajectoires.
</p>
<GlossaryPortalPanel
id="dynamiques-et-pathologies"
title="Dynamiques et pathologies"
count={`${dynamicEntries.length} entrée${dynamicEntries.length > 1 ? "s" : ""}`}
intro="Toute architecture de régulation se transforme, se ferme, se dégrade ou se réouvre. Le paradigme ne décrit donc pas seulement des formes, mais aussi leurs trajectoires."
surface={true}
className="pa-block"
>
<div class="pa-cards">
{dynamicEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -420,24 +410,18 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{methodEntries.length > 0 && (
<div class="pa-block">
<div class="pa-block__head">
<h3 id="figures-et-operateurs-methodologiques">Figures et opérateurs méthodologiques</h3>
<span class="pa-block__count">
{methodEntries.length} entrée{methodEntries.length > 1 ? "s" : ""}
</span>
</div>
<p class="pa-block__intro">
Le paradigme suppose enfin des figures, des qualifications et des
instruments danalyse capables de rendre la régulation lisible,
diagnosable, cartographiable et politiquement adressable.
</p>
<GlossaryPortalPanel
id="figures-et-operateurs-methodologiques"
title="Figures et opérateurs méthodologiques"
count={`${methodEntries.length} entrée${methodEntries.length > 1 ? "s" : ""}`}
intro="Le paradigme suppose enfin des figures, des qualifications et des instruments danalyse capables de rendre la régulation lisible, diagnosable, cartographiable et politiquement adressable."
surface={true}
className="pa-block"
>
<div class="pa-cards">
{methodEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -446,7 +430,7 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
</GlossaryPortalSection>
)}
@@ -455,6 +439,7 @@ const usefulLinks = [
<GlossaryPortalSection
id="constellation-theorique"
title="Constellation théorique"
count={`${constellationCount} entrée${constellationCount > 1 ? "s" : ""}`}
intro="Le paradigme archicratique souvre vers une constellation plus large : typologie des régimes de co-viabilité, traditions concurrentes ou complémentaires et doctrines fondatrices à partir desquelles ses déplacements deviennent plus nettement comparables."
>
<div class="pa-theory-hub">
@@ -491,29 +476,23 @@ const usefulLinks = [
</a>
</div>
<a class="pa-theory-button" href="/glossaire/paradigmes/">
<span>Ouvrir la cartographie théorique</span>
<span aria-hidden="true">↗</span>
</a>
<GlossaryPortalCta
href="/glossaire/paradigmes/"
label="Ouvrir la cartographie théorique"
className="pa-theory-hub__cta"
/>
</div>
</div>
{typologyEntries.length > 0 && (
<div class="pa-block pa-block--panel">
<div class="pa-block__head">
<h3 id="typologie-des-regimes-de-co-viabilite">Typologie des régimes de co-viabilité</h3>
<span class="pa-block__count">
{typologyEntries.length} entrée{typologyEntries.length > 1 ? "s" : ""}
</span>
</div>
<p class="pa-block__intro">
Le paradigme ne vaut pas seulement comme noyau conceptuel. Il
souvre aussi sur une typologie des formes de régulation et sur
les grandes matrices à partir desquelles les sociétés organisent
leur tenue collective.
</p>
<GlossaryPortalPanel
id="typologie-des-regimes-de-co-viabilite"
title="Typologie des régimes de co-viabilité"
count={`${typologyEntries.length} entrée${typologyEntries.length > 1 ? "s" : ""}`}
intro="Le paradigme ne vaut pas seulement comme noyau conceptuel. Il souvre aussi sur une typologie des formes de régulation et sur les grandes matrices à partir desquelles les sociétés organisent leur tenue collective."
surface={true}
className="pa-block"
>
<div class="pa-cards">
{typologyEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -522,25 +501,18 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{paradigmEntries.length > 0 && (
<div class="pa-block pa-block--panel">
<div class="pa-block__head">
<h3 id="paradigmes-mobilises">Paradigmes mobilisés</h3>
<span class="pa-block__count">
{featuredParadigmCount} repère{featuredParadigmCount > 1 ? "s" : ""} mis en avant
</span>
</div>
<p class="pa-block__intro">
Larchicratie ne sélabore pas dans un vide théorique. Elle
dialogue avec plusieurs paradigmes qui éclairent ses voisinages,
ses contrastes et ses points dappui. Le portail central en
retient ici quelques-uns, choisis pour leur portée comparative.
</p>
<GlossaryPortalPanel
id="paradigmes-mobilises"
title="Paradigmes mobilisés"
count={`${featuredParadigmCount} repère${featuredParadigmCount > 1 ? "s" : ""} mis en avant`}
intro="Larchicratie ne sélabore pas dans un vide théorique. Elle dialogue avec plusieurs paradigmes qui éclairent ses voisinages, ses contrastes et ses points dappui. Le portail central en retient ici quelques-uns, choisis pour leur portée comparative."
surface={true}
className="pa-block"
>
<div class="pa-cards">
{paradigmEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -555,25 +527,18 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{doctrineEntries.length > 0 && (
<div class="pa-block pa-block--panel">
<div class="pa-block__head">
<h3 id="doctrines-fondatrices">Doctrines fondatrices</h3>
<span class="pa-block__count">
{featuredDoctrineCount} repère{featuredDoctrineCount > 1 ? "s" : ""} mis en avant
</span>
</div>
<p class="pa-block__intro">
Certaines doctrines classiques continuent de servir de contrepoints
ou de points de départ obligés. Le paradigme archicratique les
reprend, les déplace et les resitue dans une écologie plus large
de la régulation.
</p>
<GlossaryPortalPanel
id="doctrines-fondatrices"
title="Doctrines fondatrices"
count={`${featuredDoctrineCount} repère${featuredDoctrineCount > 1 ? "s" : ""} mis en avant`}
intro="Certaines doctrines classiques continuent de servir de contrepoints ou de points de départ obligés. Le paradigme archicratique les reprend, les déplace et les resitue dans une écologie plus large de la régulation."
surface={true}
className="pa-block"
>
<div class="pa-cards">
{doctrineEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -588,7 +553,7 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
</GlossaryPortalSection>
)}
@@ -619,14 +584,13 @@ const usefulLinks = [
intro="Lun des intérêts majeurs du paradigme archicratique est de permettre des traductions institutionnelles concrètes. Dans le cas des systèmes dIA, il donne lieu à des dispositifs destinés à rouvrir les chaînes de décision, documenter les justifications et reconstruire de véritables scènes de comparution."
>
{casIaEntries.length > 0 && (
<div class="pa-block pa-block--panel">
<div class="pa-block__head">
<h3 id="traduction-contemporaine-cas-ia">Traduction contemporaine : Cas IA</h3>
<span class="pa-block__count">
{casIaEntries.length} dispositif{casIaEntries.length > 1 ? "s" : ""}
</span>
</div>
<GlossaryPortalPanel
id="traduction-contemporaine-cas-ia"
title="Traduction contemporaine : Cas IA"
count={`${casIaEntries.length} dispositif${casIaEntries.length > 1 ? "s" : ""}`}
surface={true}
className="pa-block"
>
<div class="pa-cards">
{casIaEntries.map((entry) => (
<a class="pa-card" href={hrefOf(entry)}>
@@ -635,18 +599,17 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{portalLinks.length > 0 && (
<div class="pa-block pa-block--panel">
<div class="pa-block__head">
<h3 id="portails-voisins-deja-stabilises">Portails voisins déjà stabilisés</h3>
<span class="pa-block__count">
{portalLinks.length} portail{portalLinks.length > 1 ? "s" : ""}
</span>
</div>
<GlossaryPortalPanel
id="portails-voisins-deja-stabilises"
title="Portails voisins déjà stabilisés"
count={`${portalLinks.length} portail${portalLinks.length > 1 ? "s" : ""}`}
surface={true}
className="pa-block"
>
<div class="pa-cards">
{portalLinks.map((item) => (
<a class="pa-card" href={item.href}>
@@ -655,7 +618,7 @@ const usefulLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
</GlossaryPortalSection>
)}
@@ -762,53 +725,6 @@ const usefulLinks = [
margin-top: 18px;
}
.pa-block--panel{
padding: 18px 18px 16px;
border: 1px solid rgba(127,127,127,0.18);
border-radius: 18px;
background:
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)),
rgba(127,127,127,0.035);
}
.pa-block__head{
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 8px;
}
.pa-block h3{
margin: 0;
font-size: 15px;
line-height: 1.3;
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 36px);
}
.pa-block__count{
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 10px;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 999px;
font-size: 12px;
line-height: 1.2;
opacity: .78;
white-space: nowrap;
background: rgba(127,127,127,0.04);
}
.pa-block__intro{
max-width: 78ch;
margin: 0 0 12px;
font-size: 14px;
line-height: 1.5;
opacity: .9;
}
.pa-cards{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
@@ -976,49 +892,8 @@ const usefulLinks = [
outline-offset: 3px;
}
.pa-theory-button{
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
min-height: 38px;
padding: 0 14px;
border: 1px solid rgba(0,217,255,0.24);
border-radius: 999px;
background:
linear-gradient(180deg, rgba(0,217,255,0.10), rgba(0,217,255,0.04)),
rgba(127,127,127,0.06);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.05),
0 0 0 1px rgba(0,217,255,0.04);
text-decoration: none;
font-size: 12px;
font-weight: 800;
letter-spacing: .01em;
white-space: nowrap;
transition:
transform 120ms ease,
background 120ms ease,
border-color 120ms ease,
box-shadow 120ms ease;
}
.pa-theory-button:hover{
transform: translateY(-1px);
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.08);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.06),
0 0 0 1px rgba(0,217,255,0.08),
0 10px 28px rgba(0,0,0,0.18);
text-decoration: none;
}
.pa-theory-button:focus-visible{
outline: 2px solid rgba(0,217,255,0.28);
outline-offset: 4px;
.pa-theory-hub__cta{
flex: 0 0 auto;
}
@media (max-width: 900px){
@@ -1026,7 +901,7 @@ const usefulLinks = [
align-items: stretch;
}
.pa-theory-button{
.pa-theory-hub__cta{
width: 100%;
}
}
@@ -1045,12 +920,6 @@ const usefulLinks = [
background: rgba(255,255,255,0.04);
}
.pa-block--panel{
background:
linear-gradient(180deg, rgba(255,255,255,0.03), rgba(255,255,255,0.015)),
rgba(255,255,255,0.025);
}
.pa-theory-hub{
background:
linear-gradient(180deg, rgba(255,255,255,0.03), rgba(255,255,255,0.015)),
@@ -1069,17 +938,5 @@ const usefulLinks = [
.pa-chip--link:hover{
background: rgba(0,217,255,0.08);
}
.pa-theory-button{
background:
linear-gradient(180deg, rgba(0,217,255,0.12), rgba(0,217,255,0.05)),
rgba(255,255,255,0.04);
}
.pa-theory-button:hover{
background:
linear-gradient(180deg, rgba(0,217,255,0.16), rgba(0,217,255,0.07)),
rgba(255,255,255,0.06);
}
}
</style>

View File

@@ -4,6 +4,7 @@ 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 GlossaryPortalPanel from "../../components/GlossaryPortalPanel.astro";
import { getCollection } from "astro:content";
import {
buildGlossaryBySlug,
@@ -224,20 +225,14 @@ const prolongerLinks = [
intro="Cette notion dialogue avec plusieurs diagnostics et paradigmes qui permettent den préciser la portée politique, symbolique et régulatrice."
>
{otherEntries.length > 0 && (
<div class="scene-block scene-block--panel">
<div class="scene-block__head">
<h3 id="notions-et-diagnostics-lies">Notions et diagnostics liés</h3>
<span class="scene-block__count">
{otherCount} entrée{otherCount > 1 ? "s" : ""}
</span>
</div>
<p class="scene-block__intro">
Ces entrées prolongent la scène dépreuve vers des questions
dinstituabilité, de fermeture, dempêchement ou de visibilité
de la régulation.
</p>
<GlossaryPortalPanel
id="notions-et-diagnostics-lies"
title="Notions et diagnostics liés"
count={`${otherCount} entrée${otherCount > 1 ? "s" : ""}`}
intro="Ces entrées prolongent la scène dépreuve vers des questions dinstituabilité, de fermeture, dempêchement ou de visibilité de la régulation."
surface={true}
className="scene-block"
>
<div class="scene-cards">
{otherEntries.map((entry) => (
<a class="scene-card" href={hrefOf(entry)}>
@@ -252,25 +247,18 @@ const prolongerLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
{paradigmEntries.length > 0 && (
<div class="scene-block scene-block--panel">
<div class="scene-block__head">
<h3 id="paradigmes-mobilises">Paradigmes mobilisés</h3>
<span class="scene-block__count">
{paradigmCount} paradigme{paradigmCount > 1 ? "s" : ""}
</span>
</div>
<p class="scene-block__intro">
Ces paradigmes servent de points dappui comparatifs pour mieux
comprendre ce qui, dans la scène archicratique, relève de la
conflictualité, de lapparition publique ou de la mise en litige
de la régulation.
</p>
<GlossaryPortalPanel
id="paradigmes-mobilises"
title="Paradigmes mobilisés"
count={`${paradigmCount} paradigme${paradigmCount > 1 ? "s" : ""}`}
intro="Ces paradigmes servent de points dappui comparatifs pour mieux comprendre ce qui, dans la scène archicratique, relève de la conflictualité, de lapparition publique ou de la mise en litige de la régulation."
surface={true}
className="scene-block"
>
<div class="scene-cards">
{paradigmEntries.map((entry) => (
<a class="scene-card" href={hrefOf(entry)}>
@@ -285,7 +273,7 @@ const prolongerLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
)}
</GlossaryPortalSection>
)}
@@ -388,56 +376,6 @@ const prolongerLinks = [
margin-top: 18px;
}
.scene-block--panel{
padding: 18px 18px 16px;
border: 1px solid rgba(127,127,127,0.18);
border-radius: 18px;
background:
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)),
rgba(127,127,127,0.035);
}
.scene-block + .scene-block{
margin-top: 22px;
}
.scene-block__head{
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 8px;
}
.scene-block h3{
margin: 0;
font-size: 15px;
line-height: 1.3;
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 36px);
}
.scene-block__count{
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 10px;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 999px;
font-size: 12px;
line-height: 1.2;
opacity: .78;
white-space: nowrap;
}
.scene-block__intro{
max-width: 78ch;
margin: 0 0 12px;
font-size: 14px;
line-height: 1.5;
opacity: .9;
}
.scene-cards{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
@@ -490,16 +428,8 @@ const prolongerLinks = [
opacity: .82;
}
@media (max-width: 720px){
.scene-block--panel{
padding: 16px;
border-radius: 16px;
}
}
@media (prefers-color-scheme: dark){
.scene-focus-card,
.scene-block--panel,
.scene-card{
background: rgba(255,255,255,0.04);
}

View File

@@ -4,6 +4,7 @@ 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 GlossaryPortalPanel from "../../components/GlossaryPortalPanel.astro";
import { getCollection } from "astro:content";
import {
buildGlossaryBySlug,
@@ -122,8 +123,6 @@ const irreducibleTensions = [
}));
const tensionsCount = irreducibleTensions.length;
const foundationCount = foundationEntries.length;
const resonanceCount = resonanceEntries.length;
const pageItems = [
{ href: "#orientation", label: "Orientation" },
@@ -247,23 +246,16 @@ const prolongerLinks = [
<GlossaryPortalSection
id="articulations-fondamentales"
title="Articulations fondamentales"
count={`${foundationCount} notion${foundationCount > 1 ? "s" : ""}`}
count={`${foundationEntries.length} notion${foundationEntries.length > 1 ? "s" : ""}`}
intro="Ces tensions ne prennent sens, dans le glossaire, quen relation avec quelques notions cardinales : la tension elle-même, la scène dépreuve, larchicration, la co-viabilité et larchicratie."
>
<div class="tir-block tir-block--panel">
<div class="tir-block__head">
<h3 id="noyau-structural">Noyau structural de la régulation</h3>
<span class="tir-block__count">
{foundationCount} entrée{foundationCount > 1 ? "s" : ""}
</span>
</div>
<p class="tir-block__intro">
Ces notions donnent la grammaire minimale à partir de laquelle les
tensions irréductibles peuvent être exposées, disputées et rendues
politiquement traitables.
</p>
<GlossaryPortalPanel
id="notions-cardinales"
title="Notions cardinales"
count={`${foundationEntries.length} repère${foundationEntries.length > 1 ? "s" : ""}`}
surface={true}
className="tir-block"
>
<div class="tir-link-cards">
{foundationEntries.map((entry) => (
<a class="tir-link-card" href={hrefOf(entry)}>
@@ -278,7 +270,7 @@ const prolongerLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
</GlossaryPortalSection>
)}
@@ -286,23 +278,16 @@ const prolongerLinks = [
<GlossaryPortalSection
id="resonances-theoriques"
title="Résonances théoriques"
count={`${resonanceCount} entrée${resonanceCount > 1 ? "s" : ""}`}
count={`${resonanceEntries.length} entrée${resonanceEntries.length > 1 ? "s" : ""}`}
intro="Plusieurs paradigmes déjà présents dans le glossaire permettent déclairer certains versants de ces tensions : gouvernementalité algorithmique, préemption, cosmopolitique, technodiversité, pharmacologie technique ou légitimation démocratique."
>
<div class="tir-block tir-block--panel">
<div class="tir-block__head">
<h3 id="points-dappui-comparatifs">Points dappui comparatifs</h3>
<span class="tir-block__count">
{resonanceCount} entrée{resonanceCount > 1 ? "s" : ""}
</span>
</div>
<p class="tir-block__intro">
Ces entrées ne remplacent pas la cartographie des tensions
irréductibles. Elles en éclairent certains versants en fournissant
des ressources danalyse déjà stabilisées ailleurs dans le glossaire.
</p>
<GlossaryPortalPanel
id="paradigmes-et-resonances"
title="Paradigmes et résonances"
count={`${resonanceEntries.length} entrée${resonanceEntries.length > 1 ? "s" : ""}`}
surface={true}
className="tir-block"
>
<div class="tir-link-cards">
{resonanceEntries.map((entry) => (
<a class="tir-link-card" href={hrefOf(entry)}>
@@ -317,7 +302,7 @@ const prolongerLinks = [
</a>
))}
</div>
</div>
</GlossaryPortalPanel>
</GlossaryPortalSection>
)}
@@ -385,6 +370,10 @@ const prolongerLinks = [
opacity: .92;
}
.tir-block{
margin-top: 18px;
}
.tir-cards{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
@@ -405,10 +394,7 @@ const prolongerLinks = [
.tir-card--link{
text-decoration: none;
transition:
transform 120ms ease,
background 120ms ease,
border-color 120ms ease;
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
}
.tir-card--link:hover{
@@ -438,56 +424,6 @@ const prolongerLinks = [
opacity: .92;
}
.tir-block{
margin-top: 18px;
}
.tir-block--panel{
padding: 18px 18px 16px;
border: 1px solid rgba(127,127,127,0.18);
border-radius: 18px;
background:
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)),
rgba(127,127,127,0.035);
}
.tir-block__head{
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 8px;
}
.tir-block h3{
margin: 0;
font-size: 15px;
line-height: 1.3;
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 36px);
}
.tir-block__count{
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 10px;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 999px;
font-size: 12px;
line-height: 1.2;
opacity: .78;
white-space: nowrap;
}
.tir-block__intro{
max-width: 78ch;
margin: 0 0 12px;
font-size: 14px;
line-height: 1.5;
opacity: .9;
}
.tir-link-cards{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
@@ -504,10 +440,7 @@ const prolongerLinks = [
border-radius: 16px;
background: rgba(127,127,127,0.05);
text-decoration: none;
transition:
transform 120ms ease,
background 120ms ease,
border-color 120ms ease;
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
}
.tir-link-card:hover{
@@ -534,17 +467,9 @@ const prolongerLinks = [
opacity: .72;
}
@media (max-width: 720px){
.tir-block--panel{
padding: 16px;
border-radius: 16px;
}
}
@media (prefers-color-scheme: dark){
.tir-note-card,
.tir-card,
.tir-block--panel,
.tir-link-card{
background: rgba(255,255,255,0.04);
}

View File

@@ -214,29 +214,29 @@ const usefulLinks = [
];
const prolongerLinks = [
{
href: "/glossaire/scene-depreuve/",
title: "Scène dépreuve",
text:
"Revenir à la notion-pivot de comparution, dexposition et de mise en discussion régulatrice.",
},
{
href: "/glossaire/scenes-archicratiques/",
title: "Scènes archicratiques",
text:
"Retrouver le portail synthétique des scènes, topologies et formats de comparution.",
"Revenir aux formes de comparution, dépreuve, dempêchement et de réouverture de la régulation.",
},
{
href: "/glossaire/dynamiques-archicratiques/",
title: "Dynamiques archicratiques",
text:
"Explorer les processus de fermeture, de capture, doblitération et de dérive des scènes.",
"Explorer les processus de fermeture, doblitération ou de dérive auxquels les verbes de la scène donnent une texture plus fine.",
},
{
href: "/glossaire/paradigme-archicratique/",
title: "Paradigme archicratique",
text:
"Replacer ce mini-glossaire opératoire dans larchitecture générale du système archicratique.",
},
{
href: "/glossaire/index-complet/",
title: "Index complet",
text:
"Retrouver lensemble des entrées du glossaire dans une navigation alphabétique intégrale.",
"Retrouver toutes les entrées du glossaire dans une navigation alphabétique intégrale.",
},
];
---
@@ -295,11 +295,12 @@ const prolongerLinks = [
<GlossaryPortalSection
id="prolonger-la-lecture"
title="Prolonger la lecture"
intro="Cette page forme un mini-glossaire daction. Elle permet de mieux qualifier ce qui arrive concrètement aux scènes archicratiques et prolonge la lecture vers les pages de concepts, de topologies et de dynamiques."
intro="Ce mini-glossaire opératoire complète les portails conceptuels du site. Il permet de décrire plus finement les opérations concrètes qui affectent une scène de régulation."
>
<div class="verbs-cards">
{prolongerLinks.map((item) => (
<a class="verbs-card verbs-card--link" href={item.href}>
<div class="verbs-card__index">↗</div>
<h3>{item.title}</h3>
<p class="verbs-card__definition">{item.text}</p>
</a>
@@ -349,10 +350,7 @@ const prolongerLinks = [
border: 1px solid rgba(127,127,127,0.22);
border-radius: 16px;
background: rgba(127,127,127,0.05);
transition:
background 120ms ease,
border-color 120ms ease,
transform 120ms ease;
transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
}
.verbs-card--link{
@@ -360,8 +358,7 @@ const prolongerLinks = [
color: inherit;
}
.verbs-card:hover,
.verbs-card--link:hover{
.verbs-card:hover{
transform: translateY(-1px);
background: rgba(127,127,127,0.08);
border-color: rgba(0,217,255,0.16);
@@ -394,8 +391,7 @@ const prolongerLinks = [
background: rgba(255,255,255,0.04);
}
.verbs-card:hover,
.verbs-card--link:hover{
.verbs-card:hover{
background: rgba(255,255,255,0.07);
}
}