Compare commits
56 Commits
feat/gloss
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8605b7198f | |||
| d41aed040f | |||
| bf01a83268 | |||
| 5b427d5602 | |||
| fa46971e76 | |||
| c313587b26 | |||
| 4976ddcc16 | |||
| 17e11f0322 | |||
| 7df18adfa8 | |||
| 535c5108e2 | |||
| 20705f6c90 | |||
| eabd2f5f29 | |||
| 482151c31c | |||
| 6d9d5a460e | |||
| 89d06ade16 | |||
| 69b35df10c | |||
| b5475e9be1 | |||
| fdd3aace5a | |||
| f86704d67e | |||
| ec8e29a313 | |||
| 1dc9a60580 | |||
| ee18b26d03 | |||
| 5f4a0f74db | |||
| 6b17df7320 | |||
| 0c33495342 | |||
| d8a09b1def | |||
| 39af501ea0 | |||
| 4c821d9e83 | |||
| deb4a91348 | |||
| 5b36b8e54e | |||
| eda5a877ef | |||
| 5b615a6999 | |||
| 99cf0947da | |||
| dbd1e14e4e | |||
| 7033354011 | |||
| 7345730e3c | |||
| cea94c56db | |||
| c1e24736e3 | |||
| 24bbfbc17f | |||
| a11e2f1d18 | |||
| 630b146d02 | |||
| 551360db83 | |||
| a96c282780 | |||
| d2e0f147c2 | |||
| ad95364021 | |||
| e48e322363 | |||
| a9f2a5bbd4 | |||
| 0cba8f868e | |||
| f8e3ee4cca | |||
| 92e0ad01c6 | |||
| e6c18d6b16 | |||
| a3092f5d5b | |||
| 7187b69935 | |||
| 4ba4453661 | |||
| ee42e391e3 | |||
| f7756be59e |
@@ -1,5 +1,11 @@
|
|||||||
{
|
{
|
||||||
"accepted_resets": {
|
"accepted_resets": {
|
||||||
"archicrat-ia/chapitre-1/index.html": "Reset intentionnel des ancres après révision doctrinale substantielle du chapitre 1. Site neuf, sans annotations ni compatibilité descendante à préserver."
|
"archicrat-ia/prologue/index.html": "Reset intentionnel des ancres après réimport DOCX et révision substantielle du prologue depuis la source officielle. Site neuf, sans annotations ni compatibilité descendante à préserver.",
|
||||||
|
"archicrat-ia/chapitre-1/index.html": "Reset intentionnel des ancres après révision doctrinale substantielle du chapitre 1. Site neuf, sans annotations ni compatibilité descendante à préserver.",
|
||||||
|
"archicrat-ia/chapitre-2/index.html": "Reset intentionnel des ancres après restauration doctrinale substantielle du chapitre 2 depuis la bonne source officielle. Site neuf, sans annotations ni compatibilité descendante à préserver.",
|
||||||
|
"archicrat-ia/chapitre-3/index.html": "Reset intentionnel des ancres après réimport DOCX et perfectionnement doctrinal substantiel du chapitre 3 depuis la source officielle. Site neuf, sans annotations ni compatibilité descendante à préserver.",
|
||||||
|
"archicrat-ia/chapitre-4/index.html": "Reset intentionnel des ancres après réimport DOCX et stabilisation doctrinale substantielle du chapitre 4 depuis la source officielle. Site neuf, sans annotations ni compatibilité descendante à préserver.",
|
||||||
|
"archicrat-ia/chapitre-5/index.html": "Reset intentionnel des ancres après réimport DOCX et stabilisation doctrinale substantielle du chapitre 5 depuis la source officielle. Site neuf, sans annotations ni compatibilité descendante à préserver.",
|
||||||
|
"archicrat-ia/conclusion/index.html": "Reset intentionnel des ancres après réimport DOCX et révision substantielle de la conclusion depuis la source officielle. Site neuf, sans annotations ni compatibilité descendante à préserver."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
"build": "astro build",
|
"build": "astro build",
|
||||||
"build:clean": "npm run clean && npm run build",
|
"build:clean": "npm run clean && npm run build",
|
||||||
"postbuild": "node scripts/inject-anchor-aliases.mjs && node scripts/dedupe-ids-dist.mjs && node scripts/build-para-index.mjs && node scripts/build-annotations-index.mjs && node scripts/purge-dist-dev-whoami.mjs && npx pagefind --site dist",
|
"build:search": "pagefind --site dist",
|
||||||
|
"postbuild": "node scripts/inject-anchor-aliases.mjs && node scripts/dedupe-ids-dist.mjs && node scripts/build-para-index.mjs && node scripts/build-annotations-index.mjs && node scripts/purge-dist-dev-whoami.mjs && npm run build:search",
|
||||||
"import": "node scripts/import-docx.mjs",
|
"import": "node scripts/import-docx.mjs",
|
||||||
"apply:ticket": "node scripts/apply-ticket.mjs",
|
"apply:ticket": "node scripts/apply-ticket.mjs",
|
||||||
"audit:dist": "node scripts/audit-dist.mjs",
|
"audit:dist": "node scripts/audit-dist.mjs",
|
||||||
|
|||||||
72
scripts/audit-docx-source.py
Executable file
72
scripts/audit-docx-source.py
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import unicodedata
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from zipfile import ZipFile
|
||||||
|
|
||||||
|
NS = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
|
||||||
|
|
||||||
|
FORBIDDEN = [
|
||||||
|
"coviabilité",
|
||||||
|
"sacroinstitutionnelle",
|
||||||
|
"technologistique",
|
||||||
|
"scripturonormative",
|
||||||
|
"textesrepères",
|
||||||
|
"ellemême",
|
||||||
|
"opérateur de d’archicration",
|
||||||
|
"systèmes plusieurs statuts",
|
||||||
|
"celle-ci se donne à voir",
|
||||||
|
"Pour autant il serait",
|
||||||
|
"Telles peuvent être le cas de",
|
||||||
|
"la co-viabilité devient ,",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def norm(s: str) -> str:
|
||||||
|
return unicodedata.normalize("NFC", s or "")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description="Audit simple d’un DOCX source officiel.")
|
||||||
|
parser.add_argument("docx", help="Chemin du fichier .docx")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
with ZipFile(args.docx) as zf:
|
||||||
|
data = zf.read("word/document.xml")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"ECHEC: fichier introuvable: {args.docx}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
except KeyError:
|
||||||
|
print("ECHEC: word/document.xml introuvable dans le DOCX.", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ECHEC: impossible d’ouvrir le DOCX: {e}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
root = ET.fromstring(data)
|
||||||
|
found = False
|
||||||
|
|
||||||
|
for i, p in enumerate(root.findall(".//w:p", NS), start=1):
|
||||||
|
txt = "".join(t.text or "" for t in p.findall(".//w:t", NS))
|
||||||
|
txt_n = norm(txt)
|
||||||
|
hits = [needle for needle in FORBIDDEN if needle in txt_n]
|
||||||
|
if hits:
|
||||||
|
found = True
|
||||||
|
print(f"\n[paragraphe {i}]")
|
||||||
|
print("Hits :", ", ".join(hits))
|
||||||
|
print(txt_n)
|
||||||
|
|
||||||
|
if found:
|
||||||
|
print("\nECHEC: formes interdites encore présentes dans le DOCX.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print("OK: aucune forme interdite trouvée dans le DOCX.")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
241
scripts/convert_docx_to_mdx.py
Executable file
241
scripts/convert_docx_to_mdx.py
Executable file
@@ -0,0 +1,241 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
print("Erreur : PyYAML n'est pas installé. Lance : pip3 install pyyaml")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
EDITION = "archicrat-ia"
|
||||||
|
STATUS = "essai_these"
|
||||||
|
VERSION = "0.1.0"
|
||||||
|
|
||||||
|
|
||||||
|
ORDER_MAP = {
|
||||||
|
"prologue": 10,
|
||||||
|
"chapitre-1": 20,
|
||||||
|
"chapitre-2": 30,
|
||||||
|
"chapitre-3": 40,
|
||||||
|
"chapitre-4": 50,
|
||||||
|
"chapitre-5": 60,
|
||||||
|
"conclusion": 70,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TITLE_MAP = {
|
||||||
|
"prologue": "Prologue — Fondation, finalité sociopolitique et historique",
|
||||||
|
"chapitre-1": "Chapitre 1 — Fondements épistémologiques et modélisation",
|
||||||
|
"chapitre-2": "Chapitre 2 — Archéogenèse des régimes de co-viabilité",
|
||||||
|
"chapitre-3": "Chapitre 3 — Philosophies du pouvoir et archicration",
|
||||||
|
"chapitre-4": "Chapitre 4 — Histoire archicratique des révolutions industrielles",
|
||||||
|
"chapitre-5": "Chapitre 5 — Tensions, co-viabilités et régulations",
|
||||||
|
"conclusion": "Conclusion — ArchiCraT-IA",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def slugify_name(path: Path) -> str:
|
||||||
|
stem = path.stem.lower().strip()
|
||||||
|
|
||||||
|
replacements = {
|
||||||
|
" ": "-",
|
||||||
|
"_": "-",
|
||||||
|
"—": "-",
|
||||||
|
"–": "-",
|
||||||
|
"é": "e",
|
||||||
|
"è": "e",
|
||||||
|
"ê": "e",
|
||||||
|
"ë": "e",
|
||||||
|
"à": "a",
|
||||||
|
"â": "a",
|
||||||
|
"ä": "a",
|
||||||
|
"î": "i",
|
||||||
|
"ï": "i",
|
||||||
|
"ô": "o",
|
||||||
|
"ö": "o",
|
||||||
|
"ù": "u",
|
||||||
|
"û": "u",
|
||||||
|
"ü": "u",
|
||||||
|
"ç": "c",
|
||||||
|
"'": "",
|
||||||
|
"’": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
for old, new in replacements.items():
|
||||||
|
stem = stem.replace(old, new)
|
||||||
|
|
||||||
|
stem = re.sub(r"-+", "-", stem).strip("-")
|
||||||
|
|
||||||
|
# normalisations spécifiques
|
||||||
|
stem = stem.replace("chapitre-1-fondements-epistemologiques-et-modelisation-archicratie-version-officielle-revise", "chapitre-1")
|
||||||
|
stem = stem.replace("chapitre-2", "chapitre-2")
|
||||||
|
stem = stem.replace("chapitre-3", "chapitre-3")
|
||||||
|
stem = stem.replace("chapitre-4", "chapitre-4")
|
||||||
|
stem = stem.replace("chapitre-5", "chapitre-5")
|
||||||
|
|
||||||
|
if "prologue" in stem:
|
||||||
|
return "prologue"
|
||||||
|
if "chapitre-1" in stem:
|
||||||
|
return "chapitre-1"
|
||||||
|
if "chapitre-2" in stem:
|
||||||
|
return "chapitre-2"
|
||||||
|
if "chapitre-3" in stem:
|
||||||
|
return "chapitre-3"
|
||||||
|
if "chapitre-4" in stem:
|
||||||
|
return "chapitre-4"
|
||||||
|
if "chapitre-5" in stem:
|
||||||
|
return "chapitre-5"
|
||||||
|
if "conclusion" in stem:
|
||||||
|
return "conclusion"
|
||||||
|
|
||||||
|
return stem
|
||||||
|
|
||||||
|
|
||||||
|
def extract_title_from_markdown(md_text: str) -> str | None:
|
||||||
|
for line in md_text.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
if line.startswith("# "):
|
||||||
|
return line[2:].strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def remove_first_h1(md_text: str) -> str:
|
||||||
|
lines = md_text.splitlines()
|
||||||
|
out = []
|
||||||
|
removed = False
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if not removed and line.strip().startswith("# "):
|
||||||
|
removed = True
|
||||||
|
continue
|
||||||
|
out.append(line)
|
||||||
|
|
||||||
|
text = "\n".join(out).lstrip()
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def clean_markdown(md_text: str) -> str:
|
||||||
|
text = md_text.replace("\r\n", "\n").replace("\r", "\n")
|
||||||
|
|
||||||
|
# nettoyer espaces multiples
|
||||||
|
text = re.sub(r"\n{3,}", "\n\n", text)
|
||||||
|
|
||||||
|
# supprimer éventuels signets/artefacts de liens internes Pandoc
|
||||||
|
text = re.sub(r"\[\]\(#.*?\)", "", text)
|
||||||
|
|
||||||
|
# convertir astérismes parasites
|
||||||
|
text = re.sub(r"[ \t]+$", "", text, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
return text.strip() + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def compute_level(slug: str) -> int:
|
||||||
|
if slug == "prologue":
|
||||||
|
return 1
|
||||||
|
if slug.startswith("chapitre-"):
|
||||||
|
return 1
|
||||||
|
if slug == "conclusion":
|
||||||
|
return 1
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def convert_one_file(input_docx: Path, output_dir: Path, source_root: Path):
|
||||||
|
slug = slugify_name(input_docx)
|
||||||
|
output_mdx = output_dir / f"{slug}.mdx"
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
"pandoc",
|
||||||
|
str(input_docx),
|
||||||
|
"-f",
|
||||||
|
"docx",
|
||||||
|
"-t",
|
||||||
|
"gfm+smart",
|
||||||
|
]
|
||||||
|
|
||||||
|
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
|
||||||
|
md_text = result.stdout
|
||||||
|
|
||||||
|
detected_title = extract_title_from_markdown(md_text)
|
||||||
|
md_body = remove_first_h1(md_text)
|
||||||
|
md_body = clean_markdown(md_body)
|
||||||
|
|
||||||
|
title = TITLE_MAP.get(slug) or detected_title or input_docx.stem
|
||||||
|
order = ORDER_MAP.get(slug, 999)
|
||||||
|
level = compute_level(slug)
|
||||||
|
|
||||||
|
relative_source = input_docx
|
||||||
|
try:
|
||||||
|
relative_source = input_docx.relative_to(source_root)
|
||||||
|
except ValueError:
|
||||||
|
relative_source = input_docx.name
|
||||||
|
|
||||||
|
frontmatter = {
|
||||||
|
"title": title,
|
||||||
|
"edition": EDITION,
|
||||||
|
"status": STATUS,
|
||||||
|
"level": level,
|
||||||
|
"version": VERSION,
|
||||||
|
"concepts": [],
|
||||||
|
"links": [],
|
||||||
|
"order": order,
|
||||||
|
"summary": "",
|
||||||
|
"source": {
|
||||||
|
"kind": "docx",
|
||||||
|
"path": str(relative_source),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml_block = yaml.safe_dump(
|
||||||
|
frontmatter,
|
||||||
|
allow_unicode=True,
|
||||||
|
sort_keys=False,
|
||||||
|
default_flow_style=False,
|
||||||
|
).strip()
|
||||||
|
|
||||||
|
final_text = f"---\n{yaml_block}\n---\n{md_body if md_body.startswith(chr(10)) else chr(10) + md_body}"
|
||||||
|
output_mdx.write_text(final_text, encoding="utf-8")
|
||||||
|
print(f"✅ {input_docx.name} -> {output_mdx.name}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Convertit un dossier DOCX en MDX avec frontmatter.")
|
||||||
|
parser.add_argument("input_dir", help="Dossier source contenant les DOCX")
|
||||||
|
parser.add_argument("output_dir", help="Dossier de sortie pour les MDX")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
input_dir = Path(args.input_dir).expanduser().resolve()
|
||||||
|
output_dir = Path(args.output_dir).expanduser().resolve()
|
||||||
|
|
||||||
|
if not shutil.which("pandoc"):
|
||||||
|
print("Erreur : pandoc n'est pas installé. Lance : brew install pandoc")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not input_dir.exists() or not input_dir.is_dir():
|
||||||
|
print(f"Erreur : dossier source introuvable : {input_dir}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
docx_files = sorted(input_dir.glob("*.docx"))
|
||||||
|
if not docx_files:
|
||||||
|
print(f"Aucun DOCX trouvé dans : {input_dir}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
for docx_file in docx_files:
|
||||||
|
convert_one_file(docx_file, output_dir, input_dir)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("Conversion DOCX -> MDX terminée.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
304
scripts/convert_mdx_to_docx.py
Normal file
304
scripts/convert_mdx_to_docx.py
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
print("Erreur : PyYAML n'est pas installé. Lance : pip3 install pyyaml")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from docx import Document
|
||||||
|
except ImportError:
|
||||||
|
print("Erreur : python-docx n'est pas installé. Lance : pip3 install python-docx")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def split_frontmatter(text: str):
|
||||||
|
if not text.startswith("---\n"):
|
||||||
|
return {}, text
|
||||||
|
|
||||||
|
match = re.match(r"^---\n(.*?)\n---\n(.*)$", text, flags=re.DOTALL)
|
||||||
|
if not match:
|
||||||
|
return {}, text
|
||||||
|
|
||||||
|
yaml_block = match.group(1)
|
||||||
|
body = match.group(2)
|
||||||
|
|
||||||
|
try:
|
||||||
|
metadata = yaml.safe_load(yaml_block) or {}
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Avertissement : frontmatter YAML illisible : {e}")
|
||||||
|
metadata = {}
|
||||||
|
|
||||||
|
return metadata, body
|
||||||
|
|
||||||
|
|
||||||
|
def strip_mdx_artifacts(text: str):
|
||||||
|
# imports / exports MDX
|
||||||
|
text = re.sub(r"^\s*(import|export)\s+.+?$", "", text, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
# composants autofermants : <Component />
|
||||||
|
text = re.sub(r"<[A-Z][A-Za-z0-9._-]*\b[^>]*\/>", "", text)
|
||||||
|
|
||||||
|
# composants bloc : <Component ...>...</Component>
|
||||||
|
text = re.sub(
|
||||||
|
r"<([A-Z][A-Za-z0-9._-]*)\b[^>]*>.*?</\1>",
|
||||||
|
"",
|
||||||
|
text,
|
||||||
|
flags=re.DOTALL,
|
||||||
|
)
|
||||||
|
|
||||||
|
# accolades seules résiduelles sur ligne
|
||||||
|
text = re.sub(r"^\s*{\s*}\s*$", "", text, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
# lignes vides multiples
|
||||||
|
text = re.sub(r"\n{3,}", "\n\n", text)
|
||||||
|
|
||||||
|
return text.strip() + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def inject_h1_from_title(metadata: dict, body: str):
|
||||||
|
title = metadata.get("title", "")
|
||||||
|
if not title:
|
||||||
|
return body
|
||||||
|
|
||||||
|
if re.match(r"^\s*#\s+", body):
|
||||||
|
return body
|
||||||
|
|
||||||
|
return f"# {title}\n\n{body.lstrip()}"
|
||||||
|
|
||||||
|
|
||||||
|
def find_style_by_candidates(doc, candidates):
|
||||||
|
# Cherche d'abord par nom visible
|
||||||
|
for style in doc.styles:
|
||||||
|
for candidate in candidates:
|
||||||
|
if style.name == candidate:
|
||||||
|
return style
|
||||||
|
|
||||||
|
# Puis par style_id Word interne
|
||||||
|
for style in doc.styles:
|
||||||
|
style_id = getattr(style, "style_id", "")
|
||||||
|
if style_id in {"BodyText", "Heading1", "Heading2", "Heading3", "Heading4"}:
|
||||||
|
for candidate in candidates:
|
||||||
|
if candidate in {"Body Text", "Corps de texte"} and style_id == "BodyText":
|
||||||
|
return style
|
||||||
|
if candidate in {"Heading 1", "Titre 1"} and style_id == "Heading1":
|
||||||
|
return style
|
||||||
|
if candidate in {"Heading 2", "Titre 2"} and style_id == "Heading2":
|
||||||
|
return style
|
||||||
|
if candidate in {"Heading 3", "Titre 3"} and style_id == "Heading3":
|
||||||
|
return style
|
||||||
|
if candidate in {"Heading 4", "Titre 4"} and style_id == "Heading4":
|
||||||
|
return style
|
||||||
|
return None
|
||||||
|
|
||||||
|
def strip_leading_paragraph_numbers(text: str):
|
||||||
|
"""
|
||||||
|
Supprime les numéros de paragraphe du type :
|
||||||
|
2. Texte...
|
||||||
|
11. Texte...
|
||||||
|
101. Texte...
|
||||||
|
sans toucher aux titres Markdown (#, ##, ###).
|
||||||
|
"""
|
||||||
|
fixed_lines = []
|
||||||
|
|
||||||
|
for line in text.splitlines():
|
||||||
|
stripped = line.lstrip()
|
||||||
|
|
||||||
|
# Ne jamais toucher aux titres Markdown
|
||||||
|
if stripped.startswith("#"):
|
||||||
|
fixed_lines.append(line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Supprime un numéro de paragraphe en début de ligne
|
||||||
|
line = re.sub(r"^\s*\d+\.\s+", "", line)
|
||||||
|
fixed_lines.append(line)
|
||||||
|
|
||||||
|
return "\n".join(fixed_lines) + "\n"
|
||||||
|
|
||||||
|
def normalize_non_heading_paragraphs(docx_path: Path):
|
||||||
|
"""
|
||||||
|
Force tous les paragraphes non-titres en Body Text / Corps de texte.
|
||||||
|
On laisse intacts les Heading 1-4.
|
||||||
|
"""
|
||||||
|
doc = Document(str(docx_path))
|
||||||
|
|
||||||
|
body_style = find_style_by_candidates(doc, ["Body Text", "Corps de texte"])
|
||||||
|
if body_style is None:
|
||||||
|
print(f"Avertissement : style 'Body Text / Corps de texte' introuvable dans {docx_path.name}")
|
||||||
|
return
|
||||||
|
|
||||||
|
heading_names = {
|
||||||
|
"Heading 1", "Heading 2", "Heading 3", "Heading 4",
|
||||||
|
"Titre 1", "Titre 2", "Titre 3", "Titre 4",
|
||||||
|
}
|
||||||
|
heading_ids = {"Heading1", "Heading2", "Heading3", "Heading4"}
|
||||||
|
|
||||||
|
changed = 0
|
||||||
|
|
||||||
|
for para in doc.paragraphs:
|
||||||
|
text = para.text.strip()
|
||||||
|
if not text:
|
||||||
|
continue
|
||||||
|
|
||||||
|
current_style = para.style
|
||||||
|
current_name = current_style.name if current_style else ""
|
||||||
|
current_id = getattr(current_style, "style_id", "") if current_style else ""
|
||||||
|
|
||||||
|
if current_name in heading_names or current_id in heading_ids:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Tout le reste passe en Body Text
|
||||||
|
para.style = body_style
|
||||||
|
changed += 1
|
||||||
|
|
||||||
|
doc.save(str(docx_path))
|
||||||
|
print(f" ↳ normalisation styles : {changed} paragraphe(s) mis en 'Body Text / Corps de texte'")
|
||||||
|
|
||||||
|
def remove_word_bookmarks(docx_path: Path):
|
||||||
|
"""
|
||||||
|
Supprime les bookmarks Word (signets) du DOCX.
|
||||||
|
Ce sont eux qui apparaissent comme crochets gris dans LibreOffice/Word
|
||||||
|
quand l'affichage des signets est activé.
|
||||||
|
"""
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
tmpdir = Path(tmpdir)
|
||||||
|
|
||||||
|
# Dézipper le docx
|
||||||
|
with zipfile.ZipFile(docx_path, "r") as zin:
|
||||||
|
zin.extractall(tmpdir)
|
||||||
|
|
||||||
|
xml_targets = [
|
||||||
|
tmpdir / "word" / "document.xml",
|
||||||
|
tmpdir / "word" / "footnotes.xml",
|
||||||
|
tmpdir / "word" / "endnotes.xml",
|
||||||
|
tmpdir / "word" / "comments.xml",
|
||||||
|
]
|
||||||
|
|
||||||
|
removed = 0
|
||||||
|
|
||||||
|
for xml_file in xml_targets:
|
||||||
|
if not xml_file.exists():
|
||||||
|
continue
|
||||||
|
|
||||||
|
text = xml_file.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
# enlever <w:bookmarkStart .../> et <w:bookmarkEnd .../>
|
||||||
|
text, c1 = re.subn(r"<w:bookmarkStart\b[^>]*/>", "", text)
|
||||||
|
text, c2 = re.subn(r"<w:bookmarkEnd\b[^>]*/>", "", text)
|
||||||
|
|
||||||
|
removed += c1 + c2
|
||||||
|
xml_file.write_text(text, encoding="utf-8")
|
||||||
|
|
||||||
|
# Rezipper
|
||||||
|
tmp_output = docx_path.with_suffix(".cleaned.docx")
|
||||||
|
with zipfile.ZipFile(tmp_output, "w", zipfile.ZIP_DEFLATED) as zout:
|
||||||
|
for file in tmpdir.rglob("*"):
|
||||||
|
if file.is_file():
|
||||||
|
zout.write(file, file.relative_to(tmpdir))
|
||||||
|
|
||||||
|
tmp_output.replace(docx_path)
|
||||||
|
print(f" ↳ suppression signets : {removed} balise(s) supprimée(s)")
|
||||||
|
|
||||||
|
def convert_one_file(input_path: Path, output_path: Path, reference_doc: Path | None):
|
||||||
|
raw = input_path.read_text(encoding="utf-8")
|
||||||
|
metadata, body = split_frontmatter(raw)
|
||||||
|
body = strip_mdx_artifacts(body)
|
||||||
|
body = strip_leading_paragraph_numbers(body)
|
||||||
|
body = inject_h1_from_title(metadata, body)
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile("w", suffix=".md", delete=False, encoding="utf-8") as tmp:
|
||||||
|
tmp.write(body)
|
||||||
|
tmp_md = Path(tmp.name)
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
"pandoc",
|
||||||
|
str(tmp_md),
|
||||||
|
"-f",
|
||||||
|
"markdown",
|
||||||
|
"-o",
|
||||||
|
str(output_path),
|
||||||
|
]
|
||||||
|
|
||||||
|
if reference_doc:
|
||||||
|
cmd.extend(["--reference-doc", str(reference_doc)])
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
tmp_md.unlink()
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
normalize_non_heading_paragraphs(output_path)
|
||||||
|
remove_word_bookmarks(output_path)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Convertit des fichiers MDX en DOCX en conservant H1/H2/H3/H4 et en forçant le corps en Body Text."
|
||||||
|
)
|
||||||
|
parser.add_argument("input_dir", help="Dossier contenant les .mdx")
|
||||||
|
parser.add_argument(
|
||||||
|
"--output-dir",
|
||||||
|
default=str(Path.home() / "Desktop" / "archicrat-ia-docx"),
|
||||||
|
help="Dossier de sortie DOCX"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--reference-doc",
|
||||||
|
default=None,
|
||||||
|
help="DOCX modèle Word à utiliser comme reference-doc"
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
input_dir = Path(args.input_dir)
|
||||||
|
output_dir = Path(args.output_dir)
|
||||||
|
reference_doc = Path(args.reference_doc) if args.reference_doc else None
|
||||||
|
|
||||||
|
if not shutil.which("pandoc"):
|
||||||
|
print("Erreur : pandoc n'est pas installé. Installe-le avec : brew install pandoc")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not input_dir.exists() or not input_dir.is_dir():
|
||||||
|
print(f"Erreur : dossier introuvable : {input_dir}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if reference_doc and not reference_doc.exists():
|
||||||
|
print(f"Erreur : reference-doc introuvable : {reference_doc}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
mdx_files = sorted(input_dir.glob("*.mdx"))
|
||||||
|
if not mdx_files:
|
||||||
|
print(f"Aucun fichier .mdx trouvé dans : {input_dir}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f"Conversion de {len(mdx_files)} fichier(s)...")
|
||||||
|
print(f"Entrée : {input_dir}")
|
||||||
|
print(f"Sortie : {output_dir}")
|
||||||
|
if reference_doc:
|
||||||
|
print(f"Modèle : {reference_doc}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
for mdx_file in mdx_files:
|
||||||
|
docx_name = mdx_file.with_suffix(".docx").name
|
||||||
|
out_file = output_dir / docx_name
|
||||||
|
print(f"→ {mdx_file.name} -> {docx_name}")
|
||||||
|
convert_one_file(mdx_file, out_file, reference_doc)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("✅ Conversion terminée.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
132
scripts/fix-docx-source.py
Executable file
132
scripts/fix-docx-source.py
Executable file
@@ -0,0 +1,132 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import unicodedata
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from pathlib import Path
|
||||||
|
from zipfile import ZIP_DEFLATED, ZipFile
|
||||||
|
|
||||||
|
W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||||
|
XML_NS = "http://www.w3.org/XML/1998/namespace"
|
||||||
|
NS = {"w": W_NS}
|
||||||
|
|
||||||
|
ET.register_namespace("w", W_NS)
|
||||||
|
|
||||||
|
|
||||||
|
REPLACEMENTS = {
|
||||||
|
"coviabilité": "co-viabilité",
|
||||||
|
"sacroinstitutionnelle": "sacro-institutionnelle",
|
||||||
|
"technologistique": "techno-logistique",
|
||||||
|
"scripturonormative": "scripturo-normative",
|
||||||
|
"textesrepères": "textes-repères",
|
||||||
|
"ellemême": "elle-même",
|
||||||
|
"opérateur de d’archicration": "opérateur d’archicration",
|
||||||
|
"systèmes plusieurs statuts": "systèmes à plusieurs statuts",
|
||||||
|
"celle-ci se donne à voir": "Celle-ci se donne à voir",
|
||||||
|
"Pour autant il serait": "Pour autant, il serait",
|
||||||
|
"Telles peuvent être le cas de": "Tels peuvent être les cas de",
|
||||||
|
}
|
||||||
|
|
||||||
|
# volontairement NON auto-corrigé : "la co-viabilité devient ,"
|
||||||
|
# ce cas demande une décision éditoriale humaine.
|
||||||
|
|
||||||
|
|
||||||
|
def qn(tag: str) -> str:
|
||||||
|
prefix, local = tag.split(":")
|
||||||
|
if prefix != "w":
|
||||||
|
raise ValueError(tag)
|
||||||
|
return f"{{{W_NS}}}{local}"
|
||||||
|
|
||||||
|
|
||||||
|
def norm(s: str) -> str:
|
||||||
|
return unicodedata.normalize("NFC", s or "")
|
||||||
|
|
||||||
|
|
||||||
|
def paragraph_text(p: ET.Element) -> str:
|
||||||
|
return "".join(t.text or "" for t in p.findall(".//w:t", NS))
|
||||||
|
|
||||||
|
|
||||||
|
def replaced_text(s: str) -> str:
|
||||||
|
out = norm(s)
|
||||||
|
for bad, good in REPLACEMENTS.items():
|
||||||
|
out = out.replace(bad, good)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def rewrite_paragraph_text(p: ET.Element, new_text: str) -> None:
|
||||||
|
ppr = p.find("w:pPr", NS)
|
||||||
|
|
||||||
|
for child in list(p):
|
||||||
|
if ppr is not None and child is ppr:
|
||||||
|
continue
|
||||||
|
p.remove(child)
|
||||||
|
|
||||||
|
r = ET.Element(qn("w:r"))
|
||||||
|
t = ET.SubElement(r, qn("w:t"))
|
||||||
|
t.set(f"{{{XML_NS}}}space", "preserve")
|
||||||
|
t.text = new_text
|
||||||
|
p.append(r)
|
||||||
|
|
||||||
|
|
||||||
|
def process_document_xml(xml_path: Path) -> int:
|
||||||
|
tree = ET.parse(xml_path)
|
||||||
|
root = tree.getroot()
|
||||||
|
|
||||||
|
changed = 0
|
||||||
|
|
||||||
|
for p in root.findall(".//w:p", NS):
|
||||||
|
old = paragraph_text(p)
|
||||||
|
new = replaced_text(old)
|
||||||
|
if new != old:
|
||||||
|
rewrite_paragraph_text(p, new)
|
||||||
|
changed += 1
|
||||||
|
|
||||||
|
tree.write(xml_path, encoding="utf-8", xml_declaration=True)
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
def repack_docx(tmpdir: Path, out_docx: Path) -> None:
|
||||||
|
tmp_out = out_docx.with_suffix(out_docx.suffix + ".tmp")
|
||||||
|
with ZipFile(tmp_out, "w", ZIP_DEFLATED) as zf:
|
||||||
|
for p in sorted(tmpdir.rglob("*")):
|
||||||
|
if p.is_file():
|
||||||
|
zf.write(p, p.relative_to(tmpdir))
|
||||||
|
shutil.move(tmp_out, out_docx)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(description="Répare mécaniquement certaines scories DOCX.")
|
||||||
|
parser.add_argument("docx", help="Chemin du DOCX")
|
||||||
|
parser.add_argument("--in-place", action="store_true", help="Réécrit le DOCX en place")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
src = Path(args.docx)
|
||||||
|
if not src.exists():
|
||||||
|
print(f"ECHEC: fichier introuvable: {src}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
out = src if args.in_place else src.with_name(src.stem + ".fixed.docx")
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory(prefix="docx-fix-") as td:
|
||||||
|
td_path = Path(td)
|
||||||
|
with ZipFile(src) as zf:
|
||||||
|
zf.extractall(td_path)
|
||||||
|
|
||||||
|
document_xml = td_path / "word" / "document.xml"
|
||||||
|
if not document_xml.exists():
|
||||||
|
print("ECHEC: word/document.xml absent.", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
changed = process_document_xml(document_xml)
|
||||||
|
repack_docx(td_path, out)
|
||||||
|
|
||||||
|
print(f"OK: DOCX réparé par réécriture paragraphe/XML. Paragraphes modifiés: {changed}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -205,13 +205,29 @@ async function main() {
|
|||||||
const manifestPath = path.resolve(args.manifest);
|
const manifestPath = path.resolve(args.manifest);
|
||||||
|
|
||||||
const items = await readManifest(manifestPath);
|
const items = await readManifest(manifestPath);
|
||||||
const selected = args.all ? items : items.filter(it => args.only.includes(it.slug));
|
const selected = args.all
|
||||||
|
? items
|
||||||
|
: items.filter((it) => {
|
||||||
|
const rawSlug = String(it.slug || "").trim();
|
||||||
|
const rawCollection = String(it.collection || "").trim();
|
||||||
|
const qualified = `${rawCollection}/${rawSlug}`;
|
||||||
|
return args.only.includes(rawSlug) || args.only.includes(qualified);
|
||||||
|
});
|
||||||
|
|
||||||
if (!args.all && selected.length !== args.only.length) {
|
if (!args.all) {
|
||||||
const found = new Set(selected.map(s => s.slug));
|
const found = new Set(
|
||||||
const missing = args.only.filter(s => !found.has(s));
|
selected.flatMap((s) => {
|
||||||
|
const rawSlug = String(s.slug || "").trim();
|
||||||
|
const rawCollection = String(s.collection || "").trim();
|
||||||
|
return [rawSlug, `${rawCollection}/${rawSlug}`];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const missing = args.only.filter((s) => !found.has(s));
|
||||||
|
if (missing.length > 0) {
|
||||||
throw new Error(`Some --only slugs not found in manifest: ${missing.join(", ")}`);
|
throw new Error(`Some --only slugs not found in manifest: ${missing.join(", ")}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const pandocOk = havePandoc();
|
const pandocOk = havePandoc();
|
||||||
|
|
||||||
@@ -275,7 +291,22 @@ async function main() {
|
|||||||
atlas: { edition: "atlas", status: "atlas", level: 1 },
|
atlas: { edition: "atlas", status: "atlas", level: 1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaults = schemaDefaultsByCollection[outCollection] || { edition: outCollection, status: "draft", level: 1 };
|
// Compat legacy :
|
||||||
|
// manifest collection="archicratie" + slug="archicrat-ia/..."
|
||||||
|
// => on écrit bien dans src/content/archicrat-ia/...
|
||||||
|
// => mais on conserve edition/status historiques de type archicratie/modele_sociopolitique
|
||||||
|
const defaultsKey =
|
||||||
|
String(it.collection || "").trim() === "archicratie" &&
|
||||||
|
String(it.slug || "").trim().startsWith("archicrat-ia/")
|
||||||
|
? "archicratie"
|
||||||
|
: outCollection;
|
||||||
|
|
||||||
|
const defaults =
|
||||||
|
schemaDefaultsByCollection[defaultsKey] || {
|
||||||
|
edition: defaultsKey,
|
||||||
|
status: "draft",
|
||||||
|
level: 1,
|
||||||
|
};
|
||||||
|
|
||||||
const fm = [
|
const fm = [
|
||||||
"---",
|
"---",
|
||||||
|
|||||||
29
scripts/refresh-chapter2.sh
Executable file
29
scripts/refresh-chapter2.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DOCX="sources/docx/archicrat-ia/Chapitre_2–Archeogenese_des_regimes_de_co-viabilite-version_officielle.docx"
|
||||||
|
MANIFEST="sources/manifest.yml"
|
||||||
|
ONLY="archicrat-ia/chapitre-2"
|
||||||
|
|
||||||
|
echo "== Audit source avant fix =="
|
||||||
|
if ! python3 scripts/audit-docx-source.py "$DOCX"; then
|
||||||
|
echo
|
||||||
|
echo "== Fix source =="
|
||||||
|
python3 scripts/fix-docx-source.py --in-place "$DOCX"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Audit source après fix =="
|
||||||
|
python3 scripts/audit-docx-source.py "$DOCX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Réimport =="
|
||||||
|
node scripts/import-docx.mjs --manifest "$MANIFEST" --only "$ONLY" --force
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Build =="
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Tests =="
|
||||||
|
npm test
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -14,44 +14,44 @@ docs:
|
|||||||
# Archicratie — Essai-thèse "ArchiCraT-IA"
|
# Archicratie — Essai-thèse "ArchiCraT-IA"
|
||||||
# =========================
|
# =========================
|
||||||
- source: sources/docx/archicrat-ia/Prologue—Archicratie-fondation_et_finalite_sociopolitique_et_historique-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Prologue—Archicratie-fondation_et_finalite_sociopolitique_et_historique-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/prologue
|
slug: prologue
|
||||||
title: "Prologue — Fondation et finalité sociopolitique et historique"
|
title: "Prologue — Fondation, finalité sociopolitique et historique"
|
||||||
order: 10
|
order: 10
|
||||||
|
|
||||||
- source: sources/docx/archicrat-ia/Chapitre_1—Fondements_epistemologiques_et_modelisation_Archicratie-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Chapitre_1—Fondements_epistemologiques_et_modelisation_Archicratie-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/chapitre-1
|
slug: chapitre-1
|
||||||
title: "Chapitre 1 — Fondements épistémologiques et modélisation"
|
title: "Chapitre 1 — Fondements épistémologiques et modélisation"
|
||||||
order: 20
|
order: 20
|
||||||
|
|
||||||
- source: sources/docx/archicrat-ia/Chapitre_2–Archeogenese_des_regimes_de_co-viabilite-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Chapitre_2–Archeogenese_des_regimes_de_co-viabilite-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/chapitre-2
|
slug: chapitre-2
|
||||||
title: "Chapitre 2 — Archéogenèse des régimes de co-viabilité"
|
title: "Chapitre 2 — Archéogenèse des régimes de co-viabilité"
|
||||||
order: 30
|
order: 30
|
||||||
|
|
||||||
- source: sources/docx/archicrat-ia/Chapitre_3—Philosophies_du_pouvoir_et_Archicration-pour_une_topologie_differenciee_des_regimes_regulateurs-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Chapitre_3—Philosophies_du_pouvoir_et_Archicration-pour_une_topologie_differenciee_des_regimes_regulateurs-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/chapitre-3
|
slug: chapitre-3
|
||||||
title: "Chapitre 3 — Philosophies du pouvoir et archicration"
|
title: "Chapitre 3 — Philosophies du pouvoir et archicration"
|
||||||
order: 40
|
order: 40
|
||||||
|
|
||||||
- source: sources/docx/archicrat-ia/Chapitre_4—Vers_une_histoire_archicratique_des_revolutions_industrielles-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Chapitre_4—Vers_une_histoire_archicratique_des_revolutions_industrielles-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/chapitre-4
|
slug: chapitre-4
|
||||||
title: "Chapitre 4 — Histoire archicratique des révolutions industrielles"
|
title: "Chapitre 4 — Histoire archicratique des révolutions industrielles"
|
||||||
order: 50
|
order: 50
|
||||||
|
|
||||||
- source: sources/docx/archicrat-ia/Chapitre_5—Problematiques_des_tensions_des_co-viabilites_et_des_regulations_archicratiques-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Chapitre_5—Problematiques_des_tensions_des_co-viabilites_et_des_regulations_archicratiques-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/chapitre-5
|
slug: chapitre-5
|
||||||
title: "Chapitre 5 — Tensions, co-viabilités et régulations"
|
title: "Chapitre 5 — Tensions, co-viabilités et régulations"
|
||||||
order: 60
|
order: 60
|
||||||
|
|
||||||
- source: sources/docx/archicrat-ia/Conclusion-Archicrat-IA-version_officielle.docx
|
- source: sources/docx/archicrat-ia/Conclusion-Archicrat-IA-version_officielle.docx
|
||||||
collection: archicratie
|
collection: archicrat-ia
|
||||||
slug: archicrat-ia/conclusion
|
slug: conclusion
|
||||||
title: "Conclusion — ArchiCraT-IA"
|
title: "Conclusion — ArchiCraT-IA"
|
||||||
order: 70
|
order: 70
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1 @@
|
|||||||
{
|
{}
|
||||||
"/archicrat-ia/prologue/": {
|
|
||||||
"p-0-d7974f88": "p-0-e729df02",
|
|
||||||
"p-17-b8c5bf21": "p-17-3deef56b",
|
|
||||||
"p-22-a416d473": "p-22-5bfa283b",
|
|
||||||
"p-23-d91a7b78": "p-23-0e7b37e9",
|
|
||||||
"p-4-8ed4f807": "p-4-90b2a1cc",
|
|
||||||
"p-5-85126fa5": "p-5-d788c546",
|
|
||||||
"p-7-64a0ca9c": "p-7-4efdb1d4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,13 +22,28 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
const bt = String(b.data.title ?? b.data.term ?? slugOf(b));
|
const bt = String(b.data.title ?? b.data.term ?? slugOf(b));
|
||||||
return collator.compare(at, bt);
|
return collator.compare(at, bt);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const tocId = `toc-global-${collection}-${String(basePath).replace(/[^\w-]+/g, "-")}`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<nav class="toc-global" aria-label={label}>
|
<nav
|
||||||
<div class="toc-global__head">
|
class="toc-global"
|
||||||
<div class="toc-global__title">{label}</div>
|
aria-label={label}
|
||||||
</div>
|
data-toc-global
|
||||||
|
data-toc-key={`global:${collection}:${basePath}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="toc-global__head toc-global__toggle"
|
||||||
|
type="button"
|
||||||
|
aria-expanded="true"
|
||||||
|
aria-controls={tocId}
|
||||||
|
>
|
||||||
|
<span class="toc-global__title">{label}</span>
|
||||||
|
<span class="toc-global__chevron" aria-hidden="true">▾</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="toc-global__body-clip" id={tocId}>
|
||||||
|
<div class="toc-global__body">
|
||||||
<ol class="toc-global__list">
|
<ol class="toc-global__list">
|
||||||
{entries.map((e) => {
|
{entries.map((e) => {
|
||||||
const slug = slugOf(e);
|
const slug = slugOf(e);
|
||||||
@@ -38,11 +53,9 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
<li class={`toc-item ${active ? "is-active" : ""}`}>
|
<li class={`toc-item ${active ? "is-active" : ""}`}>
|
||||||
<a class="toc-link" href={hrefOf(e)} aria-current={active ? "page" : undefined}>
|
<a class="toc-link" href={hrefOf(e)} aria-current={active ? "page" : undefined}>
|
||||||
<span class="toc-link__row">
|
<span class="toc-link__row">
|
||||||
{active ? (
|
<span class={`toc-active-mark ${active ? "is-on" : ""}`} aria-hidden="true">
|
||||||
<span class="toc-active-indicator" aria-hidden="true">👉</span>
|
<span class="toc-active-mark__dot"></span>
|
||||||
) : (
|
</span>
|
||||||
<span class="toc-active-spacer" aria-hidden="true"></span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<span class="toc-link__title">{e.data.title}</span>
|
<span class="toc-link__title">{e.data.title}</span>
|
||||||
|
|
||||||
@@ -59,6 +72,8 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ol>
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -69,7 +84,22 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
background: rgba(127,127,127,0.06);
|
background: rgba(127,127,127,0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toc-global__toggle{
|
||||||
|
width: 100%;
|
||||||
|
appearance: none;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.toc-global__head{
|
.toc-global__head{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
border-bottom: 1px dashed rgba(127,127,127,0.25);
|
border-bottom: 1px dashed rgba(127,127,127,0.25);
|
||||||
@@ -82,11 +112,36 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
opacity: .88;
|
opacity: .88;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toc-global__chevron{
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: .7;
|
||||||
|
transition: transform 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global__body-clip{
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
transition:
|
||||||
|
grid-template-rows 220ms ease,
|
||||||
|
opacity 160ms ease,
|
||||||
|
margin-top 220ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global__body{
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.toc-global__list{
|
.toc-global__list{
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
max-height: 44vh;
|
||||||
|
overflow: auto;
|
||||||
|
padding-right: 8px;
|
||||||
|
scrollbar-gutter: stable;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-global__list li::marker{ content: ""; }
|
.toc-global__list li::marker{ content: ""; }
|
||||||
|
|
||||||
.toc-item{ margin: 6px 0; }
|
.toc-item{ margin: 6px 0; }
|
||||||
@@ -112,13 +167,33 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-active-indicator{
|
.toc-active-mark{
|
||||||
font-size: 14px;
|
width: 14px;
|
||||||
line-height: 1;
|
height: 14px;
|
||||||
|
display: inline-grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
opacity: .55;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-active-spacer{
|
.toc-active-mark__dot{
|
||||||
width: 14px;
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: currentColor;
|
||||||
|
opacity: .65;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-active-mark.is-on{
|
||||||
|
border-color: rgba(127,127,127,0.34);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-active-mark.is-on .toc-active-mark__dot{
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-link__title{
|
.toc-link__title{
|
||||||
@@ -156,11 +231,66 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
.toc-global{
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global__head{
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global__title{
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global__body-clip{
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global.is-collapsed .toc-global__body-clip{
|
||||||
|
grid-template-rows: 0fr;
|
||||||
|
opacity: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global__body{
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: opacity 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global.is-collapsed .toc-global__body{
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-global.is-collapsed .toc-global__chevron{
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-link{
|
||||||
|
padding: 7px 9px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-link__title{
|
||||||
|
font-size: 12.5px;
|
||||||
|
line-height: 1.22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-badge{
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 2px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
.toc-global__list{
|
.toc-global__list{
|
||||||
max-height: 44vh;
|
max-height: min(42vh, 360px);
|
||||||
overflow: auto;
|
padding-right: 4px;
|
||||||
padding-right: 8px;
|
}
|
||||||
scrollbar-gutter: stable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
@media (prefers-color-scheme: dark){
|
||||||
@@ -168,12 +298,88 @@ const entries = [...await getCollection(collection)].sort((a, b) => {
|
|||||||
.toc-link:hover{ background: rgba(255,255,255,0.06); }
|
.toc-link:hover{ background: rgba(255,255,255,0.06); }
|
||||||
.toc-item.is-active .toc-link{ background: rgba(255,255,255,0.06); }
|
.toc-item.is-active .toc-link{ background: rgba(255,255,255,0.06); }
|
||||||
.toc-badge{ background: rgba(255,255,255,0.06); }
|
.toc-badge{ background: rgba(255,255,255,0.06); }
|
||||||
|
.toc-active-mark.is-on{ border-color: rgba(255,255,255,0.22); }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
(() => {
|
(() => {
|
||||||
const active = document.querySelector(".toc-global .toc-item.is-active");
|
function init() {
|
||||||
|
document.querySelectorAll("[data-toc-global]").forEach((nav) => {
|
||||||
|
if (nav.dataset.tocReady === "1") return;
|
||||||
|
nav.dataset.tocReady = "1";
|
||||||
|
|
||||||
|
const toggle = nav.querySelector(".toc-global__toggle");
|
||||||
|
const bodyClip = nav.querySelector(".toc-global__body-clip");
|
||||||
|
const active = nav.querySelector(".toc-item.is-active");
|
||||||
|
const mq = window.matchMedia("(max-width: 980px)");
|
||||||
|
const key = `archicratie:${nav.dataset.tocKey || "toc-global"}`;
|
||||||
|
|
||||||
|
if (!toggle || !bodyClip) return;
|
||||||
|
|
||||||
|
const read = () => {
|
||||||
|
try {
|
||||||
|
const v = localStorage.getItem(key);
|
||||||
|
if (v === "open") return true;
|
||||||
|
if (v === "closed") return false;
|
||||||
|
} catch {}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const write = (open) => {
|
||||||
|
try { localStorage.setItem(key, open ? "open" : "closed"); } catch {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setOpen = (open, { persist = true } = {}) => {
|
||||||
|
const isMobile = mq.matches;
|
||||||
|
nav.classList.toggle("is-collapsed", isMobile && !open);
|
||||||
|
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
||||||
|
if (persist && isMobile) write(open);
|
||||||
|
};
|
||||||
|
|
||||||
|
const initState = () => {
|
||||||
|
if (!mq.matches) {
|
||||||
|
setOpen(true, { persist: false });
|
||||||
if (active) active.scrollIntoView({ block: "nearest" });
|
if (active) active.scrollIntoView({ block: "nearest" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stored = read();
|
||||||
|
const open = stored == null ? false : stored;
|
||||||
|
setOpen(open, { persist: false });
|
||||||
|
|
||||||
|
if (open && active) active.scrollIntoView({ block: "nearest" });
|
||||||
|
};
|
||||||
|
|
||||||
|
toggle.addEventListener("click", () => {
|
||||||
|
const open = toggle.getAttribute("aria-expanded") !== "true";
|
||||||
|
setOpen(open);
|
||||||
|
if (open && active) active.scrollIntoView({ block: "nearest" });
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
window.dispatchEvent(new CustomEvent("archicratie:tocGlobalOpen"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("archicratie:tocLocalOpen", () => {
|
||||||
|
if (!mq.matches) return;
|
||||||
|
setOpen(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mq.addEventListener) {
|
||||||
|
mq.addEventListener("change", initState);
|
||||||
|
} else if (mq.addListener) {
|
||||||
|
mq.addListener(initState);
|
||||||
|
}
|
||||||
|
|
||||||
|
initState();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
window.addEventListener("DOMContentLoaded", init, { once: true });
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
@@ -1,14 +1,7 @@
|
|||||||
---
|
---
|
||||||
import {
|
import {
|
||||||
familyOf,
|
getGlossaryEntryAsideData,
|
||||||
getContextualTheory,
|
getGlossaryPortalLinks,
|
||||||
getDisplayDomain,
|
|
||||||
getDisplayFamily,
|
|
||||||
getDisplayLevel,
|
|
||||||
getEntriesOfSameFamily,
|
|
||||||
getFondamentaux,
|
|
||||||
getRelationSections,
|
|
||||||
getSameFamilyTitle,
|
|
||||||
hrefOfGlossaryEntry,
|
hrefOfGlossaryEntry,
|
||||||
slugOfGlossaryEntry,
|
slugOfGlossaryEntry,
|
||||||
} from "../lib/glossary";
|
} from "../lib/glossary";
|
||||||
@@ -19,28 +12,21 @@ const {
|
|||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
const currentSlug = slugOfGlossaryEntry(currentEntry);
|
const currentSlug = slugOfGlossaryEntry(currentEntry);
|
||||||
const currentFamily = familyOf(currentEntry);
|
|
||||||
|
|
||||||
const fondamentaux = getFondamentaux(allEntries);
|
const {
|
||||||
|
displayFamily,
|
||||||
|
displayDomain,
|
||||||
|
displayLevel,
|
||||||
|
showNoyau,
|
||||||
|
showSameFamily,
|
||||||
|
fondamentaux,
|
||||||
|
sameFamilyTitle,
|
||||||
|
sameFamilyEntries,
|
||||||
|
relationSections,
|
||||||
|
contextualTheory,
|
||||||
|
} = getGlossaryEntryAsideData(currentEntry, allEntries);
|
||||||
|
|
||||||
const displayFamily = getDisplayFamily(currentEntry);
|
const portalLinks = getGlossaryPortalLinks();
|
||||||
const displayDomain = getDisplayDomain(currentEntry);
|
|
||||||
const displayLevel = getDisplayLevel(currentEntry);
|
|
||||||
|
|
||||||
const sameFamilyEntries = getEntriesOfSameFamily(currentEntry, allEntries);
|
|
||||||
const sameFamilyTitle = getSameFamilyTitle(currentEntry);
|
|
||||||
|
|
||||||
const contextualTheory = getContextualTheory(currentEntry, allEntries);
|
|
||||||
|
|
||||||
const showNoyau =
|
|
||||||
currentFamily !== "concept-fondamental" &&
|
|
||||||
fondamentaux.length > 0;
|
|
||||||
|
|
||||||
const showSameFamily =
|
|
||||||
sameFamilyEntries.length > 0 &&
|
|
||||||
currentFamily !== "concept-fondamental";
|
|
||||||
|
|
||||||
const relationSections = getRelationSections(currentEntry, allEntries);
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<nav class="glossary-aside" aria-label="Navigation du glossaire">
|
<nav class="glossary-aside" aria-label="Navigation du glossaire">
|
||||||
@@ -52,26 +38,40 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
<span class="glossary-aside__pill glossary-aside__pill--family">
|
<span class="glossary-aside__pill glossary-aside__pill--family">
|
||||||
{displayFamily}
|
{displayFamily}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
{displayDomain && (
|
||||||
<span class="glossary-aside__pill">{displayDomain}</span>
|
<span class="glossary-aside__pill">{displayDomain}</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{displayLevel && (
|
||||||
<span class="glossary-aside__pill">{displayLevel}</span>
|
<span class="glossary-aside__pill">{displayLevel}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="glossary-aside__block">
|
<details class="glossary-aside__block glossary-aside__disclosure" open>
|
||||||
<h2 class="glossary-aside__heading">Portails</h2>
|
<summary class="glossary-aside__summary">
|
||||||
|
<span class="glossary-aside__heading">Portails</span>
|
||||||
|
<span class="glossary-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-aside__panel">
|
||||||
<ul class="glossary-aside__list">
|
<ul class="glossary-aside__list">
|
||||||
<li><a href="/glossaire/">Accueil du glossaire</a></li>
|
{portalLinks.map((item) => (
|
||||||
<li><a href="/glossaire/index-complet/">Index complet</a></li>
|
<li><a href={item.href}>{item.label}</a></li>
|
||||||
<li><a href="/glossaire/paradigme-archicratique/">Paradigme archicratique</a></li>
|
))}
|
||||||
<li><a href="/glossaire/archicrations/">Archicrations</a></li>
|
|
||||||
<li><a href="/glossaire/paradigmes/">Paradigmes et doctrines</a></li>
|
|
||||||
<li><a href="/glossaire/tensions-irreductibles/">Tensions irréductibles</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
{showNoyau && (
|
{showNoyau && (
|
||||||
<section class="glossary-aside__block">
|
<details class="glossary-aside__block glossary-aside__disclosure" open>
|
||||||
<h2 class="glossary-aside__heading">Noyau archicratique</h2>
|
<summary class="glossary-aside__summary">
|
||||||
|
<span class="glossary-aside__heading">Noyau archicratique</span>
|
||||||
|
<span class="glossary-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-aside__panel">
|
||||||
<ul class="glossary-aside__list">
|
<ul class="glossary-aside__list">
|
||||||
{fondamentaux.map((entry) => {
|
{fondamentaux.map((entry) => {
|
||||||
const active = slugOfGlossaryEntry(entry) === currentSlug;
|
const active = slugOfGlossaryEntry(entry) === currentSlug;
|
||||||
@@ -88,12 +88,18 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showSameFamily && (
|
{showSameFamily && (
|
||||||
<section class="glossary-aside__block">
|
<details class="glossary-aside__block glossary-aside__disclosure" open>
|
||||||
<h2 class="glossary-aside__heading">{sameFamilyTitle}</h2>
|
<summary class="glossary-aside__summary">
|
||||||
|
<span class="glossary-aside__heading">{sameFamilyTitle}</span>
|
||||||
|
<span class="glossary-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-aside__panel">
|
||||||
<ul class="glossary-aside__list">
|
<ul class="glossary-aside__list">
|
||||||
{sameFamilyEntries.map((entry) => {
|
{sameFamilyEntries.map((entry) => {
|
||||||
const active = slugOfGlossaryEntry(entry) === currentSlug;
|
const active = slugOfGlossaryEntry(entry) === currentSlug;
|
||||||
@@ -110,13 +116,18 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{relationSections.length > 0 && (
|
{relationSections.length > 0 && (
|
||||||
<section class="glossary-aside__block">
|
<details class="glossary-aside__block glossary-aside__disclosure" open>
|
||||||
<h2 class="glossary-aside__heading">Autour de cette fiche</h2>
|
<summary class="glossary-aside__summary">
|
||||||
|
<span class="glossary-aside__heading">Autour de cette fiche</span>
|
||||||
|
<span class="glossary-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-aside__panel">
|
||||||
{relationSections.map((section) => (
|
{relationSections.map((section) => (
|
||||||
<>
|
<>
|
||||||
<h3 class="glossary-aside__subheading">{section.title}</h3>
|
<h3 class="glossary-aside__subheading">{section.title}</h3>
|
||||||
@@ -127,18 +138,25 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{contextualTheory.length > 0 && (
|
{contextualTheory.length > 0 && (
|
||||||
<section class="glossary-aside__block">
|
<details class="glossary-aside__block glossary-aside__disclosure" open>
|
||||||
<h2 class="glossary-aside__heading">Paysage théorique</h2>
|
<summary class="glossary-aside__summary">
|
||||||
|
<span class="glossary-aside__heading">Paysage théorique</span>
|
||||||
|
<span class="glossary-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-aside__panel">
|
||||||
<ul class="glossary-aside__list">
|
<ul class="glossary-aside__list">
|
||||||
{contextualTheory.map((entry) => (
|
{contextualTheory.map((entry) => (
|
||||||
<li><a href={hrefOfGlossaryEntry(entry)}>{entry.data.term}</a></li>
|
<li><a href={hrefOfGlossaryEntry(entry)}>{entry.data.term}</a></li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -147,6 +165,7 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__block{
|
.glossary-aside__block{
|
||||||
@@ -154,6 +173,7 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
background: rgba(127,127,127,0.05);
|
background: rgba(127,127,127,0.05);
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__block--intro{
|
.glossary-aside__block--intro{
|
||||||
@@ -171,10 +191,10 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__title{
|
.glossary-aside__title{
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 800;
|
font-weight: 850;
|
||||||
letter-spacing: .2px;
|
letter-spacing: .1px;
|
||||||
line-height: 1.3;
|
line-height: 1.22;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__pills{
|
.glossary-aside__pills{
|
||||||
@@ -194,6 +214,7 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
opacity: .92;
|
opacity: .92;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__pill--family{
|
.glossary-aside__pill--family{
|
||||||
@@ -201,12 +222,54 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.glossary-aside__disclosure{
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__summary{
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__summary::-webkit-details-marker{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__summary:hover{
|
||||||
|
background: rgba(127,127,127,0.035);
|
||||||
|
}
|
||||||
|
|
||||||
.glossary-aside__heading{
|
.glossary-aside__heading{
|
||||||
margin: 0 0 11px;
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 850;
|
||||||
|
line-height: 1.28;
|
||||||
|
opacity: .97;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__chevron{
|
||||||
|
flex: 0 0 auto;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
line-height: 1;
|
||||||
line-height: 1.35;
|
opacity: .72;
|
||||||
opacity: .94;
|
transform: rotate(0deg);
|
||||||
|
transition: transform 160ms ease, opacity 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__disclosure[open] .glossary-aside__chevron{
|
||||||
|
transform: rotate(180deg);
|
||||||
|
opacity: .96;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__panel{
|
||||||
|
padding: 0 14px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__subheading{
|
.glossary-aside__subheading{
|
||||||
@@ -233,16 +296,210 @@ const relationSections = getRelationSections(currentEntry, allEntries);
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-aside__list a.is-active{
|
.glossary-aside__list a.is-active{
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-aside{
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__block{
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__block--intro{
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__back{
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.28;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__title{
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 1.18;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__pills{
|
||||||
|
gap: 6px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__pill{
|
||||||
|
padding: 4px 9px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.26;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__summary{
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__heading{
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__panel{
|
||||||
|
padding: 0 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__subheading{
|
||||||
|
margin: 10px 0 6px;
|
||||||
|
font-size: 11.5px;
|
||||||
|
line-height: 1.26;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__list li{
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__list a{
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.34;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__disclosure:not([open]) .glossary-aside__panel{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-aside__disclosure{
|
||||||
|
background: rgba(127,127,127,0.045);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__disclosure[open] .glossary-aside__summary{
|
||||||
|
border-bottom: 1px solid rgba(127,127,127,0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-aside{
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__block{
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__block--intro{
|
||||||
|
padding: 10px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__back{
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__title{
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.14;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__pills{
|
||||||
|
gap: 5px;
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__pill{
|
||||||
|
padding: 3px 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__summary{
|
||||||
|
padding: 10px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__heading{
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__panel{
|
||||||
|
padding: 0 11px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__subheading{
|
||||||
|
margin: 8px 0 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.18;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__list li{
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__list a{
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.28;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 861px){
|
||||||
|
.glossary-aside__summary{
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-aside__chevron{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
@media (prefers-color-scheme: dark){
|
||||||
.glossary-aside__block,
|
.glossary-aside__block,
|
||||||
.glossary-aside__pill{
|
.glossary-aside__pill{
|
||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255,255,255,0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.glossary-aside__summary:hover{
|
||||||
|
background: rgba(255,255,255,0.03);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
(() => {
|
||||||
|
const syncMobileDisclosure = () => {
|
||||||
|
const mobile = window.matchMedia("(max-width: 860px)").matches;
|
||||||
|
const smallLandscape = window.matchMedia(
|
||||||
|
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||||||
|
).matches;
|
||||||
|
|
||||||
|
const compact = mobile || smallLandscape;
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll(".glossary-aside__disclosure")
|
||||||
|
.forEach((el, index) => {
|
||||||
|
if (!(el instanceof HTMLDetailsElement)) return;
|
||||||
|
|
||||||
|
if (compact) {
|
||||||
|
if (!el.dataset.mobileInit) {
|
||||||
|
el.open = index === 0;
|
||||||
|
el.dataset.mobileInit = "true";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
el.open = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", syncMobileDisclosure, { once: true });
|
||||||
|
} else {
|
||||||
|
syncMobileDisclosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", syncMobileDisclosure);
|
||||||
|
window.addEventListener("pageshow", syncMobileDisclosure);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
110
src/components/GlossaryCardGrid.astro
Normal file
110
src/components/GlossaryCardGrid.astro
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
---
|
||||||
|
import { hrefOfGlossaryEntry, type GlossaryEntry } from "../lib/glossary";
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
entries?: GlossaryEntry[];
|
||||||
|
wide?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
entries = [],
|
||||||
|
wide = false,
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="glossary-cards">
|
||||||
|
{entries.map((entry) => (
|
||||||
|
<a
|
||||||
|
class:list={[
|
||||||
|
"glossary-card",
|
||||||
|
wide && "glossary-card--wide",
|
||||||
|
]}
|
||||||
|
href={hrefOfGlossaryEntry(entry)}
|
||||||
|
>
|
||||||
|
<strong>{entry.data.term}</strong>
|
||||||
|
<span>{entry.data.definitionShort}</span>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-cards{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 7px;
|
||||||
|
padding: 13px 14px;
|
||||||
|
border: 1px solid var(--glossary-border);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: var(--glossary-bg-soft);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card:hover{
|
||||||
|
transform: translateY(-1px);
|
||||||
|
background: var(--glossary-bg-soft-strong);
|
||||||
|
border-color: rgba(0,217,255,0.16);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card--wide{
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card strong{
|
||||||
|
color: var(--glossary-accent);
|
||||||
|
font-size: 1.02rem;
|
||||||
|
line-height: 1.24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card span{
|
||||||
|
color: inherit;
|
||||||
|
font-size: .98rem;
|
||||||
|
line-height: 1.46;
|
||||||
|
opacity: .94;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-cards{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card{
|
||||||
|
gap: 6px;
|
||||||
|
padding: 12px 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card strong{
|
||||||
|
font-size: .98rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card span{
|
||||||
|
font-size: .94rem;
|
||||||
|
line-height: 1.42;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card--wide{
|
||||||
|
grid-column: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-card{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-card:hover{
|
||||||
|
background: rgba(255,255,255,0.07);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
16
src/components/GlossaryEntryBody.astro
Normal file
16
src/components/GlossaryEntryBody.astro
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="glossary-entry-body">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-entry-body{
|
||||||
|
margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.glossary-entry-body h2),
|
||||||
|
:global(.glossary-entry-body h3),
|
||||||
|
:global(.glossary-relations h2),
|
||||||
|
:global(.glossary-relations h3){
|
||||||
|
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 18px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
260
src/components/GlossaryEntryHero.astro
Normal file
260
src/components/GlossaryEntryHero.astro
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
---
|
||||||
|
interface Props {
|
||||||
|
term: string;
|
||||||
|
definitionShort: string;
|
||||||
|
displayFamily: string;
|
||||||
|
displayDomain?: string;
|
||||||
|
displayLevel?: string;
|
||||||
|
mobilizedAuthors?: string[];
|
||||||
|
comparisonTraditions?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
term,
|
||||||
|
definitionShort,
|
||||||
|
displayFamily,
|
||||||
|
displayDomain = "",
|
||||||
|
displayLevel = "",
|
||||||
|
mobilizedAuthors = [],
|
||||||
|
comparisonTraditions = [],
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
const hasScholarlyMeta =
|
||||||
|
mobilizedAuthors.length > 0 ||
|
||||||
|
comparisonTraditions.length > 0;
|
||||||
|
---
|
||||||
|
|
||||||
|
<header class="glossary-entry-head" data-ge-hero>
|
||||||
|
<div class="glossary-entry-head__title">
|
||||||
|
<h1>{term}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="glossary-entry-summary">
|
||||||
|
<p class="glossary-entry-dek">
|
||||||
|
<em>{definitionShort}</em>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="glossary-entry-signals" aria-label="Repères de lecture">
|
||||||
|
<span class="glossary-pill glossary-pill--family">
|
||||||
|
<strong>Famille :</strong> {displayFamily}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{displayDomain && (
|
||||||
|
<span class="glossary-pill">
|
||||||
|
<strong>Domaine :</strong> {displayDomain}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{displayLevel && (
|
||||||
|
<span class="glossary-pill">
|
||||||
|
<strong>Niveau :</strong> {displayLevel}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{hasScholarlyMeta && (
|
||||||
|
<div class="glossary-entry-meta">
|
||||||
|
{mobilizedAuthors.length > 0 && (
|
||||||
|
<p>
|
||||||
|
<strong>Auteurs mobilisés :</strong> {mobilizedAuthors.join(" / ")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{comparisonTraditions.length > 0 && (
|
||||||
|
<p>
|
||||||
|
<strong>Traditions de comparaison :</strong> {comparisonTraditions.join(" / ")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-entry-head{
|
||||||
|
position: sticky;
|
||||||
|
top: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px));
|
||||||
|
z-index: 11;
|
||||||
|
margin: 0 0 22px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.18);
|
||||||
|
border-radius: 24px;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(0,0,0,0.60), rgba(0,0,0,0.92)),
|
||||||
|
radial-gradient(900px 240px at 20% 0%, rgba(0,217,255,0.08), transparent 60%);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
overflow: hidden;
|
||||||
|
transition:
|
||||||
|
border-radius 180ms ease,
|
||||||
|
box-shadow 180ms ease,
|
||||||
|
border-color 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-head__title{
|
||||||
|
padding:
|
||||||
|
var(--entry-hero-pad-top, 18px)
|
||||||
|
var(--entry-hero-pad-x, 18px)
|
||||||
|
calc(var(--entry-hero-pad-top, 18px) - 2px);
|
||||||
|
transition: padding 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-head h1{
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--entry-hero-h1-size, clamp(2.2rem, 4vw, 3.15rem));
|
||||||
|
line-height: 1.02;
|
||||||
|
letter-spacing: -.04em;
|
||||||
|
font-weight: 850;
|
||||||
|
transition: font-size 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-summary{
|
||||||
|
display: grid;
|
||||||
|
gap: var(--entry-hero-gap, 14px);
|
||||||
|
padding:
|
||||||
|
calc(var(--entry-hero-pad-bottom, 18px) - 2px)
|
||||||
|
var(--entry-hero-pad-x, 18px)
|
||||||
|
var(--entry-hero-pad-bottom, 18px);
|
||||||
|
border-top: 1px solid rgba(127,127,127,0.14);
|
||||||
|
background: rgba(255,255,255,0.02);
|
||||||
|
transition: gap 180ms ease, padding 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-dek{
|
||||||
|
margin: 0;
|
||||||
|
max-width: var(--entry-hero-dek-maxw, 76ch);
|
||||||
|
font-size: var(--entry-hero-dek-size, 1.04rem);
|
||||||
|
line-height: var(--entry-hero-dek-lh, 1.55);
|
||||||
|
opacity: .94;
|
||||||
|
transition:
|
||||||
|
max-width 180ms ease,
|
||||||
|
font-size 180ms ease,
|
||||||
|
line-height 180ms ease;
|
||||||
|
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 4;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-signals{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 7px;
|
||||||
|
margin: 0;
|
||||||
|
transition: gap 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-pill{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 5px 9px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.24);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(127,127,127,0.05);
|
||||||
|
font-size: 12.5px;
|
||||||
|
line-height: 1.28;
|
||||||
|
transition:
|
||||||
|
padding 180ms ease,
|
||||||
|
font-size 180ms ease,
|
||||||
|
background 120ms ease,
|
||||||
|
border-color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-pill--family{
|
||||||
|
border-color: rgba(127,127,127,0.36);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-meta{
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.18);
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgba(127,127,127,0.04);
|
||||||
|
max-height: var(--entry-hero-meta-max-h, 12rem);
|
||||||
|
opacity: var(--entry-hero-meta-opacity, 1);
|
||||||
|
overflow: hidden;
|
||||||
|
transition:
|
||||||
|
max-height 180ms ease,
|
||||||
|
opacity 140ms ease,
|
||||||
|
padding 180ms ease,
|
||||||
|
border-color 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-meta p{
|
||||||
|
margin: 0;
|
||||||
|
font-size: 13.5px;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-meta p + p{
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-entry-head{
|
||||||
|
position: static;
|
||||||
|
border-radius: 18px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-head__title{
|
||||||
|
padding: 12px 12px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-summary{
|
||||||
|
gap: 9px;
|
||||||
|
padding: 10px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-dek{
|
||||||
|
max-width: none;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-signals{
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-pill{
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 520px){
|
||||||
|
.glossary-entry-head{
|
||||||
|
border-radius: 16px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-head__title{
|
||||||
|
padding: 10px 10px 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-summary{
|
||||||
|
gap: 8px;
|
||||||
|
padding: 9px 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-entry-dek{
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-pill{
|
||||||
|
font-size: 11.5px;
|
||||||
|
padding: 3px 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-entry-meta{
|
||||||
|
background: rgba(255,255,255,0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-pill{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
31
src/components/GlossaryEntryLegacyNote.astro
Normal file
31
src/components/GlossaryEntryLegacyNote.astro
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
interface Props {
|
||||||
|
canonicalHref: string;
|
||||||
|
term: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { canonicalHref, term } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<p class="glossary-legacy-note">
|
||||||
|
Cette entrée a été renommée. L’intitulé canonique est :
|
||||||
|
<a href={canonicalHref}>{term}</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-legacy-note{
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.22);
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgba(127,127,127,0.05);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.45;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-legacy-note{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
289
src/components/GlossaryEntryStickySync.astro
Normal file
289
src/components/GlossaryEntryStickySync.astro
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
<script is:inline>
|
||||||
|
(() => {
|
||||||
|
const boot = () => {
|
||||||
|
const body = document.body;
|
||||||
|
const root = document.documentElement;
|
||||||
|
const hero = document.querySelector("[data-ge-hero]");
|
||||||
|
const follow = document.getElementById("reading-follow");
|
||||||
|
const mqMobile = window.matchMedia("(max-width: 860px)");
|
||||||
|
const mqSmallLandscape = window.matchMedia(
|
||||||
|
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!body || !root || !hero || !follow) return;
|
||||||
|
|
||||||
|
const BODY_CLASS = "is-glossary-entry-page";
|
||||||
|
const FOLLOW_ON_CLASS = "glossary-entry-follow-on";
|
||||||
|
|
||||||
|
let lastHeight = -1;
|
||||||
|
let lastFollowOn = null;
|
||||||
|
let raf = 0;
|
||||||
|
|
||||||
|
body.classList.add(BODY_CLASS);
|
||||||
|
|
||||||
|
const isCompactViewport = () =>
|
||||||
|
mqMobile.matches || mqSmallLandscape.matches;
|
||||||
|
|
||||||
|
const heroHeight = () =>
|
||||||
|
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
||||||
|
|
||||||
|
const neutralizeGlobalFollowIfCompact = () => {
|
||||||
|
if (!isCompactViewport()) {
|
||||||
|
follow.style.display = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
follow.classList.remove("is-on");
|
||||||
|
follow.setAttribute("aria-hidden", "true");
|
||||||
|
follow.style.display = "none";
|
||||||
|
root.style.setProperty("--followbar-h", "0px");
|
||||||
|
};
|
||||||
|
|
||||||
|
const computeFollowOn = () =>
|
||||||
|
!isCompactViewport() &&
|
||||||
|
follow.classList.contains("is-on") &&
|
||||||
|
follow.style.display !== "none" &&
|
||||||
|
follow.getAttribute("aria-hidden") !== "true";
|
||||||
|
|
||||||
|
const stripLocalSticky = () => {
|
||||||
|
document
|
||||||
|
.querySelectorAll(
|
||||||
|
".glossary-entry-body h2, .glossary-entry-body h3, .glossary-relations h2, .glossary-relations h3"
|
||||||
|
)
|
||||||
|
.forEach((el) => {
|
||||||
|
el.classList.remove("is-sticky");
|
||||||
|
el.removeAttribute("data-sticky-active");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyLocalStickyHeight = () => {
|
||||||
|
const h = isCompactViewport() ? 0 : heroHeight();
|
||||||
|
if (h === lastHeight) return;
|
||||||
|
lastHeight = h;
|
||||||
|
|
||||||
|
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
||||||
|
window.__archiSetLocalStickyHeight(h);
|
||||||
|
} else {
|
||||||
|
root.style.setProperty("--glossary-local-sticky-h", `${h}px`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncFollowState = () => {
|
||||||
|
const on = computeFollowOn();
|
||||||
|
if (on === lastFollowOn) return;
|
||||||
|
lastFollowOn = on;
|
||||||
|
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncAll = () => {
|
||||||
|
neutralizeGlobalFollowIfCompact();
|
||||||
|
stripLocalSticky();
|
||||||
|
syncFollowState();
|
||||||
|
applyLocalStickyHeight();
|
||||||
|
};
|
||||||
|
|
||||||
|
const schedule = () => {
|
||||||
|
if (raf) return;
|
||||||
|
raf = requestAnimationFrame(() => {
|
||||||
|
raf = 0;
|
||||||
|
syncAll();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const followObserver = new MutationObserver(schedule);
|
||||||
|
followObserver.observe(follow, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ["class", "style", "aria-hidden"],
|
||||||
|
subtree: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const heroResizeObserver =
|
||||||
|
typeof ResizeObserver !== "undefined"
|
||||||
|
? new ResizeObserver(schedule)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
heroResizeObserver?.observe(hero);
|
||||||
|
|
||||||
|
window.addEventListener("resize", schedule);
|
||||||
|
window.addEventListener("pageshow", schedule);
|
||||||
|
|
||||||
|
if (document.fonts?.ready) {
|
||||||
|
document.fonts.ready.then(schedule).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mqMobile.addEventListener) {
|
||||||
|
mqMobile.addEventListener("change", schedule);
|
||||||
|
} else if (mqMobile.addListener) {
|
||||||
|
mqMobile.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>
|
||||||
|
:global(body.is-glossary-entry-page #reading-follow){
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-head){
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
box-shadow: 0 8px 20px rgba(0,0,0,0.10);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-head h1){
|
||||||
|
letter-spacing: -.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-summary){
|
||||||
|
gap: 8px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-top-color: rgba(127,127,127,0.10);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-dek){
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-signals){
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-pill){
|
||||||
|
gap: 4px;
|
||||||
|
padding: 3px 7px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-meta){
|
||||||
|
padding: 0;
|
||||||
|
border-color: transparent;
|
||||||
|
max-height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on #reading-follow){
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on #reading-follow .reading-follow__inner){
|
||||||
|
margin-top: -1px;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page .glossary-entry-body h2.is-sticky),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-entry-body h2[data-sticky-active="true"]),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-entry-body h3.is-sticky),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-entry-body h3[data-sticky-active="true"]),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-relations h2.is-sticky),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-relations h2[data-sticky-active="true"]),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-relations h3.is-sticky),
|
||||||
|
:global(body.is-glossary-entry-page .glossary-relations h3[data-sticky-active="true"]){
|
||||||
|
position: static !important;
|
||||||
|
top: auto !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
:global(body.is-glossary-entry-page #reading-follow),
|
||||||
|
:global(body.is-glossary-entry-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page){
|
||||||
|
--followbar-h: 0px !important;
|
||||||
|
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-head){
|
||||||
|
margin-bottom: 18px;
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-summary){
|
||||||
|
gap: 6px;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-dek){
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-signals){
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-pill){
|
||||||
|
padding: 3px 6px;
|
||||||
|
font-size: 10.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
:global(body.is-glossary-entry-page #reading-follow),
|
||||||
|
:global(body.is-glossary-entry-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page){
|
||||||
|
--followbar-h: 0px !important;
|
||||||
|
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-head){
|
||||||
|
margin-bottom: 14px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-summary){
|
||||||
|
gap: 5px;
|
||||||
|
padding-top: 6px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-dek){
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-pill){
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
import {
|
import {
|
||||||
countGlossaryEntriesByFamily,
|
|
||||||
countGlossaryEntriesByKind,
|
|
||||||
getFondamentaux,
|
getFondamentaux,
|
||||||
|
getGlossaryHomeStats,
|
||||||
|
getGlossaryPortalLinks,
|
||||||
hrefOfGlossaryEntry,
|
hrefOfGlossaryEntry,
|
||||||
} from "../lib/glossary";
|
} from "../lib/glossary";
|
||||||
|
|
||||||
@@ -11,23 +11,14 @@ const {
|
|||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
const fondamentaux = getFondamentaux(allEntries);
|
const fondamentaux = getFondamentaux(allEntries);
|
||||||
|
const portalLinks = getGlossaryPortalLinks();
|
||||||
|
|
||||||
const totalEntries = allEntries.length;
|
const {
|
||||||
const paradigmesCount = countGlossaryEntriesByKind(allEntries, "paradigme");
|
totalEntries,
|
||||||
const doctrinesCount = countGlossaryEntriesByKind(allEntries, "doctrine");
|
paradigmesCount,
|
||||||
const metaRegimesCount = countGlossaryEntriesByFamily(allEntries, "meta-regime");
|
doctrinesCount,
|
||||||
|
metaRegimesCount,
|
||||||
const portalLinks = [
|
} = getGlossaryHomeStats(allEntries);
|
||||||
{ href: "/glossaire/concepts-fondamentaux/", label: "Concepts fondamentaux" },
|
|
||||||
{ href: "/glossaire/index-complet/", label: "Index complet" },
|
|
||||||
{ 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/archicrations/", label: "Méta-régimes archicratiques" },
|
|
||||||
{ href: "/glossaire/paradigmes/", label: "Paradigmes et doctrines" },
|
|
||||||
{ href: "/glossaire/verbes-de-la-scene/", label: "Verbes de la scène" },
|
|
||||||
];
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<nav class="glossary-home-aside" aria-label="Navigation du portail du glossaire">
|
<nav class="glossary-home-aside" aria-label="Navigation du portail du glossaire">
|
||||||
@@ -46,24 +37,36 @@ const portalLinks = [
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="glossary-home-aside__block">
|
<details class="glossary-home-aside__block glossary-home-aside__disclosure" open>
|
||||||
<h2 class="glossary-home-aside__heading">Parcours du glossaire</h2>
|
<summary class="glossary-home-aside__summary">
|
||||||
|
<span class="glossary-home-aside__heading">Parcours du glossaire</span>
|
||||||
|
<span class="glossary-home-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-home-aside__panel">
|
||||||
<ul class="glossary-home-aside__list">
|
<ul class="glossary-home-aside__list">
|
||||||
{portalLinks.map((item) => (
|
{portalLinks.map((item) => (
|
||||||
<li><a href={item.href}>{item.label}</a></li>
|
<li><a href={item.href}>{item.label}</a></li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
{fondamentaux.length > 0 && (
|
{fondamentaux.length > 0 && (
|
||||||
<section class="glossary-home-aside__block">
|
<details class="glossary-home-aside__block glossary-home-aside__disclosure" open>
|
||||||
<h2 class="glossary-home-aside__heading">Noyau archicratique</h2>
|
<summary class="glossary-home-aside__summary">
|
||||||
|
<span class="glossary-home-aside__heading">Noyau archicratique</span>
|
||||||
|
<span class="glossary-home-aside__chevron" aria-hidden="true">▾</span>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="glossary-home-aside__panel">
|
||||||
<ul class="glossary-home-aside__list">
|
<ul class="glossary-home-aside__list">
|
||||||
{fondamentaux.map((entry) => (
|
{fondamentaux.map((entry) => (
|
||||||
<li><a href={hrefOfGlossaryEntry(entry)}>{entry.data.term}</a></li>
|
<li><a href={hrefOfGlossaryEntry(entry)}>{entry.data.term}</a></li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -72,6 +75,7 @@ const portalLinks = [
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-home-aside__block{
|
.glossary-home-aside__block{
|
||||||
@@ -79,6 +83,7 @@ const portalLinks = [
|
|||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
background: rgba(127,127,127,0.05);
|
background: rgba(127,127,127,0.05);
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-home-aside__block--intro{
|
.glossary-home-aside__block--intro{
|
||||||
@@ -87,10 +92,10 @@ const portalLinks = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
.glossary-home-aside__title{
|
.glossary-home-aside__title{
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 800;
|
font-weight: 850;
|
||||||
letter-spacing: .2px;
|
letter-spacing: .1px;
|
||||||
line-height: 1.3;
|
line-height: 1.22;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-home-aside__meta{
|
.glossary-home-aside__meta{
|
||||||
@@ -117,14 +122,57 @@ const portalLinks = [
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
opacity: .92;
|
opacity: .92;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__disclosure{
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__summary{
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__summary::-webkit-details-marker{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__summary:hover{
|
||||||
|
background: rgba(127,127,127,0.035);
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-home-aside__heading{
|
.glossary-home-aside__heading{
|
||||||
margin: 0 0 11px;
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 850;
|
||||||
|
line-height: 1.28;
|
||||||
|
opacity: .97;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__chevron{
|
||||||
|
flex: 0 0 auto;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
line-height: 1;
|
||||||
line-height: 1.35;
|
opacity: .72;
|
||||||
opacity: .94;
|
transform: rotate(0deg);
|
||||||
|
transition: transform 160ms ease, opacity 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__disclosure[open] .glossary-home-aside__chevron{
|
||||||
|
transform: rotate(180deg);
|
||||||
|
opacity: .96;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__panel{
|
||||||
|
padding: 0 14px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glossary-home-aside__list{
|
.glossary-home-aside__list{
|
||||||
@@ -140,7 +188,148 @@ const portalLinks = [
|
|||||||
.glossary-home-aside__list a{
|
.glossary-home-aside__list a{
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.4;
|
line-height: 1.42;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-home-aside{
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__block{
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__block--intro{
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__title{
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 1.18;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__meta{
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__pills{
|
||||||
|
gap: 6px;
|
||||||
|
margin-top: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__pill{
|
||||||
|
padding: 4px 9px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.28;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__summary{
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__heading{
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__panel{
|
||||||
|
padding: 0 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__list li{
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__list a{
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.34;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__disclosure:not([open]) .glossary-home-aside__panel{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-home-aside__disclosure{
|
||||||
|
background: rgba(127,127,127,0.045);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__disclosure[open] .glossary-home-aside__summary{
|
||||||
|
border-bottom: 1px solid rgba(127,127,127,0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-home-aside{
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__block{
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__block--intro{
|
||||||
|
padding: 10px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__title{
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.14;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__meta{
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.26;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__pills{
|
||||||
|
gap: 5px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__pill{
|
||||||
|
padding: 3px 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__summary{
|
||||||
|
padding: 10px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__heading{
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__panel{
|
||||||
|
padding: 0 11px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__list li{
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__list a{
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.28;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 861px){
|
||||||
|
.glossary-home-aside__summary{
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__chevron{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
@media (prefers-color-scheme: dark){
|
||||||
@@ -148,5 +337,46 @@ const portalLinks = [
|
|||||||
.glossary-home-aside__pill{
|
.glossary-home-aside__pill{
|
||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255,255,255,0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.glossary-home-aside__summary:hover{
|
||||||
|
background: rgba(255,255,255,0.03);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
(() => {
|
||||||
|
const syncMobileDisclosure = () => {
|
||||||
|
const mobile = window.matchMedia("(max-width: 860px)").matches;
|
||||||
|
const smallLandscape = window.matchMedia(
|
||||||
|
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||||||
|
).matches;
|
||||||
|
|
||||||
|
const compact = mobile || smallLandscape;
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll(".glossary-home-aside__disclosure")
|
||||||
|
.forEach((el, index) => {
|
||||||
|
if (!(el instanceof HTMLDetailsElement)) return;
|
||||||
|
|
||||||
|
if (compact) {
|
||||||
|
if (!el.dataset.mobileInit) {
|
||||||
|
el.open = index === 0;
|
||||||
|
el.dataset.mobileInit = "true";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
el.open = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", syncMobileDisclosure, { once: true });
|
||||||
|
} else {
|
||||||
|
syncMobileDisclosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", syncMobileDisclosure);
|
||||||
|
window.addEventListener("pageshow", syncMobileDisclosure);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
364
src/components/GlossaryHomeHero.astro
Normal file
364
src/components/GlossaryHomeHero.astro
Normal file
@@ -0,0 +1,364 @@
|
|||||||
|
---
|
||||||
|
export interface Props {
|
||||||
|
kicker?: string;
|
||||||
|
title?: string;
|
||||||
|
intro?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
kicker = "Référentiel terminologique",
|
||||||
|
title = "Glossaire archicratique",
|
||||||
|
intro = "Ce glossaire n’est pas seulement un index de définitions. Il constitue une porte d’entrée dans la pensée archicratique : une cartographie raisonnée des concepts fondamentaux, des scènes, des dynamiques et des méta-régimes à partir desquels une société peut être décrite comme organisation de tensions et recherche de co-viabilité.",
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<header class="glossary-hero" id="glossary-hero">
|
||||||
|
<p class="glossary-kicker">{kicker}</p>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
|
||||||
|
<div class="glossary-hero__collapsible">
|
||||||
|
<p
|
||||||
|
class="glossary-intro"
|
||||||
|
id="glossary-hero-intro"
|
||||||
|
aria-hidden="false"
|
||||||
|
>
|
||||||
|
{intro}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="glossary-hero__toggle"
|
||||||
|
id="glossary-hero-toggle"
|
||||||
|
type="button"
|
||||||
|
aria-controls="glossary-hero-intro"
|
||||||
|
aria-expanded="false"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
lire la suite
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2
|
||||||
|
class="glossary-hero-follow"
|
||||||
|
id="glossary-hero-follow"
|
||||||
|
aria-hidden="true"
|
||||||
|
></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-hero{
|
||||||
|
position: sticky;
|
||||||
|
top: var(--glossary-sticky-top);
|
||||||
|
z-index: 12;
|
||||||
|
margin-bottom: 28px;
|
||||||
|
padding: 14px 16px 18px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.18);
|
||||||
|
border-radius: 28px;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(0,0,0,0.60), rgba(0,0,0,0.90)),
|
||||||
|
radial-gradient(900px 240px at 20% 0%, rgba(0,217,255,0.08), transparent 60%);
|
||||||
|
transition:
|
||||||
|
padding 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
border-radius 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
background 300ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
border-color 300ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
box-shadow 300ms cubic-bezier(.22,.8,.22,1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
display: grid;
|
||||||
|
row-gap: 12px;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-kicker{
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
letter-spacing: .12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
opacity: .72;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero h1{
|
||||||
|
margin: 0;
|
||||||
|
font-size: clamp(2.2rem, 4vw, 3.15rem);
|
||||||
|
line-height: 1.02;
|
||||||
|
letter-spacing: -.04em;
|
||||||
|
font-weight: 850;
|
||||||
|
transition:
|
||||||
|
font-size 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
line-height 220ms cubic-bezier(.22,.8,.22,1);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__collapsible{
|
||||||
|
display: grid;
|
||||||
|
row-gap: 6px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-intro{
|
||||||
|
margin: 0;
|
||||||
|
max-width: 72ch;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
line-height: 1.55;
|
||||||
|
opacity: .94;
|
||||||
|
min-width: 0;
|
||||||
|
transition:
|
||||||
|
font-size 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
line-height 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
max-height 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
opacity 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__toggle{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: fit-content;
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 3px 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
letter-spacing: .01em;
|
||||||
|
opacity: .72;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
transition:
|
||||||
|
opacity 120ms ease,
|
||||||
|
transform 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__toggle:hover{
|
||||||
|
opacity: .92;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__toggle:focus-visible{
|
||||||
|
outline: 2px solid rgba(0,217,255,0.24);
|
||||||
|
outline-offset: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__toggle[hidden]{
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero-follow{
|
||||||
|
margin: 2px 0 0;
|
||||||
|
min-height: var(--glossary-follow-height);
|
||||||
|
display: block;
|
||||||
|
max-width: min(100%, 22ch);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px) scale(.985);
|
||||||
|
filter: blur(6px);
|
||||||
|
transition:
|
||||||
|
opacity 220ms cubic-bezier(.22,1,.36,1),
|
||||||
|
transform 320ms cubic-bezier(.22,1,.36,1),
|
||||||
|
filter 320ms cubic-bezier(.22,1,.36,1);
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
will-change: opacity, transform, filter;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero-follow.is-visible{
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0) scale(1);
|
||||||
|
filter: blur(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero{
|
||||||
|
padding: 12px 14px 14px;
|
||||||
|
border-bottom-left-radius: 18px;
|
||||||
|
border-bottom-right-radius: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero h1{
|
||||||
|
font-size: clamp(1.7rem, 3.2vw, 2.2rem);
|
||||||
|
line-height: 1.02;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on:not(.glossary-home-hero-expanded)) .glossary-intro{
|
||||||
|
font-size: .94rem;
|
||||||
|
line-height: 1.34;
|
||||||
|
max-height: 2.7em;
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on:not(.glossary-home-hero-expanded)) .glossary-hero__toggle{
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-hero{
|
||||||
|
top: calc(var(--glossary-sticky-top) - 2px);
|
||||||
|
padding: 12px 14px 16px;
|
||||||
|
border-radius: 22px;
|
||||||
|
row-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero h1{
|
||||||
|
font-size: clamp(1.9rem, 8vw, 2.45rem);
|
||||||
|
line-height: 1.02;
|
||||||
|
letter-spacing: -.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__collapsible{
|
||||||
|
row-gap: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-intro{
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: .98rem;
|
||||||
|
line-height: 1.44;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero{
|
||||||
|
padding: 10px 13px 12px;
|
||||||
|
border-radius: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero h1{
|
||||||
|
font-size: clamp(1.45rem, 6vw, 1.8rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on:not(.glossary-home-hero-expanded)) .glossary-intro{
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: .86rem;
|
||||||
|
line-height: 1.24;
|
||||||
|
max-height: 2.48em;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
opacity: .9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__toggle{
|
||||||
|
min-height: 28px;
|
||||||
|
font-size: 11.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero-follow{
|
||||||
|
max-width: min(100%, 24ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 520px){
|
||||||
|
.glossary-hero{
|
||||||
|
padding: 11px 12px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-intro{
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: .94rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero{
|
||||||
|
padding: 9px 11px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on:not(.glossary-home-hero-expanded)) .glossary-intro{
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: .84rem;
|
||||||
|
line-height: 1.22;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-hero{
|
||||||
|
padding: 10px 12px 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
row-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-kicker{
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: .1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero h1{
|
||||||
|
font-size: clamp(1.35rem, 4vw, 1.8rem);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-intro{
|
||||||
|
font-size: .84rem;
|
||||||
|
line-height: 1.24;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero{
|
||||||
|
padding: 9px 11px 10px;
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on) .glossary-hero h1{
|
||||||
|
font-size: clamp(1.1rem, 3vw, 1.35rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.glossary-home-follow-on:not(.glossary-home-hero-expanded)) .glossary-intro{
|
||||||
|
font-size: .8rem;
|
||||||
|
line-height: 1.18;
|
||||||
|
max-height: 2.36em;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
opacity: .88;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero__toggle{
|
||||||
|
min-height: 24px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero-follow{
|
||||||
|
max-width: min(100%, 26ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-hero{
|
||||||
|
position: static !important;
|
||||||
|
top: auto !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
margin-bottom: 18px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero-follow{
|
||||||
|
display: none !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
transform: none !important;
|
||||||
|
filter: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-hero{
|
||||||
|
position: static !important;
|
||||||
|
top: auto !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
margin-bottom: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-hero-follow{
|
||||||
|
display: none !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
transform: none !important;
|
||||||
|
filter: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
133
src/components/GlossaryHomeSection.astro
Normal file
133
src/components/GlossaryHomeSection.astro
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
export interface Props {
|
||||||
|
id?: string;
|
||||||
|
title: string;
|
||||||
|
intro?: string;
|
||||||
|
followSection?: string;
|
||||||
|
ctaHref?: string;
|
||||||
|
ctaLabel?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
intro,
|
||||||
|
followSection,
|
||||||
|
ctaHref,
|
||||||
|
ctaLabel,
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
const resolvedFollowSection = (followSection || title || "").trim();
|
||||||
|
const showCta = Boolean(ctaHref && ctaLabel);
|
||||||
|
---
|
||||||
|
|
||||||
|
<section id={id} class="glossary-section">
|
||||||
|
<div class="glossary-section__head">
|
||||||
|
<div>
|
||||||
|
<h2 data-follow-section={resolvedFollowSection}>{title}</h2>
|
||||||
|
|
||||||
|
{intro && (
|
||||||
|
<p class="glossary-intro">{intro}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showCta && (
|
||||||
|
<a class="glossary-cta" href={ctaHref}>
|
||||||
|
{ctaLabel}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-section{
|
||||||
|
margin-top: 34px;
|
||||||
|
scroll-margin-top: calc(var(--glossary-sticky-top) + 150px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-section__head{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: start;
|
||||||
|
gap: 14px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-section h2{
|
||||||
|
margin: 0;
|
||||||
|
font-size: clamp(1.8rem, 3vw, 2.55rem);
|
||||||
|
line-height: 1.06;
|
||||||
|
letter-spacing: -.03em;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-intro{
|
||||||
|
margin: 0;
|
||||||
|
max-width: 72ch;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.52;
|
||||||
|
opacity: .94;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-section__head .glossary-intro{
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-cta{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 38px;
|
||||||
|
border: 1px solid var(--glossary-border-strong);
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 6px 13px;
|
||||||
|
color: var(--glossary-accent);
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: transform 120ms ease, background 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-cta:hover{
|
||||||
|
background: var(--glossary-bg-soft-strong);
|
||||||
|
text-decoration: none;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-section{
|
||||||
|
margin-top: 24px;
|
||||||
|
scroll-margin-top: calc(var(--glossary-sticky-top) + 110px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-section__head{
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-section h2{
|
||||||
|
font-size: clamp(1.45rem, 6vw, 1.95rem);
|
||||||
|
line-height: 1.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-intro{
|
||||||
|
font-size: .95rem;
|
||||||
|
line-height: 1.42;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-section__head .glossary-intro{
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-cta{
|
||||||
|
width: fit-content;
|
||||||
|
min-height: 35px;
|
||||||
|
padding: 5px 12px;
|
||||||
|
font-size: .95rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
219
src/components/GlossaryPortalAside.astro
Normal file
219
src/components/GlossaryPortalAside.astro
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
---
|
||||||
|
interface LinkItem {
|
||||||
|
href: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
ariaLabel: string;
|
||||||
|
title: string;
|
||||||
|
meta?: string;
|
||||||
|
backHref?: string;
|
||||||
|
backLabel?: string;
|
||||||
|
pageItems?: LinkItem[];
|
||||||
|
usefulLinks?: LinkItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
ariaLabel,
|
||||||
|
title,
|
||||||
|
meta,
|
||||||
|
backHref = "/glossaire/",
|
||||||
|
backLabel = "← Retour au glossaire",
|
||||||
|
pageItems = [],
|
||||||
|
usefulLinks = [],
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav class="glossary-portal-aside" aria-label={ariaLabel}>
|
||||||
|
<div class="glossary-portal-aside__block">
|
||||||
|
<a class="glossary-portal-aside__back" href={backHref}>{backLabel}</a>
|
||||||
|
<div class="glossary-portal-aside__title">{title}</div>
|
||||||
|
{meta && <div class="glossary-portal-aside__meta">{meta}</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{pageItems.length > 0 && (
|
||||||
|
<div class="glossary-portal-aside__block">
|
||||||
|
<h2 class="glossary-portal-aside__heading">Dans cette page</h2>
|
||||||
|
<ul class="glossary-portal-aside__list">
|
||||||
|
{pageItems.map((item) => (
|
||||||
|
<li><a href={item.href}>{item.label}</a></li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{usefulLinks.length > 0 && (
|
||||||
|
<div class="glossary-portal-aside__block">
|
||||||
|
<h2 class="glossary-portal-aside__heading">Renvois utiles</h2>
|
||||||
|
<ul class="glossary-portal-aside__list">
|
||||||
|
{usefulLinks.map((item) => (
|
||||||
|
<li><a href={item.href}>{item.label}</a></li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-portal-aside{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__block{
|
||||||
|
border: 1px solid rgba(127,127,127,0.22);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 14px;
|
||||||
|
background: rgba(127,127,127,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__back{
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.35;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__title{
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: .2px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__meta{
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.4;
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__heading{
|
||||||
|
margin: 0 0 11px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.35;
|
||||||
|
opacity: .94;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list{
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list li{
|
||||||
|
margin: 7px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list a{
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
.glossary-portal-aside{
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__block{
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-portal-aside{
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__block{
|
||||||
|
padding: 11px 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__back{
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__title{
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__meta{
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__heading{
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list li{
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list a{
|
||||||
|
font-size: 12.5px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-portal-aside{
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__block{
|
||||||
|
padding: 9px 10px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__back{
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__title{
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.18;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__meta{
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__heading{
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.18;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list li{
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-aside__list a{
|
||||||
|
font-size: 11.5px;
|
||||||
|
line-height: 1.22;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-portal-aside__block{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
67
src/components/GlossaryPortalCta.astro
Normal file
67
src/components/GlossaryPortalCta.astro
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
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;
|
||||||
|
min-height: 40px;
|
||||||
|
padding: 7px 14px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.24);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(127,127,127,0.05);
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1.2;
|
||||||
|
transition:
|
||||||
|
transform 120ms ease,
|
||||||
|
background 120ms ease,
|
||||||
|
border-color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-cta:hover{
|
||||||
|
transform: translateY(-1px);
|
||||||
|
background: rgba(127,127,127,0.08);
|
||||||
|
border-color: rgba(0,217,255,0.18);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-cta:focus-visible{
|
||||||
|
outline: 2px solid rgba(0,217,255,0.28);
|
||||||
|
outline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-portal-cta{
|
||||||
|
min-height: 36px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-portal-cta{
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
118
src/components/GlossaryPortalGrid.astro
Normal file
118
src/components/GlossaryPortalGrid.astro
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
---
|
||||||
|
export type GlossaryPortalGridItem = {
|
||||||
|
href: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
meta: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
items?: GlossaryPortalGridItem[];
|
||||||
|
secondary?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
items = [],
|
||||||
|
secondary = false,
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div
|
||||||
|
class:list={[
|
||||||
|
"glossary-portals",
|
||||||
|
secondary && "glossary-portals--secondary",
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{items.map((item) => (
|
||||||
|
<a class="glossary-portal-card" href={item.href}>
|
||||||
|
<strong>{item.title}</strong>
|
||||||
|
<span>{item.description}</span>
|
||||||
|
<small>{item.meta}</small>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-portals{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 7px;
|
||||||
|
padding: 14px 15px;
|
||||||
|
border: 1px solid var(--glossary-border);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: var(--glossary-bg-soft);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card:hover{
|
||||||
|
transform: translateY(-1px);
|
||||||
|
background: var(--glossary-bg-soft-strong);
|
||||||
|
border-color: rgba(0,217,255,0.16);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card strong{
|
||||||
|
color: var(--glossary-accent);
|
||||||
|
font-size: 1.04rem;
|
||||||
|
line-height: 1.24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card span{
|
||||||
|
color: inherit;
|
||||||
|
font-size: .98rem;
|
||||||
|
line-height: 1.46;
|
||||||
|
opacity: .94;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card small{
|
||||||
|
color: var(--glossary-accent);
|
||||||
|
font-size: .9rem;
|
||||||
|
line-height: 1.28;
|
||||||
|
opacity: .9;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-portals{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card{
|
||||||
|
padding: 12px 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card strong{
|
||||||
|
font-size: .98rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card span{
|
||||||
|
font-size: .94rem;
|
||||||
|
line-height: 1.42;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card small{
|
||||||
|
font-size: .85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-portal-card{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-card:hover{
|
||||||
|
background: rgba(255,255,255,0.07);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
260
src/components/GlossaryPortalHero.astro
Normal file
260
src/components/GlossaryPortalHero.astro
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
---
|
||||||
|
interface Props {
|
||||||
|
prefix: string;
|
||||||
|
kicker: string;
|
||||||
|
title: string;
|
||||||
|
intro: string;
|
||||||
|
moreParagraphs?: string[];
|
||||||
|
introMaxWidth?: string;
|
||||||
|
followIntroMaxWidth?: string;
|
||||||
|
moreMaxHeight?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
prefix,
|
||||||
|
kicker,
|
||||||
|
title,
|
||||||
|
intro,
|
||||||
|
moreParagraphs = [],
|
||||||
|
introMaxWidth = "70ch",
|
||||||
|
followIntroMaxWidth = "62ch",
|
||||||
|
moreMaxHeight = "18rem",
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="glossary-portal-hero glossary-page-hero"
|
||||||
|
data-glossary-portal-hero
|
||||||
|
style={`--portal-hero-intro-max-w:${introMaxWidth}; --portal-hero-follow-intro-max-w:${followIntroMaxWidth}; --portal-hero-secondary-max-h:${moreMaxHeight};`}
|
||||||
|
>
|
||||||
|
<p class="glossary-portal-hero__kicker">{kicker}</p>
|
||||||
|
|
||||||
|
<h1>{title}</h1>
|
||||||
|
|
||||||
|
<p class="glossary-portal-hero__intro glossary-portal-hero__intro--lead">
|
||||||
|
{intro}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{moreParagraphs.length > 0 && (
|
||||||
|
<div class="glossary-portal-hero__collapsible">
|
||||||
|
<div
|
||||||
|
class="glossary-portal-hero__more"
|
||||||
|
id={`${prefix}-hero-more`}
|
||||||
|
data-glossary-portal-more
|
||||||
|
aria-hidden="false"
|
||||||
|
>
|
||||||
|
{moreParagraphs.map((paragraph) => (
|
||||||
|
<p class="glossary-portal-hero__intro glossary-portal-hero__intro--more">
|
||||||
|
{paragraph}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="glossary-portal-hero__toggle"
|
||||||
|
id={`${prefix}-hero-toggle`}
|
||||||
|
data-glossary-portal-toggle
|
||||||
|
type="button"
|
||||||
|
aria-controls={`${prefix}-hero-more`}
|
||||||
|
aria-expanded="false"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
lire la suite
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-portal-hero{
|
||||||
|
position: sticky;
|
||||||
|
top: var(--glossary-sticky-top);
|
||||||
|
z-index: 12;
|
||||||
|
margin-bottom: var(--portal-hero-margin-bottom, 28px);
|
||||||
|
padding:
|
||||||
|
var(--portal-hero-pad-top, 20px)
|
||||||
|
var(--portal-hero-pad-x, 18px)
|
||||||
|
var(--portal-hero-pad-bottom, 22px);
|
||||||
|
border: 1px solid rgba(127,127,127,0.18);
|
||||||
|
border-radius: 28px;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(0,0,0,0.60), rgba(0,0,0,0.92)),
|
||||||
|
radial-gradient(980px 260px at 18% 0%, rgba(0,217,255,0.08), transparent 60%);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
display: grid;
|
||||||
|
row-gap: var(--portal-hero-gap, 16px);
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition:
|
||||||
|
background 280ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
border-color 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
box-shadow 220ms cubic-bezier(.22,.8,.22,1),
|
||||||
|
border-radius 220ms ease,
|
||||||
|
padding 220ms ease,
|
||||||
|
row-gap 220ms ease,
|
||||||
|
margin-bottom 220ms ease;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255,255,255,0.02),
|
||||||
|
0 10px 26px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__kicker{
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--portal-kicker-size, 12px);
|
||||||
|
line-height: var(--portal-kicker-lh, 1.2);
|
||||||
|
letter-spacing: var(--portal-kicker-spacing, .14em);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 650;
|
||||||
|
opacity: .74;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero h1{
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--portal-hero-h1-size, clamp(3rem, 4.8vw, 4.15rem));
|
||||||
|
line-height: var(--portal-hero-h1-lh, .98);
|
||||||
|
letter-spacing: var(--portal-hero-h1-spacing, -.045em);
|
||||||
|
font-weight: 850;
|
||||||
|
text-wrap: balance;
|
||||||
|
transition:
|
||||||
|
font-size 180ms ease,
|
||||||
|
line-height 180ms ease,
|
||||||
|
letter-spacing 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__intro{
|
||||||
|
margin: 0;
|
||||||
|
max-width: var(--portal-hero-intro-max-w, 70ch);
|
||||||
|
font-size: var(--portal-hero-intro-size, 1.06rem);
|
||||||
|
line-height: var(--portal-hero-intro-lh, 1.6);
|
||||||
|
text-wrap: pretty;
|
||||||
|
transition:
|
||||||
|
font-size 180ms ease,
|
||||||
|
line-height 180ms ease,
|
||||||
|
max-width 180ms ease,
|
||||||
|
opacity 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__intro--lead{ opacity: .95; }
|
||||||
|
.glossary-portal-hero__intro--more{ opacity: .89; }
|
||||||
|
|
||||||
|
.glossary-portal-hero__collapsible{
|
||||||
|
display: grid;
|
||||||
|
row-gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__more{
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
max-height: var(--portal-hero-secondary-max-h, 20em);
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: var(--portal-hero-secondary-opacity, .92);
|
||||||
|
min-width: 0;
|
||||||
|
transition:
|
||||||
|
max-height 220ms ease,
|
||||||
|
opacity 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__toggle{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: fit-content;
|
||||||
|
min-height: 34px;
|
||||||
|
padding: 5px 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 12.5px;
|
||||||
|
line-height: 1.2;
|
||||||
|
letter-spacing: .01em;
|
||||||
|
opacity: .72;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
transition:
|
||||||
|
opacity 120ms ease,
|
||||||
|
transform 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__toggle:hover{
|
||||||
|
opacity: .92;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__toggle:focus-visible{
|
||||||
|
outline: 2px solid rgba(0,217,255,0.24);
|
||||||
|
outline-offset: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__toggle[hidden]{
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
.glossary-portal-hero{
|
||||||
|
border-radius: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero h1{
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero__more{
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
.glossary-portal-hero{
|
||||||
|
position: static !important;
|
||||||
|
top: auto !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
margin-bottom: 18px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
min-width: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero h1,
|
||||||
|
.glossary-portal-hero__intro,
|
||||||
|
.glossary-portal-hero__more,
|
||||||
|
.glossary-portal-hero__collapsible{
|
||||||
|
min-width: 0 !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-portal-hero{
|
||||||
|
position: static !important;
|
||||||
|
top: auto !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
margin-bottom: 14px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
min-width: 0 !important;
|
||||||
|
border-radius: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-hero h1,
|
||||||
|
.glossary-portal-hero__intro,
|
||||||
|
.glossary-portal-hero__more,
|
||||||
|
.glossary-portal-hero__collapsible{
|
||||||
|
min-width: 0 !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-portal-hero{
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255,255,255,0.02),
|
||||||
|
0 14px 34px rgba(0,0,0,0.16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
127
src/components/GlossaryPortalPanel.astro
Normal file
127
src/components/GlossaryPortalPanel.astro
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
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: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel--surface{
|
||||||
|
padding:
|
||||||
|
var(--portal-panel-pad-y, 16px)
|
||||||
|
var(--portal-panel-pad-x, 16px);
|
||||||
|
border: 1px solid var(--glossary-border, rgba(127,127,127,0.18));
|
||||||
|
border-radius: var(--portal-panel-radius, 18px);
|
||||||
|
background:
|
||||||
|
var(--glossary-bg-soft, rgba(127,127,127,0.035));
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__head{
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__head h3{
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--portal-local-h3-size, clamp(1.35rem, 2vw, 1.7rem));
|
||||||
|
line-height: var(--portal-local-h3-lh, 1.15);
|
||||||
|
letter-spacing: -.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__count{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 26px;
|
||||||
|
padding: 0 9px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.20);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(127,127,127,0.04);
|
||||||
|
font-size: 11.5px;
|
||||||
|
line-height: 1.2;
|
||||||
|
opacity: .8;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__intro{
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--portal-card-text-size, 14px);
|
||||||
|
line-height: var(--portal-card-text-lh, 1.45);
|
||||||
|
opacity: .92;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-portal-panel{
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__head{
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__count{
|
||||||
|
min-height: 23px;
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: 10.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-portal-panel{
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__head{
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-panel__count{
|
||||||
|
min-height: 21px;
|
||||||
|
padding: 0 7px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-portal-panel--surface{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
143
src/components/GlossaryPortalSection.astro
Normal file
143
src/components/GlossaryPortalSection.astro
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
---
|
||||||
|
interface Props {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
count?: string;
|
||||||
|
intro?: string;
|
||||||
|
final?: boolean;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
count,
|
||||||
|
intro,
|
||||||
|
final = false,
|
||||||
|
className,
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<section class:list={["glossary-portal-section", final && "glossary-portal-section--final", className]}>
|
||||||
|
<div class="glossary-portal-section__head">
|
||||||
|
<h2 id={id}>{title}</h2>
|
||||||
|
{count && <span class="glossary-portal-section__count">{count}</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{intro && <p class="glossary-portal-section__intro">{intro}</p>}
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-portal-section{
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section h2{
|
||||||
|
margin: 0;
|
||||||
|
font-size: clamp(1.8rem, 3vw, 2.35rem);
|
||||||
|
line-height: 1.05;
|
||||||
|
letter-spacing: -.03em;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__head{
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__count{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid rgba(127,127,127,0.20);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(127,127,127,0.04);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
opacity: .8;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__intro{
|
||||||
|
margin: 0;
|
||||||
|
max-width: 76ch;
|
||||||
|
font-size: var(--portal-body-size, 1rem);
|
||||||
|
line-height: var(--portal-body-lh, 1.55);
|
||||||
|
opacity: .94;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section--final{
|
||||||
|
margin-top: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
.glossary-portal-section{
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section h2{
|
||||||
|
font-size: clamp(1.6rem, 4.4vw, 2rem);
|
||||||
|
line-height: 1.04;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-portal-section{
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__head{
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section h2{
|
||||||
|
font-size: clamp(1.34rem, 6.5vw, 1.72rem);
|
||||||
|
line-height: 1.04;
|
||||||
|
letter-spacing: -.022em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__count{
|
||||||
|
min-height: 24px;
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section--final{
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.glossary-portal-section{
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__head{
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section h2{
|
||||||
|
font-size: clamp(1.12rem, 4.2vw, 1.34rem);
|
||||||
|
line-height: 1.02;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section__count{
|
||||||
|
min-height: 22px;
|
||||||
|
padding: 0 7px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-portal-section--final{
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
487
src/components/GlossaryPortalStickySync.astro
Normal file
487
src/components/GlossaryPortalStickySync.astro
Normal file
@@ -0,0 +1,487 @@
|
|||||||
|
---
|
||||||
|
interface Props {
|
||||||
|
heroMoreId: string;
|
||||||
|
heroToggleId: string;
|
||||||
|
sectionHeadSelector?: string;
|
||||||
|
mobileBreakpoint?: number;
|
||||||
|
autoCollapseDelta?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
heroMoreId,
|
||||||
|
heroToggleId,
|
||||||
|
sectionHeadSelector = ".glossary-portal-section__head",
|
||||||
|
mobileBreakpoint = 860,
|
||||||
|
autoCollapseDelta = 160,
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<script
|
||||||
|
is:inline
|
||||||
|
define:vars={{ heroMoreId, heroToggleId, sectionHeadSelector, mobileBreakpoint, autoCollapseDelta }}
|
||||||
|
>
|
||||||
|
(() => {
|
||||||
|
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 heroMore = document.getElementById(heroMoreId);
|
||||||
|
const heroToggle = document.getElementById(heroToggleId);
|
||||||
|
|
||||||
|
if (!body || !root || !hero || !follow) return;
|
||||||
|
|
||||||
|
const BODY_CLASS = "is-glossary-portal-page";
|
||||||
|
const FOLLOW_ON_CLASS = "glossary-portal-follow-on";
|
||||||
|
const EXPANDED_CLASS = "glossary-portal-hero-expanded";
|
||||||
|
const CONDENSED_CLASS = "glossary-portal-hero-condensed";
|
||||||
|
|
||||||
|
const mqMobile = window.matchMedia(`(max-width: ${mobileBreakpoint}px)`);
|
||||||
|
const mqSmallLandscape = window.matchMedia(
|
||||||
|
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||||||
|
);
|
||||||
|
|
||||||
|
let expandedAtY = null;
|
||||||
|
let lastScrollY = window.scrollY || 0;
|
||||||
|
let raf = 0;
|
||||||
|
let lastFollowOn = null;
|
||||||
|
let lastCondensed = null;
|
||||||
|
let lastHeroHeight = -1;
|
||||||
|
|
||||||
|
body.classList.add(BODY_CLASS);
|
||||||
|
|
||||||
|
const isCompactViewport = () =>
|
||||||
|
mqMobile.matches || mqSmallLandscape.matches;
|
||||||
|
|
||||||
|
const stripLocalSticky = () => {
|
||||||
|
document.querySelectorAll(sectionHeadSelector).forEach((el) => {
|
||||||
|
el.classList.remove("is-sticky");
|
||||||
|
el.removeAttribute("data-sticky-active");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const readStickyTop = () => {
|
||||||
|
const raw = getComputedStyle(document.documentElement)
|
||||||
|
.getPropertyValue("--glossary-sticky-top")
|
||||||
|
.trim();
|
||||||
|
const n = Number.parseFloat(raw);
|
||||||
|
return Number.isFinite(n) ? n : 64;
|
||||||
|
};
|
||||||
|
|
||||||
|
const computeFollowOn = () =>
|
||||||
|
!isCompactViewport() &&
|
||||||
|
follow.classList.contains("is-on") &&
|
||||||
|
follow.style.display !== "none" &&
|
||||||
|
follow.getAttribute("aria-hidden") !== "true";
|
||||||
|
|
||||||
|
const computeCondensed = () => {
|
||||||
|
if (isCompactViewport()) return false;
|
||||||
|
|
||||||
|
const heroRect = hero.getBoundingClientRect();
|
||||||
|
const stickyTop = readStickyTop();
|
||||||
|
|
||||||
|
return heroRect.top <= stickyTop + 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
const measureHeroHeight = () =>
|
||||||
|
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
||||||
|
|
||||||
|
const PIN_EPS = 3;
|
||||||
|
|
||||||
|
const isHeroPinned = () => {
|
||||||
|
if (isCompactViewport()) return false;
|
||||||
|
|
||||||
|
const rect = hero.getBoundingClientRect();
|
||||||
|
const stickyTop = readStickyTop();
|
||||||
|
const cs = getComputedStyle(hero);
|
||||||
|
|
||||||
|
if (cs.position !== "sticky") return false;
|
||||||
|
|
||||||
|
const pinnedOnRail = Math.abs(rect.top - stickyTop) <= PIN_EPS;
|
||||||
|
const stillVisible = rect.bottom > stickyTop + 24;
|
||||||
|
|
||||||
|
return pinnedOnRail && stillVisible;
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyLocalStickyHeight = () => {
|
||||||
|
const h = isHeroPinned() ? measureHeroHeight() : 0;
|
||||||
|
if (h === lastHeroHeight) return;
|
||||||
|
lastHeroHeight = h;
|
||||||
|
|
||||||
|
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
||||||
|
window.__archiSetLocalStickyHeight(h);
|
||||||
|
} else {
|
||||||
|
root.style.setProperty("--glossary-local-sticky-h", `${h}px`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncFollowState = () => {
|
||||||
|
const on = computeFollowOn();
|
||||||
|
|
||||||
|
if (on !== lastFollowOn) {
|
||||||
|
lastFollowOn = on;
|
||||||
|
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
||||||
|
}
|
||||||
|
|
||||||
|
return on;
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncCondensedState = () => {
|
||||||
|
const condensed = computeCondensed();
|
||||||
|
|
||||||
|
if (condensed !== lastCondensed) {
|
||||||
|
lastCondensed = condensed;
|
||||||
|
body.classList.toggle(CONDENSED_CLASS, condensed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return condensed;
|
||||||
|
};
|
||||||
|
|
||||||
|
const collapseHero = () => {
|
||||||
|
if (!body.classList.contains(EXPANDED_CLASS)) return;
|
||||||
|
|
||||||
|
body.classList.remove(EXPANDED_CLASS);
|
||||||
|
expandedAtY = null;
|
||||||
|
|
||||||
|
if (heroMore) {
|
||||||
|
heroMore.setAttribute("aria-hidden", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroToggle) {
|
||||||
|
heroToggle.hidden = false;
|
||||||
|
heroToggle.setAttribute("aria-expanded", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.__archiUpdateFollow?.();
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
schedule();
|
||||||
|
};
|
||||||
|
|
||||||
|
const expandHero = () => {
|
||||||
|
body.classList.add(EXPANDED_CLASS);
|
||||||
|
expandedAtY = window.scrollY || 0;
|
||||||
|
|
||||||
|
if (heroMore) {
|
||||||
|
heroMore.setAttribute("aria-hidden", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroToggle) {
|
||||||
|
heroToggle.hidden = true;
|
||||||
|
heroToggle.setAttribute("aria-expanded", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.__archiUpdateFollow?.();
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
schedule();
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncHeroState = (condensed) => {
|
||||||
|
const expanded = body.classList.contains(EXPANDED_CLASS);
|
||||||
|
const collapsed = condensed && !expanded;
|
||||||
|
|
||||||
|
if (isCompactViewport() || !condensed) {
|
||||||
|
body.classList.remove(EXPANDED_CLASS);
|
||||||
|
expandedAtY = null;
|
||||||
|
|
||||||
|
if (heroMore) {
|
||||||
|
heroMore.setAttribute("aria-hidden", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroToggle) {
|
||||||
|
heroToggle.hidden = true;
|
||||||
|
heroToggle.setAttribute("aria-expanded", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroMore) {
|
||||||
|
heroMore.setAttribute("aria-hidden", collapsed ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroToggle) {
|
||||||
|
heroToggle.hidden = !collapsed;
|
||||||
|
heroToggle.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const maybeAutoCollapseOnScroll = () => {
|
||||||
|
if (isCompactViewport()) {
|
||||||
|
lastScrollY = window.scrollY || 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!body.classList.contains(EXPANDED_CLASS)) {
|
||||||
|
lastScrollY = window.scrollY || 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expandedAtY == null) {
|
||||||
|
lastScrollY = window.scrollY || 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentY = window.scrollY || 0;
|
||||||
|
const scrollingDown = currentY > lastScrollY;
|
||||||
|
const delta = currentY - expandedAtY;
|
||||||
|
|
||||||
|
if (scrollingDown && delta >= autoCollapseDelta) {
|
||||||
|
collapseHero();
|
||||||
|
}
|
||||||
|
|
||||||
|
lastScrollY = currentY;
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncAll = () => {
|
||||||
|
stripLocalSticky();
|
||||||
|
|
||||||
|
if (isCompactViewport()) {
|
||||||
|
body.classList.remove(FOLLOW_ON_CLASS);
|
||||||
|
body.classList.remove(CONDENSED_CLASS);
|
||||||
|
body.classList.remove(EXPANDED_CLASS);
|
||||||
|
|
||||||
|
lastFollowOn = false;
|
||||||
|
lastCondensed = false;
|
||||||
|
expandedAtY = null;
|
||||||
|
|
||||||
|
if (heroMore) {
|
||||||
|
heroMore.setAttribute("aria-hidden", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroToggle) {
|
||||||
|
heroToggle.hidden = true;
|
||||||
|
heroToggle.setAttribute("aria-expanded", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
applyLocalStickyHeight();
|
||||||
|
try {
|
||||||
|
window.__archiUpdateFollow?.();
|
||||||
|
} catch {}
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const condensed = syncCondensedState();
|
||||||
|
syncHeroState(condensed);
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
applyLocalStickyHeight();
|
||||||
|
syncFollowState();
|
||||||
|
try {
|
||||||
|
window.__archiUpdateFollow?.();
|
||||||
|
} catch {}
|
||||||
|
});
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
applyLocalStickyHeight();
|
||||||
|
try {
|
||||||
|
window.__archiUpdateFollow?.();
|
||||||
|
} catch {}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const schedule = () => {
|
||||||
|
if (raf) return;
|
||||||
|
raf = requestAnimationFrame(() => {
|
||||||
|
raf = 0;
|
||||||
|
syncAll();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
heroToggle?.addEventListener("click", expandHero);
|
||||||
|
|
||||||
|
const onScroll = () => {
|
||||||
|
maybeAutoCollapseOnScroll();
|
||||||
|
schedule();
|
||||||
|
};
|
||||||
|
|
||||||
|
const followObserver = new MutationObserver(schedule);
|
||||||
|
followObserver.observe(follow, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ["class", "style", "aria-hidden"],
|
||||||
|
subtree: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const heroResizeObserver =
|
||||||
|
typeof ResizeObserver !== "undefined"
|
||||||
|
? new ResizeObserver(schedule)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
heroResizeObserver?.observe(hero);
|
||||||
|
|
||||||
|
window.addEventListener("scroll", onScroll, { passive: true });
|
||||||
|
window.addEventListener("resize", schedule);
|
||||||
|
window.addEventListener("pageshow", schedule);
|
||||||
|
|
||||||
|
if (document.fonts?.ready) {
|
||||||
|
document.fonts.ready.then(schedule).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mqMobile.addEventListener) {
|
||||||
|
mqMobile.addEventListener("change", schedule);
|
||||||
|
} else if (mqMobile.addListener) {
|
||||||
|
mqMobile.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>
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow){
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Le hero se condense dès qu’il devient sticky */
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed .glossary-portal-hero){
|
||||||
|
padding:
|
||||||
|
var(--portal-hero-pad-top-condensed, 14px)
|
||||||
|
var(--portal-hero-pad-x-condensed, 16px)
|
||||||
|
var(--portal-hero-pad-bottom-condensed, 16px);
|
||||||
|
row-gap: var(--portal-hero-gap-condensed, 10px);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255,255,255,0.02),
|
||||||
|
0 8px 20px rgba(0,0,0,0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed .glossary-portal-hero h1){
|
||||||
|
font-size: var(--portal-hero-h1-size-condensed, clamp(2.05rem, 3.15vw, 2.7rem));
|
||||||
|
line-height: var(--portal-hero-h1-lh-condensed, 1);
|
||||||
|
letter-spacing: var(--portal-hero-h1-spacing-condensed, -.04em);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed .glossary-portal-hero__intro){
|
||||||
|
max-width: var(--portal-hero-follow-intro-max-w, 62ch);
|
||||||
|
font-size: var(--portal-hero-intro-size-condensed, .98rem);
|
||||||
|
line-height: var(--portal-hero-intro-lh-condensed, 1.46);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed .glossary-portal-hero__kicker){
|
||||||
|
opacity: .68;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Le more se replie dès l’état condensé */
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed:not(.glossary-portal-hero-expanded) .glossary-portal-hero__more){
|
||||||
|
max-height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed:not(.glossary-portal-hero-expanded) .glossary-portal-hero__toggle){
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* L’accolage hero + follow n’arrive que quand le follow est actif */
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-hero-condensed.glossary-portal-follow-on .glossary-portal-hero){
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-follow-on #reading-follow .reading-follow__inner){
|
||||||
|
margin-top: -1px;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page.glossary-portal-follow-on #reading-follow .rf-h2){
|
||||||
|
letter-spacing: -.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-section__head.is-sticky),
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-section__head[data-sticky-active="true"]){
|
||||||
|
position: static !important;
|
||||||
|
top: auto !important;
|
||||||
|
z-index: auto !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow),
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page){
|
||||||
|
--followbar-h: 0px !important;
|
||||||
|
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-hero){
|
||||||
|
margin-bottom: var(--portal-hero-margin-bottom, 18px);
|
||||||
|
border-radius: 20px !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-hero__more){
|
||||||
|
max-height: none !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-hero__toggle){
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow),
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page){
|
||||||
|
--followbar-h: 0px !important;
|
||||||
|
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-hero){
|
||||||
|
margin-bottom: var(--portal-hero-margin-bottom, 12px);
|
||||||
|
border-radius: 16px !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-hero__more){
|
||||||
|
max-height: none !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page .glossary-portal-hero__toggle){
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,12 +7,15 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { relationBlocks = [] } = Astro.props;
|
const { relationBlocks = [] } = Astro.props;
|
||||||
|
const relationsHeadingId = "relations-conceptuelles";
|
||||||
---
|
---
|
||||||
|
|
||||||
{relationBlocks.length > 0 && (
|
{relationBlocks.length > 0 && (
|
||||||
<section class="glossary-relations" aria-label="Relations conceptuelles">
|
<section
|
||||||
<h2>Relations conceptuelles</h2>
|
class="glossary-relations"
|
||||||
|
aria-labelledby={relationsHeadingId}
|
||||||
|
>
|
||||||
|
<h2 id={relationsHeadingId}>Relations conceptuelles</h2>
|
||||||
<div class="glossary-relations-grid">
|
<div class="glossary-relations-grid">
|
||||||
{relationBlocks.map((block) => (
|
{relationBlocks.map((block) => (
|
||||||
<section class={`glossary-relations-card ${block.className}`}>
|
<section class={`glossary-relations-card ${block.className}`}>
|
||||||
@@ -30,3 +33,93 @@ const { relationBlocks = [] } = Astro.props;
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.glossary-relations{
|
||||||
|
margin-top: 22px;
|
||||||
|
padding-top: 14px;
|
||||||
|
border-top: 1px solid rgba(127,127,127,0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations h2{
|
||||||
|
margin: 0 0 12px;
|
||||||
|
font-size: clamp(1.35rem, 3vw, 1.8rem);
|
||||||
|
line-height: 1.08;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-grid{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card{
|
||||||
|
border: 1px solid rgba(127,127,127,0.20);
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 12px 13px;
|
||||||
|
background: rgba(127,127,127,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card h3{
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card ul{
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card li{
|
||||||
|
margin-bottom: 7px;
|
||||||
|
font-size: 13.5px;
|
||||||
|
line-height: 1.42;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card li:last-child{
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card span{
|
||||||
|
opacity: .88;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.glossary-relations{
|
||||||
|
margin-top: 18px;
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations h2{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-grid{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card{
|
||||||
|
padding: 11px 11px;
|
||||||
|
border-radius: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card h3{
|
||||||
|
font-size: 13px;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-relations-card li{
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.38;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark){
|
||||||
|
.glossary-relations-card{
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -68,7 +68,6 @@ const { initialLevel = 1 } = Astro.props;
|
|||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// init : storage > initialLevel
|
|
||||||
let start = clampLevel(initialLevel);
|
let start = clampLevel(initialLevel);
|
||||||
try {
|
try {
|
||||||
const stored = localStorage.getItem(KEY);
|
const stored = localStorage.getItem(KEY);
|
||||||
@@ -77,13 +76,11 @@ const { initialLevel = 1 } = Astro.props;
|
|||||||
|
|
||||||
applyLevel(start, { persist: false });
|
applyLevel(start, { persist: false });
|
||||||
|
|
||||||
// clicks
|
|
||||||
wrap.addEventListener("click", (ev) => {
|
wrap.addEventListener("click", (ev) => {
|
||||||
const btn = ev.target?.closest?.("button[data-level]");
|
const btn = ev.target?.closest?.("button[data-level]");
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
// ✅ crucial : on capture la position AVANT le reflow lié au changement de niveau
|
|
||||||
captureBeforeLevelSwitch();
|
captureBeforeLevelSwitch();
|
||||||
applyLevel(btn.dataset.level);
|
applyLevel(btn.dataset.level);
|
||||||
});
|
});
|
||||||
@@ -95,6 +92,8 @@ const { initialLevel = 1 } = Astro.props;
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-btn{
|
.level-btn{
|
||||||
@@ -106,6 +105,7 @@ const { initialLevel = 1 } = Astro.props;
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
transition: filter .12s ease, transform .12s ease, background .12s ease, border-color .12s ease;
|
transition: filter .12s ease, transform .12s ease, background .12s ease, border-color .12s ease;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-btn:hover{
|
.level-btn:hover{
|
||||||
@@ -125,4 +125,21 @@ const { initialLevel = 1 } = Astro.props;
|
|||||||
.level-btn:active{
|
.level-btn:active{
|
||||||
transform: translateY(1px);
|
transform: translateY(1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
.level-toggle{
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-btn{
|
||||||
|
padding: 5px 9px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.level-toggle{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -3,12 +3,23 @@ const { headings } = Astro.props;
|
|||||||
|
|
||||||
// H2/H3 seulement
|
// H2/H3 seulement
|
||||||
const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
||||||
|
const tocId = `toc-local-${Math.random().toString(36).slice(2, 9)}`;
|
||||||
---
|
---
|
||||||
|
|
||||||
{items.length > 0 && (
|
{items.length > 0 && (
|
||||||
<nav class="toc-local" aria-label="Dans ce chapitre">
|
<nav class="toc-local" aria-label="Dans ce chapitre" data-toc-local>
|
||||||
<div class="toc-local__title">Dans ce chapitre</div>
|
<button
|
||||||
|
class="toc-local__head toc-local__toggle"
|
||||||
|
type="button"
|
||||||
|
aria-expanded="true"
|
||||||
|
aria-controls={tocId}
|
||||||
|
>
|
||||||
|
<span class="toc-local__title">Dans ce chapitre</span>
|
||||||
|
<span class="toc-local__chevron" aria-hidden="true">▾</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="toc-local__body-clip" id={tocId}>
|
||||||
|
<div class="toc-local__body">
|
||||||
<ol class="toc-local__list">
|
<ol class="toc-local__list">
|
||||||
{items.map((h) => (
|
{items.map((h) => (
|
||||||
<li
|
<li
|
||||||
@@ -18,34 +29,96 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
data-id={h.slug}
|
data-id={h.slug}
|
||||||
>
|
>
|
||||||
<a href={`#${h.slug}`} data-toc-link data-slug={h.slug}>
|
<a href={`#${h.slug}`} data-toc-link data-slug={h.slug}>
|
||||||
{h.text}
|
<span class="toc-local__mark" aria-hidden="true"></span>
|
||||||
|
<span class="toc-local__text">{h.text}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ol>
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
(() => {
|
(() => {
|
||||||
function init() {
|
function init() {
|
||||||
const toc = document.querySelector(".toc-local");
|
const toc = document.querySelector(".toc-local[data-toc-local]");
|
||||||
if (!toc) return;
|
if (!toc || toc.dataset.tocReady === "1") return;
|
||||||
|
toc.dataset.tocReady = "1";
|
||||||
|
|
||||||
|
const toggle = toc.querySelector(".toc-local__toggle");
|
||||||
|
const bodyClip = toc.querySelector(".toc-local__body-clip");
|
||||||
|
const mq = window.matchMedia("(max-width: 980px)");
|
||||||
|
const KEY = `archicratie:toc-local:${window.location.pathname}`;
|
||||||
|
|
||||||
|
if (!toggle || !bodyClip) return;
|
||||||
|
|
||||||
|
const readState = () => {
|
||||||
|
try {
|
||||||
|
const v = localStorage.getItem(KEY);
|
||||||
|
if (v === "open") return true;
|
||||||
|
if (v === "closed") return false;
|
||||||
|
} catch {}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const writeState = (open) => {
|
||||||
|
try { localStorage.setItem(KEY, open ? "open" : "closed"); } catch {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setOpen = (open, { persist = true, emit = true } = {}) => {
|
||||||
|
const isMobile = mq.matches;
|
||||||
|
toc.classList.toggle("is-collapsed", isMobile && !open);
|
||||||
|
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
||||||
|
|
||||||
|
if (persist && isMobile) writeState(open);
|
||||||
|
|
||||||
|
if (emit && open && isMobile) {
|
||||||
|
window.dispatchEvent(new CustomEvent("archicratie:tocLocalOpen"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initAccordion = () => {
|
||||||
|
if (!mq.matches) {
|
||||||
|
setOpen(true, { persist: false, emit: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const stored = readState();
|
||||||
|
setOpen(stored == null ? true : stored, { persist: false, emit: false });
|
||||||
|
};
|
||||||
|
|
||||||
|
toggle.addEventListener("click", () => {
|
||||||
|
const next = toggle.getAttribute("aria-expanded") !== "true";
|
||||||
|
setOpen(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mq.addEventListener) {
|
||||||
|
mq.addEventListener("change", initAccordion);
|
||||||
|
} else if (mq.addListener) {
|
||||||
|
mq.addListener(initAccordion);
|
||||||
|
}
|
||||||
|
|
||||||
const itemEls = Array.from(toc.querySelectorAll("[data-toc-item]"));
|
const itemEls = Array.from(toc.querySelectorAll("[data-toc-item]"));
|
||||||
if (!itemEls.length) return;
|
if (!itemEls.length) {
|
||||||
|
initAccordion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ordered = itemEls
|
const ordered = itemEls
|
||||||
.map((li) => {
|
.map((li) => {
|
||||||
const a = li.querySelector("a[data-toc-link]");
|
const a = li.querySelector("a[data-toc-link]");
|
||||||
const id = li.getAttribute("data-id") || a?.dataset.slug || "";
|
const id = li.getAttribute("data-id") || a?.dataset.slug || "";
|
||||||
const depth = Number(li.getAttribute("data-depth") || "0");
|
const depth = Number(li.getAttribute("data-depth") || "0");
|
||||||
const el = id ? document.getElementById(id) : null; // span.details-anchor OU h3[id]
|
const el = id ? document.getElementById(id) : null;
|
||||||
return (a && id && el) ? { id, depth, li, a, el } : null;
|
return (a && id && el) ? { id, depth, li, a, el } : null;
|
||||||
})
|
})
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
if (!ordered.length) return;
|
if (!ordered.length) {
|
||||||
|
initAccordion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
for (const t of ordered) {
|
for (const t of ordered) {
|
||||||
@@ -55,14 +128,29 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openDetailsIfNeeded = (el) => {
|
const openDetailsIfNeeded = (el) => {
|
||||||
const d = el?.closest?.("details");
|
try {
|
||||||
if (d && !d.open) d.open = true;
|
if (!el) return;
|
||||||
|
|
||||||
|
let d = el.closest?.("details") || null;
|
||||||
|
|
||||||
|
if (!d && el.classList?.contains("details-anchor")) {
|
||||||
|
const n = el.nextElementSibling;
|
||||||
|
if (n && n.tagName === "DETAILS") d = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
const s = el.closest?.("summary");
|
||||||
|
if (s && s.parentElement && s.parentElement.tagName === "DETAILS") d = s.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d && d.tagName === "DETAILS" && !d.open) d.open = true;
|
||||||
|
} catch {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let current = "";
|
let current = "";
|
||||||
|
|
||||||
const setCurrent = (id) => {
|
const setCurrent = (id, { autoOpen = true } = {}) => {
|
||||||
if (!id || id === current) return;
|
if (!id) return;
|
||||||
const t = ordered.find((x) => x.id === id);
|
const t = ordered.find((x) => x.id === id);
|
||||||
if (!t) return;
|
if (!t) return;
|
||||||
|
|
||||||
@@ -74,17 +162,21 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
t.a.setAttribute("aria-current", "true");
|
t.a.setAttribute("aria-current", "true");
|
||||||
t.li.classList.add("is-current");
|
t.li.classList.add("is-current");
|
||||||
|
|
||||||
// ✅ IMPORTANT: plus de scrollIntoView ici
|
if (mq.matches && autoOpen && toc.classList.contains("is-collapsed")) {
|
||||||
// sinon ça scroll l'aside pendant le scroll du reading => TOC global “disparaît”.
|
setOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent("archicratie:tocLocalActive", { detail: { id } })
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const computeActive = () => {
|
const computeActive = () => {
|
||||||
const visible = ordered.filter((t) => {
|
const visible = ordered.filter((t) => {
|
||||||
const d = t.el.closest?.("details");
|
const d = t.el.closest?.("details");
|
||||||
if (d && !d.open) {
|
if (d && !d.open) {
|
||||||
// Si l'élément est dans <summary>, il reste visible même details fermé
|
|
||||||
const inSummary = !!t.el.closest?.("summary");
|
const inSummary = !!t.el.closest?.("summary");
|
||||||
if (!inSummary) return false;
|
if (!inSummary && !t.el.classList?.contains("details-anchor")) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -102,7 +194,7 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!best) best = visible[0];
|
if (!best) best = visible[0];
|
||||||
setCurrent(best.id);
|
if (best && best.id !== current) setCurrent(best.id, { autoOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
let ticking = false;
|
let ticking = false;
|
||||||
@@ -117,11 +209,14 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
|
|
||||||
const syncFromHash = () => {
|
const syncFromHash = () => {
|
||||||
const id = (location.hash || "").slice(1);
|
const id = (location.hash || "").slice(1);
|
||||||
if (!id) { computeActive(); return; }
|
if (!id) {
|
||||||
|
computeActive();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const el = document.getElementById(id);
|
const el = document.getElementById(id);
|
||||||
if (el) openDetailsIfNeeded(el);
|
if (el) openDetailsIfNeeded(el);
|
||||||
setCurrent(id);
|
setCurrent(id, { autoOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
toc.addEventListener("click", (ev) => {
|
toc.addEventListener("click", (ev) => {
|
||||||
@@ -133,13 +228,14 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
const el = document.getElementById(id);
|
const el = document.getElementById(id);
|
||||||
if (el) openDetailsIfNeeded(el);
|
if (el) openDetailsIfNeeded(el);
|
||||||
|
|
||||||
setCurrent(id);
|
setCurrent(id, { autoOpen: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("scroll", onScroll, { passive: true });
|
window.addEventListener("scroll", onScroll, { passive: true });
|
||||||
window.addEventListener("resize", onScroll);
|
window.addEventListener("resize", onScroll);
|
||||||
window.addEventListener("hashchange", syncFromHash);
|
window.addEventListener("hashchange", syncFromHash);
|
||||||
|
|
||||||
|
initAccordion();
|
||||||
syncFromHash();
|
syncFromHash();
|
||||||
onScroll();
|
onScroll();
|
||||||
}
|
}
|
||||||
@@ -153,30 +249,183 @@ const items = (headings || []).filter((h) => h.depth >= 2 && h.depth <= 3);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.toc-local{margin-top:12px;border:1px solid rgba(127,127,127,.25);border-radius:16px;padding:12px}
|
.toc-local{
|
||||||
.toc-local__title{font-size:13px;opacity:.85;margin-bottom:8px}
|
margin-top: 12px;
|
||||||
|
border: 1px solid rgba(127,127,127,.25);
|
||||||
.toc-local__list{list-style:none;margin:0;padding:0}
|
border-radius: 16px;
|
||||||
.toc-local__item::marker{content:""}
|
padding: 12px;
|
||||||
.toc-local__item{margin:6px 0}
|
background: rgba(127,127,127,0.03);
|
||||||
.toc-local__item.d3{margin-left:12px;opacity:.9}
|
|
||||||
|
|
||||||
.toc-local__item.is-current > a{
|
|
||||||
font-weight: 750;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-local a{
|
.toc-local__toggle{
|
||||||
display:inline-block;
|
width: 100%;
|
||||||
max-width:100%;
|
appearance: none;
|
||||||
text-decoration:none;
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.toc-local a:hover{ text-decoration: underline; }
|
|
||||||
|
.toc-local__head{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__title{
|
||||||
|
font-size: 13px;
|
||||||
|
opacity: .85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__chevron{
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: .72;
|
||||||
|
transition: transform 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__body-clip{
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
transition:
|
||||||
|
grid-template-rows 220ms ease,
|
||||||
|
opacity 160ms ease,
|
||||||
|
margin-top 220ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__body{
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.toc-local__list{
|
.toc-local__list{
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
max-height: 44vh;
|
max-height: 44vh;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
scrollbar-gutter: stable;
|
scrollbar-gutter: stable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toc-local__item::marker{ content:""; }
|
||||||
|
.toc-local__item{ margin: 6px 0; }
|
||||||
|
|
||||||
|
.toc-local__item.d3{
|
||||||
|
margin-left: 14px;
|
||||||
|
opacity: .94;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local a{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: start;
|
||||||
|
max-width: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local a:hover{
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__mark{
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
margin-top: .36em;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(127,127,127,.34);
|
||||||
|
background: transparent;
|
||||||
|
opacity: .68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__text{
|
||||||
|
line-height: 1.28;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item.is-current > a{
|
||||||
|
font-weight: 760;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item.is-current > a .toc-local__mark{
|
||||||
|
background: currentColor;
|
||||||
|
border-color: currentColor;
|
||||||
|
box-shadow: 0 0 0 3px rgba(127,127,127,.10);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
.toc-local{
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__head{
|
||||||
|
margin-bottom: 0;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__body-clip{
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local.is-collapsed .toc-local__body-clip{
|
||||||
|
grid-template-rows: 0fr;
|
||||||
|
opacity: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__body{
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: opacity 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local.is-collapsed .toc-local__body{
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local.is-collapsed .toc-local__chevron{
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__title{
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__list{
|
||||||
|
max-height: min(42vh, 360px);
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item{
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item.d2 > a .toc-local__text{
|
||||||
|
font-size: 12.9px;
|
||||||
|
line-height: 1.24;
|
||||||
|
font-weight: 680;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item.d3{
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item.d3 > a .toc-local__text{
|
||||||
|
font-size: 12.1px;
|
||||||
|
line-height: 1.22;
|
||||||
|
opacity: .95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-local__item.d3 > a .toc-local__mark{
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
margin-top: .42em;
|
||||||
|
opacity: .55;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,251 +1,417 @@
|
|||||||
---
|
---
|
||||||
title: "Conclusion — ArchiCraT-IA"
|
title: Conclusion — ArchiCraT-IA
|
||||||
edition: "archicratie"
|
edition: archicrat-ia
|
||||||
status: "modele_sociopolitique"
|
status: essai_these
|
||||||
level: 1
|
level: 1
|
||||||
version: "0.1.0"
|
version: 0.1.0
|
||||||
concepts: []
|
concepts: []
|
||||||
links: []
|
links: []
|
||||||
order: 70
|
order: 70
|
||||||
summary: ""
|
summary: ''
|
||||||
source:
|
source:
|
||||||
kind: docx
|
kind: docx
|
||||||
path: "sources/docx/archicrat-ia/Conclusion-Archicrat-IA-version_officielle.docx"
|
path: sources/docx/archicrat-ia/Conclusion-Archicrat-IA-version_officielle.docx
|
||||||
---
|
---
|
||||||
Nous n’assistons ni à un retour primordial du désordre ni à une raréfaction du pouvoir. Nous assistons à autre chose, plus discret et plus décisif : la montée en régime d’une régulation sans scène, où la plupart des décisions qui engagent nos vies sont prises et appliquées sans lieu institué d’énonciation, sans temps de différé, sans exposition reconnaissable de leurs auteurs. La conflictualité ne disparaît pas, elle est déportée : reconfigurée en flux, en scores, en interfaces, en procédures qui se présentent comme de simples enchaînements techniques, alors même qu’elles opèrent des choix normatifs massifs.
|
|
||||||
|
|
||||||
Ce manque n’est pas un vide. Il ne signifie ni l’absence de normes, ni l’effondrement du pouvoir, mais ce que nous avons appelé, dans cet essai-thèse, une *oblitération archicratique* : le recouvrement progressif de la scène par la seule *cratialité*, c’est-à-dire par des dispositifs d’exécution qui se substituent à la mise en débat des fondements et des effets. Ce n’est pas le pouvoir qui manque, c’est la possibilité de le voir, de le nommer, de l’adresser. La régulation se donne alors comme évidence fonctionnelle, là où elle devrait apparaître comme ce qu’elle est toujours : un ordre situé, contestable et révisable en respect des promesses démocratiques.
|
Nous n'assistons ni à un retour primordial du désordre ni à une
|
||||||
|
raréfaction du pouvoir. Ce qui se transforme, plus discrètement mais de
|
||||||
La thèse défendue ici n’est pas que toute scène aurait disparu, ni que l’histoire se réduirait à un glissement univoque vers l’automatisation intégrale. Elle est plus précise et plus falsifiable : dans les principaux dispositifs contemporains – sociaux, écologiques, numériques –, les conditions d’existence d’une scène archicrative sont systématiquement affaiblies, fragmentées, reléguées à la marge. Là où l’on pouvait autrefois identifier un lieu, un temps, des personnes et des procédures pour organiser et mettre à l’épreuve les décisions, nous rencontrons désormais, de manière récurrente, des agencements où l’énonciation s’efface derrière la mesure, la simulation, la plateformisation et l’automatisation.
|
manière décisive, ce sont les conditions mêmes sous lesquelles la
|
||||||
|
régulation peut apparaître. Ce qui se reconfigure sous nos yeux n'est
|
||||||
C’est pourquoi nous avons forgé la notion d’*oblitération archicratique* : non pas l’absence de tout recours, mais la tendance structurelle à produire de la norme hors scène, à démultiplier les dispositifs auto-référés – architectures, algorithmes, barèmes, chaînes logistiques – les supports d’une régulation qui se déclare purement opératoire, *autarchicratique*. Cette hypothèse est réfutable : elle serait démentie si l’on observait, de façon durable, que les grandes décisions collectives demeurent adossées à des scènes d’épreuve robustes, effectives, où les fondements et les effets peuvent être mis en discussion. Elle gagnerait, inversement, en pertinence si des enquêtes empiriques mettent en évidence l’inaccessibilité des recours, l’ineffectivité des délibérations politiques, la surdétermination des décisions par des scripts non publics protégés par le droit des affaires.
|
pas d'abord la quantité de pouvoir à l'œuvre dans nos sociétés, mais la
|
||||||
|
manière dont ce pouvoir se rend — ou ne se rend plus — visible,
|
||||||
Dans cette perspective, l’*archicratie* n’est ni un idéal abstrait, ni un type de régime supplémentaire qu’il s’agirait d’ajouter à la liste déjà longue des formes politiques. Elle désigne la *condition minimale pour que la régulation soit habitable* : la possibilité, pour une société, d’instituer et de maintenir un seuil où l’*arcalité* (ce qui fonde et justifie), la *cratialité* (ce qui opère et exécute) et l’*archicration* (ce qui met en épreuve, suspend, requalifie) demeurent distinctes, articulées et exposées. Un ordre est archicratique en ce sens précis : non parce qu’il serait juste ou égalitaire par essence, mais parce qu’il se laisse amener en scène, devant des instances où ses prétentions peuvent être critiquées, ses instruments retravaillés, ses effets révisés.
|
adressable, contestable. La conflictualité ne disparaît pas ; elle
|
||||||
|
change de régime d'existence. Là où elle trouvait autrefois à se
|
||||||
L’enjeu de cette conclusion est de formuler une hypothèse régulatrice : la *co-viabilité* des collectifs humains et non-humains dépend de la capacité à maintenir, à rouvrir, à inventer des scènes d’épreuve où l’on puisse adresser le pouvoir qui nous affecte. En nommant l’*archicratie*, nous ne sacralisons pas un modèle ; nous désignons un seuil au-dessous duquel la régulation se dégrade en pure opération, et au-dessus duquel elle devient au moins discutable, opposable, révisable, modifiable, différant.
|
formuler dans des lieux identifiables, à se différer dans des
|
||||||
|
temporalités instituées, à se confronter dans des espaces d'énonciation
|
||||||
C’est là seulement que prend sens le projet d’une “cinquième révolution régulatrice”. Non pas un nouvel âge d’or, ni une résolution miraculeuse des contradictions, mais un changement de régime dans la manière même de fabriquer la régulation : un tournant où la scène – longtemps tenue pour « simple décor du pouvoir », ou pour « luxe démocratique » – redeviendrait son opérateur central. L’ambition de ce texte n’est pas de prédire cette révolution, et moins encore de la prescrire. Il s’agit de montrer en quel sens elle est pensable, souhaitable, et sous quelles conditions elle pourrait être mise à l’épreuve et mise en pratique.
|
reconnus, elle se trouve de plus en plus distribuée dans des chaînes
|
||||||
|
opératoires qui se présentent comme de simples enchaînements techniques.
|
||||||
Ce que nous observons n’est ni une défaillance accidentelle du cadre démocratique, ni une déviation autoritaire des gouvernances contemporaines, mais une mutation profonde des formes de régulation effective qui tendent à se configurer hors-scène démocratique instituée. Dans ce modèle, le pouvoir tend à se déporter hors scène instituée : privatisé, déterritorialisé, encapsulé, automatisé, rendu algorithme, crypté, incompréhensible et incritiquable du fait de sa propre efficacité. Il ne s’explique plus, il fonctionne. Il ne s’adresse plus, il déclenche. Il ne fonde plus, il applique. Et la régulation tend à se déporter hors scène instituée, tandis que persistent des scènes partielles, alternatives ou multilatérales qu’il faut reconnaître et saluer. Que ce soit la méta-fédération des soulèvements de la Terre, ou l’initiative internationale PauseIA, pour ne nommer que ces deux, leurs discours et leurs expertises apportent informations et discernements sur les enjeux écologiques et les développements d’intelligences artificielles.
|
Flux, scores, interfaces, barèmes, protocoles : autant de formes qui
|
||||||
|
n'abolissent pas les décisions, mais en modifient profondément les
|
||||||
Le processus est d’autant plus difficile à saisir qu’il est continu, fonctionnel, présenté comme neutre. Les interfaces remplacent les guichets, les tableaux de bord supplantent les délibérations, les retours algorithmiques prennent la place de la justification publique. Le conflit est désamorcé au nom de la fluidité. Le délai est perçu comme dysfonction. L’exposition est dégradée en transparence visuelle sans énoncé.
|
conditions d'apparition. Ce qui relevait d'une épreuve devient
|
||||||
|
traitement. Ce qui relevait d'une adresse devient calcul. Ce qui
|
||||||
Le terme d’oblitération archicratique, proposé et conceptualisé dans les chapitres précédents, désigne exactement cette dynamique : une substitution douce, mais décisive, de la scène par l’exécution, du différé par l’automaticité, de l’énonciation par la trace, de l’épreuve par la donnée. Cette oblitération ne se donne pas comme rupture, mais comme évidence : elle agit dans la logique même des dispositifs, dans leur conception, leur design, leur temporalité.
|
relevait d'une justification devient paramétrage.
|
||||||
|
|
||||||
Il faut ici refuser toute simplification. Si la scène instituée se raréfie, des scènes latérales, résiduelles ou émergentes persistent (communautés locales, contre-institutions, pratiques rituelles), il est grand temps de les reconnaître et de les légitimer au lieu de les folkloriser. Ce monde sans scène n’est ni totalement anarchique, ni totalement chaotique, ni même nécessairement injuste dans ses effets immédiats. Il est, en revanche, injustifiable. Il est insoutenable dans le temps, car il est aveugle à sa propre normativité. Il ne dispose d’aucun espace dans lequel ses propres décisions peuvent être rejouées, exposées, interrogées, rediscutées ou reformulées.
|
Ce déplacement est d'autant plus difficile à saisir qu'il ne se donne
|
||||||
|
pas comme rupture. Il s'installe dans la continuité apparente des
|
||||||
Cette régulation sans scène est une régulation sans mémoire, sans récit, sans réversibilité. Elle fonctionne, et souvent très efficacement. Mais elle ne critique rien, ne se confronte à rien, ne se relance jamais à partir de ses propres limites. Elle produit de la norme sans fondement énoncé, du pilotage sans institution, de la gouvernance sans fondation, un pouvoir simulé à tout moment proche du simulacre.
|
dispositifs, dans l'amélioration de leur efficacité, dans la promesse
|
||||||
|
d'une gestion plus rapide, plus fluide, plus objective des situations.
|
||||||
Les conséquences sont majeures. On croit pouvoir protester, mais l’interlocuteur est absent. On tente un recours, mais le délai est dépassé avant même d’avoir commencé. On cherche le fondement d’une décision, mais on ne trouve qu’un critère, un score, une règle d’application sans justification. Derrière la façade d’efficacité, ce qui s’installe, c’est un monde post-scénique, dans lequel les gouvernés n’ont plus d’espace institué pour adresser la régulation qui les constitue.
|
Le conflit y est désamorcé au nom de la performance. Le différé y est
|
||||||
|
perçu comme ralentissement. L'exposition y est remplacée par une
|
||||||
Ce diagnostic n’est pas une vérité révélée, mais une hypothèse régulatrice : il postule que, dans les principaux dispositifs contemporains (sociaux, écologiques, numériques), l’instance scénique a été reléguée au profit d’une *cratialité autarcique*. Il pourrait être réfuté par des recherches qui montreraient l’inverse, par exemple des domaines où des scènes archicratives fortes subsistent et structurent réellement les décisions. Il serait confirmé, au contraire, par des enquêtes qui objectiveraient l’inaccessibilité des scènes, l’ineffectivité des recours, la pure performativité des algorithmes.
|
visibilité sans interlocution, où tout semble disponible sans que rien
|
||||||
|
ne soit véritablement tenu. Il ne s'agit pas d'un vide. Il ne s'agit pas
|
||||||
Et c’est précisément là que s’ouvre une nécessité, celle de refonder la scène comme condition première de toute co-viabilité. Une scène véritable : espace différé, public, opposable, fondé — nullement décorative ni consultative. Une scène où la décision peut être relancée. Où le fondement peut être demandé. Où le délai est un droit. Où l’épreuve est reconnue comme condition de la légitimité.
|
d'un monde sans normes ni d'un effondrement du pouvoir. Il s'agit d'un
|
||||||
|
recouvrement. Ce que cet essai-thèse a nommé oblitération archicratique
|
||||||
Cette scène, c’est ce que nous avons nommé, construit, modélisé et mis à l’épreuve : l’*archicration*. Et c’est depuis son absence — criante et tout à la fois quasi imperceptible — que la cinquième révolution régulatrice devient pensable et indispensable.
|
désigne cette dynamique précise : la substitution progressive de la
|
||||||
|
scène par l'exécution, du différé par l'automaticité, de l'énonciation
|
||||||
Au seuil d’une ère où la capacité à ordonner, à segmenter, à attribuer ou à refuser se maintient sans que jamais ces gestes soient exposés à une scène d’épreuve instituée, la nécessité d’un concept opératoire, capable de désigner la forme régulatrice minimale d’un monde habitable, s’impose. Ce concept, l’*archicratie*, nous l’avons forgé, au-delà de la nécessité d’invention lexicale, comme condensation critique d’un constat systémique.
|
par la trace, de l'épreuve par la donnée.
|
||||||
|
|
||||||
L’*archicratie* ne renvoie ni à un type de régime spécifique, ni à une forme de gouvernement, ni même à une institution particulière. Elle ne se laisse classer dans aucune catégorie traditionnelle de la philosophie politique, car elle opère en amont des structures représentatives, et en-deça et au-delà des appareils juridiques. Elle est le mode de consistance scénique d’une régulation soutenable, c’est-à-dire d’un ordre qui accepte d’être mis en épreuve, d’être différé dans son exécution, d’être reconfiguré à partir de sa propre exposition sous critères de viabilité. Il s’agit donc du régime d’apparition du pouvoir fondé, là où une décision peut être tenue, dans le temps et dans l’espace, devant ceux qu’elle affecte, au sein d’une scène constituée pour qu’elle puisse être questionnée, retardée, amendée, voire annulée.
|
Le pouvoir ne cesse pas d'opérer ; il cesse de comparaître. Les
|
||||||
|
décisions continuent d'être prises ; elles cessent d'être tenues. Elles
|
||||||
Dans cette perspective, l’*archicratie* n’est ni utopie ni abstraction : elle fixe la condition de viabilité de tout dispositif qui prétend réguler — affecter des conduites, orienter des possibles, ouvrir/fermer des accès — sans se refermer sur une logique exclusivement opératoire. Il ne s’agit pas ici de défendre une figure morale du pouvoir, mais de poser une exigence structurelle : aucune régulation n’est légitime si elle ne peut être exposée à son propre fondement. Et aucune scène d’exposition n’est opérante si elle ne permet pas la convocation des énonciateurs, la traçabilité des instruments, la suspension des effets, la confrontation des justifications et la reconfiguration des décisions.
|
ne disparaissent pas ; elles se soustraient aux formes où elles
|
||||||
|
pourraient être rapportées à leurs fondements, confrontées à leurs
|
||||||
L’*archicratie* devient ainsi le seuil entre une régulation purement fonctionnelle, capable d’exécuter des procédures, de reproduire des normes, de gérer des flux automatisés et une régulation fondée, visible, opposable, justifiable, révisable — c’est-à-dire co-viable décidée par des humains.
|
effets, reprises à partir de ce qu'elles affectent.
|
||||||
|
|
||||||
Comme annoncé dans le Prologue, cette conclusion opère la remontée critique à partir des cinq épreuves de notre essai-thèse : (1) l’épreuve de détectabilité des régimes (chapitre 1), (2) l’archéogenèse des formes scéniques de régulation (chapitre 2), (3) la morphologie des régimes de pouvoir (chapitre 3), (4) la généalogie des révolutions régulatrices (chapitre 4), et (5) les tensions de co-viabilité au sein des dispositifs contemporains (chapitre 5).
|
Ce qui caractérise ainsi notre situation n'est pas une crise de la
|
||||||
|
conflictualité, mais une crise de sa tenue. Non l'absence de dissensus,
|
||||||
Pour penser ce seuil, notre essai-thèse a posé les conditions de détection d’une régulation minimale, structurée autour de trois prises fondamentales, dont la coprésence différenciée et articulée constitue la grammaire de toute régulation habitée. Ces trois prises — *arcalité, cratialité, archicration* — ne sont pas des dimensions logiques. Elles sont des formes d’existence différenciées de l’ordre régulateur.
|
mais l'altération des formes capables de le porter. Non la disparition
|
||||||
|
du politique, mais sa désarticulation progressive hors des scènes où il
|
||||||
Comme nous l’avons vu, l’*arcalité* désigne la condition d’énonciation du pouvoir. Elle ne se réduit pas à une source légale ou à une tradition instituée. Elle renvoie à la capacité d’un dispositif à exposer son propre fondement comme fondement, à dire : "voici sur quoi nous agissons, pourquoi, selon quelle vision du monde, selon quelle fiction ou axiome opératoire". Dans une régulation archicratique, l’*arcalité* est convoquée, nommée, rendue visible, tenue.
|
pouvait encore apparaître comme tel. À ce niveau, ce que nous appelons
|
||||||
|
crise ne relève plus d'un dysfonctionnement partiel, ni d'une dérive
|
||||||
La *cratialité*, quant à elle, n’est pas simplement l’opérativité technique. Elle est l’ensemble des vecteurs concrets d’application du pouvoir, qu’il s’agisse de normes, d’algorithmes, de barèmes, de codes juridiques, de métriques ou d’interfaces. C’est le pouvoir dans sa matérialité d’exécution. Loin de n’être qu’un détail de mise en œuvre, la *cratialité* constitue une scène en elle-même : celle où les affects se traduisent en effets, celle où le monde se divise, s’organise, se hiérarchise. Toute *cratialité* rendue opaque tend à devenir *hypertopique*.
|
simplement sectorielle. Elle engage les conditions même dans lesquelles
|
||||||
|
un monde peut encore faire apparaître, soutenir et transformer ce qui le
|
||||||
Enfin, l’*archicration* désigne la scène elle-même : l’espace-temps de l’épreuve régulatrice. Il ne se réduit pas à un dispositif de concertation ou à un droit de recours formel, mais bien plus à une scène effective, où le délai est institué, où les énoncés sont exposés, où les décisions sont suspendues, et où les parties affectées peuvent agir sur les termes mêmes de la régulation. Une *archicration* est une scène fondée, différée, ouverte, documentée, capable de transformer ce qu’elle expose. Elle se doit donc d’être publique et aucunement privée.
|
traverse.
|
||||||
|
|
||||||
Ces trois prises ne sont jamais données d’emblée. Elles sont inégalement distribuées, plus ou moins visibles, plus ou moins consolidées. Ce que permet l’*archicratie*, c’est d’en faire un modèle d’analyse différentielle, capable d’évaluer non ce que les institutions disent d’elles-mêmes, mais ce qu’elles rendent effectivement détectable, contestable, modifiable.
|
Ce déplacement du regard a commandé tout le parcours accompli. Il a
|
||||||
|
d'abord fallu apprendre à voir. Distinguer ce qui fonde de ce qui opère,
|
||||||
C’est à ce titre que nous avons élaboré une axiomatique de la détectabilité régulatrice, qui ne repose pas sur la conformité juridique, mais sur des critères structurels : la coprésence des prises ; leur différenciation fonctionnelle ; la publicité du fondement ; l’opposabilité des normes ; la révision périodique ; le droit au différé contradictoire.
|
ce qui opère de ce qui met à l'épreuve. Rompre avec les confusions qui
|
||||||
|
font passer l'exécution pour la justification, la visibilité pour
|
||||||
Ce modèle ne s’oppose pas aux régimes existants. Il les requalifie selon une grammaire de viabilité. Il ne dit pas ce qui est souhaitable. Il indique ce qui est soutenable.
|
l'opposabilité, la procédure pour la scène. Sans cette discipline de
|
||||||
|
détectabilité, le présent demeure illisible et la critique se dissout
|
||||||
Au terme de ce parcours, notre essai-thèse propose d’abord une *grammaire minimale de la régulation habitable*, en distinguant rigoureusement *arcalité, cratialité* et *archicration* comme trois prises irréductibles mais articulables du pouvoir. Il offre ensuite une archéogenèse comparée des méta-régimes régulateurs, qui permet de lire des configurations très hétérogènes – proto-symboliques, scripturaires, marchandes, guerrières, techno-logistiques – sans les rabattre sur le seul État, le seul marché ou la seule souveraineté. Il recompose en outre les “révolutions industrielles” comme des *révolutions régulatrices*, c’est-à-dire comme des histoires différentielles de la scène et de son oblitération, jusqu’au diagnostic contemporain d’*autarchicratie* et de *régulation hors scène*. Enfin, il élabore une politique des épreuves viables, en substituant à la fiction de la durabilité le paradigme de la *co-viabilité archicratique*, et en proposant quelques gestes concrets par lesquels cette exigence pourrait être mise à l’épreuve dans les institutions, les territoires et les dispositifs numériques.
|
dans des généralités. L'une des ambitions premières de ce travail aura
|
||||||
|
donc été de donner des prises : non pas inventer un vocabulaire pour le
|
||||||
Là réside le geste décisif : faire de l’*archicratie* une condition de lisibilité du pouvoir, dans un monde où les décisions sont de plus en plus produites sans fondement explicité, en accès et décision privés, appliquées sans seuil d’entrée et exécutées sans scène d’exposition explicite (algorithmes de recommandations, IA générative, etc.).
|
plaisir de l'invention, mais rendre discernable ce que les descriptions
|
||||||
|
ordinaires du pouvoir, de la gouvernance et de l'administration laissent
|
||||||
En nommant l’*archicratie*, ce que nous faisons, ce n’est pas inventer une utopie : c’est dégager, à partir des marges critiques de la modernité régulatrice, un principe de consistance qui permet de discerner ce qui peut encore être appelé régulation — et ce qui ne relève plus que de l’automatisation du monde, son *autarchicratie*.
|
trop souvent se confondre.
|
||||||
|
|
||||||
Comme l’écrivait Claude Lefort, “le lieu du pouvoir est vide, et le pouvoir est un lieu duquel personne ne peut s’arroger la propriété” : c’est ce vide fondateur qui, sans scène, devient mutisme algorithmique. L’archicration ne cherche pas à combler ce vide, mais à en réinstituer l’adresse. Car l’*archicratie* n’est pas l’alternative à un système. Elle est ce qui rend possible le fait même qu’un système puisse tenir, mais aussi être interrompu, contesté et refondé. Elle est la condition minimale de tout ordre qui ne veut pas être sa propre clôture et sa pure et propre reproduction sociale.
|
Encore fallait-il que ce vocabulaire n'usurpe pas sa propre nécessité.
|
||||||
|
L'archicratie ne vaut pas parce qu'elle pourrait tout redire dans sa
|
||||||
Ce que nous avons appelé scène n’est ni une métaphore théâtrale, ni un artifice rhétorique, ni un dispositif de communication. Elle n’est pas le lieu décoratif du pouvoir. Elle n’est pas ce que l’on ajoute, une fois la régulation pensée, pour en valider symboliquement l’acceptabilité. Elle est, à l’inverse, la matrice originaire d’où émerge toute forme de régulation vivable, bien avant l’État, bien avant le droit, et en dehors des grammaires modernes du gouvernement.
|
langue ; elle vaut seulement là où elle permet de discerner quelque
|
||||||
|
chose qui, sans elle, resterait confondu, euphémisé ou inaperçu. Elle ne
|
||||||
L’histoire politique des sociétés humaines ne commence pas avec l’institution étatique. Elle commence par l’apparition de lieux différés dans lesquels le pouvoir se donne à voir, se laisse convoquer, se met en épreuve. Partout où l’on observe la mise en forme de relations collectives durables, on trouve, en amont de la codification, des scènes d’ajournement et de dispute — des espaces de rituel, de conseil, de circulation de paroles, de suspension du geste immédiat.
|
constitue donc ni une théorie totale du politique, ni une clef
|
||||||
|
universelle des mondes historiques, mais un instrument critique situé,
|
||||||
Les premières figures de la régulation ne sont pas des lois, mais des cercles. Ce sont des feux autour desquels on raconte ce qui a été fait, ce qui pourrait être fait autrement, ce qui doit être décidé ensemble. Ce sont des seuils marqués, des temps de deuil ou de conflit ajourné, des prises de parole dans l’épure, où l’événement est reconvoqué dans un espace plus grand que lui. C’est ici que s’institue, sans formalisation juridique, la première *archicration* : une scène anthropologique de différé, de dispute et de co-présence du conflit.
|
tenu à une obligation de retenue : se taire là où il n'apporte aucun
|
||||||
|
gain de lisibilité, et répondre de ses distinctions là où il prétend en
|
||||||
L’archéogenèse de la scène, telle que nous l’avons retracé, ne vise pas à plaquer une origine sur le concept d’*archicratie*. Elle permet de montrer que l’exposition du pouvoir au regard des autres n’est pas un luxe moderne, mais une fonction vitale de toute organisation collective. On ne fonde pas une cité parce que l’on a établi une loi ; on fonde une cité parce que l’on a produit un lieu dans lequel des lois pouvaient être explicitées, différées, adressées et même révisées.
|
produire. C'est à cette condition seulement qu'un paradigme cesse d'être
|
||||||
|
un idiome de surplomb pour devenir une épreuve réelle de connaissance.
|
||||||
Les régimes que nous considérons comme proto-politiques ne reposent pas sur des appareils coercitifs permanents, mais sur des dispositifs de régulation publique des différends. Ce que l’on appelait jadis “conseil des anciens”, “assemblée des vivants”, “place de palabres”, “moment du jugement”, sont autant de scènes dans lesquelles une communauté suspend l’exécution brute des normes pour produire, en commun, un réexamen des conditions du vivre-ensemble.
|
|
||||||
|
Il a fallu ensuite remonter plus loin. Reconnaître que les formes
|
||||||
Il y a ici un renversement majeur : ce n’est pas la violence qui précède l’ordre, mais la scène qui ajourne la violence par son existence et son efficience. Loin d’être un ornement cérémoniel, la scène permet de transformer une décision en acte politique, en la soumettant à un espace d’apparition partagé. On ne gouverne pas parce qu’on détient un pouvoir, on gouverne parce que l’on accepte d’exposer le pouvoir dans un lieu où il peut être contesté.
|
d'épreuve ne sont ni des raffinements tardifs des modernités
|
||||||
|
représentatives, ni des suppléments ajoutés à des ordres déjà
|
||||||
Et ce geste ne disparaît pas avec la modernité : il se déplace, se reconfigure, parfois se cache. Les formes scéniques de l’époque moderne — parlements, tribunaux, conseils, consultations — ne sont pas des innovations *ex nihilo*, mais des transpositions institutionnelles d’une exigence anthropologique fondamentale : rendre le pouvoir visible dans un espace différé, public, contradictoire pour le légitimer dans son autorité.
|
constitués, mais des conditions plus profondes de la tenue des mondes
|
||||||
|
humains. Avant les États, avant les bureaucraties, avant les
|
||||||
Ce que nous appelons aujourd’hui *archicratie*, à travers le triptyque *arcalité-cratialité-archicration*, ne naît donc pas avec la gouvernance algorithmique, ni avec la crise contemporaine des institutions : c’est le nom que nous donnons à une exigence anthropologique longue — rendre le pouvoir visible dans un espace différé, public, contradictoire — que les mutations modernes ont partiellement codifiée, mais jamais totalement effacée. Même les régimes autoritaires, même les appareils technocratiques les plus opaques, tentent de simuler la scène, d’en mimer les apparences, comme si toute régulation devait, d’une manière ou d’une autre, s’appuyer sur une forme scénique minimale, fût-elle falsifiée, spectaculaire, dé-saisissante ou accablante.
|
codifications juridiques stabilisées, des collectifs ont dû inventer des
|
||||||
|
manières de différer, de ritualiser, d'exposer ce qui les traversait.
|
||||||
L’effondrement actuel, tel que nous le décrivons, ne réside pas dans une rupture historique absolue, mais dans une disjonction cumulative, où la régulation devient performative, prédictive, auto-exécutive, tout en prétendant conserver l’apparence de la scène. Ce que les plateformes administratives, les interfaces de recours, les simulateurs d’opinion, les visualisations de données simulent, ce n’est pas la norme — c’est le différé. Ce n’est pas la décision — c’est la contestation.
|
L'histoire du politique ne commence pas avec la souveraineté constituée
|
||||||
|
; elle commence avec la nécessité, pour un monde traversé de forces
|
||||||
En ce sens, réinstituer la scène aujourd’hui revient à réactiver une fonction anthropologique enfouie, plutôt qu’à restaurer une forme passée enfouie sous les couches technocratiques, une fonction sans laquelle aucun ordre collectif ne peut être su, ajusté, ni corrigé, ni habité. Nous ne parlons pas ici de restauration, plutôt d’un geste de fondation renouvelé : retrouver la capacité de construire des espaces différés d’apparition du pouvoir, où la norme peut être visible, où la décision peut être suspendue, où l’effet peut être discuté, et où le fondement peut être relancé.
|
hétérogènes, de ne pas s'abandonner à leur pure immédiateté. Elle
|
||||||
|
commence là où quelque chose comme une reprise devient possible, là où
|
||||||
L’histoire de la scène est celle de l’ajournement du pouvoir brut au nom d’une *co-présence* instituée du conflit. Et c’est à cette hauteur anthropologique que l’*archicratie* trouve son origine : non dans une forme constitutionnelle, mais dans la structure même du fait politique, dès lors qu’il accepte de s’exposer à autre chose que sa propre exécution.
|
ce qui affecte peut être reconduit à une forme d'exposition, si
|
||||||
|
rudimentaire, violente ou dissymétrique soit-elle. La scène n'est donc
|
||||||
Ce que nous appelons *co-viabilité* n’est pensable que dans cette tension : entre un pouvoir qui affecte, et un espace où cette affectation peut être exposée. La scène est le seul lieu où cette tension devient habitable, c’est-à-dire vivable, réformable, traversable. Sans scène, ce sont alors des processus, des opérations, des machines qui dominent.
|
pas un luxe moderne. Elle appartient à la structure même des mondes qui
|
||||||
|
tiennent.
|
||||||
C’est pourquoi, dans notre essai-thèse, l’*archicration* n’est jamais une solution institutionnelle, ni une forme de gouvernement. Elle est la condition minimale d’un monde capable de s’interrompre pour se refonder. Elle est ce qui permet, encore et toujours, de revenir sur ce qui est en train de s’imposer. Elle est le lieu de surgissement de la viabilité.
|
|
||||||
|
Il a fallu également traverser les grandes pensées du pouvoir, non pour
|
||||||
Et c’est à partir de cette scène — non comme décor, mais comme forme originaire de la dispute différée — que peut se penser la cinquième révolution régulatrice, non comme innovation technologique, mais comme retour conscient à une exigence anthropologique que l’histoire n’a jamais pu dissoudre.
|
les annuler, ni pour les annexer de force à un nouveau système, mais
|
||||||
|
pour en mesurer les prises et les limites. Certaines ont privilégié le
|
||||||
Il n’est désormais plus possible d’analyser la question de la régulation sans la confronter à ses deux périls contemporains les plus massifs, les plus urgents, les plus irréversibles : la désintégration sociale et l’inhabitation écologique. Ces deux lignes de fracture ne constituent pas des petits “sujets” parmi d’autres, ni même des crises externes au champ de la régulation. Elles sont les lieux mêmes où se joue la soutenabilité du monde commun, et à partir desquels se manifeste avec la plus grande intensité la nécessité d’une scène archicratique instituée.
|
fondement, d'autres l'opération, d'autres encore la conflictualité, la
|
||||||
|
dispersion des dispositifs, l'individuation, la justification ou le
|
||||||
D’un côté, les sociétés contemporaines sont travaillées par une fragmentation socio-économique accélérée, où les droits, les protections, les accès aux ressources, à la santé, à l’habitat, au travail, à la dignité même, sont de plus en plus conditionnés par des régimes de critères invisibles, des barèmes automatisés, des normes silencieuses dont la contestation n’a ni lieu ni délai. Ce que produit cette fragmentation, ce n’est pas simplement de l’injustice – c’est une dés-institution du social, un abandon de la possibilité de fonder l’ordre sur une scène où les règles peuvent être exposées, comprises, opposées, amendées.
|
dissensus. Toutes ont saisi quelque chose de réel ; aucune n'a tenu
|
||||||
|
entièrement ensemble les conditions d'une régulation habitable. Ce que
|
||||||
De l’autre côté, l’environnement planétaire est soumis à un processus de désintégration physique, chimique, biologique, systémique, dont les causes sont connues, mesurées, modélisées — mais dont la régulation demeure hors scène. Les grands instruments du pilotage écologique (quotas carbone, marché de droits d’émission, régulations incitatives, taxonomies vertes, solutions technologiques à haute intensité énergétique) ne répondent pas à une scène fondée de délibération environnementale. Ils opèrent à partir d’indicateurs pré-déterminés, de modèles économétriques rendus irréfutables, d’institutions fermées dont les critères ne sont ni exposés, ni opposables.
|
cette traversée a rendu possible, ce n'est pas une synthèse des
|
||||||
|
doctrines, mais une méta-grammaire du politique, capable de les relire à
|
||||||
Dans les deux cas, ce que l’on appelle régulation n’est souvent rien d’autre qu’un régime d’administration automatique de la catastrophe, une façon de moduler les seuils d’acceptabilité de l’inacceptable, de stabiliser temporairement des déséquilibres massifs sans jamais exposer les choix, les arbitrages, les priorités, à une scène d’épreuve collective.
|
partir de ce qu'elles permettent — ou non — de penser : comment un
|
||||||
|
ordre se fonde, comment il opère, comment il accepte d'être mis à
|
||||||
Le mot “durabilité”, en ce sens, est devenu l’un des opérateurs les plus puissants de cette fiction régulatrice. Il donne à croire qu’un monde peut être maintenu dans son état actuel par l’ajustement de ses paramètres – sans refondation, sans débat, sans conflit institué. On parle de transition, mais sans définir qui en décide, selon quels délais, avec quelles conséquences, sur quels critères effectifs et crédibles. On évoque l’empreinte carbone, sans jamais dire ce que cela signifie politiquement, historiquement, anthropologiquement. Le terme de “durabilité” produit ainsi un effet de clôture : il neutralise la conflictualité fondatrice de toute scène régulatrice, en la remplaçant par un récit d’optimisation continue, une fable pseudo-scientifique.
|
l'épreuve.
|
||||||
|
|
||||||
Ce que notre essai-thèse oppose à cette fiction, ce n’est pas une autre gestion du risque, ni une autre version du développement : c’est une refondation de la question régulatrice à partir du paradigme de la co-viabilité. Et cette refondation ne peut s’opérer que dans une configuration archicratique, c’est-à-dire dans une scène fondée où la viabilité ne se décrète pas, mais s’éprouve, se dispute, se rejoue, se transforme.
|
Il a fallu enfin éprouver cette grammaire dans l'histoire effective des
|
||||||
|
transformations modernes, là où les capacités de régulation ont atteint
|
||||||
Celle-ci ne peut être réduite à la compatibilité des intérêts humains et non-humains, ni à une coexistence pacifiée entre agents différenciés. Elle n’est pas un horizon harmonique. Elle est un régime d’épreuves instituées, dans lequel les formes du vivant, des milieux, des infrastructures, des symboles, peuvent être convoquées dans des scènes de régulation explicite, différée, révisable.
|
une intensité inédite. Ce qui apparaît alors n'est pas seulement une
|
||||||
|
succession d'innovations techniques, mais une série de reconfigurations
|
||||||
Ce que cela signifie, très concrètement, c’est que les arbitrages sur l’eau, l’énergie, la mobilité, le territoire, la réparation, le soin, ne peuvent plus être externalisés dans des modèles d’impact ou des courbes d’efficacité. Ils doivent être rapportés à une scène, où l’on peut interroger non seulement les effets des décisions, mais leurs fondements, leurs seuils, leurs instruments, leurs alternatives.
|
du rapport entre fondement, opération et épreuve. Chaque révolution
|
||||||
|
industrielle a redessiné ce triangle ; chacune a accru certaines
|
||||||
L’*archicration* écologique prend corps dans des scènes territoriales où les habitants font apparaître les conditions d’habitabilité, contestent les infrastructures et proposent des configurations de subsistance — bien au-delà des conférences quinquennales et des tableaux de bord numériques d’objectifs carbone ; elle suppose une arcalisation du vivant (reconnaissance des entités existantes), une cratialisation des milieux (identification des champs de forces et d’agissements), une archicration du conflit, autrement dit une politisation complète de ce qui, trop longtemps, a été traité comme données environnementales inertes.
|
puissances tout en décalant, fragmentant ou fragilisant les formes
|
||||||
|
capables de les soutenir. L'histoire moderne n'apparaît plus comme celle
|
||||||
Sur le plan social, la logique est la même. Là où les critères d’attribution des droits deviennent des scripts inaccessibles, là où les plateformes d’accès remplacent les guichets, là où les aides sociales sont suspendues sans énoncé, là où les publics fragiles sont évalués par des algorithmes de “comportement à risque”, le droit s’automatise, la scène disparaît, la dignité s’efface.
|
d'un progrès simplement technique ; elle devient lisible comme celle des
|
||||||
|
déplacements successifs du lieu où le pouvoir se rend — ou cesse de se
|
||||||
Ce n’est pas une question d’inefficacité, ni même d’injustice procédurale : c’est une désactivation du régime de reconnaissance. Car un droit qui ne peut plus être justifié publiquement, réclamé dans une scène, opposé dans un délai, contesté par une présence, n’est plus un droit. C’est une variable. Une allocation. Un flux à tout moment suspensif.
|
rendre — comparable, contestable, révisable.
|
||||||
|
|
||||||
Réinstituer l’*archicration* sociale, c’est donc reconstruire la scène de l’accès au droit — non pas à travers des démarches participatives formelles, mais à travers des dispositifs d’exposition des critères, des formes de visibilité des seuils, des délais contradictoires obligatoires, des lieux de confrontation réels, soutenus, équipés, où l’on peut dire : “Ce n’est pas acceptable. Voici pourquoi. Voici ce que je propose.” C’est là, dans ces scènes de l’interpellation, que la co-viabilité sociale devient pensable.
|
C'est au point le plus brûlant du présent que cette exigence se révèle
|
||||||
|
avec la plus grande netteté. Les tensions contemporaines ne se laissent
|
||||||
Il ne s’agit donc pas de “réconcilier” social et écologie, mais de comprendre qu’ils sont deux effets d’une même oblitération scénique, et que leur relance ne peut passer que par la reconstruction des conditions archicratiques du désaccord institué.
|
pas comprendre comme des crises séparées, ni comme des anomalies
|
||||||
|
sectorielles. Elles manifestent, chacune à leur manière, la difficulté
|
||||||
C’est ici que l’hypothèse archicratique devient non plus un outil critique, mais une proposition civilisationnelle. Car un monde durablement privé de scènes archicratives tend à devenir aveugle à sa propre destinée. Un monde incapable de suspendre ce qu’il fait. Incapable d’en répondre. Incapable de s’ajuster depuis elles et ceux qu’il affecte.
|
croissante à instituer des formes dans lesquelles ce qui est affecté par
|
||||||
|
les décisions peut être reconduit à une épreuve. Ce qui manque n'est pas
|
||||||
À cette cécité organisée, la *co-viabilité* oppose la lumière rugueuse de l’exposition et du différé, la présence irréductible des vivants, la scène ouverte des conflits fondateurs canalisés par les récits de vie. Et c’est à partir de cette tension — vitale et irréductible — que peut encore s’inventer un devenir commun concerté fondé sur nos vulnérabilités, nos résiliences et nos robustesses conscientisées et politisées.
|
la capacité à produire des normes, des infrastructures, des critères,
|
||||||
|
des instruments. Ce qui manque, de plus en plus, c'est l'habileté à les
|
||||||
La régulation contemporaine, dans sa formulation dominante, se présente sous les atours rassurants d’un horizon consensuel : celui de la durabilité. Ce terme, devenu mantra technico-politique, irrigue désormais l’intégralité des champs du discours institutionnel — des traités internationaux aux chartes locales, des stratégies d’entreprise aux programmes éducatifs, des plans d’action gouvernementaux aux critères d’investissement privé. Il semble à la fois évident et indiscutable, fédérateur et apaisant. À son contact, les conflits s’effacent, les alternatives se suspendent, la temporalité se normalise, et la gouvernance acquiert une forme de légitimité indolore, anesthésiante, presque tautologique. Au point que ce qui est durable est ce qui mérite de durer.
|
porter. De là la nécessité d'un déplacement conceptuel décisif :
|
||||||
|
substituer au lexique lisse de la durabilité la notion de co-viabilité.
|
||||||
Sous sa surface consensuelle, la “durabilité” se ferme à l’épreuve : elle transforme le dissensus en anomalie et recode la régulation en pilotage continu d’indicateurs non révisables. Le problème n’est pas l’objectif écologique en lui-même, mais la structure régulatrice qui l’impose hors scène, et surtout, dans bien des cas, hors-sol, et bien plus, par cœur ou par calcul. Contre cette clôture, la politique des épreuves viables et soutenables substitue à l’optimisation des variables la publicité des critères recevables, au pilotage continu automatisé le jeu et le différé contradictoire, à la gestion d’impacts et de risques l’énonciation de leurs fondements pour éveiller les raisons — conditions pour que les décisions redeviennent adressables et opposables sous critères de discernement.
|
Non pas un équilibre supposé entre intérêts déjà constitués, ni la
|
||||||
|
correction technocratique d'externalités, mais l'institution toujours
|
||||||
Car jusqu’à présent, les stratégies dites “durables” fonctionnent selon un régime algorithmique d’autorité, où les seuils d’acceptabilité sont déterminés en amont, les priorités dictées par les logiques d’efficience, les variables manipulées sans scène d’exposition. On y parle de neutralité carbone, de trajectoires optimales, de plans de transition, mais jamais de fondement public de ces trajectoires, ni de scène dans laquelle elles pourraient être tenues devant ceux qu’elles affectent. C’est dans cette évacuation de la scène — plus encore que dans le contenu des politiques — que réside le cœur du problème. Ce n’est pas l’objectif de durabilité qui est en cause, c’est la structure régulatrice silencieuse qui le porte, le légitime et l’impose.
|
fragile, toujours révisable, toujours conflictuelle, des conditions sous
|
||||||
|
lesquelles des formes de vie hétérogènes peuvent encore tenir ensemble
|
||||||
Pour rendre ce mécanisme visible, rappelons-nous que toute régulation suppose deux opérations irréductibles : d’une part, une *normativité explicite* (ce qui doit être régulé, pourquoi, selon quels principes) ; d’autre part, une *opérativité outillée* (comment cette norme s’applique, à travers quels instruments, sur quels objets). Mais entre les deux, il faut une troisième instance, que la durabilité contemporaine tend précisément à effacer : la *scène d’épreuve*. C’est cette scène — différée, fondée, contradictoire — qui permet aux décisions de ne pas s’exécuter à l’abri du regard, aux critères d’être rendus publics, aux seuils d’être contestés, aux affects d’être entendus, aux représentations de monde d’être opposables contre tout arbitraire.
|
sans destruction irréversible.
|
||||||
|
|
||||||
En ce sens, la durabilité n’est pas qu’une fiction apolitique : elle est le récit qui permet l’exécution sans scène, la régulation sans fondement, la gouvernance sans convocation. Elle naturalise les instruments, en les présentant comme neutres. Elle réduit les choix à des données. Elle transforme la dispute en friction technique. Et ce faisant, elle désarme les communautés, les privant du droit d’ajourner, de relancer, de reformuler ce qui les affecte.
|
Ce qui se dégage ainsi de l'ensemble n'est pas une doctrine
|
||||||
|
supplémentaire, encore moins un système clos. C'est une condition — qui ne garantit ni harmonie ni salut, mais sans laquelle aucune
|
||||||
La politique des épreuves viables, telle que nous la proposons ici, ne consiste pas à rejeter les impératifs écologiques et sociaux. Elle ne nie pas la nécessité de limites, ni l’urgence de transformations structurelles. Elle refuse simplement que ces transformations soient imposées hors scène, dans le silence d’une régulation désaffectée. Elle postule que toute décision ayant un impact majeur sur les conditions de vie, de subsistance, d’habitation, doit passer par une épreuve fondée, différée, partagée. Elle postule que ce qui n’est pas disputé ne peut être dit durable.
|
régulation ne peut être tenue comme monde. Cette condition peut
|
||||||
|
désormais être formulée simplement : une régulation ne devient habitable
|
||||||
Une politique des épreuves viables suppose donc une ré-institution intégrale des conditions archicratiques de la décision. Plutôt qu’une réforme des indicateurs, une amélioration des consultations ou une simple transparence des données, il faut une scénarisation complète de la régulation selon une grammaire fondée sur quatre principes irréductibles, que nous avons articulés dans le cadre de notre modèle archicratique.
|
qu'à la mesure où ce qui la fonde, ce qui l'opère et ce qui la met à
|
||||||
|
l'épreuve demeurent distinguables, articulés et exposables. Toute la
|
||||||
Quatre exigences, déjà inscrites dans notre axiomatique, organisent la politique des épreuves viables : le *différé contradictoire*, qui rend l’exécution ajournable ; la *publicité des critères*, qui reconduit tout seuil à son fondement ; l’*opposabilité réelle*, qui ouvre la décision à l’intervention des affectés avant, pendant et après son application ; la *révision périodique*, qui interdit la clôture. Ces exigences ne sont pas des ajouts déontologiques : elles matérialisent l’axiome de détectabilité, confirment la disjonction fonctionnelle des prises arcales, cratiales et archicratiques et prolongent l’épreuve critique comme norme de vitalité du régime.
|
difficulté tient alors à ceci : maintenir cette distinction sans les
|
||||||
|
dissocier, et cette articulation sans les confondre. Là où ces
|
||||||
Mais ces principes ne peuvent exister qu’à une condition : qu’il y ait une scène. Une scène qui ne se contente ni de spectacle, ni de consultation décorative, ni de simple mise en visibilité : mais bien une scène où le pouvoir se fonde en apparaissant, où l’épreuve est instituée, où la transformation s’engage réellement depuis ceux qu’elle affecte.
|
dimensions se confondent, se disjoignent ou se dérobent à l'exposition,
|
||||||
|
la régulation peut continuer à fonctionner ; elle cesse de se tenir.
|
||||||
L’exemple des politiques climatiques l’illustre avec une clarté glaçante. Les objectifs de réduction d’émissions sont fixés par des trajectoires macroéconomiques, sans fondement ontologique débattu. Les instruments de marché (droits d’émission, taxes, incitations) sont conçus dans des enceintes d’expertise, sans contre-scène démocratique. Les seuils sont négociés entre États et industries, sans présence des vivants affectés. Résultat : une régulation performante sur le papier, mais fondamentalement désarchicratique. Elle s’exécute sans différé, sans dispute, sans publicité explicite des choix de monde. Là encore, la matrice d’audit du chapitre 1 s’applique : hypotopies (prises faibles sous-déterminantes), hypertopies (prises surdéterminantes), atopies (pseudo-scènes indéterminées), permettant de situer les déficits scéniques des dispositifs climatiques.
|
|
||||||
|
C'est cette condition minimale que nous avons nommée archicratie. Ni
|
||||||
Ce que nous appelons épreuve viable, c’est ce qui manque ici : la possibilité d’exposer les décisions à une scène où le fondement devient enjeu, où les milieux parlent, où les vivants contestent, où les représentations s’affrontent, dans un cadre institué, soutenu, non clôturé.
|
régime parmi d'autres, ni forme institutionnelle déterminée, ni idéal
|
||||||
|
moral à incarner : un seuil. Le seuil au-dessous duquel la régulation se
|
||||||
Dans les politiques sociales, le mécanisme est identique. Les aides sont attribuées selon des barèmes automatisés, les exclusions sont déclenchées sans justification explicite, les critères de mérite, de comportement, de mobilité sont intégrés dans des scripts sans adresse. On parle d’insertion, d’autonomie, de parcours. *Mais où est la scène ?* Où est l’espace où une personne peut dire : « ce critère est inacceptable » ; « cette décision ne me reconnaît pas » ; « je demande une autre forme de régulation » ?
|
réduit à sa propre opérativité, et au-dessus duquel elle devient, au
|
||||||
|
moins en droit, habitable, parce qu'elle laisse ouverte la possibilité
|
||||||
Dans bien des dispositifs sociaux, la scène formelle d’accès au droit s’est amincie ou s’est déportée dans des circuits techniques ; elle persiste toutefois sous des formes intermittentes, fragiles ou latérales — commissions locales, permanences associatives, médiations juridictionnelles *ad hoc*. Le problème n’est donc pas l’absence pure et simple, mais la dégradation topologique de la scène : hypotopies (prises faibles ou non reliées), hypertopies (cratialité sur-déterminante) et atopies (simulacres participatifs). Comme nous l’avons établi au chapitre 1, cette typologie ne renvoie pas à un argument d’autorité mais à une matrice d’audit : elle sert à objectiver les prises, à situer les déficits et à rouvrir la possibilité d’une scène tenue, opposable et révisable.
|
de sa reprise. L'archicratie ne désigne ni la justice, ni la bonté, ni
|
||||||
|
la douceur des décisions ; elle désigne la condition sans laquelle ces
|
||||||
Face à cela, une politique des épreuves viables implique une redéfinition complète de l’acte régulateur : non plus l’ajustement d’un système fermé, mais l’institution d’une scène ouverte. Elle transforme le pouvoir de gouverner en obligation de se laisser apparaître. Elle transforme le savoir d’expert en condition de fondation publique. Elle transforme la gestion en exposition contradictoire.
|
questions elles-mêmes cessent de pouvoir être posées politiquement.
|
||||||
|
|
||||||
Nous nommons *autarchicratie* la concrétisation achevée de la désarchicration : le méta-régime dans lequel la *cratialité se met en autarcie*. Il ne s’agit pas d’un gouvernement de la société par elle-même, mais d’un *gouvernement de la régulation par elle-même* : indicateurs, modèles de risque, scripts algorithmiques et procédures de contrôle deviennent leurs propres critères de validité, sans plus devoir passer par des scènes d’épreuve archicratives praticables. La *cratialité* s’y auto-référence et s’y auto-certifie, dans des boucles où tout fonctionne — calculs, audits, *reporting* — mais où plus rien ne se laisse vraiment contester ni même énoncer. Cette mise en autarcie de la régulation prolonge, jusqu’à son point de bascule, les tendances déjà repérées dans la gouvernementalité néolibérale, la rationalisation managériale et la numérisation intégrale des prises.
|
Ce qui fonde une régulation ne se confond ni avec une autorité
|
||||||
|
abstraite, ni avec un texte, ni avec une tradition invoquée une fois
|
||||||
L’*autarchicratie* n’est donc pas une fiction dystopique : c’est une destination possible, et déjà en partie à l’œuvre, de nos régimes contemporains. Nous en avons suivi les lignes de force dans l’histoire des révolutions industrielles (chapitre 4), lorsque la scène archicrative se trouve progressivement oblitérée au profit de modèles prédictifs et de dispositifs d’automatisation normative. Nous en avons observé les manifestations concrètes dans les politiques climatiques, sociales et numériques (chapitre 5), sous la forme de *pseudo-archicrations fantômes* et de pilotages algorithmiques où les circuits de décision se suffisent à eux-mêmes. Dans tous ces cas, la régulation subsiste juridiquement et techniquement, mais elle se maintient hors seuil d’opposabilité : scènes inaccessibles, délais inopérants, motifs indisponibles, paramètres non auditables. Tout fonctionne ; mais plus rien ne s’expose ni ne s’explique.
|
pour toutes ; cela renvoie à la capacité d'un ordre à exposer ses
|
||||||
|
raisons comme telles. Ce qui opère désigne les instruments, procédures
|
||||||
Dès lors, le péril n’est pas l’*archicratie* elle-même — qui institue la scène et rend contestables les effets —, mais sa disparition performative dans l’*autarchicratie*. Ainsi, refaire monter la scène n’est pas un supplément procédural : c’est revenir au seuil où la décision cesse d’être instrument et redevient fondation ; c’est rétablir, contre l’autarcie régulatrice, la possibilité d’un différé, d’une justification opposable, d’une réversibilité des effets — conditions sans lesquelles il n’y a plus de politique, mais seulement à terme des processus automatiques ou des pratiques machinales.
|
et dispositifs par lesquels le monde est effectivement découpé,
|
||||||
|
distribué, transformé. Ce qui met à l'épreuve, enfin, ne relève ni d'une
|
||||||
Or c’est bien cela que permet encore le concept d’*archicratie* — refonder la régulation comme scène, comme institution de l’interruption, de la dispute, du différé, de la relance — puisqu’elle permet de nommer ce qui auparavant était pour bonne part occulté bien que présent. Les épreuves viables posent ainsi la question de ce qui fait tenir un monde — et à quelles conditions il mérite encore de tenir.
|
consultation formelle ni d'un recours marginal, mais de formes
|
||||||
|
instituées où fondements, opérations et effets peuvent être suspendus,
|
||||||
Si la scène constitue, comme nous l’avons montré, la matrice fondamentale de toute régulation archicratique, alors son absence appelle autre chose qu’un tragique constat critique ou une nostalgie institutionnelle. Elle appelle un geste pleinement instituant, une projection agissante, un surgissement conceptuel doublé d’un projet matériel. Il ne suffit pas de rappeler que les normes s’appliquent aujourd’hui sans exposition, que les seuils gouvernent sans adresse, que les décisions s’exécutent sans différé. Il faut désormais concevoir les formes par lesquelles cette dérive peut être arrêtée, inversée, transformée depuis son propre cœur. Cela ne relève ni du réformisme, ni de l’utopie, mais d’un geste proprement archicratique : instituer une scène là où il n’y a plus que des tentations de scripts ou de prompts.
|
confrontés, repris.
|
||||||
|
|
||||||
Car l’absence de scène ne signifie pas une absence de régulation. Celle-ci se manifeste au contraire par un trop-plein de formes technico-administratives, de logiques procédurales, de chaînes opératoires sans seuil de réflexivité. Elle ne manque pas d’arènes, de plateformes, de forums, de simulateurs. Par contre, elle manque de lieux où l’on peut exprimer que ce pouvoir n’est pas encore justifié ; que cette norme ne peut pas encore s’appliquer ; que cette décision doit être suspendue tant qu’elle n’a pas été tenue devant celles et ceux qu’elle transforme. La scène n’est donc pas une instance supplémentaire : elle est ce sans quoi toute instance devient violence déguisée et insidieuse. Elle ne s’ajoute pas au dispositif ; elle en est la condition de légitimité. Et pour cette raison, elle doit être conçue, pensée, projetée et instituée.
|
Ces prises ne sont jamais données à l'état pur. Elles se recouvrent, se
|
||||||
|
déplacent, se distribuent inégalement selon les configurations. Mais
|
||||||
Toutefois, réinstituer les scènes ne consiste pas nécessairement à restaurer les formes d’assemblée du passé. Il ne s’agit pas non plus de réanimer les dispositifs dévitalisés de la représentation, ni de raviver des formes symboliques inertes. Il s’agit de penser des espaces dans lesquels une décision devient apparente avant d’être exécutoire, dans lesquels le temps retrouve sa densité, dans lesquels le pouvoir accepte d’être différé, exposé, débattu, amendé, contredit. Cela implique une refondation des infrastructures de la régulation, dans leur matérialité comme dans leur temporalité.
|
leur coprésence différenciée constitue la condition minimale d'une
|
||||||
|
régulation vivable. Là où l'opération se déploie sans être reconduite à
|
||||||
Il faudra donc des lieux, des calendriers, des organisations, des compétences, des statuts, des rôles, des budgets, des procédures, mais aussi des rituels, des langues, des gestes, des seuils symboliques. Car la scène est un dispositif complexe : elle n’émerge pas d’elle-même, elle ne se décrète pas, elle s’institue par un ensemble cohérent de formes, d’espaces, d’affects et de récits. Et c’est ce tissu qu’il faut aujourd’hui remailler.
|
ses raisons, là où les décisions s'appliquent sans passer par des
|
||||||
|
épreuves effectives, la régulation bascule vers une forme de fermeture
|
||||||
Là où les politiques publiques s’élaborent aujourd’hui dans les anti-chambres des ministères ou la clôture des cabinets d’audit, il faudra ouvrir des délais formels et irréductibles à la consultation. Là où les plateformes déploient leurs standards d’usage sur des populations entières sans épreuve fondatrice, il faudra bâtir des scènes où le code peut être ajourné, explicité, confronté. Là où les territoires sont remodelés par des logiques d’optimisation, il faudra des lieux où l’habitabilité puisse être requalifiée, où les milieux puissent apparaître, où les formes de vie puissent être représentées dans leur altérité. Là où les seuils d’attribution, de sanction, d’accès ou d’aide s’appliquent par automatisme, il faudra instituer des régimes où la décision elle-même devienne visible, révisable, reconductible à partir d’une épreuve contradictoire menée par des humains. Et cela ne se fera pas par décret. Cela exigera de nouveaux dispositifs, de nouvelles instances, de nouvelles formes, à inventer depuis le cœur même de la crise scénique contemporaine, probablement au plus près des acteurs de l’économie sociale et solidaire et des professions intermédiaires.
|
qui ne relève ni du chaos ni du retrait du pouvoir, mais de son
|
||||||
|
auto-suffisance. Dans une telle configuration, le pouvoir ne se retire
|
||||||
Qu’on admette alors ceci : bien comprendre la scène dans l’ordonnancement archicratique n’est pas une option procédurale. Elle est l’un des opérateurs décisifs par lesquels une décision cesse d’être purement instrumentale pour devenir fondatrice. C’est dans la scène que le pouvoir se redéploie en se laissant affecter. C’est dans la scène que la temporalité s’épaissit, que les conséquences deviennent lisibles, que les fondements peuvent être relancés. C’est là que peut émerger une *co-viabilité régulatrice*. Il ne s’agit donc pas d’ajouter de la transparence, de la participation ou de la communication. Il s’agit de concevoir des scènes dans lesquelles l’ordre peut être temporairement suspendu, afin d’être à nouveau institué depuis ceux qu’il affecte.
|
pas ; il s'accomplit sans comparution. Il produit des effets, parfois
|
||||||
|
avec une grande précision, mais sans se laisser reprendre dans des
|
||||||
Ce travail d’institution scénique ne peut être séparé de la question de l’échelle. Il devra se jouer à tous les niveaux : au sein des écoles, des collectivités, des juridictions, des plateformes, des infrastructures, des régulations techniques, des politiques sociales, des gouvernances écologiques... Chaque strate et lieu de l’*archicratie* doit trouver sa scène d’apparition, adaptée à sa texture propre, mais reliée par une même exigence : qu’*aucune décision structurante et agissante ne puisse advenir sans être tenue devant celles et ceux qu’elle engage.* Cela implique un effort considérable de conception, de financement, de formation, mais surtout un déplacement ontologique de ce qu’on appelle “gouverner”. Gouverner ne consistera plus à appliquer avec justesse des normes bien conçues, mais à rendre ces normes ajournables, discutables, contestables, et davantage réformables sous conditions de *co-viabilité* sociale et écologique.
|
formes où ces effets pourraient être rapportés à des raisons
|
||||||
|
discutables. Il opère, mais ne s'expose plus. Il décide, mais ne se
|
||||||
Il faudra, pour cela, concevoir de nouveaux lieux : des espaces où l’on entre sans savoir ce qui va en sortir, mais où chacun peut venir avec ses preuves, ses objections, ses propositions, ses arguments. Des scènes sans clôture prédéterminée, mais avec un cadre fort. Des scènes traversées par les conflits, mais équipées pour les soutenir. Des scènes lentes, où l’on prend le temps de tout reprendre. Des scènes modestes, parfois, mais constantes. Des scènes qui ne soient pas des moments exceptionnels, mais des rythmes d’institution continue. Des scènes enfin que l’on peut convoquer, non pour donner son avis, mais pour rouvrir le monde.
|
laisse plus adresser. Tout fonctionne ; mais plus rien ne s'expose ni ne
|
||||||
|
s'explique.
|
||||||
Et plus encore que des lieux, il faudra forger une culture. Une culture du différé, une culture de la justification, une culture de l’apparition fondée. Il faudra former à la convocation des énonciateurs, à la reconstruction des axiomes, à la mise en tension des critères. Il faudra réapprendre à interrompre sans détruire, à disputer sans humilier, à exposer sans désincarner. Il faudra bâtir des formes dans lesquelles le pouvoir n’aura plus peur d’être vu, entendu, relancé. Mais cela, aucun règlement ne pourra le prescrire. Ce sera l’œuvre d’une génération entière, qui ne se contentera pas de revendiquer des droits, mais qui acceptera de se constituer comme puissance politique — non dans l’éclat du spectaculaire, mais dans la densité fondatrice d’un monde à relancer avant effondrement déjà annoncée.
|
|
||||||
|
La différence décisive se situe là. Entre une régulation capable
|
||||||
À ce niveau, réinstituer la scène n’est plus un programme. C’est un appel. Un appel à cesser de gérer les régulations comme si elles pouvaient s’auto-référencer indéfiniment. Un appel à rouvrir l’espace du pouvoir comme espace d’épreuve, non de domination. Un appel à instituer un régime dans lequel les décisions cessent d’être des faits pour redevenir des actes. C’est ainsi que l’*archicratie* prendra sens comme projet. Non comme forme de gouvernement, mais comme respiration de toute société qui veut encore se gouverner elle-même dans son évolution pour assurer son avenir.
|
d'exécuter des procédures, de reproduire des normes, de gérer des flux,
|
||||||
|
et une régulation capable de se rapporter à elle-même à partir de ce
|
||||||
Toute régulation s’inscrit dans une histoire. Non seulement dans l’histoire des régimes politiques ou des institutions juridiques, mais dans une histoire plus profonde encore : celle des formes d’articulation entre pouvoir, savoir, énergie et monde, autrement dit, celle des configurations systémiques au sein desquelles l’humain, le vivant, le milieu, la technique et le symbolique se tiennent dans un certain rapport. Ce que nous appelons ici “révolution régulatrice” ne renvoie donc pas à un événement politique localisé, ni à une invention technologique isolée, mais à une transformation systémique de la manière dont un monde se produit, se reproduit, se règle et se légitime.
|
qu'elle affecte, la différence ne tient pas à l'intensité du pouvoir,
|
||||||
|
mais à la possibilité de sa mise à l'épreuve. Ce qui rend un monde
|
||||||
Les quatre grandes révolutions qui scandent la modernité industrielle – mécanisation disciplinaire, organisation taylorienne-fordiste, cybernétisation néolibérale, numérisation généralisée – ne sont pas seulement des séquences techniques. Chacune a reconfiguré, à sa manière, le rapport entre *arcalité*, *cratialité* et *archicration* : nouvelles promesses de légitimation, nouveaux dispositifs d’exécution, nouvelles formes – ou nouvelles défausses – de scène. La quatrième, celle de la numérisation intégrale des systèmes de décision, pousse à l’extrême un mouvement amorcé de longue date : la possibilité de faire fonctionner la régulation sans passer par des lieux reconnaissables d’épreuve.
|
habitable n'est ni l'absence de tensions, ni la stabilité de ses
|
||||||
|
équilibres, ni la pure efficacité de ses dispositifs. C'est la forme
|
||||||
C’est précisément contre cette clôture systémique que se dessine ce que nous proposons d’appeler, par convention, une cinquième révolution régulatrice. Elle ne consisterait pas en un supplément d’automatisation ni en une sophistication accrue des instruments. Elle tiendrait dans un déplacement plus radical : le fait de considérer que l’instance décisive n’est plus l’outil, ni le flux, ni la procédure, mais la scène où ces éléments deviennent adressables, critiquables, reconfigurables. Là où les révolutions précédentes ont privilégié l’extension des capacités de calcul, de production ou de circulation, celle-ci privilégierait la capacité à exposer ces capacités, à en faire l’objet d’une épreuve publique.
|
dans laquelle ce qui le traverse peut être porté sans être nié, différé
|
||||||
|
sans être dissous, exposé sans être annihilé.
|
||||||
Dire qu’il s’agit d’une “cinquième révolution” ne signifie pas que l’histoire suivrait un cours nécessaire et linéaire. Le terme n’a ici qu’une valeur heuristique : il sert à concentrer, sous un même nom, des processus multiples, hétérochrones et dispersés – luttes pour la transparence effective des algorithmes, revendications de recours opposables, demandes de traçabilité des décisions, inventions de nouvelles assemblées scéniques. Il serait erroné de croire que cette révolution viendra s’ajouter, comme une étape finale, à une série déjà écrite. Elle pourrait tout aussi bien rester avortée, partielle, récupérée par les dispositifs qu’elle prétend contraindre.
|
|
||||||
|
À partir de là, la question n'est plus d'abord celle d'un bon régime,
|
||||||
C’est pourquoi l’idée de cinquième révolution doit être explicitement soumise à épreuve. Elle serait infirmée si l’on constatait que les scènes existantes continuent de se vider de toute capacité effective, que les espaces de recours se réduisent à des simulacres sans impact sur les décisions, que les tentatives de réinstitutions scéniques se réduisent à des mises en récit sans prise sur les cratialités. Elle gagnerait en consistance, au contraire, si des pratiques, même locales, montraient que la création de nouvelles scènes – dans les hôpitaux, les écoles, les plateformes, les politiques écologiques – modifie réellement la manière dont les décisions sont justifiées, prises et requalifiées pour assurer la co-viabilité.
|
mais celle d'un monde qui tient. Non d'un monde pacifié, homogène ou
|
||||||
|
réconcilié, mais d'un monde capable de porter ce qui le traverse sans
|
||||||
Nous parlons donc de “cinquième révolution” moins comme d’un avenir promis que comme d’un horizon de travail : une invitation à relire les conflits présents à partir de la question scénique. Chaque fois qu’un collectif lutte pour un délai, pour un droit au différé, pour la présence d’énonciateurs identifiables, pour un droit de regard sur les paramètres qui le gouvernent, quelque chose de cette révolution est mis en jeu. Chaque fois qu’il s’en remet au contraire à la seule fluidité des ajustements automatiques, il s’en éloigne. Le paradigme archicratique propose de tenir ensemble ces expériences, de les comparer, de les instruire, sans décider à l’avance de leur issue.
|
s'abolir dans sa propre exécution. Un monde qui ne tient ni par inertie,
|
||||||
|
ni par répétition, ni par l'évidence supposée de ses fondements. Il
|
||||||
Cette cinquième révolution n’est pas un futur abstrait : elle advient chaque fois qu’un seuil est suspendu, qu’un fondement est reconvoqué, qu’un recours devient opérant, qu’une voix exclue trouve scène, délai et adresse ; chaque fois que la transparence cesse d’être visualisation pour redevenir publicité des critères, que la participation quitte la consultation pour rejoindre l’épreuve, que la gouvernance s’efface devant la fondation.
|
tient parce qu'il est capable de porter ce qui le traverse sans le nier,
|
||||||
|
de différer ce qui l'affecte sans le dissoudre, d'exposer ce qui le
|
||||||
Nous parlons de “cinquième révolution” par convention, en pleine conscience que l’histoire effective procède par recompositions régulatrices hétérochrones, stratifiées, feuilletées, sérialisées, désynchronisées selon les régimes symboliques et techniques ; de sorte que l’“événement” est devenu une prise de pouvoir de la scène dans l’architecture des dispositifs industriels.
|
gouverne sans s'effondrer sous sa propre mise en question. Habiter un
|
||||||
|
monde ne signifie pas simplement y vivre. Cela signifie pouvoir y
|
||||||
Dans un monde où les infrastructures et les superstructures établissent les nouvelles normes, où les plateformes sont devenues de nouveaux territoires de nos êtres, où les systèmes d’intelligence artificielle s’inventent comme nouveaux gouvernants, seule une révolution scénique permettrait au politique de ne pas s’effacer. Mais celle-ci ne se décrète pas : elle se sculpte par des décisions, des dispositifs, des pratiques et des langages ; elle requiert des artisans, des architectes, des dramaturges du politique ; elle accepte de perdre en fluidité ce qu’elle gagne en légitimité. Et c’est cela, précisément, que nomme l’*archicration* : une révolution régulatrice en acte, bien plus que le modèle institutionnel qu’elle instaurerait en conscience — l’*archicratie*.
|
comparaître. Pouvoir y demander d'où parle ce qui décide. Pouvoir y
|
||||||
|
identifier ce qui opère. Pouvoir y rouvrir le temps lorsque l'exécution
|
||||||
Il faut aujourd’hui prononcer un appel ancré dans le vivant, là où les institutions ne font plus apparaître les polémiques, là où les discordes tendent à se faire taire. Un appel qui ne soit ni un cri, ni un mot d’ordre, ni un acte de foi, mais une *archicration vivante* : c’est-à-dire l’apparition d’énoncés fondés, publics, discutables, adressables, révisables — une parole instituante, dans ce sens précis et exigeant que nous redonnons au mot “politique”. Le droit de vivre ! De tous vivre ! De chacun selon ses capacités, et à chacun selon ses besoins…
|
tend à se refermer sur elle-même. Pouvoir y faire apparaître ce qui,
|
||||||
|
sans cela, demeurerait converti en variable, en score, en flux.
|
||||||
Car ce que notre monde ne sait plus faire advenir, ce ne sont pas les règles ou les normes en elles-mêmes, mais la capacité populaire à les exposer, à les critiquer, à les instituer grâce à des formes collectives constituées par celles et ceux qui les subissent en premier lieu. Cette incapacité n’est ni technique, ni conjoncturelle. Elle est le symptôme d’un effondrement structurel qui au-delà de produire de l’injustice, nous conduit à une crise de viabilité civilisationnelle.
|
|
||||||
|
La scène prend ici son sens le plus fort. Elle n'est ni un supplément
|
||||||
Nous vivons dans un monde où l’humain et le non-humain sont liés par une même absence de considération. Le vivant, dans son immense diversité de formes, d’agencements, de langages, de résistances, est soustrait à la parole, au temps et à la forme. Et ce que notre thèse a permis de penser, c’est que ce processus d’invisibilisation n’est pas un effet secondaire des logiques économiques, mais une conséquence directe de la disparition de la scène de confrontation. Là où il n’y a plus de scène, il ne peut y avoir ni représentant, ni interpellation, ni suspension, ni réparation. Le vivant devient bruit, excès, variable et externalité à occulter.
|
institutionnel, ni un décor ajouté au pouvoir pour en améliorer
|
||||||
|
l'acceptabilité, ni une métaphore commode pour désigner des espaces de
|
||||||
Il faut donc le dire avec toute la solennité nécessaire. Un monde sans *archicration* rend le vivant politiquement illisible, donc indéfendable : le conflit perd sa scène et le temps son droit de retour ; or le vivant a besoin d’un lieu d’apparition où les règles qui le concernent sont convoquées, tenues et différées. Parce qu’il a besoin d’une scène comme condition de reconnaissance mutuelle inscrite dans le temps. Parce qu’il ne peut être gouverné sans être d’abord entendu, représenté, institué dans la durée de conflits assumés, dans la densité d’un désaccord soutenu qui permette tout de même la *co-viabilité*.
|
parole. Elle est l'une des formes à travers lesquelles un ordre cesse
|
||||||
|
d'être purement opératoire pour devenir politiquement tenable. Là où il
|
||||||
Ce n’est pas tant un supplément de conscience écologique que requiert notre temps, qu’une réinscription du vivant dans le cœur même de la procédure régulatrice. Il faut que le vivant retrouve la capacité de faire épreuve comme acteur instituant. Cela implique de convoquer de nouveaux formats d’apparition, de nouvelles figures de représentation, de nouvelles juridictions du milieu, de nouveaux porte-paroles, mais aussi de nouvelles scènes, de nouveaux délais et de nouveaux seuils. Et c’est là que l’*archicration*, en tant que forme d’institution de la régulation, redevient notre outil premier, notre geste inaugural, notre obligation radicale.
|
y a scène au sens fort — c'est-à-dire espace différé, documenté,
|
||||||
|
institué, capable de suspendre et de requalifier — la régulation ne se
|
||||||
Mais ce ne sont pas uniquement les vivants non-humains qui exigent ce retour à la scène. Ce sont les humains eux-mêmes, dans leur diversité traversée de douleurs, de silences, de disparitions, de récits corrompus ou interrompus. Ce sont les corps précarisés, expulsés, captés, mécanisés, racisés, discriminés. Ce sont les voix sans adresse, les luttes étouffées, les demandes restées lettres mortes, les souffrances converties en statistiques, les communautés disqualifiées ou reléguées. Là encore, ce n’est pas un “plus de participation” qu’il faut : c’est un *acte fondateur de refondation*. Ce n’est pas une réforme du droit d’accès à la parole : c’est l’institution d’un droit d’épreuve et de reconnaissance. Encore une fois d’*archicrations* !
|
contente pas d'agir : elle accepte de comparaître. C'est dans cette
|
||||||
|
comparution que se joue la possibilité, pour un monde, de ne pas se
|
||||||
Et ce droit n’est pas métaphysique. Il est scénique. Il s’inscrit dans des formes précises, différées, structurées. Il suppose des lieux, des interlocuteurs, des procédures, des archives, des délais, des énonciateurs. Il suppose des scènes que l’on peut habiter, relancer, réinterroger. Il suppose que la parole soit tenue, mais aussi reçue, exposée, contredite, reformulée. Il suppose, enfin, que cette parole soit retenue dans l’architecture même de la régulation. Qu’il ne soit pas juste documenté, mais qu’il puisse reconfigurer le pouvoir sous condition de recevabilité.
|
réduire à ce qu'il exécute.
|
||||||
|
|
||||||
Nous appelons donc, à ce stade ultime de notre œuvre, à un réarmement du commun par la scène. Rien d’un théâtre idéologique bien plutôt une architecture du vivre-ensemble, régulatrice, opposable, fondée. Car il ne peut y avoir de monde commun sans scène, pas de scène sans différé, et pas de différé sans pouvoir qui accepte de suspendre son exécution pour se reformuler devant celles et ceux qu’il engage. Ce geste — si simple en apparence, si révolutionnaire en pratique — est le cœur de toute *archicration*. Et c’est à ce titre probablement à tout le moins l’une des rares voies régulatrices encore tenables et viables à nos yeux.
|
Il faut ici maintenir une distinction que tout ce travail a jugée
|
||||||
|
décisive. Dire que la scène est condition de viabilité ne signifie
|
||||||
À ce point de saturation du monde — saturation des flux, des normes, des récits, des simulacres de participation — une respiration possible reste celle du moratoire et du différé. La seule densité politique entendable est celle de l’épreuve et des preuves. La seule fondation encore pensable est celle qui accepte de se laisser instituer à nouveau, à se laisser revisiter, en pleine conscience. C’est cela, notre appel : reconvoquer le vivant dans la scène, refaire de l’apparition, de l’information, de l’opinion un droit, refonder la régulation politique en processus d’*archicrations*. Il ne s’agit pas d’ajouter un modèle de plus, mais de rendre à l’histoire ce dont elle a été amputée, faute d’occultation et faute d’impensé : ses scènes fondatrices, émancipatrices et régulatrices qui font tenir les mondes.
|
nullement que toute scène serait en elle-même juste, démocratique ou
|
||||||
|
émancipatrice. L'histoire des formes politiques, juridiques,
|
||||||
Ce que notre époque appelle, est bien plus qu’un ajustement marginal des politiques existantes, bien plus qu’une moralisation incrémentale des comportements individuels. C’est une réinvention des conditions mêmes d’apparition et de mobilisation du pouvoir : des lieux, des temps, des procédures, des mémoires où les décisions qui nous engagent puissent être amenées en scène, instruites, contestées, requalifiées. Les dix gestes qui suivent n’ont pas valeur de programme clos ni de plan de réforme. Ils constituent des hypothèses archicratiques : des propositions de formes scéniques minimales, destinées à être discutées, expérimentées, corrigées. Ils n’ont de sens que s’ils deviennent eux-mêmes objets d’épreuve.
|
religieuses, administratives, guerrières, marchandes ou sacrificielles
|
||||||
|
montre au contraire que des scènes peuvent être violentes,
|
||||||
Premier geste : *instaurer un droit universel au différé contradictoire*. Un tel droit ne viserait pas à ralentir indistinctement toute décision, mais à garantir que toute mesure qui affecte substantiellement une existence – allocation, sanction, fermeture, expulsion, tri automatique – puisse être suspendue dans un temps institué, devant une instance capable d’en reconsidérer les motifs et les effets. Ce droit ne se confond pas avec un simple droit au recours individuel : il institue le temps scénique comme composante non négociable de la régulation.
|
dissymétriques, inquisitoriales, spectaculaires, capturées. La scène
|
||||||
|
n'est pas bonne parce qu'elle apparaît ; elle devient politiquement
|
||||||
Deuxième geste : *fonder, pour chaque grand dispositif de régulation, un journal de justification*. Il ne s’agirait pas d’ajouter un rapport de plus aux archives administratives, mais d’exiger que toute décision structurante (création d’un algorithme, d’un barème, d’un standard) soit accompagnée d’un récit argumenté de ses raisons, des alternatives écartées, des effets anticipés. Ce journal ne sanctifie pas la décision ; il la rend adressable. Il crée une mémoire publique du fondement, à partir de laquelle critiques, révisions et contre-propositions peuvent être formulées.
|
décisive lorsqu'elle institue réellement l'épreuve de ce qu'elle expose.
|
||||||
|
Ce qui compte n'est pas l'existence abstraite d'un lieu d'apparition,
|
||||||
Troisième geste : *instituer un visa d’affectation pour les principaux instruments de calcul et de qualification*. Chaque indicateur, chaque score, chaque seuil ne serait plus un simple paramètre technique, mais devrait porter trace de ses finalités déclarées et des collectifs qui en ont débattu. Ce visa n’autorise pas seulement l’utilisation d’un outil ; il inscrit l’outil dans une adresse éthique et politique : qui décide que telle métrique est légitime pour mesurer telle réalité, avec quelles garanties, pour combien de temps ?
|
mais la possibilité effective qu'il ouvre : peut-on y demander les
|
||||||
|
fondements ? Les instruments peuvent-ils y être rendus visibles ? Les
|
||||||
Quatrième geste : *instaurer un coupe-circuit citoyen*. Il s’agirait de prévoir, dans les dispositifs institutionnels, des mécanismes par lesquels des collectifs – citoyens, usagers, travailleurs, habitants – puissent suspendre temporairement l’application d’une décision lorsque des contradictions graves, des effets non prévus ou des injustices manifestes apparaissent. Ce geste n’est pas un droit d’obstruction généralisée ; il est la traduction procédurale du principe selon lequel aucune *cratialité* ne doit se déployer sans possibilité d’interruption scénique.
|
effets peuvent-ils y être rapportés à ceux qu'ils affectent ? Le différé
|
||||||
|
est-il réel ou purement fictif ? La suspension a-t-elle une force
|
||||||
Cinquième geste : *instituer un tribunal de l’algorithme*. Non pas un organe chargé de valider ou d’interdire abstraitement la technique, mais une scène d’épreuve où les architectures computationnelles qui organisent l’accès aux droits, à l’information, aux ressources, soient rendues comparables, critiquables, reformulables. Un tel tribunal devrait être doté de compétences mixtes – juridiques, techniques, sociales – et travailler à partir de cas concrets. Il ne s’agit pas d’ajouter une couche de contrôle symbolique ; il s’agit de ramener l’algorithme en scène.
|
transformatrice ou n'est-elle qu'un rite sans prise ?
|
||||||
|
|
||||||
Sixième geste : *rétablir des assemblées d’affectation là où les décisions sont aujourd’hui dispersées dans des chaînes opaques*. Dans les hôpitaux, les écoles, les agences sociales, les plateformes, ces assemblées seraient chargées d’instruire publiquement la manière dont les ressources, les priorités, les charges et les risques sont distribués. Elles ne se substituent pas aux institutions existantes ; elles en constituent le moment scénique, là où les critères implicites peuvent être explicités, contestés, ajustés.
|
Il n'en demeure pas moins que, sans scène, la régulation se dégrade
|
||||||
|
qualitativement. Elle peut continuer à fonctionner ; elle peut même
|
||||||
Septième geste : *rendre révocables les mandats au sein des institutions qui conçoivent, paramètrent et pilotent les dispositifs de régulation*, qu’il s’agisse d’instances publiques, de régulateurs indépendants ou de structures privées investies de missions d’intérêt général. La révocabilité ne signifie pas l’instabilité permanente, mais la possibilité, pour les collectifs concernés, de mettre fin à un mandat lorsqu’il apparaît que l’*archicration* est durablement contournée, que les fondements ne sont plus adressés, que la *cratialité* s’est autonomisée.
|
gagner en efficacité apparente. Mais elle perd sa mémoire, sa
|
||||||
|
réversibilité, sa capacité à se rapporter à elle-même autrement que par
|
||||||
Huitième geste : *instaurer, dans chaque budget institutionnel d’importance, un budget scénique*. Il ne s’agirait pas d’un poste décoratif, mais d’une ligne dédiée au financement des dispositifs d’épreuve : temps de délibération, traduction, médiation, expertise contradictoire, dispositifs de restitution. Un budget sans scène est un budget sans adresse. Reconnaître un budget scénique, c’est faire de la scène non plus un coût superflu, mais une condition de validité de la dépense.
|
recalibrage interne. Elle applique, classe, répartit, déclenche, module
|
||||||
|
; mais elle ne se reprend plus. Elle produit des normes sans en exposer
|
||||||
Neuvième geste : *inscrire dans le droit un principe général de révision archicrative*. Ce principe reconnaîtrait que toute architecture régulatrice – loi, norme, algorithme, accord institutionnel – doit pouvoir être réexaminée à intervalles déterminés, à partir d’instances où les personnes affectées, les savoirs concernés, les effets constatés sont convoqués. Il ne s’agit pas d’instaurer une instabilité chronique, mais de consacrer le fait que la *co-viabilité* ne se maintient qu’au prix d’une disponibilité organisée à la révision.
|
les raisons, des décisions sans en instituer l'épreuve, des effets sans
|
||||||
|
en organiser le retour. Elle tient encore ; mais elle ne sait plus
|
||||||
Dixième geste : *construire des cartographies des scènes manquantes.* Au lieu de se contenter d’analyses sectorielles, il s’agirait de repérer, sur un territoire ou dans une chaîne de valeur, les lieux où des décisions structurantes sont prises sans scène identifiable, où les personnes affectées n’ont ni adresse, ni délai, ni recours. De telles cartographies ne sont pas un exercice académique de plus : elles constituent un instrument politique central pour orienter l’invention des scènes à venir, pour ne pas laisser invisible ce que la seule *cratialité* préfère absorber.
|
répondre de la manière dont elle tient. C'est en ce point qu'un monde
|
||||||
|
sans scène devient injustifiable. Non pas nécessairement injuste dans
|
||||||
Ces dix gestes n’épuisent pas la gamme des formes possibles d’*archicration*. Ils ne valent pas comme une doctrine à appliquer, mais comme une invitation à la mise à l’épreuve : ils devront être discutés, critiqués, complétés, remplacés, parfois abandonnés. Leur seule prétention est de montrer que l’*archicratie*, loin d’être un mot abstrait, peut se traduire en dispositifs concrets, situés, qui redonnent aux collectifs la capacité d’adresser le pouvoir qui les traverse. Et c’est à ce niveau que nous posons notre ouvrage, moins une doctrine qu’une mise à l’épreuve publique, moins un programme qu’une fondation différée : l’invitation à restaurer la capacité institutionnelle de refonder le “pouvoir de” et le “pouvoir sur” nos vies, à hauteur de la *téra-machine* en constitution*.*
|
chacun de ses effets immédiats ; non pas chaotique ; non pas dépourvu de
|
||||||
|
cohérence locale. Il peut très bien fonctionner, produire des résultats,
|
||||||
|
stabiliser provisoirement des situations, maintenir des chaînes
|
||||||
|
d'obéissance ou d'adaptation. Mais il devient injustifiable parce qu'il
|
||||||
|
ne dispose plus des formes dans lesquelles ses propres décisions peuvent
|
||||||
|
être rejouées, exposées, interrogées, reformulées.
|
||||||
|
|
||||||
|
On comprend alors ce que la co-viabilité signifie exactement. Elle ne
|
||||||
|
désigne ni la simple coexistence de formes de vie différentes, ni leur
|
||||||
|
compatibilité gestionnaire, ni un optimum de répartition des ressources
|
||||||
|
ou des charges. Elle désigne la capacité, toujours fragile, toujours
|
||||||
|
située, toujours révisable, d'un monde à instituer des formes dans
|
||||||
|
lesquelles les hétérogènes qui le traversent peuvent être mis en tension
|
||||||
|
sans être soit mutuellement détruits, soit administrativement
|
||||||
|
neutralisés. Elle est moins un état qu'un régime d'épreuves. Elle ne se
|
||||||
|
mesure pas seulement à l'efficacité des ajustements ; elle se mesure à
|
||||||
|
la possibilité qu'un ordre laisse ouvert sa propre reprise à partir de
|
||||||
|
ce qu'il affecte.
|
||||||
|
|
||||||
|
C'est à ce niveau que le diagnostic du présent trouve sa formulation la
|
||||||
|
plus nette. Non dans l'idée d'un monde privé de régulation, mais dans
|
||||||
|
celle d'un monde où la régulation tend à se déployer hors des formes qui
|
||||||
|
permettaient de la tenir. Qu'il s'agisse des droits sociaux, de
|
||||||
|
l'habitabilité écologique des milieux ou des architectures numériques de
|
||||||
|
décision, la même logique se renforce : les dispositifs deviennent plus
|
||||||
|
puissants au moment même où les formes capables d'en soutenir l'épreuve
|
||||||
|
deviennent plus fragiles, plus tardives, plus périphériques. Ce ne sont
|
||||||
|
pas les décisions qui disparaissent ; ce sont les manières dont elles
|
||||||
|
pourraient être tenues.
|
||||||
|
|
||||||
|
Les droits, dans de nombreuses configurations sociales, se trouvent
|
||||||
|
intermédiés par des procédures dont la logique demeure difficilement
|
||||||
|
accessible à ceux qu'elles affectent ; les décisions qui concernent
|
||||||
|
l'habitabilité écologique des milieux se trouvent portées par des
|
||||||
|
instruments puissants, mais rarement rapportées à des espaces où leurs
|
||||||
|
fondements pourraient être disputés ; les architectures numériques et
|
||||||
|
algorithmiques rendent possible une distribution fine des traitements,
|
||||||
|
des classements, des accès, sans rendre aisément localisable le lieu de
|
||||||
|
leur mise à l'épreuve. Ces dimensions ne doivent pas être comprises
|
||||||
|
comme des sphères séparées. Elles constituent les expressions
|
||||||
|
différenciées d'un même processus : celui par lequel la régulation tend
|
||||||
|
à se déployer hors des formes d'épreuve qui permettaient de la tenir
|
||||||
|
comme monde.
|
||||||
|
|
||||||
|
C'est en ce sens que l'autarchicratie peut être nommée comme la
|
||||||
|
contre-figure terminale de l'archicratie. Non un régime au sens
|
||||||
|
classique, ni une idéologie, ni un type d'État, mais une configuration
|
||||||
|
dans laquelle la régulation tend à se refermer sur sa propre
|
||||||
|
opérativité, à produire ses propres critères de validité, à
|
||||||
|
s'auto-justifier sans passer par des épreuves effectives. Dans une telle
|
||||||
|
configuration, les instruments, les modèles, les indicateurs, les
|
||||||
|
procédures deviennent à la fois ce qui opère et ce qui justifie. Les
|
||||||
|
boucles se ferment. Les ajustements se font à partir de leurs propres
|
||||||
|
résultats. Les audits vérifient la conformité à des critères produits
|
||||||
|
par les systèmes eux-mêmes. La régulation devient auto-référentielle.
|
||||||
|
|
||||||
|
Cette bascule ne doit pas être dramatisée comme si elle était totale,
|
||||||
|
homogène, déjà accomplie. Des scènes subsistent, parfois robustes,
|
||||||
|
parfois fragiles. Des espaces de contestation, de délibération, de
|
||||||
|
reprise continuent d'exister. Mais ils apparaissent souvent comme
|
||||||
|
disjoints des lieux où les décisions se prennent effectivement. La
|
||||||
|
tension se joue moins entre présence et absence de scène qu'entre leur
|
||||||
|
centralité et leur marginalisation. Le problème décisif n'est pas de
|
||||||
|
savoir si toute scène a disparu ; il est de comprendre que la dynamique
|
||||||
|
dominante tend à rendre optionnelle l'épreuve dont dépend pourtant la
|
||||||
|
viabilité de la régulation.
|
||||||
|
|
||||||
|
C'est ici que la distinction entre durabilité et co-viabilité prend
|
||||||
|
toute sa force. La durabilité, telle qu'elle s'est imposée dans les
|
||||||
|
discours contemporains, ne doit pas être critiquée d'abord pour ses
|
||||||
|
intentions, mais pour sa forme. Elle tend à fonctionner comme un
|
||||||
|
opérateur de neutralisation de la conflictualité : en posant comme
|
||||||
|
objectif la préservation ou l'ajustement de certains équilibres, elle
|
||||||
|
déplace l'attention vers la gestion des variables, l'optimisation des
|
||||||
|
paramètres, la correction des trajectoires. Ce déplacement n'est pas
|
||||||
|
illégitime en soi ; il le devient lorsqu'il s'accompagne d'une
|
||||||
|
évacuation des formes dans lesquelles les choix qui structurent ces
|
||||||
|
trajectoires pourraient être discutés. La durabilité peut alors
|
||||||
|
s'accommoder d'une régulation sans scène. La co-viabilité, elle, en fait
|
||||||
|
une impossibilité.
|
||||||
|
|
||||||
|
La différence est décisive. La première tend à organiser la continuité
|
||||||
|
des systèmes ; la seconde à instituer les conditions de leur reprise. La
|
||||||
|
première privilégie l'ajustement des variables ; la seconde la mise à
|
||||||
|
l'épreuve des fondements. La première peut se satisfaire d'une
|
||||||
|
gouvernance qui corrige des déséquilibres ; la seconde exige des formes
|
||||||
|
dans lesquelles les conditions mêmes de ces corrections peuvent être
|
||||||
|
adressées, contestées, transformées. Ainsi comprise, la co-viabilité ne
|
||||||
|
constitue pas un idéal abstrait. Elle désigne le régime minimal dans
|
||||||
|
lequel un monde peut continuer à se transformer sans se soustraire à sa
|
||||||
|
propre interrogation. Elle n'abolit pas les tensions ; elle en organise
|
||||||
|
la tenue. Elle n'élimine pas les conflits ; elle en rend l'épreuve
|
||||||
|
possible. Elle ne garantit pas la justice ; elle rend au moins pensable
|
||||||
|
sa recherche.
|
||||||
|
|
||||||
|
Il reste alors à comprendre ce qui, en dernière instance, est affecté
|
||||||
|
par cette transformation. Non pas seulement des institutions, des
|
||||||
|
règles, des procédures, mais des formes d'existence. Des vies. Des
|
||||||
|
milieux. Des devenirs. Si l'archicratie prend finalement une telle
|
||||||
|
importance, ce n'est pas parce qu'elle offrirait une théorie plus
|
||||||
|
satisfaisante du pouvoir ; c'est parce qu'elle reconduit l'analyse à ce
|
||||||
|
qui, sans scène, devient politiquement illisible. Là où la régulation se
|
||||||
|
déploie sous forme de flux, de calculs, de traitements, le vivant tend à
|
||||||
|
être reconduit à des variables. Les milieux deviennent des stocks ou des
|
||||||
|
contraintes. Les corps deviennent des profils, des trajectoires, des
|
||||||
|
cas. Les expériences deviennent des données d'ajustement. Ce processus
|
||||||
|
n'est pas nécessairement intentionnel. Il résulte de la logique même des
|
||||||
|
dispositifs qui, pour fonctionner, doivent simplifier, catégoriser,
|
||||||
|
standardiser. Mais cette simplification a un effet décisif : elle
|
||||||
|
désinscrit le vivant de la scène. Elle le rend opérable sans qu'il ait à
|
||||||
|
apparaître.
|
||||||
|
|
||||||
|
Le vivant ne disparaît pas ; il devient politiquement illisible. Il est
|
||||||
|
là, partout affecté, mobilisé, transformé — mais de moins en moins
|
||||||
|
capable de faire retour sur ce qui l'affecte. Un monde sans archicration
|
||||||
|
est un monde dans lequel le vivant est présent sans être représentable,
|
||||||
|
affecté sans être adressable, engagé sans être entendu. Il est pris dans
|
||||||
|
des opérations, mais il ne peut plus apparaître comme ce à partir de
|
||||||
|
quoi celles-ci devraient être interrogées.
|
||||||
|
|
||||||
|
C'est en ce sens que l'oblitération archicratique produit une crise de
|
||||||
|
reconnaissance. Non pas au sens restreint d'une reconnaissance morale ou
|
||||||
|
symbolique, mais au sens plus fondamental d'une reconnaissance comme
|
||||||
|
condition d'apparition dans un espace où l'on peut être pris en compte.
|
||||||
|
Reconnaître ne signifie pas simplement identifier ou décrire. Cela
|
||||||
|
signifie instituer des formes dans lesquelles ce qui est affecté peut
|
||||||
|
être reconduit à une scène, où il peut être exposé, où il peut entrer en
|
||||||
|
relation avec ce qui décide. Sans cette reconnaissance, le vivant peut
|
||||||
|
être protégé, géré, optimisé ; il ne peut pas être politiquement tenu.
|
||||||
|
|
||||||
|
Il faut alors comprendre que la question de la scène n'est pas
|
||||||
|
extérieure à celle de la liberté. Elle en constitue l'une des conditions
|
||||||
|
minimales. Non la liberté comme autonomie absolue, mais comme
|
||||||
|
possibilité d'intervenir sur les conditions qui nous affectent. Une
|
||||||
|
société qui ne dispose plus de formes dans lesquelles ses propres
|
||||||
|
régulations puissent être interrogées tend à se percevoir comme soumise
|
||||||
|
à des nécessités. Elle perd la capacité de distinguer ce qui relève de
|
||||||
|
contraintes inévitables et ce qui relève de choix. À l'inverse, une
|
||||||
|
société qui institue des épreuves se dote de la possibilité de se
|
||||||
|
rapporter à elle-même comme à un ensemble de décisions révisables. Elle
|
||||||
|
ne supprime pas les contraintes, mais elle les inscrit dans des formes
|
||||||
|
où elles peuvent être discutées.
|
||||||
|
|
||||||
|
À ce point, aucune réponse définitive ne peut être apportée. Aucun
|
||||||
|
modèle achevé ne peut être proposé. Mais une exigence demeure, désormais
|
||||||
|
visible et irréductible. Un monde ne devient inhabitable ni parce qu'il
|
||||||
|
est traversé de tensions, ni parce qu'il doit décider dans
|
||||||
|
l'incertitude, ni parce qu'il affronte des contraintes puissantes. Il le
|
||||||
|
devient lorsqu'il ne dispose plus des formes capables de porter ce qui
|
||||||
|
le traverse autrement que par la pure exécution. Ce qui est en jeu n'est
|
||||||
|
ni la suppression du conflit, ni l'optimisation des dispositifs, ni la
|
||||||
|
stabilisation d'un équilibre. Ce qui est en jeu, c'est la possibilité de
|
||||||
|
maintenir ouvertes les formes dans lesquelles un monde peut se rapporter
|
||||||
|
à lui-même à partir de ce qu'il affecte. La possibilité, toujours
|
||||||
|
fragile, toujours menacée, de ne pas confondre ce qui fonctionne avec ce
|
||||||
|
qui se tient.
|
||||||
|
|
||||||
|
Rendre à la régulation les formes dans lesquelles elle peut encore être
|
||||||
|
tenue comme monde : telle est l'exigence à laquelle reconduit l'ensemble
|
||||||
|
de ce parcours. Non comme un programme, ni comme une promesse, mais
|
||||||
|
comme ce sans quoi aucune transformation ne peut être habitée. Car ce
|
||||||
|
n'est jamais l'ordre seul qui fait tenir un monde. C'est la possibilité,
|
||||||
|
pour cet ordre, d'être interrompu, exposé, repris. Là où cette
|
||||||
|
possibilité se ferme, le monde peut continuer à marcher ; il cesse peu à
|
||||||
|
peu d'être habitable. Là où elle demeure ouverte, fût-ce dans le
|
||||||
|
conflit, sous contrainte, précairement, quelque chose du politique
|
||||||
|
subsiste encore : non la paix, ni l'innocence, ni l'harmonie, mais la
|
||||||
|
capacité d'un monde à ne pas se confondre avec sa propre exécution.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,38 +26,118 @@ const {
|
|||||||
</EditionLayout>
|
</EditionLayout>
|
||||||
|
|
||||||
<style is:global>
|
<style is:global>
|
||||||
|
/* =========================================================
|
||||||
|
FICHES GLOSSAIRE — état normal
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-entry"]{
|
||||||
|
--entry-hero-pad-top: 18px;
|
||||||
|
--entry-hero-pad-x: 18px;
|
||||||
|
--entry-hero-pad-bottom: 18px;
|
||||||
|
--entry-hero-gap: 14px;
|
||||||
|
|
||||||
|
--entry-hero-h1-size: clamp(2.2rem, 4vw, 3.15rem);
|
||||||
|
|
||||||
|
--entry-hero-dek-size: 1.04rem;
|
||||||
|
--entry-hero-dek-lh: 1.55;
|
||||||
|
--entry-hero-dek-maxw: 76ch;
|
||||||
|
|
||||||
|
--entry-hero-meta-max-h: 12rem;
|
||||||
|
--entry-hero-meta-opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-entry"].glossary-entry-follow-on{
|
||||||
|
--entry-hero-pad-top: 8px;
|
||||||
|
--entry-hero-pad-x: 14px;
|
||||||
|
--entry-hero-pad-bottom: 6px;
|
||||||
|
--entry-hero-gap: 6px;
|
||||||
|
|
||||||
|
--entry-hero-h1-size: clamp(1.45rem, 2.4vw, 1.9rem);
|
||||||
|
|
||||||
|
--entry-hero-dek-size: .90rem;
|
||||||
|
--entry-hero-dek-lh: 1.32;
|
||||||
|
--entry-hero-dek-maxw: 56ch;
|
||||||
|
|
||||||
|
--entry-hero-meta-max-h: 0px;
|
||||||
|
--entry-hero-meta-opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
PORTAILS GLOSSAIRE — socle premium desktop
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"]{
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"]{
|
||||||
--portal-hero-pad-top: 18px;
|
/* hero : état plein */
|
||||||
|
--portal-hero-margin-bottom: 28px;
|
||||||
|
|
||||||
|
--portal-hero-pad-top: 20px;
|
||||||
--portal-hero-pad-x: 18px;
|
--portal-hero-pad-x: 18px;
|
||||||
--portal-hero-pad-bottom: 20px;
|
--portal-hero-pad-bottom: 22px;
|
||||||
--portal-hero-gap: 14px;
|
--portal-hero-gap: 16px;
|
||||||
|
|
||||||
--portal-hero-h1-size: clamp(2.2rem, 4vw, 3.15rem);
|
--portal-kicker-size: 12px;
|
||||||
|
--portal-kicker-lh: 1.2;
|
||||||
|
--portal-kicker-spacing: .14em;
|
||||||
|
|
||||||
--portal-hero-intro-size: 1.04rem;
|
--portal-hero-h1-size: clamp(3rem, 4.8vw, 4.15rem);
|
||||||
--portal-hero-intro-lh: 1.55;
|
--portal-hero-h1-lh: .98;
|
||||||
--portal-hero-intro-maxw: 76ch;
|
--portal-hero-h1-spacing: -.045em;
|
||||||
|
|
||||||
|
--portal-hero-intro-size: 1.06rem;
|
||||||
|
--portal-hero-intro-lh: 1.6;
|
||||||
|
--portal-hero-intro-maxw: 70ch;
|
||||||
|
|
||||||
|
--portal-hero-follow-intro-max-w: 62ch;
|
||||||
--portal-hero-secondary-max-h: 20em;
|
--portal-hero-secondary-max-h: 20em;
|
||||||
--portal-hero-secondary-opacity: .94;
|
--portal-hero-secondary-opacity: .92;
|
||||||
}
|
|
||||||
|
/* hero : état condensé */
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-follow-on{
|
--portal-hero-pad-top-condensed: 14px;
|
||||||
--portal-hero-pad-top: 12px;
|
--portal-hero-pad-x-condensed: 16px;
|
||||||
--portal-hero-pad-x: 16px;
|
--portal-hero-pad-bottom-condensed: 16px;
|
||||||
--portal-hero-pad-bottom: 14px;
|
--portal-hero-gap-condensed: 10px;
|
||||||
--portal-hero-gap: 8px;
|
|
||||||
|
--portal-hero-h1-size-condensed: clamp(2.05rem, 3.15vw, 2.7rem);
|
||||||
--portal-hero-h1-size: clamp(1.95rem, 3.3vw, 2.6rem);
|
--portal-hero-h1-lh-condensed: 1;
|
||||||
|
--portal-hero-h1-spacing-condensed: -.04em;
|
||||||
--portal-hero-intro-size: .98rem;
|
|
||||||
--portal-hero-intro-lh: 1.46;
|
--portal-hero-intro-size-condensed: .98rem;
|
||||||
--portal-hero-intro-maxw: 68ch;
|
--portal-hero-intro-lh-condensed: 1.46;
|
||||||
|
|
||||||
--portal-hero-secondary-max-h: 4.6em;
|
/* rythme vertical */
|
||||||
--portal-hero-secondary-opacity: .82;
|
--portal-page-pad-top: 8px;
|
||||||
|
--portal-page-pad-bottom: 24px;
|
||||||
|
|
||||||
|
--portal-block-gap: 20px;
|
||||||
|
--portal-grid-gap: 14px;
|
||||||
|
|
||||||
|
/* cartes / panels */
|
||||||
|
--portal-card-pad-y: 14px;
|
||||||
|
--portal-card-pad-x: 16px;
|
||||||
|
--portal-card-radius: 16px;
|
||||||
|
|
||||||
|
--portal-panel-pad-y: 16px;
|
||||||
|
--portal-panel-pad-x: 16px;
|
||||||
|
--portal-panel-radius: 18px;
|
||||||
|
|
||||||
|
--portal-focus-pad-y: 18px;
|
||||||
|
--portal-focus-pad-x: 20px;
|
||||||
|
--portal-focus-radius: 18px;
|
||||||
|
|
||||||
|
/* typo locale */
|
||||||
|
--portal-body-size: 1rem;
|
||||||
|
--portal-body-lh: 1.55;
|
||||||
|
|
||||||
|
--portal-card-title-size: 15px;
|
||||||
|
--portal-card-text-size: 14px;
|
||||||
|
--portal-card-text-lh: 1.45;
|
||||||
|
--portal-card-meta-size: 12px;
|
||||||
|
|
||||||
|
--portal-local-h3-size: clamp(1.35rem, 2vw, 1.7rem);
|
||||||
|
--portal-local-h3-lh: 1.15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* transition commune */
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"] .scene-hero,
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"] .scene-hero,
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"] .glossary-portal-hero,
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"] .glossary-portal-hero,
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"] .glossary-page-hero{
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"] .glossary-page-hero{
|
||||||
@@ -65,18 +145,298 @@ const {
|
|||||||
border-radius 180ms ease,
|
border-radius 180ms ease,
|
||||||
padding 180ms ease,
|
padding 180ms ease,
|
||||||
row-gap 180ms ease,
|
row-gap 180ms ease,
|
||||||
margin-bottom 180ms ease;
|
margin-bottom 180ms ease,
|
||||||
|
box-shadow 180ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-follow-on .scene-hero,
|
/* raccord premium hero + follow */
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-follow-on .glossary-portal-hero,
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-portal-follow-on .scene-hero,
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-follow-on .glossary-page-hero{
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-portal-follow-on .glossary-portal-hero,
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-portal-follow-on .glossary-page-hero{
|
||||||
border-bottom-left-radius: 0 !important;
|
border-bottom-left-radius: 0 !important;
|
||||||
border-bottom-right-radius: 0 !important;
|
border-bottom-right-radius: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-follow-on #reading-follow .reading-follow__inner{
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"].glossary-portal-follow-on #reading-follow .reading-follow__inner{
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
TABLETTE / INTERMÉDIAIRE
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
@media (max-width: 980px){
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"]{
|
||||||
|
--portal-hero-margin-bottom: 22px;
|
||||||
|
|
||||||
|
--portal-hero-pad-top: 18px;
|
||||||
|
--portal-hero-pad-x: 16px;
|
||||||
|
--portal-hero-pad-bottom: 18px;
|
||||||
|
--portal-hero-gap: 14px;
|
||||||
|
|
||||||
|
--portal-hero-h1-size: clamp(2.45rem, 4.4vw, 3.25rem);
|
||||||
|
--portal-hero-h1-lh: .99;
|
||||||
|
--portal-hero-h1-spacing: -.04em;
|
||||||
|
|
||||||
|
--portal-hero-intro-size: 1rem;
|
||||||
|
--portal-hero-intro-lh: 1.5;
|
||||||
|
--portal-hero-intro-maxw: 68ch;
|
||||||
|
|
||||||
|
--portal-hero-pad-top-condensed: 13px;
|
||||||
|
--portal-hero-pad-x-condensed: 14px;
|
||||||
|
--portal-hero-pad-bottom-condensed: 14px;
|
||||||
|
--portal-hero-gap-condensed: 9px;
|
||||||
|
|
||||||
|
--portal-hero-h1-size-condensed: clamp(1.88rem, 3vw, 2.35rem);
|
||||||
|
--portal-hero-h1-lh-condensed: 1;
|
||||||
|
--portal-hero-intro-size-condensed: .95rem;
|
||||||
|
--portal-hero-intro-lh-condensed: 1.42;
|
||||||
|
|
||||||
|
--portal-page-pad-top: 6px;
|
||||||
|
--portal-page-pad-bottom: 20px;
|
||||||
|
|
||||||
|
--portal-block-gap: 17px;
|
||||||
|
--portal-grid-gap: 11px;
|
||||||
|
|
||||||
|
--portal-card-pad-y: 13px;
|
||||||
|
--portal-card-pad-x: 14px;
|
||||||
|
--portal-card-radius: 15px;
|
||||||
|
|
||||||
|
--portal-panel-pad-y: 14px;
|
||||||
|
--portal-panel-pad-x: 14px;
|
||||||
|
--portal-panel-radius: 16px;
|
||||||
|
|
||||||
|
--portal-focus-pad-y: 16px;
|
||||||
|
--portal-focus-pad-x: 16px;
|
||||||
|
--portal-focus-radius: 16px;
|
||||||
|
|
||||||
|
--portal-body-size: .96rem;
|
||||||
|
--portal-body-lh: 1.46;
|
||||||
|
|
||||||
|
--portal-card-title-size: 14px;
|
||||||
|
--portal-card-text-size: 13px;
|
||||||
|
--portal-card-text-lh: 1.4;
|
||||||
|
--portal-card-meta-size: 11.5px;
|
||||||
|
|
||||||
|
--portal-local-h3-size: clamp(1.18rem, 2.2vw, 1.42rem);
|
||||||
|
--portal-local-h3-lh: 1.14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
MOBILE
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-entry"]{
|
||||||
|
--entry-hero-pad-top: 12px;
|
||||||
|
--entry-hero-pad-x: 12px;
|
||||||
|
--entry-hero-pad-bottom: 12px;
|
||||||
|
--entry-hero-gap: 9px;
|
||||||
|
|
||||||
|
--entry-hero-h1-size: clamp(1.55rem, 7vw, 2rem);
|
||||||
|
|
||||||
|
--entry-hero-dek-size: .95rem;
|
||||||
|
--entry-hero-dek-lh: 1.42;
|
||||||
|
--entry-hero-dek-maxw: 100%;
|
||||||
|
|
||||||
|
--entry-hero-meta-max-h: 0px;
|
||||||
|
--entry-hero-meta-opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-entry"].glossary-entry-follow-on{
|
||||||
|
--entry-hero-pad-top: 8px;
|
||||||
|
--entry-hero-pad-x: 10px;
|
||||||
|
--entry-hero-pad-bottom: 8px;
|
||||||
|
--entry-hero-gap: 6px;
|
||||||
|
|
||||||
|
--entry-hero-h1-size: clamp(1.15rem, 5.2vw, 1.35rem);
|
||||||
|
|
||||||
|
--entry-hero-dek-size: .82rem;
|
||||||
|
--entry-hero-dek-lh: 1.25;
|
||||||
|
--entry-hero-dek-maxw: 100%;
|
||||||
|
|
||||||
|
--entry-hero-meta-max-h: 0px;
|
||||||
|
--entry-hero-meta-opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"]{
|
||||||
|
--portal-hero-margin-bottom: 18px;
|
||||||
|
|
||||||
|
--portal-hero-pad-top: 12px;
|
||||||
|
--portal-hero-pad-x: 12px;
|
||||||
|
--portal-hero-pad-bottom: 12px;
|
||||||
|
--portal-hero-gap: 8px;
|
||||||
|
|
||||||
|
--portal-kicker-size: 11px;
|
||||||
|
--portal-kicker-lh: 1.18;
|
||||||
|
--portal-kicker-spacing: .12em;
|
||||||
|
|
||||||
|
--portal-hero-h1-size: clamp(1.72rem, 7vw, 2.08rem);
|
||||||
|
--portal-hero-h1-lh: 1.01;
|
||||||
|
--portal-hero-h1-spacing: -.03em;
|
||||||
|
|
||||||
|
--portal-hero-intro-size: .95rem;
|
||||||
|
--portal-hero-intro-lh: 1.4;
|
||||||
|
--portal-hero-intro-maxw: 100%;
|
||||||
|
--portal-hero-follow-intro-max-w: 100%;
|
||||||
|
|
||||||
|
--portal-hero-secondary-max-h: none;
|
||||||
|
--portal-hero-secondary-opacity: 1;
|
||||||
|
|
||||||
|
/* valeurs condensées mobiles dédiées */
|
||||||
|
--portal-hero-pad-top-condensed: 10px;
|
||||||
|
--portal-hero-pad-x-condensed: 12px;
|
||||||
|
--portal-hero-pad-bottom-condensed: 10px;
|
||||||
|
--portal-hero-gap-condensed: 7px;
|
||||||
|
|
||||||
|
--portal-hero-h1-size-condensed: clamp(1.42rem, 5.8vw, 1.8rem);
|
||||||
|
--portal-hero-h1-lh-condensed: 1.02;
|
||||||
|
--portal-hero-h1-spacing-condensed: -.028em;
|
||||||
|
|
||||||
|
--portal-hero-intro-size-condensed: .88rem;
|
||||||
|
--portal-hero-intro-lh-condensed: 1.3;
|
||||||
|
|
||||||
|
--portal-page-pad-top: 4px;
|
||||||
|
--portal-page-pad-bottom: 16px;
|
||||||
|
|
||||||
|
--portal-block-gap: 14px;
|
||||||
|
--portal-grid-gap: 9px;
|
||||||
|
|
||||||
|
--portal-card-pad-y: 12px;
|
||||||
|
--portal-card-pad-x: 12px;
|
||||||
|
--portal-card-radius: 14px;
|
||||||
|
|
||||||
|
--portal-panel-pad-y: 12px;
|
||||||
|
--portal-panel-pad-x: 12px;
|
||||||
|
--portal-panel-radius: 14px;
|
||||||
|
|
||||||
|
--portal-focus-pad-y: 13px;
|
||||||
|
--portal-focus-pad-x: 13px;
|
||||||
|
--portal-focus-radius: 14px;
|
||||||
|
|
||||||
|
--portal-body-size: .9rem;
|
||||||
|
--portal-body-lh: 1.34;
|
||||||
|
|
||||||
|
--portal-card-title-size: 13.5px;
|
||||||
|
--portal-card-text-size: 12.5px;
|
||||||
|
--portal-card-text-lh: 1.34;
|
||||||
|
--portal-card-meta-size: 11px;
|
||||||
|
|
||||||
|
--portal-local-h3-size: clamp(1.02rem, 4.8vw, 1.2rem);
|
||||||
|
--portal-local-h3-lh: 1.12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 520px){
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-entry"]{
|
||||||
|
--entry-hero-pad-top: 10px;
|
||||||
|
--entry-hero-pad-x: 10px;
|
||||||
|
--entry-hero-pad-bottom: 10px;
|
||||||
|
--entry-hero-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-entry"].glossary-entry-follow-on{
|
||||||
|
--entry-hero-pad-top: 7px;
|
||||||
|
--entry-hero-pad-x: 8px;
|
||||||
|
--entry-hero-pad-bottom: 7px;
|
||||||
|
--entry-hero-gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"]{
|
||||||
|
--portal-hero-margin-bottom: 16px;
|
||||||
|
|
||||||
|
--portal-hero-pad-top: 10px;
|
||||||
|
--portal-hero-pad-x: 10px;
|
||||||
|
--portal-hero-pad-bottom: 10px;
|
||||||
|
--portal-hero-gap: 7px;
|
||||||
|
|
||||||
|
--portal-hero-pad-top-condensed: 8px;
|
||||||
|
--portal-hero-pad-x-condensed: 8px;
|
||||||
|
--portal-hero-pad-bottom-condensed: 8px;
|
||||||
|
--portal-hero-gap-condensed: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-home"].glossary-home-follow-on #reading-follow .reading-follow__inner{
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
PAYSAGE COMPACT
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
body[data-edition-key="glossaire"][data-sticky-mode="glossary-portal"]{
|
||||||
|
--portal-hero-margin-bottom: 12px;
|
||||||
|
|
||||||
|
--portal-hero-pad-top: 10px;
|
||||||
|
--portal-hero-pad-x: 10px;
|
||||||
|
--portal-hero-pad-bottom: 10px;
|
||||||
|
--portal-hero-gap: 6px;
|
||||||
|
|
||||||
|
--portal-kicker-size: 10px;
|
||||||
|
--portal-kicker-lh: 1.14;
|
||||||
|
--portal-kicker-spacing: .1em;
|
||||||
|
|
||||||
|
--portal-hero-h1-size: clamp(1.24rem, 4vw, 1.52rem);
|
||||||
|
--portal-hero-h1-lh: 1.02;
|
||||||
|
--portal-hero-h1-spacing: -.022em;
|
||||||
|
|
||||||
|
--portal-hero-intro-size: .82rem;
|
||||||
|
--portal-hero-intro-lh: 1.24;
|
||||||
|
--portal-hero-intro-maxw: 100%;
|
||||||
|
--portal-hero-follow-intro-max-w: 100%;
|
||||||
|
|
||||||
|
--portal-hero-secondary-max-h: none;
|
||||||
|
--portal-hero-secondary-opacity: 1;
|
||||||
|
|
||||||
|
--portal-hero-pad-top-condensed: 8px;
|
||||||
|
--portal-hero-pad-x-condensed: 10px;
|
||||||
|
--portal-hero-pad-bottom-condensed: 8px;
|
||||||
|
--portal-hero-gap-condensed: 5px;
|
||||||
|
|
||||||
|
--portal-hero-h1-size-condensed: clamp(1.08rem, 3.4vw, 1.28rem);
|
||||||
|
--portal-hero-h1-lh-condensed: 1.02;
|
||||||
|
--portal-hero-h1-spacing-condensed: -.018em;
|
||||||
|
|
||||||
|
--portal-hero-intro-size-condensed: .76rem;
|
||||||
|
--portal-hero-intro-lh-condensed: 1.18;
|
||||||
|
|
||||||
|
--portal-page-pad-top: 2px;
|
||||||
|
--portal-page-pad-bottom: 12px;
|
||||||
|
|
||||||
|
--portal-block-gap: 10px;
|
||||||
|
--portal-grid-gap: 8px;
|
||||||
|
|
||||||
|
--portal-card-pad-y: 10px;
|
||||||
|
--portal-card-pad-x: 10px;
|
||||||
|
--portal-card-radius: 12px;
|
||||||
|
|
||||||
|
--portal-panel-pad-y: 10px;
|
||||||
|
--portal-panel-pad-x: 10px;
|
||||||
|
--portal-panel-radius: 12px;
|
||||||
|
|
||||||
|
--portal-focus-pad-y: 10px;
|
||||||
|
--portal-focus-pad-x: 10px;
|
||||||
|
--portal-focus-radius: 12px;
|
||||||
|
|
||||||
|
--portal-body-size: .82rem;
|
||||||
|
--portal-body-lh: 1.24;
|
||||||
|
|
||||||
|
--portal-card-title-size: 12.5px;
|
||||||
|
--portal-card-text-size: 11.5px;
|
||||||
|
--portal-card-text-lh: 1.24;
|
||||||
|
--portal-card-meta-size: 10.5px;
|
||||||
|
|
||||||
|
--portal-local-h3-size: clamp(.96rem, 3.2vw, 1.08rem);
|
||||||
|
--portal-local-h3-lh: 1.1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -2,6 +2,53 @@ import type { CollectionEntry } from "astro:content";
|
|||||||
|
|
||||||
export type GlossaryEntry = CollectionEntry<"glossaire">;
|
export type GlossaryEntry = CollectionEntry<"glossaire">;
|
||||||
|
|
||||||
|
export type GlossaryPortalLink = {
|
||||||
|
href: string;
|
||||||
|
label: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GlossaryRelationSection = {
|
||||||
|
title: string;
|
||||||
|
items: GlossaryEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GlossaryRelationBlock = GlossaryRelationSection & {
|
||||||
|
className: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GlossaryHomeStats = {
|
||||||
|
totalEntries: number;
|
||||||
|
paradigmesCount: number;
|
||||||
|
doctrinesCount: number;
|
||||||
|
metaRegimesCount: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GlossaryEntryAsideData = {
|
||||||
|
displayFamily: string;
|
||||||
|
displayDomain: string;
|
||||||
|
displayLevel: string;
|
||||||
|
showNoyau: boolean;
|
||||||
|
showSameFamily: boolean;
|
||||||
|
fondamentaux: GlossaryEntry[];
|
||||||
|
sameFamilyTitle: string;
|
||||||
|
sameFamilyEntries: GlossaryEntry[];
|
||||||
|
relationSections: GlossaryRelationSection[];
|
||||||
|
contextualTheory: GlossaryEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GlossaryHomeData = {
|
||||||
|
fondamentaux: GlossaryEntry[];
|
||||||
|
scenes: GlossaryEntry[];
|
||||||
|
dynamiques: GlossaryEntry[];
|
||||||
|
metaRegimes: GlossaryEntry[];
|
||||||
|
metaRegimesPreview: GlossaryEntry[];
|
||||||
|
arcalite?: GlossaryEntry;
|
||||||
|
cratialite?: GlossaryEntry;
|
||||||
|
tension?: GlossaryEntry;
|
||||||
|
sceneDepreuve?: GlossaryEntry;
|
||||||
|
archicration?: GlossaryEntry;
|
||||||
|
};
|
||||||
|
|
||||||
export const GLOSSARY_COLLATOR = new Intl.Collator("fr", {
|
export const GLOSSARY_COLLATOR = new Intl.Collator("fr", {
|
||||||
sensitivity: "base",
|
sensitivity: "base",
|
||||||
numeric: true,
|
numeric: true,
|
||||||
@@ -75,6 +122,34 @@ export const FAMILY_SECTION_TITLES: Record<string, string> = {
|
|||||||
epistemologie: "Outillage épistémologique",
|
epistemologie: "Outillage épistémologique",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PREFERRED_PARADIGME_SLUGS = [
|
||||||
|
"gouvernementalite",
|
||||||
|
"gouvernementalite-algorithmique",
|
||||||
|
"cybernetique",
|
||||||
|
"biopolitique",
|
||||||
|
"domination-legale-rationnelle",
|
||||||
|
"democratie-deliberative",
|
||||||
|
"gouvernance-des-communs",
|
||||||
|
"agencement-machinique",
|
||||||
|
"pharmacologie-technique",
|
||||||
|
"preemption-algorithmique",
|
||||||
|
"dissensus-politique",
|
||||||
|
"lieu-vide-du-pouvoir",
|
||||||
|
"habitus-et-violence-symbolique",
|
||||||
|
"theorie-de-la-resonance",
|
||||||
|
"conatus-et-multitude",
|
||||||
|
"configuration-et-interdependance",
|
||||||
|
"technodiversite-et-cosmotechnie",
|
||||||
|
"grammatisation-et-proletarisation-cognitive",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const PREFERRED_DOCTRINE_SLUGS = [
|
||||||
|
"contractualisme-hobbesien",
|
||||||
|
"droit-naturel-et-propriete",
|
||||||
|
"volonte-generale",
|
||||||
|
"decisionnisme-souverain",
|
||||||
|
] as const;
|
||||||
|
|
||||||
export function normalizeGlossarySlug(value: unknown): string {
|
export function normalizeGlossarySlug(value: unknown): string {
|
||||||
return String(value ?? "")
|
return String(value ?? "")
|
||||||
.trim()
|
.trim()
|
||||||
@@ -99,9 +174,7 @@ export function hrefOfGlossaryEntry(
|
|||||||
export function buildGlossaryBySlug(
|
export function buildGlossaryBySlug(
|
||||||
entries: GlossaryEntry[] = [],
|
entries: GlossaryEntry[] = [],
|
||||||
): Map<string, GlossaryEntry> {
|
): Map<string, GlossaryEntry> {
|
||||||
return new Map(
|
return new Map(entries.map((entry) => [slugOfGlossaryEntry(entry), entry]));
|
||||||
entries.map((entry) => [slugOfGlossaryEntry(entry), entry]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sortGlossaryEntries(
|
export function sortGlossaryEntries(
|
||||||
@@ -128,6 +201,36 @@ export function uniqueGlossaryEntries(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function slugsOfGlossaryEntries(
|
||||||
|
entries: GlossaryEntry[] = [],
|
||||||
|
): Set<string> {
|
||||||
|
const slugs = new Set<string>();
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const slug = slugOfGlossaryEntry(entry);
|
||||||
|
if (!slug) continue;
|
||||||
|
slugs.add(slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
return slugs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function excludeGlossaryEntries(
|
||||||
|
entries: GlossaryEntry[] = [],
|
||||||
|
excluded: Iterable<string> = [],
|
||||||
|
): GlossaryEntry[] {
|
||||||
|
const excludedSlugs = new Set(
|
||||||
|
Array.from(excluded)
|
||||||
|
.map((value) => normalizeGlossarySlug(value))
|
||||||
|
.filter(Boolean),
|
||||||
|
);
|
||||||
|
|
||||||
|
return entries.filter((entry) => {
|
||||||
|
const slug = slugOfGlossaryEntry(entry);
|
||||||
|
return Boolean(slug) && !excludedSlugs.has(slug);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveGlossaryEntriesInSourceOrder(
|
export function resolveGlossaryEntriesInSourceOrder(
|
||||||
slugs: string[] = [],
|
slugs: string[] = [],
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
@@ -188,7 +291,11 @@ export function familyOf(
|
|||||||
if (slug === "autarchicratie") return "pathologie";
|
if (slug === "autarchicratie") return "pathologie";
|
||||||
if (slug === "obliteration-archicratique") return "dynamique";
|
if (slug === "obliteration-archicratique") return "dynamique";
|
||||||
|
|
||||||
if (FONDAMENTAUX_WANTED.includes(slug as (typeof FONDAMENTAUX_WANTED)[number])) {
|
if (
|
||||||
|
FONDAMENTAUX_WANTED.includes(
|
||||||
|
slug as (typeof FONDAMENTAUX_WANTED)[number],
|
||||||
|
)
|
||||||
|
) {
|
||||||
return "concept-fondamental";
|
return "concept-fondamental";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +366,47 @@ export function countGlossaryEntriesByFamily(
|
|||||||
return entries.filter((entry) => familyOf(entry) === familyKey).length;
|
return entries.filter((entry) => familyOf(entry) === familyKey).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGlossaryPortalLinks(): GlossaryPortalLink[] {
|
||||||
|
return [
|
||||||
|
{ href: "/glossaire/", label: "Accueil du glossaire" },
|
||||||
|
{ href: "/glossaire/concepts-fondamentaux/", label: "Concepts fondamentaux" },
|
||||||
|
{ href: "/glossaire/index-complet/", label: "Index complet" },
|
||||||
|
{
|
||||||
|
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/archicrations/",
|
||||||
|
label: "Méta-régimes archicratiques",
|
||||||
|
},
|
||||||
|
{ href: "/glossaire/paradigmes/", label: "Paradigmes et doctrines" },
|
||||||
|
{ href: "/glossaire/verbes-de-la-scene/", label: "Verbes de la scène" },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGlossaryHomeStats(
|
||||||
|
allEntries: GlossaryEntry[] = [],
|
||||||
|
): GlossaryHomeStats {
|
||||||
|
return {
|
||||||
|
totalEntries: allEntries.length,
|
||||||
|
paradigmesCount: countGlossaryEntriesByKind(allEntries, "paradigme"),
|
||||||
|
doctrinesCount: countGlossaryEntriesByKind(allEntries, "doctrine"),
|
||||||
|
metaRegimesCount: countGlossaryEntriesByFamily(allEntries, "meta-regime"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function getEntriesOfSameFamily(
|
export function getEntriesOfSameFamily(
|
||||||
entry: GlossaryEntry,
|
entry: GlossaryEntry,
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
@@ -279,12 +427,6 @@ export function getSameFamilyTitle(
|
|||||||
return FAMILY_SECTION_TITLES[familyOf(entry)] ?? "Même famille";
|
return FAMILY_SECTION_TITLES[familyOf(entry)] ?? "Même famille";
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GlossaryRelationBlock = {
|
|
||||||
title: string;
|
|
||||||
items: GlossaryEntry[];
|
|
||||||
className: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getRelationBlocks(
|
export function getRelationBlocks(
|
||||||
entry: GlossaryEntry,
|
entry: GlossaryEntry,
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
@@ -328,7 +470,7 @@ export function getRelationBlocks(
|
|||||||
export function getRelationSections(
|
export function getRelationSections(
|
||||||
entry: GlossaryEntry,
|
entry: GlossaryEntry,
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
): Array<{ title: string; items: GlossaryEntry[] }> {
|
): GlossaryRelationSection[] {
|
||||||
return getRelationBlocks(entry, allEntries).map(({ title, items }) => ({
|
return getRelationBlocks(entry, allEntries).map(({ title, items }) => ({
|
||||||
title,
|
title,
|
||||||
items,
|
items,
|
||||||
@@ -347,34 +489,6 @@ function isTheoryEntry(entry: GlossaryEntry): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PREFERRED_PARADIGME_SLUGS = [
|
|
||||||
"gouvernementalite",
|
|
||||||
"gouvernementalite-algorithmique",
|
|
||||||
"cybernetique",
|
|
||||||
"biopolitique",
|
|
||||||
"domination-legale-rationnelle",
|
|
||||||
"democratie-deliberative",
|
|
||||||
"gouvernance-des-communs",
|
|
||||||
"agencement-machinique",
|
|
||||||
"pharmacologie-technique",
|
|
||||||
"preemption-algorithmique",
|
|
||||||
"dissensus-politique",
|
|
||||||
"lieu-vide-du-pouvoir",
|
|
||||||
"habitus-et-violence-symbolique",
|
|
||||||
"theorie-de-la-resonance",
|
|
||||||
"conatus-et-multitude",
|
|
||||||
"configuration-et-interdependance",
|
|
||||||
"technodiversite-et-cosmotechnie",
|
|
||||||
"grammatisation-et-proletarisation-cognitive",
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
const PREFERRED_DOCTRINE_SLUGS = [
|
|
||||||
"contractualisme-hobbesien",
|
|
||||||
"droit-naturel-et-propriete",
|
|
||||||
"volonte-generale",
|
|
||||||
"decisionnisme-souverain",
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export function getContextualTheory(
|
export function getContextualTheory(
|
||||||
entry: GlossaryEntry,
|
entry: GlossaryEntry,
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
@@ -383,15 +497,15 @@ export function getContextualTheory(
|
|||||||
const bySlug = buildGlossaryBySlug(allEntries);
|
const bySlug = buildGlossaryBySlug(allEntries);
|
||||||
|
|
||||||
const fromRelations = uniqueGlossaryEntries([
|
const fromRelations = uniqueGlossaryEntries([
|
||||||
...resolveGlossaryEntries(entry.data.related ?? [], allEntries),
|
...resolveGlossaryEntriesInSourceOrder(entry.data.related ?? [], allEntries),
|
||||||
...resolveGlossaryEntries(entry.data.seeAlso ?? [], allEntries),
|
...resolveGlossaryEntriesInSourceOrder(entry.data.seeAlso ?? [], allEntries),
|
||||||
...resolveGlossaryEntries(entry.data.opposedTo ?? [], allEntries),
|
...resolveGlossaryEntriesInSourceOrder(entry.data.opposedTo ?? [], allEntries),
|
||||||
])
|
])
|
||||||
.filter((item) => slugOfGlossaryEntry(item) !== currentSlug)
|
.filter((item) => slugOfGlossaryEntry(item) !== currentSlug)
|
||||||
.filter((item) => isTheoryEntry(item));
|
.filter((item) => isTheoryEntry(item));
|
||||||
|
|
||||||
if (fromRelations.length > 0) {
|
if (fromRelations.length > 0) {
|
||||||
return sortGlossaryEntries(fromRelations).slice(0, 6);
|
return fromRelations.slice(0, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (familyOf(entry) === "paradigme") {
|
if (familyOf(entry) === "paradigme") {
|
||||||
@@ -414,3 +528,80 @@ export function getContextualTheory(
|
|||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGlossaryEntryAsideData(
|
||||||
|
currentEntry: GlossaryEntry,
|
||||||
|
allEntries: GlossaryEntry[] = [],
|
||||||
|
): GlossaryEntryAsideData {
|
||||||
|
const currentFamily = familyOf(currentEntry);
|
||||||
|
const currentSlug = slugOfGlossaryEntry(currentEntry);
|
||||||
|
|
||||||
|
const fondamentaux = getFondamentaux(allEntries);
|
||||||
|
const sameFamilyTitle = getSameFamilyTitle(currentEntry);
|
||||||
|
const relationSections = getRelationSections(currentEntry, allEntries);
|
||||||
|
|
||||||
|
const relationEntries = uniqueGlossaryEntries(
|
||||||
|
relationSections.flatMap((section) => section.items),
|
||||||
|
);
|
||||||
|
const relationSlugs = slugsOfGlossaryEntries(relationEntries);
|
||||||
|
|
||||||
|
const contextualTheory = excludeGlossaryEntries(
|
||||||
|
getContextualTheory(currentEntry, allEntries),
|
||||||
|
new Set([currentSlug, ...relationSlugs]),
|
||||||
|
).slice(0, 6);
|
||||||
|
const contextualTheorySlugs = slugsOfGlossaryEntries(contextualTheory);
|
||||||
|
|
||||||
|
const sameFamilyEntries = excludeGlossaryEntries(
|
||||||
|
getEntriesOfSameFamily(currentEntry, allEntries),
|
||||||
|
new Set([currentSlug, ...relationSlugs, ...contextualTheorySlugs]),
|
||||||
|
).slice(0, 8);
|
||||||
|
|
||||||
|
const showNoyau =
|
||||||
|
currentFamily !== "concept-fondamental" &&
|
||||||
|
fondamentaux.length > 0;
|
||||||
|
|
||||||
|
const showSameFamily =
|
||||||
|
currentFamily !== "concept-fondamental" &&
|
||||||
|
sameFamilyEntries.length > 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
displayFamily: getDisplayFamily(currentEntry),
|
||||||
|
displayDomain: getDisplayDomain(currentEntry),
|
||||||
|
displayLevel: getDisplayLevel(currentEntry),
|
||||||
|
showNoyau,
|
||||||
|
showSameFamily,
|
||||||
|
fondamentaux,
|
||||||
|
sameFamilyTitle,
|
||||||
|
sameFamilyEntries: showSameFamily ? sameFamilyEntries : [],
|
||||||
|
relationSections,
|
||||||
|
contextualTheory,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGlossaryHomeData(
|
||||||
|
entries: GlossaryEntry[] = [],
|
||||||
|
): GlossaryHomeData {
|
||||||
|
const bySlug = buildGlossaryBySlug(entries);
|
||||||
|
|
||||||
|
const fondamentaux = getGlossaryEntriesByFamily(entries, "concept-fondamental");
|
||||||
|
const scenes = getGlossaryEntriesByFamily(entries, "scene");
|
||||||
|
const dynamiques = sortGlossaryEntries(
|
||||||
|
entries.filter((entry) =>
|
||||||
|
["dynamique", "pathologie"].includes(familyOf(entry)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const metaRegimes = getGlossaryEntriesByFamily(entries, "meta-regime");
|
||||||
|
|
||||||
|
return {
|
||||||
|
fondamentaux,
|
||||||
|
scenes,
|
||||||
|
dynamiques,
|
||||||
|
metaRegimes,
|
||||||
|
metaRegimesPreview: metaRegimes.slice(0, 6),
|
||||||
|
arcalite: bySlug.get("arcalite"),
|
||||||
|
cratialite: bySlug.get("cratialite"),
|
||||||
|
tension: bySlug.get("tension"),
|
||||||
|
sceneDepreuve: bySlug.get("scene-depreuve"),
|
||||||
|
archicration: bySlug.get("archicration"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
||||||
import GlossaryAside from "../../components/GlossaryAside.astro";
|
import GlossaryAside from "../../components/GlossaryAside.astro";
|
||||||
import GlossaryRelationCards from "../../components/GlossaryRelationCards.astro";
|
import GlossaryRelationCards from "../../components/GlossaryRelationCards.astro";
|
||||||
|
import GlossaryEntryLegacyNote from "../../components/GlossaryEntryLegacyNote.astro";
|
||||||
|
import GlossaryEntryHero from "../../components/GlossaryEntryHero.astro";
|
||||||
|
import GlossaryEntryBody from "../../components/GlossaryEntryBody.astro";
|
||||||
|
import GlossaryEntryStickySync from "../../components/GlossaryEntryStickySync.astro";
|
||||||
import { getCollection, render } from "astro:content";
|
import { getCollection, render } from "astro:content";
|
||||||
import {
|
import {
|
||||||
getDisplayDomain,
|
getDisplayDomain,
|
||||||
@@ -61,10 +65,6 @@ const relationBlocks = getRelationBlocks(entry, allEntries);
|
|||||||
const displayFamily = getDisplayFamily(entry);
|
const displayFamily = getDisplayFamily(entry);
|
||||||
const displayDomain = getDisplayDomain(entry);
|
const displayDomain = getDisplayDomain(entry);
|
||||||
const displayLevel = getDisplayLevel(entry);
|
const displayLevel = getDisplayLevel(entry);
|
||||||
|
|
||||||
const hasScholarlyMeta =
|
|
||||||
(entry.data.mobilizedAuthors?.length ?? 0) > 0 ||
|
|
||||||
(entry.data.comparisonTraditions?.length ?? 0) > 0;
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<GlossaryLayout
|
<GlossaryLayout
|
||||||
@@ -77,434 +77,27 @@ const hasScholarlyMeta =
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
{isAliasRoute && (
|
{isAliasRoute && (
|
||||||
<p class="glossary-legacy-note">
|
<GlossaryEntryLegacyNote
|
||||||
Cette entrée a été renommée. L’intitulé canonique est :
|
canonicalHref={canonicalHref}
|
||||||
<a href={canonicalHref}>{entry.data.term}</a>.
|
term={entry.data.term}
|
||||||
</p>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<header class="glossary-entry-head" data-ge-hero>
|
<GlossaryEntryHero
|
||||||
<div class="glossary-entry-head__title">
|
term={entry.data.term}
|
||||||
<h1>{entry.data.term}</h1>
|
definitionShort={entry.data.definitionShort}
|
||||||
</div>
|
displayFamily={displayFamily}
|
||||||
|
displayDomain={displayDomain}
|
||||||
|
displayLevel={displayLevel}
|
||||||
|
mobilizedAuthors={entry.data.mobilizedAuthors ?? []}
|
||||||
|
comparisonTraditions={entry.data.comparisonTraditions ?? []}
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="glossary-entry-summary">
|
<GlossaryEntryBody>
|
||||||
<p class="glossary-entry-dek">
|
|
||||||
<em>{entry.data.definitionShort}</em>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="glossary-entry-signals" aria-label="Repères de lecture">
|
|
||||||
<span class="glossary-pill glossary-pill--family">
|
|
||||||
<strong>Famille :</strong> {displayFamily}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{displayDomain && (
|
|
||||||
<span class="glossary-pill">
|
|
||||||
<strong>Domaine :</strong> {displayDomain}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{displayLevel && (
|
|
||||||
<span class="glossary-pill">
|
|
||||||
<strong>Niveau :</strong> {displayLevel}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{hasScholarlyMeta && (
|
|
||||||
<div class="glossary-entry-meta">
|
|
||||||
{(entry.data.mobilizedAuthors?.length ?? 0) > 0 && (
|
|
||||||
<p>
|
|
||||||
<strong>Auteurs mobilisés :</strong> {entry.data.mobilizedAuthors.join(" / ")}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(entry.data.comparisonTraditions?.length ?? 0) > 0 && (
|
|
||||||
<p>
|
|
||||||
<strong>Traditions de comparaison :</strong> {entry.data.comparisonTraditions.join(" / ")}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="glossary-entry-body">
|
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</GlossaryEntryBody>
|
||||||
|
|
||||||
<GlossaryRelationCards relationBlocks={relationBlocks} />
|
<GlossaryRelationCards relationBlocks={relationBlocks} />
|
||||||
|
|
||||||
|
<GlossaryEntryStickySync />
|
||||||
</GlossaryLayout>
|
</GlossaryLayout>
|
||||||
|
|
||||||
<script is:inline>
|
|
||||||
(() => {
|
|
||||||
const boot = () => {
|
|
||||||
const body = document.body;
|
|
||||||
const root = document.documentElement;
|
|
||||||
const hero = document.querySelector("[data-ge-hero]");
|
|
||||||
const follow = document.getElementById("reading-follow");
|
|
||||||
const mqMobile = window.matchMedia("(max-width: 860px)");
|
|
||||||
|
|
||||||
if (!body || !root || !hero || !follow) return;
|
|
||||||
|
|
||||||
const BODY_CLASS = "is-glossary-entry-page";
|
|
||||||
const FOLLOW_ON_CLASS = "glossary-entry-follow-on";
|
|
||||||
|
|
||||||
let lastHeight = -1;
|
|
||||||
let lastFollowOn = null;
|
|
||||||
let raf = 0;
|
|
||||||
|
|
||||||
body.classList.add(BODY_CLASS);
|
|
||||||
|
|
||||||
const heroHeight = () =>
|
|
||||||
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
|
||||||
|
|
||||||
const computeFollowOn = () =>
|
|
||||||
!mqMobile.matches &&
|
|
||||||
follow.classList.contains("is-on") &&
|
|
||||||
follow.style.display !== "none" &&
|
|
||||||
follow.getAttribute("aria-hidden") !== "true";
|
|
||||||
|
|
||||||
const stripLocalSticky = () => {
|
|
||||||
document
|
|
||||||
.querySelectorAll(
|
|
||||||
".glossary-entry-body h2, .glossary-entry-body h3, .glossary-relations h2, .glossary-relations h3"
|
|
||||||
)
|
|
||||||
.forEach((el) => {
|
|
||||||
el.classList.remove("is-sticky");
|
|
||||||
el.removeAttribute("data-sticky-active");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const applyLocalStickyHeight = () => {
|
|
||||||
const h = mqMobile.matches ? 0 : heroHeight();
|
|
||||||
if (h === lastHeight) return;
|
|
||||||
lastHeight = h;
|
|
||||||
|
|
||||||
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
|
||||||
window.__archiSetLocalStickyHeight(h);
|
|
||||||
} else {
|
|
||||||
root.style.setProperty("--glossary-local-sticky-h", `${h}px`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncFollowState = () => {
|
|
||||||
const on = computeFollowOn();
|
|
||||||
if (on === lastFollowOn) return;
|
|
||||||
lastFollowOn = on;
|
|
||||||
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncAll = () => {
|
|
||||||
stripLocalSticky();
|
|
||||||
syncFollowState();
|
|
||||||
applyLocalStickyHeight();
|
|
||||||
};
|
|
||||||
|
|
||||||
const schedule = () => {
|
|
||||||
if (raf) return;
|
|
||||||
raf = requestAnimationFrame(() => {
|
|
||||||
raf = 0;
|
|
||||||
syncAll();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const followObserver = new MutationObserver(schedule);
|
|
||||||
followObserver.observe(follow, {
|
|
||||||
attributes: true,
|
|
||||||
attributeFilter: ["class", "style", "aria-hidden"],
|
|
||||||
subtree: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const heroResizeObserver =
|
|
||||||
typeof ResizeObserver !== "undefined"
|
|
||||||
? new ResizeObserver(schedule)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
heroResizeObserver?.observe(hero);
|
|
||||||
|
|
||||||
window.addEventListener("resize", schedule);
|
|
||||||
window.addEventListener("pageshow", schedule);
|
|
||||||
|
|
||||||
if (document.fonts?.ready) {
|
|
||||||
document.fonts.ready.then(schedule).catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mqMobile.addEventListener) {
|
|
||||||
mqMobile.addEventListener("change", schedule);
|
|
||||||
} else if (mqMobile.addListener) {
|
|
||||||
mqMobile.addListener(schedule);
|
|
||||||
}
|
|
||||||
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (document.readyState === "loading") {
|
|
||||||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
|
||||||
} else {
|
|
||||||
boot();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.glossary-legacy-note{
|
|
||||||
padding: 10px 12px;
|
|
||||||
border: 1px solid rgba(127,127,127,0.22);
|
|
||||||
border-radius: 12px;
|
|
||||||
background: rgba(127,127,127,0.05);
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.45;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-head{
|
|
||||||
position: sticky;
|
|
||||||
top: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px));
|
|
||||||
z-index: 11;
|
|
||||||
margin: 0 0 24px;
|
|
||||||
border: 1px solid rgba(127,127,127,0.18);
|
|
||||||
border-radius: 28px;
|
|
||||||
background:
|
|
||||||
linear-gradient(180deg, rgba(0,0,0,0.60), rgba(0,0,0,0.92)),
|
|
||||||
radial-gradient(900px 240px at 20% 0%, rgba(0,217,255,0.08), transparent 60%);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
-webkit-backdrop-filter: blur(10px);
|
|
||||||
overflow: hidden;
|
|
||||||
transition:
|
|
||||||
border-radius 180ms ease,
|
|
||||||
box-shadow 180ms ease,
|
|
||||||
border-color 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-head__title{
|
|
||||||
padding: 18px 18px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-head h1{
|
|
||||||
margin: 0;
|
|
||||||
font-size: clamp(2.2rem, 4vw, 3.15rem);
|
|
||||||
line-height: 1.02;
|
|
||||||
letter-spacing: -.04em;
|
|
||||||
font-weight: 850;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-summary{
|
|
||||||
display: grid;
|
|
||||||
gap: 14px;
|
|
||||||
padding: 16px 18px 18px;
|
|
||||||
border-top: 1px solid rgba(127,127,127,0.14);
|
|
||||||
background: rgba(255,255,255,0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-dek{
|
|
||||||
margin: 0;
|
|
||||||
max-width: 76ch;
|
|
||||||
font-size: 1.04rem;
|
|
||||||
line-height: 1.55;
|
|
||||||
opacity: .94;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-signals{
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-pill{
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
border: 1px solid rgba(127,127,127,0.24);
|
|
||||||
border-radius: 999px;
|
|
||||||
background: rgba(127,127,127,0.05);
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 1.35;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-pill--family{
|
|
||||||
border-color: rgba(127,127,127,0.36);
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-meta{
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px 12px;
|
|
||||||
border: 1px solid rgba(127,127,127,0.18);
|
|
||||||
border-radius: 12px;
|
|
||||||
background: rgba(127,127,127,0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-meta p{
|
|
||||||
margin: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-meta p + p{
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-body{
|
|
||||||
margin-bottom: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-body h2,
|
|
||||||
.glossary-entry-body h3,
|
|
||||||
.glossary-relations h2,
|
|
||||||
.glossary-relations h3{
|
|
||||||
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 18px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations{
|
|
||||||
margin-top: 26px;
|
|
||||||
padding-top: 18px;
|
|
||||||
border-top: 1px solid rgba(127,127,127,0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations h2{
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-grid{
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-card{
|
|
||||||
border: 1px solid rgba(127,127,127,0.22);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 14px 16px;
|
|
||||||
background: rgba(127,127,127,0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-card h3{
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 1.35;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-card ul{
|
|
||||||
margin: 0;
|
|
||||||
padding-left: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-card li{
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.45;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-card li:last-child{
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-relations-card span{
|
|
||||||
opacity: .9;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page #reading-follow){
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-head){
|
|
||||||
margin-bottom: 0;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-summary){
|
|
||||||
gap: 10px;
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-signals){
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-meta){
|
|
||||||
padding: 8px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on #reading-follow){
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on #reading-follow .reading-follow__inner){
|
|
||||||
margin-top: -1px;
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page .glossary-entry-body h2.is-sticky),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-entry-body h2[data-sticky-active="true"]),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-entry-body h3.is-sticky),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-entry-body h3[data-sticky-active="true"]),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-relations h2.is-sticky),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-relations h2[data-sticky-active="true"]),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-relations h3.is-sticky),
|
|
||||||
:global(body.is-glossary-entry-page .glossary-relations h3[data-sticky-active="true"]){
|
|
||||||
position: static !important;
|
|
||||||
top: auto !important;
|
|
||||||
z-index: auto !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
border: 0 !important;
|
|
||||||
background: transparent !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
backdrop-filter: none !important;
|
|
||||||
-webkit-backdrop-filter: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 720px){
|
|
||||||
.glossary-entry-signals{
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-pill{
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 860px){
|
|
||||||
.glossary-entry-head{
|
|
||||||
position: static;
|
|
||||||
border-radius: 22px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-head__title{
|
|
||||||
padding: 14px 14px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-summary{
|
|
||||||
gap: 12px;
|
|
||||||
padding: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-entry-dek{
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-glossary-entry-page.glossary-entry-follow-on .glossary-entry-head){
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 22px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
|
||||||
.glossary-entry-meta{
|
|
||||||
background: rgba(255,255,255,0.03);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-legacy-note,
|
|
||||||
.glossary-pill,
|
|
||||||
.glossary-relations-card{
|
|
||||||
background: rgba(255,255,255,0.04);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
---
|
---
|
||||||
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
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 { getCollection } from "astro:content";
|
||||||
|
import {
|
||||||
|
buildGlossaryBySlug,
|
||||||
|
hrefOfGlossaryEntry,
|
||||||
|
} from "../../lib/glossary";
|
||||||
|
|
||||||
const entries = await getCollection("glossaire");
|
const entries = await getCollection("glossaire");
|
||||||
|
|
||||||
const slugOf = (entry) => String(entry.id).replace(/\.(md|mdx)$/i, "");
|
|
||||||
const hrefOf = (entry) => `/glossaire/${slugOf(entry)}/`;
|
|
||||||
|
|
||||||
const collator = new Intl.Collator("fr", { sensitivity: "base", numeric: true });
|
const collator = new Intl.Collator("fr", { sensitivity: "base", numeric: true });
|
||||||
const bySlug = new Map(entries.map((entry) => [slugOf(entry), entry]));
|
const bySlug = buildGlossaryBySlug(entries);
|
||||||
|
const hrefOf = hrefOfGlossaryEntry;
|
||||||
|
|
||||||
function resolve(slugs = []) {
|
function resolve(slugs = []) {
|
||||||
return slugs
|
return slugs
|
||||||
@@ -74,6 +80,49 @@ const sections = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const totalCount = sections.reduce((sum, section) => sum + section.items.length, 0);
|
const totalCount = sections.reduce((sum, section) => sum + section.items.length, 0);
|
||||||
|
|
||||||
|
const pageItems = [
|
||||||
|
...sections.map((section) => ({
|
||||||
|
href: `#${section.id}`,
|
||||||
|
label: section.title,
|
||||||
|
})),
|
||||||
|
{ href: "#prolonger-la-lecture", label: "Prolonger la lecture" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const usefulLinks = [
|
||||||
|
{ href: "/glossaire/archicration/", label: "Archicration" },
|
||||||
|
{ href: "/glossaire/archicratie/", label: "Archicratie" },
|
||||||
|
{ href: "/glossaire/arcalite/", label: "Arcalité" },
|
||||||
|
{ href: "/glossaire/cratialite/", label: "Cratialité" },
|
||||||
|
{ href: "/glossaire/co-viabilite/", label: "Co-viabilité" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const prolongerLinks = [
|
||||||
|
{
|
||||||
|
href: "/glossaire/concepts-fondamentaux/",
|
||||||
|
title: "Concepts fondamentaux",
|
||||||
|
text:
|
||||||
|
"Revenir au noyau minimal : arcalité, cratialité, tension, archicration, co-viabilité et archicratie.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/glossaire/paradigmes/",
|
||||||
|
title: "Paradigmes et doctrines",
|
||||||
|
text:
|
||||||
|
"Situer les archicrations dans le paysage théorique au sein duquel l’archicratie se compare et se distingue.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/glossaire/tensions-irreductibles/",
|
||||||
|
title: "Tensions irréductibles",
|
||||||
|
text:
|
||||||
|
"Revenir aux foyers structuraux de conflictualité que les archicrations stabilisent sans les abolir.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/glossaire/index-complet/",
|
||||||
|
title: "Index complet",
|
||||||
|
text:
|
||||||
|
"Retrouver l’ensemble des entrées du glossaire dans une navigation alphabétique intégrale.",
|
||||||
|
},
|
||||||
|
];
|
||||||
---
|
---
|
||||||
|
|
||||||
<GlossaryLayout
|
<GlossaryLayout
|
||||||
@@ -82,99 +131,49 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
stickyMode="glossary-portal"
|
stickyMode="glossary-portal"
|
||||||
>
|
>
|
||||||
<Fragment slot="aside">
|
<Fragment slot="aside">
|
||||||
<nav class="archi-aside" aria-label="Navigation des archicrations">
|
<GlossaryPortalAside
|
||||||
<div class="archi-aside__block">
|
ariaLabel="Navigation des archicrations"
|
||||||
<a class="archi-aside__back" href="/glossaire/">← Retour au glossaire</a>
|
title="Archicrations"
|
||||||
<div class="archi-aside__title">Archicrations</div>
|
meta={`${totalCount} type${totalCount > 1 ? "s" : ""} cartographié${totalCount > 1 ? "s" : ""}`}
|
||||||
<div class="archi-aside__meta">{totalCount} types cartographiés</div>
|
pageItems={pageItems}
|
||||||
</div>
|
usefulLinks={usefulLinks}
|
||||||
|
/>
|
||||||
<div class="archi-aside__block">
|
|
||||||
<h2 class="archi-aside__heading">Dans cette page</h2>
|
|
||||||
<ul class="archi-aside__list">
|
|
||||||
{sections.map((section) => (
|
|
||||||
<li><a href={`#${section.id}`}>{section.title}</a></li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="archi-aside__block">
|
|
||||||
<h2 class="archi-aside__heading">Renvois utiles</h2>
|
|
||||||
<ul class="archi-aside__list">
|
|
||||||
<li><a href="/glossaire/archicration/">Archicration</a></li>
|
|
||||||
<li><a href="/glossaire/archicratie/">Archicratie</a></li>
|
|
||||||
<li><a href="/glossaire/arcalite/">Arcalité</a></li>
|
|
||||||
<li><a href="/glossaire/cratialite/">Cratialité</a></li>
|
|
||||||
<li><a href="/glossaire/co-viabilite/">Co-viabilité</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
<section class="archi-page" data-archi-page>
|
<section class="archi-page">
|
||||||
<div class="archi-hero glossary-page-hero" data-archi-hero>
|
<GlossaryPortalHero
|
||||||
<p class="archi-kicker">Topologie archicratique</p>
|
prefix="archi"
|
||||||
<h1>Archicrations</h1>
|
kicker="Topologie archicratique"
|
||||||
|
title="Archicrations"
|
||||||
<p class="archi-intro">
|
intro="Cette page rassemble les principales formes d’archicration distinguées dans le glossaire. Elle propose une vue d’ensemble des grands régimes de co-viabilité à partir desquels un collectif se stabilise, se transmet, se transforme ou se recompose."
|
||||||
Cette page rassemble les principales formes d’archicration distinguées
|
moreParagraphs={[
|
||||||
dans le glossaire. Elle propose une vue d’ensemble des grands régimes de
|
"Les catégories proposées ci-dessous ne valent pas comme cases closes, mais comme repères de lecture permettant de situer les différentes topologies de régulation et leurs articulations.",
|
||||||
co-viabilité à partir desquels un collectif se stabilise, se transmet,
|
]}
|
||||||
se transforme ou se recompose.
|
introMaxWidth="72ch"
|
||||||
</p>
|
followIntroMaxWidth="68ch"
|
||||||
|
moreMaxHeight="18rem"
|
||||||
<div class="archi-hero-collapsible">
|
/>
|
||||||
<div
|
|
||||||
class="archi-hero-more"
|
|
||||||
id="archi-hero-more"
|
|
||||||
data-archi-more
|
|
||||||
aria-hidden="false"
|
|
||||||
>
|
|
||||||
<p class="archi-intro">
|
|
||||||
Les catégories proposées ci-dessous ne valent pas comme cases closes,
|
|
||||||
mais comme repères de lecture permettant de situer les différentes
|
|
||||||
topologies de régulation et leurs articulations.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="archi-hero-toggle"
|
|
||||||
id="archi-hero-toggle"
|
|
||||||
data-archi-more-toggle
|
|
||||||
type="button"
|
|
||||||
aria-controls="archi-hero-more"
|
|
||||||
aria-expanded="false"
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
lire la suite
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{sections.map((section) => (
|
{sections.map((section) => (
|
||||||
<section class="archi-section">
|
<GlossaryPortalSection
|
||||||
<div class="archi-section__head">
|
id={section.id}
|
||||||
<h2 id={section.id}>{section.title}</h2>
|
title={section.title}
|
||||||
<span class="archi-section__count">
|
count={`${section.items.length} fiche${section.items.length > 1 ? "s" : ""}`}
|
||||||
{section.items.length} fiche{section.items.length > 1 ? "s" : ""}
|
intro={section.intro}
|
||||||
</span>
|
>
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="archi-section__intro">{section.intro}</p>
|
|
||||||
|
|
||||||
<div class="archi-cards">
|
<div class="archi-cards">
|
||||||
{section.items.map((entry) => (
|
{section.items.map((entry) => (
|
||||||
<a class="archi-card" href={hrefOf(entry)}>
|
<a class="archi-card" href={hrefOf(entry)}>
|
||||||
<strong>{entry.data.term}</strong>
|
<strong>{entry.data.term}</strong>
|
||||||
<span>{entry.data.definitionShort}</span>
|
<span>{entry.data.definitionShort}</span>
|
||||||
|
|
||||||
{entry.data.comparisonTraditions && (
|
{(entry.data.comparisonTraditions?.length ?? 0) > 0 && (
|
||||||
<small>
|
<small>
|
||||||
Traditions de comparaison : {entry.data.comparisonTraditions.join(" / ")}
|
Traditions de comparaison : {entry.data.comparisonTraditions.join(" / ")}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{entry.data.mobilizedAuthors?.length > 0 && (
|
{(entry.data.mobilizedAuthors?.length ?? 0) > 0 && (
|
||||||
<small>
|
<small>
|
||||||
Auteurs mobilisés : {entry.data.mobilizedAuthors.join(" / ")}
|
Auteurs mobilisés : {entry.data.mobilizedAuthors.join(" / ")}
|
||||||
</small>
|
</small>
|
||||||
@@ -182,11 +181,29 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</GlossaryPortalSection>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<section class="archi-section archi-section--final">
|
<GlossaryPortalSection
|
||||||
<h2>Portée d’ensemble</h2>
|
id="prolonger-la-lecture"
|
||||||
|
title="Prolonger la lecture"
|
||||||
|
intro="Cette cartographie des archicrations peut ensuite être replacée dans le noyau conceptuel, dans le paysage théorique général et dans l’index complet du glossaire."
|
||||||
|
>
|
||||||
|
<div class="archi-cards">
|
||||||
|
{prolongerLinks.map((item) => (
|
||||||
|
<a class="archi-card" href={item.href}>
|
||||||
|
<strong>{item.title}</strong>
|
||||||
|
<span>{item.text}</span>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</GlossaryPortalSection>
|
||||||
|
|
||||||
|
<GlossaryPortalSection
|
||||||
|
id="portee-densemble"
|
||||||
|
title="Portée d’ensemble"
|
||||||
|
final={true}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
Cette cartographie permet de lire les archicrations non comme des formes
|
Cette cartographie permet de lire les archicrations non comme des formes
|
||||||
isolées, mais comme des topologies de régulation susceptibles de se
|
isolées, mais comme des topologies de régulation susceptibles de se
|
||||||
@@ -195,223 +212,78 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
<a href="/glossaire/archicratie/">archicratie</a> peut être pensée comme
|
<a href="/glossaire/archicratie/">archicratie</a> peut être pensée comme
|
||||||
intelligibilité d’ensemble des formes de co-viabilité.
|
intelligibilité d’ensemble des formes de co-viabilité.
|
||||||
</p>
|
</p>
|
||||||
|
</GlossaryPortalSection>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
|
||||||
|
<GlossaryPortalStickySync
|
||||||
|
heroMoreId="archi-hero-more"
|
||||||
|
heroToggleId="archi-hero-toggle"
|
||||||
|
/>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
(() => {
|
(() => {
|
||||||
const boot = () => {
|
const boot = () => {
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
const hero = document.querySelector("[data-archi-hero]");
|
|
||||||
const follow = document.getElementById("reading-follow");
|
const follow = document.getElementById("reading-follow");
|
||||||
const heroMore = document.getElementById("archi-hero-more");
|
|
||||||
const heroToggle = document.getElementById("archi-hero-toggle");
|
|
||||||
|
|
||||||
if (!body || !root || !hero || !follow) return;
|
if (!body || !root || !follow) return;
|
||||||
|
|
||||||
|
body.classList.add("is-glossary-portal-page");
|
||||||
|
|
||||||
const BODY_CLASS = "is-archicrations-page";
|
|
||||||
const FOLLOW_ON_CLASS = "archi-follow-on";
|
|
||||||
const EXPANDED_CLASS = "archi-hero-expanded";
|
|
||||||
const mqMobile = window.matchMedia("(max-width: 860px)");
|
const mqMobile = window.matchMedia("(max-width: 860px)");
|
||||||
const AUTO_COLLAPSE_DELTA = 160;
|
const mqSmallLandscape = window.matchMedia(
|
||||||
|
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||||||
|
);
|
||||||
|
|
||||||
let expandedAtY = null;
|
const isCompactViewport = () =>
|
||||||
let lastScrollY = window.scrollY || 0;
|
mqMobile.matches || mqSmallLandscape.matches;
|
||||||
|
|
||||||
body.classList.add(BODY_CLASS);
|
const disableFollow = () => {
|
||||||
|
if (!isCompactViewport()) return;
|
||||||
|
|
||||||
const heroHeight = () =>
|
follow.classList.remove("is-on");
|
||||||
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
follow.setAttribute("aria-hidden", "true");
|
||||||
|
follow.style.display = "none";
|
||||||
|
follow.innerHTML = "";
|
||||||
|
|
||||||
const stripLocalSticky = () => {
|
root.style.setProperty("--followbar-h", "0px");
|
||||||
document.querySelectorAll(".archi-section__head").forEach((el) => {
|
root.style.setProperty(
|
||||||
el.classList.remove("is-sticky");
|
"--sticky-offset-px",
|
||||||
el.removeAttribute("data-sticky-active");
|
"calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px))"
|
||||||
});
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const computeFollowOn = () =>
|
const enableFollow = () => {
|
||||||
!mqMobile.matches &&
|
if (isCompactViewport()) return;
|
||||||
follow.classList.contains("is-on") &&
|
|
||||||
follow.style.display !== "none" &&
|
|
||||||
follow.getAttribute("aria-hidden") !== "true";
|
|
||||||
|
|
||||||
const applyLocalStickyHeight = () => {
|
follow.style.display = "";
|
||||||
const h = mqMobile.matches ? 0 : heroHeight();
|
};
|
||||||
|
|
||||||
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
const sync = () => {
|
||||||
window.__archiSetLocalStickyHeight(h);
|
if (isCompactViewport()) {
|
||||||
|
disableFollow();
|
||||||
} else {
|
} else {
|
||||||
root.style.setProperty("--glossary-local-sticky-h", `${h}px`);
|
enableFollow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const syncFollowState = () => {
|
|
||||||
const on = computeFollowOn();
|
|
||||||
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
|
||||||
return on;
|
|
||||||
};
|
|
||||||
|
|
||||||
const collapseHero = () => {
|
|
||||||
if (!body.classList.contains(EXPANDED_CLASS)) return;
|
|
||||||
|
|
||||||
body.classList.remove(EXPANDED_CLASS);
|
|
||||||
expandedAtY = null;
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = false;
|
|
||||||
heroToggle.setAttribute("aria-expanded", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.__archiUpdateFollow?.();
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
const expandHero = () => {
|
|
||||||
body.classList.add(EXPANDED_CLASS);
|
|
||||||
expandedAtY = window.scrollY || 0;
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = true;
|
|
||||||
heroToggle.setAttribute("aria-expanded", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.__archiUpdateFollow?.();
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncHeroState = () => {
|
|
||||||
const followOn = computeFollowOn();
|
|
||||||
const expanded = body.classList.contains(EXPANDED_CLASS);
|
|
||||||
const collapsed = followOn && !expanded;
|
|
||||||
|
|
||||||
if (!followOn || mqMobile.matches) {
|
|
||||||
body.classList.remove(EXPANDED_CLASS);
|
|
||||||
expandedAtY = null;
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = true;
|
|
||||||
heroToggle.setAttribute("aria-expanded", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", collapsed ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = !collapsed;
|
|
||||||
heroToggle.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const maybeAutoCollapseOnScroll = () => {
|
|
||||||
if (mqMobile.matches) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!computeFollowOn()) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!body.classList.contains(EXPANDED_CLASS)) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expandedAtY == null) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentY = window.scrollY || 0;
|
|
||||||
const scrollingDown = currentY > lastScrollY;
|
|
||||||
const delta = currentY - expandedAtY;
|
|
||||||
|
|
||||||
if (scrollingDown && delta >= AUTO_COLLAPSE_DELTA) {
|
|
||||||
collapseHero();
|
|
||||||
}
|
|
||||||
|
|
||||||
lastScrollY = currentY;
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncAll = () => {
|
|
||||||
stripLocalSticky();
|
|
||||||
syncFollowState();
|
|
||||||
syncHeroState();
|
|
||||||
applyLocalStickyHeight();
|
|
||||||
};
|
|
||||||
|
|
||||||
let raf = 0;
|
|
||||||
const schedule = () => {
|
|
||||||
if (raf) return;
|
|
||||||
raf = requestAnimationFrame(() => {
|
|
||||||
raf = 0;
|
|
||||||
requestAnimationFrame(syncAll);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
heroToggle?.addEventListener("click", () => {
|
|
||||||
expandHero();
|
|
||||||
});
|
|
||||||
|
|
||||||
const onScroll = () => {
|
|
||||||
maybeAutoCollapseOnScroll();
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
const followObserver = new MutationObserver(schedule);
|
|
||||||
followObserver.observe(follow, {
|
|
||||||
attributes: true,
|
|
||||||
attributeFilter: ["class", "style", "aria-hidden"],
|
|
||||||
subtree: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const heroResizeObserver =
|
|
||||||
typeof ResizeObserver !== "undefined"
|
|
||||||
? new ResizeObserver(schedule)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
heroResizeObserver?.observe(hero);
|
|
||||||
|
|
||||||
window.addEventListener("scroll", onScroll, { passive: true });
|
|
||||||
window.addEventListener("resize", schedule);
|
|
||||||
window.addEventListener("pageshow", schedule);
|
|
||||||
|
|
||||||
if (document.fonts?.ready) {
|
|
||||||
document.fonts.ready.then(schedule).catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mqMobile.addEventListener) {
|
if (mqMobile.addEventListener) {
|
||||||
mqMobile.addEventListener("change", schedule);
|
mqMobile.addEventListener("change", sync);
|
||||||
} else if (mqMobile.addListener) {
|
} else if (mqMobile.addListener) {
|
||||||
mqMobile.addListener(schedule);
|
mqMobile.addListener(sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule();
|
if (mqSmallLandscape.addEventListener) {
|
||||||
|
mqSmallLandscape.addEventListener("change", sync);
|
||||||
|
} else if (mqSmallLandscape.addListener) {
|
||||||
|
mqSmallLandscape.addListener(sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", sync);
|
||||||
|
window.addEventListener("pageshow", sync);
|
||||||
|
|
||||||
|
sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (document.readyState === "loading") {
|
if (document.readyState === "loading") {
|
||||||
@@ -428,139 +300,6 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
padding: 8px 0 24px;
|
padding: 8px 0 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.archi-hero{
|
|
||||||
position: sticky;
|
|
||||||
top: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px));
|
|
||||||
z-index: 11;
|
|
||||||
margin: 0 0 24px;
|
|
||||||
padding: 18px 18px 20px;
|
|
||||||
border: 1px solid rgba(127,127,127,0.18);
|
|
||||||
border-radius: 28px;
|
|
||||||
background:
|
|
||||||
linear-gradient(180deg, rgba(0,0,0,0.60), rgba(0,0,0,0.92)),
|
|
||||||
radial-gradient(900px 240px at 20% 0%, rgba(0,217,255,0.08), transparent 60%);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
-webkit-backdrop-filter: blur(10px);
|
|
||||||
display: grid;
|
|
||||||
row-gap: 14px;
|
|
||||||
transition:
|
|
||||||
margin-bottom 180ms ease,
|
|
||||||
border-radius 180ms ease,
|
|
||||||
padding 180ms ease,
|
|
||||||
row-gap 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-kicker{
|
|
||||||
margin: 0;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: .08em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
opacity: .72;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero h1{
|
|
||||||
margin: 0;
|
|
||||||
font-size: clamp(2.2rem, 4vw, 3.15rem);
|
|
||||||
line-height: 1.02;
|
|
||||||
letter-spacing: -.04em;
|
|
||||||
font-weight: 850;
|
|
||||||
transition: font-size 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-intro{
|
|
||||||
margin: 0;
|
|
||||||
max-width: 72ch;
|
|
||||||
font-size: 1.04rem;
|
|
||||||
line-height: 1.55;
|
|
||||||
opacity: .94;
|
|
||||||
transition:
|
|
||||||
font-size 180ms ease,
|
|
||||||
line-height 180ms ease,
|
|
||||||
max-width 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-collapsible{
|
|
||||||
display: grid;
|
|
||||||
row-gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-more{
|
|
||||||
display: grid;
|
|
||||||
row-gap: 14px;
|
|
||||||
max-height: 18rem;
|
|
||||||
overflow: hidden;
|
|
||||||
opacity: 1;
|
|
||||||
transition:
|
|
||||||
max-height 220ms ease,
|
|
||||||
opacity 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-toggle{
|
|
||||||
display: none;
|
|
||||||
align-self: flex-start;
|
|
||||||
width: fit-content;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: inherit;
|
|
||||||
font: inherit;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.2;
|
|
||||||
letter-spacing: .01em;
|
|
||||||
text-transform: none;
|
|
||||||
opacity: .56;
|
|
||||||
cursor: pointer;
|
|
||||||
text-decoration: underline;
|
|
||||||
text-underline-offset: .12em;
|
|
||||||
text-decoration-thickness: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-toggle:hover{
|
|
||||||
opacity: .84;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-toggle:focus-visible{
|
|
||||||
outline: 2px solid rgba(0,217,255,0.24);
|
|
||||||
outline-offset: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-toggle[hidden]{
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-section{
|
|
||||||
margin-top: 34px;
|
|
||||||
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 28px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-section h2{
|
|
||||||
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 28px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-section__head{
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-section__count{
|
|
||||||
font-size: 13px;
|
|
||||||
opacity: .72;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-section__intro{
|
|
||||||
max-width: 78ch;
|
|
||||||
margin: 0;
|
|
||||||
opacity: .92;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-cards{
|
.archi-cards{
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||||
@@ -604,153 +343,8 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
opacity: .72;
|
opacity: .72;
|
||||||
}
|
}
|
||||||
|
|
||||||
.archi-section--final{
|
|
||||||
margin-top: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__block{
|
|
||||||
border: 1px solid rgba(127,127,127,0.22);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 12px;
|
|
||||||
background: rgba(127,127,127,0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__back{
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__title{
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: .2px;
|
|
||||||
line-height: 1.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__meta{
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.35;
|
|
||||||
opacity: .78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__heading{
|
|
||||||
margin: 0 0 10px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 800;
|
|
||||||
opacity: .9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__list{
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__list li{
|
|
||||||
margin: 6px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-aside__list a{
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page #reading-follow){
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on .archi-hero){
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding: 12px 16px 14px;
|
|
||||||
row-gap: 10px;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on .archi-hero h1){
|
|
||||||
font-size: clamp(1.9rem, 3.2vw, 2.55rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on .archi-intro){
|
|
||||||
max-width: 68ch;
|
|
||||||
font-size: .98rem;
|
|
||||||
line-height: 1.48;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on:not(.archi-hero-expanded) .archi-hero-more){
|
|
||||||
max-height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on:not(.archi-hero-expanded) .archi-hero-toggle){
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on #reading-follow .reading-follow__inner){
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page .archi-section__head.is-sticky),
|
|
||||||
:global(body.is-archicrations-page .archi-section__head[data-sticky-active="true"]){
|
|
||||||
position: static !important;
|
|
||||||
top: auto !important;
|
|
||||||
z-index: auto !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
border: 0 !important;
|
|
||||||
background: transparent !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
backdrop-filter: none !important;
|
|
||||||
-webkit-backdrop-filter: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 860px){
|
|
||||||
.archi-hero{
|
|
||||||
position: static;
|
|
||||||
border-radius: 22px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 14px 14px 16px;
|
|
||||||
row-gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-intro{
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-more{
|
|
||||||
max-height: none;
|
|
||||||
opacity: 1;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.archi-hero-toggle{
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-archicrations-page.archi-follow-on .archi-hero){
|
|
||||||
border-radius: 22px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 14px 14px 16px;
|
|
||||||
row-gap: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
@media (prefers-color-scheme: dark){
|
||||||
.archi-card,
|
.archi-card{
|
||||||
.archi-aside__block{
|
|
||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255,255,255,0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,4 +352,50 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
background: rgba(255,255,255,0.07);
|
background: rgba(255,255,255,0.07);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.archi-cards{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.archi-cards{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow){
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow),
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-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-glossary-portal-page #reading-follow),
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page){
|
||||||
|
--followbar-h: 0px !important;
|
||||||
|
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,9 @@
|
|||||||
---
|
---
|
||||||
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
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";
|
||||||
|
|
||||||
const sections = [
|
const sections = [
|
||||||
{
|
{
|
||||||
@@ -189,6 +193,52 @@ const sections = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const totalCount = sections.reduce((sum, section) => sum + section.items.length, 0);
|
const totalCount = sections.reduce((sum, section) => sum + section.items.length, 0);
|
||||||
|
|
||||||
|
const pageItems = [
|
||||||
|
...sections.map((section) => ({
|
||||||
|
href: `#${section.id}`,
|
||||||
|
label: section.title,
|
||||||
|
})),
|
||||||
|
{ href: "#prolonger-la-lecture", label: "Prolonger la lecture" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const usefulLinks = [
|
||||||
|
{ href: "/glossaire/scene-depreuve/", label: "Scène d’épreuve" },
|
||||||
|
{ href: "/glossaire/archicration/", label: "Archicration" },
|
||||||
|
{ href: "/glossaire/obliteration-archicratique/", label: "Oblitération archicratique" },
|
||||||
|
{ href: "/glossaire/archicration-obliteree/", label: "Archicration oblitérée" },
|
||||||
|
{ href: "/glossaire/synchrotopie/", label: "Synchrotopie" },
|
||||||
|
{ href: "/glossaire/hypotopie/", label: "Hypotopie" },
|
||||||
|
{ href: "/glossaire/hypertopie/", label: "Hypertopie" },
|
||||||
|
{ href: "/glossaire/atopie/", label: "Atopie" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const prolongerLinks = [
|
||||||
|
{
|
||||||
|
href: "/glossaire/scenes-archicratiques/",
|
||||||
|
title: "Scènes archicratiques",
|
||||||
|
text:
|
||||||
|
"Revenir aux formes de comparution, d’épreuve, d’empêchement et de réouverture de la régulation.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/glossaire/dynamiques-archicratiques/",
|
||||||
|
title: "Dynamiques archicratiques",
|
||||||
|
text:
|
||||||
|
"Explorer les processus de fermeture, d’oblité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 l’architecture générale du système archicratique.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/glossaire/index-complet/",
|
||||||
|
title: "Index complet",
|
||||||
|
text:
|
||||||
|
"Retrouver toutes les entrées du glossaire dans une navigation alphabétique intégrale.",
|
||||||
|
},
|
||||||
|
];
|
||||||
---
|
---
|
||||||
|
|
||||||
<GlossaryLayout
|
<GlossaryLayout
|
||||||
@@ -197,88 +247,36 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
stickyMode="glossary-portal"
|
stickyMode="glossary-portal"
|
||||||
>
|
>
|
||||||
<Fragment slot="aside">
|
<Fragment slot="aside">
|
||||||
<nav class="verbs-aside" aria-label="Navigation des verbes de la scène">
|
<GlossaryPortalAside
|
||||||
<div class="verbs-aside__block">
|
ariaLabel="Navigation des verbes de la scène"
|
||||||
<a class="verbs-aside__back" href="/glossaire/">← Retour au glossaire</a>
|
title="Verbes de la scène"
|
||||||
<div class="verbs-aside__title">Verbes de la scène</div>
|
meta={`${totalCount} verbe${totalCount > 1 ? "s" : ""} cartographié${totalCount > 1 ? "s" : ""}`}
|
||||||
<div class="verbs-aside__meta">{totalCount} verbes cartographiés</div>
|
pageItems={pageItems}
|
||||||
</div>
|
usefulLinks={usefulLinks}
|
||||||
|
/>
|
||||||
<div class="verbs-aside__block">
|
|
||||||
<h2 class="verbs-aside__heading">Dans cette page</h2>
|
|
||||||
<ul class="verbs-aside__list">
|
|
||||||
{sections.map((section) => (
|
|
||||||
<li><a href={`#${section.id}`}>{section.title}</a></li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="verbs-aside__block">
|
|
||||||
<h2 class="verbs-aside__heading">Renvois utiles</h2>
|
|
||||||
<ul class="verbs-aside__list">
|
|
||||||
<li><a href="/glossaire/scene-depreuve/">Scène d’épreuve</a></li>
|
|
||||||
<li><a href="/glossaire/archicration/">Archicration</a></li>
|
|
||||||
<li><a href="/glossaire/obliteration-archicratique/">Oblitération archicratique</a></li>
|
|
||||||
<li><a href="/glossaire/archicration-obliteree/">Archicration oblitérée</a></li>
|
|
||||||
<li><a href="/glossaire/synchrotopie/">Synchrotopie</a></li>
|
|
||||||
<li><a href="/glossaire/hypotopie/">Hypotopie</a></li>
|
|
||||||
<li><a href="/glossaire/hypertopie/">Hypertopie</a></li>
|
|
||||||
<li><a href="/glossaire/atopie/">Atopie</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
<section class="verbs-page" data-verbs-page>
|
<section class="verbs-page">
|
||||||
<div class="verbs-hero glossary-page-hero" data-verbs-hero>
|
<GlossaryPortalHero
|
||||||
<p class="verbs-kicker">Mini-glossaire systémique</p>
|
prefix="verbs"
|
||||||
<h1>Verbes de la scène archicratique</h1>
|
kicker="Mini-glossaire systémique"
|
||||||
|
title="Verbes de la scène archicratique"
|
||||||
<p class="verbs-intro">
|
intro="Cette page ne rassemble pas des notions de régime, de topologie ou de processus, mais des verbes d’analyse. Elle sert à qualifier ce qui arrive à une scène : comment elle s’ouvre, comment elle s’éloigne, comment elle se ferme, comment elle est capturée, et comment un archicrate peut encore y répondre."
|
||||||
Cette page ne rassemble pas des notions de régime, de topologie ou de processus,
|
moreParagraphs={[
|
||||||
mais des verbes d’analyse. Elle sert à qualifier ce qui arrive à une scène :
|
"Elle constitue ainsi un outil de description fin, complémentaire des fiches consacrées aux scènes, aux topologies et aux dynamiques archicratiques.",
|
||||||
comment elle s’ouvre, comment elle s’éloigne, comment elle se ferme,
|
]}
|
||||||
comment elle est capturée, et comment un archicrate peut encore y répondre.
|
introMaxWidth="76ch"
|
||||||
</p>
|
followIntroMaxWidth="68ch"
|
||||||
|
moreMaxHeight="12rem"
|
||||||
<div class="verbs-hero-collapsible">
|
/>
|
||||||
<div
|
|
||||||
class="verbs-hero-more"
|
|
||||||
id="verbs-hero-more"
|
|
||||||
data-verbs-more
|
|
||||||
aria-hidden="false"
|
|
||||||
>
|
|
||||||
<p class="verbs-intro">
|
|
||||||
Elle constitue ainsi un outil de description fin, complémentaire des fiches
|
|
||||||
consacrées aux scènes, aux topologies et aux dynamiques archicratiques.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="verbs-hero-toggle"
|
|
||||||
id="verbs-hero-toggle"
|
|
||||||
data-verbs-more-toggle
|
|
||||||
type="button"
|
|
||||||
aria-controls="verbs-hero-more"
|
|
||||||
aria-expanded="false"
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
lire la suite
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{sections.map((section) => (
|
{sections.map((section) => (
|
||||||
<section class="verbs-section">
|
<GlossaryPortalSection
|
||||||
<div class="verbs-section__head">
|
id={section.id}
|
||||||
<h2 id={section.id}>{section.title}</h2>
|
title={section.title}
|
||||||
<span class="verbs-section__count">
|
count={`${section.items.length} verbe${section.items.length > 1 ? "s" : ""}`}
|
||||||
{section.items.length} verbe{section.items.length > 1 ? "s" : ""}
|
intro={section.intro}
|
||||||
</span>
|
>
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="verbs-section__intro">{section.intro}</p>
|
|
||||||
|
|
||||||
<div class="verbs-cards">
|
<div class="verbs-cards">
|
||||||
{section.items.map((item) => (
|
{section.items.map((item) => (
|
||||||
<article class="verbs-card">
|
<article class="verbs-card">
|
||||||
@@ -291,11 +289,30 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</GlossaryPortalSection>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<section class="verbs-section verbs-section--final">
|
<GlossaryPortalSection
|
||||||
<h2>Portée d’ensemble</h2>
|
id="prolonger-la-lecture"
|
||||||
|
title="Prolonger la lecture"
|
||||||
|
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>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</GlossaryPortalSection>
|
||||||
|
|
||||||
|
<GlossaryPortalSection
|
||||||
|
id="portee-densemble"
|
||||||
|
title="Portée d’ensemble"
|
||||||
|
final={true}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
Ces verbes permettent de distinguer plus finement les niveaux du paradigme :
|
Ces verbes permettent de distinguer plus finement les niveaux du paradigme :
|
||||||
une <a href="/glossaire/scene-depreuve/">scène</a> dit où quelque chose peut comparaître,
|
une <a href="/glossaire/scene-depreuve/">scène</a> dit où quelque chose peut comparaître,
|
||||||
@@ -304,223 +321,77 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
un processus comme la <a href="/glossaire/desarchicration/">désarchicration</a>
|
un processus comme la <a href="/glossaire/desarchicration/">désarchicration</a>
|
||||||
dit ce qui se transforme, et ces verbes disent ce qu’on fait concrètement à la scène.
|
dit ce qui se transforme, et ces verbes disent ce qu’on fait concrètement à la scène.
|
||||||
</p>
|
</p>
|
||||||
|
</GlossaryPortalSection>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
|
||||||
|
<GlossaryPortalStickySync
|
||||||
|
heroMoreId="verbs-hero-more"
|
||||||
|
heroToggleId="verbs-hero-toggle"
|
||||||
|
/>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
(() => {
|
(() => {
|
||||||
const boot = () => {
|
const boot = () => {
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
const hero = document.querySelector("[data-verbs-hero]");
|
|
||||||
const follow = document.getElementById("reading-follow");
|
const follow = document.getElementById("reading-follow");
|
||||||
const heroMore = document.getElementById("verbs-hero-more");
|
|
||||||
const heroToggle = document.getElementById("verbs-hero-toggle");
|
|
||||||
|
|
||||||
if (!body || !root || !hero || !follow) return;
|
if (!body || !root || !follow) return;
|
||||||
|
|
||||||
|
body.classList.add("is-glossary-portal-page");
|
||||||
|
|
||||||
const BODY_CLASS = "is-verbes-de-la-scene-page";
|
|
||||||
const FOLLOW_ON_CLASS = "verbs-follow-on";
|
|
||||||
const EXPANDED_CLASS = "verbs-hero-expanded";
|
|
||||||
const mqMobile = window.matchMedia("(max-width: 860px)");
|
const mqMobile = window.matchMedia("(max-width: 860px)");
|
||||||
const AUTO_COLLAPSE_DELTA = 160;
|
const mqSmallLandscape = window.matchMedia(
|
||||||
|
"(orientation: landscape) and (max-width: 920px) and (max-height: 520px)"
|
||||||
|
);
|
||||||
|
|
||||||
let expandedAtY = null;
|
const isCompactViewport = () =>
|
||||||
let lastScrollY = window.scrollY || 0;
|
mqMobile.matches || mqSmallLandscape.matches;
|
||||||
|
|
||||||
body.classList.add(BODY_CLASS);
|
const disableFollow = () => {
|
||||||
|
if (!isCompactViewport()) return;
|
||||||
|
|
||||||
const heroHeight = () =>
|
follow.classList.remove("is-on");
|
||||||
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
follow.setAttribute("aria-hidden", "true");
|
||||||
|
follow.style.display = "none";
|
||||||
|
follow.innerHTML = "";
|
||||||
|
|
||||||
const stripLocalSticky = () => {
|
root.style.setProperty("--followbar-h", "0px");
|
||||||
document.querySelectorAll(".verbs-section__head").forEach((el) => {
|
root.style.setProperty(
|
||||||
el.classList.remove("is-sticky");
|
"--sticky-offset-px",
|
||||||
el.removeAttribute("data-sticky-active");
|
"calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px))"
|
||||||
});
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const computeFollowOn = () =>
|
const enableFollow = () => {
|
||||||
!mqMobile.matches &&
|
if (isCompactViewport()) return;
|
||||||
follow.classList.contains("is-on") &&
|
follow.style.display = "";
|
||||||
follow.style.display !== "none" &&
|
};
|
||||||
follow.getAttribute("aria-hidden") !== "true";
|
|
||||||
|
|
||||||
const applyLocalStickyHeight = () => {
|
const sync = () => {
|
||||||
const h = mqMobile.matches ? 0 : heroHeight();
|
if (isCompactViewport()) {
|
||||||
|
disableFollow();
|
||||||
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
|
||||||
window.__archiSetLocalStickyHeight(h);
|
|
||||||
} else {
|
} else {
|
||||||
root.style.setProperty("--glossary-local-sticky-h", `${h}px`);
|
enableFollow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const syncFollowState = () => {
|
|
||||||
const on = computeFollowOn();
|
|
||||||
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
|
||||||
return on;
|
|
||||||
};
|
|
||||||
|
|
||||||
const collapseHero = () => {
|
|
||||||
if (!body.classList.contains(EXPANDED_CLASS)) return;
|
|
||||||
|
|
||||||
body.classList.remove(EXPANDED_CLASS);
|
|
||||||
expandedAtY = null;
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = false;
|
|
||||||
heroToggle.setAttribute("aria-expanded", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.__archiUpdateFollow?.();
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
const expandHero = () => {
|
|
||||||
body.classList.add(EXPANDED_CLASS);
|
|
||||||
expandedAtY = window.scrollY || 0;
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = true;
|
|
||||||
heroToggle.setAttribute("aria-expanded", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.__archiUpdateFollow?.();
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncHeroState = () => {
|
|
||||||
const followOn = computeFollowOn();
|
|
||||||
const expanded = body.classList.contains(EXPANDED_CLASS);
|
|
||||||
const collapsed = followOn && !expanded;
|
|
||||||
|
|
||||||
if (!followOn || mqMobile.matches) {
|
|
||||||
body.classList.remove(EXPANDED_CLASS);
|
|
||||||
expandedAtY = null;
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = true;
|
|
||||||
heroToggle.setAttribute("aria-expanded", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroMore) {
|
|
||||||
heroMore.setAttribute("aria-hidden", collapsed ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heroToggle) {
|
|
||||||
heroToggle.hidden = !collapsed;
|
|
||||||
heroToggle.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const maybeAutoCollapseOnScroll = () => {
|
|
||||||
if (mqMobile.matches) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!computeFollowOn()) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!body.classList.contains(EXPANDED_CLASS)) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expandedAtY == null) {
|
|
||||||
lastScrollY = window.scrollY || 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentY = window.scrollY || 0;
|
|
||||||
const scrollingDown = currentY > lastScrollY;
|
|
||||||
const delta = currentY - expandedAtY;
|
|
||||||
|
|
||||||
if (scrollingDown && delta >= AUTO_COLLAPSE_DELTA) {
|
|
||||||
collapseHero();
|
|
||||||
}
|
|
||||||
|
|
||||||
lastScrollY = currentY;
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncAll = () => {
|
|
||||||
stripLocalSticky();
|
|
||||||
syncFollowState();
|
|
||||||
syncHeroState();
|
|
||||||
applyLocalStickyHeight();
|
|
||||||
};
|
|
||||||
|
|
||||||
let raf = 0;
|
|
||||||
const schedule = () => {
|
|
||||||
if (raf) return;
|
|
||||||
raf = requestAnimationFrame(() => {
|
|
||||||
raf = 0;
|
|
||||||
requestAnimationFrame(syncAll);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
heroToggle?.addEventListener("click", () => {
|
|
||||||
expandHero();
|
|
||||||
});
|
|
||||||
|
|
||||||
const onScroll = () => {
|
|
||||||
maybeAutoCollapseOnScroll();
|
|
||||||
schedule();
|
|
||||||
};
|
|
||||||
|
|
||||||
const followObserver = new MutationObserver(schedule);
|
|
||||||
followObserver.observe(follow, {
|
|
||||||
attributes: true,
|
|
||||||
attributeFilter: ["class", "style", "aria-hidden"],
|
|
||||||
subtree: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const heroResizeObserver =
|
|
||||||
typeof ResizeObserver !== "undefined"
|
|
||||||
? new ResizeObserver(schedule)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
heroResizeObserver?.observe(hero);
|
|
||||||
|
|
||||||
window.addEventListener("scroll", onScroll, { passive: true });
|
|
||||||
window.addEventListener("resize", schedule);
|
|
||||||
window.addEventListener("pageshow", schedule);
|
|
||||||
|
|
||||||
if (document.fonts?.ready) {
|
|
||||||
document.fonts.ready.then(schedule).catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mqMobile.addEventListener) {
|
if (mqMobile.addEventListener) {
|
||||||
mqMobile.addEventListener("change", schedule);
|
mqMobile.addEventListener("change", sync);
|
||||||
} else if (mqMobile.addListener) {
|
} else if (mqMobile.addListener) {
|
||||||
mqMobile.addListener(schedule);
|
mqMobile.addListener(sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule();
|
if (mqSmallLandscape.addEventListener) {
|
||||||
|
mqSmallLandscape.addEventListener("change", sync);
|
||||||
|
} else if (mqSmallLandscape.addListener) {
|
||||||
|
mqSmallLandscape.addListener(sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", sync);
|
||||||
|
window.addEventListener("pageshow", sync);
|
||||||
|
|
||||||
|
sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (document.readyState === "loading") {
|
if (document.readyState === "loading") {
|
||||||
@@ -534,160 +405,32 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.verbs-page{
|
.verbs-page{
|
||||||
padding: 8px 0 24px;
|
padding: var(--portal-page-pad-top, 8px) 0 var(--portal-page-pad-bottom, 24px);
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero{
|
|
||||||
position: sticky;
|
|
||||||
top: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px));
|
|
||||||
z-index: 11;
|
|
||||||
margin: 0 0 24px;
|
|
||||||
padding: 18px 18px 20px;
|
|
||||||
border: 1px solid rgba(127,127,127,0.18);
|
|
||||||
border-radius: 28px;
|
|
||||||
background:
|
|
||||||
linear-gradient(180deg, rgba(0,0,0,0.60), rgba(0,0,0,0.92)),
|
|
||||||
radial-gradient(900px 240px at 20% 0%, rgba(0,217,255,0.08), transparent 60%);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
-webkit-backdrop-filter: blur(10px);
|
|
||||||
display: grid;
|
|
||||||
row-gap: 14px;
|
|
||||||
transition:
|
|
||||||
margin-bottom 180ms ease,
|
|
||||||
border-radius 180ms ease,
|
|
||||||
padding 180ms ease,
|
|
||||||
row-gap 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-kicker{
|
|
||||||
margin: 0;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: .08em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
opacity: .72;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero h1{
|
|
||||||
margin: 0;
|
|
||||||
font-size: clamp(2.2rem, 4vw, 3.15rem);
|
|
||||||
line-height: 1.02;
|
|
||||||
letter-spacing: -.04em;
|
|
||||||
font-weight: 850;
|
|
||||||
transition: font-size 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-intro{
|
|
||||||
max-width: 76ch;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.04rem;
|
|
||||||
line-height: 1.55;
|
|
||||||
opacity: .94;
|
|
||||||
transition:
|
|
||||||
font-size 180ms ease,
|
|
||||||
line-height 180ms ease,
|
|
||||||
max-width 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-collapsible{
|
|
||||||
display: grid;
|
|
||||||
row-gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-more{
|
|
||||||
display: grid;
|
|
||||||
row-gap: 14px;
|
|
||||||
max-height: 12rem;
|
|
||||||
overflow: hidden;
|
|
||||||
opacity: 1;
|
|
||||||
transition:
|
|
||||||
max-height 220ms ease,
|
|
||||||
opacity 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-toggle{
|
|
||||||
display: none;
|
|
||||||
align-self: flex-start;
|
|
||||||
width: fit-content;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: inherit;
|
|
||||||
font: inherit;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.2;
|
|
||||||
letter-spacing: .01em;
|
|
||||||
text-transform: none;
|
|
||||||
opacity: .56;
|
|
||||||
cursor: pointer;
|
|
||||||
text-decoration: underline;
|
|
||||||
text-underline-offset: .12em;
|
|
||||||
text-decoration-thickness: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-toggle:hover{
|
|
||||||
opacity: .84;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-toggle:focus-visible{
|
|
||||||
outline: 2px solid rgba(0,217,255,0.24);
|
|
||||||
outline-offset: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-toggle[hidden]{
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-section{
|
|
||||||
margin-top: 34px;
|
|
||||||
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 28px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-section h2{
|
|
||||||
scroll-margin-top: calc(var(--sticky-offset-px, 96px) + 28px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-section__head{
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-section__count{
|
|
||||||
font-size: 13px;
|
|
||||||
opacity: .72;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-section__intro{
|
|
||||||
max-width: 78ch;
|
|
||||||
margin: 0;
|
|
||||||
opacity: .92;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.verbs-cards{
|
.verbs-cards{
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-top: 14px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.verbs-card{
|
.verbs-card{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 14px 16px;
|
padding: var(--portal-card-pad-y, 14px) var(--portal-card-pad-x, 16px);
|
||||||
border: 1px solid rgba(127,127,127,0.22);
|
border: 1px solid rgba(127,127,127,0.22);
|
||||||
border-radius: 16px;
|
border-radius: var(--portal-card-radius, 16px);
|
||||||
background: rgba(127,127,127,0.05);
|
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{
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.verbs-card:hover{
|
.verbs-card:hover{
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
background: rgba(127,127,127,0.08);
|
background: rgba(127,127,127,0.08);
|
||||||
@@ -704,165 +447,20 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
|
|
||||||
.verbs-card h3{
|
.verbs-card h3{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 15px;
|
font-size: var(--portal-card-title-size, 15px);
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.verbs-card__definition,
|
.verbs-card__definition,
|
||||||
.verbs-card__example{
|
.verbs-card__example{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 14px;
|
font-size: var(--portal-card-text-size, 14px);
|
||||||
line-height: 1.5;
|
line-height: var(--portal-card-text-lh, 1.5);
|
||||||
opacity: .92;
|
opacity: .92;
|
||||||
}
|
}
|
||||||
|
|
||||||
.verbs-section--final{
|
|
||||||
margin-top: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__block{
|
|
||||||
border: 1px solid rgba(127,127,127,0.22);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 12px;
|
|
||||||
background: rgba(127,127,127,0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__back{
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__title{
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: .2px;
|
|
||||||
line-height: 1.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__meta{
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.35;
|
|
||||||
opacity: .78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__heading{
|
|
||||||
margin: 0 0 10px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 800;
|
|
||||||
opacity: .9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__list{
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__list li{
|
|
||||||
margin: 6px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-aside__list a{
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page #reading-follow){
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on .verbs-hero){
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding: 12px 16px 14px;
|
|
||||||
row-gap: 10px;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on .verbs-hero h1){
|
|
||||||
font-size: clamp(1.9rem, 3.2vw, 2.55rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on .verbs-intro){
|
|
||||||
max-width: 68ch;
|
|
||||||
font-size: .98rem;
|
|
||||||
line-height: 1.48;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on:not(.verbs-hero-expanded) .verbs-hero-more){
|
|
||||||
max-height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on:not(.verbs-hero-expanded) .verbs-hero-toggle){
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on #reading-follow .reading-follow__inner){
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page .verbs-section__head.is-sticky),
|
|
||||||
:global(body.is-verbes-de-la-scene-page .verbs-section__head[data-sticky-active="true"]){
|
|
||||||
position: static !important;
|
|
||||||
top: auto !important;
|
|
||||||
z-index: auto !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
border: 0 !important;
|
|
||||||
background: transparent !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
backdrop-filter: none !important;
|
|
||||||
-webkit-backdrop-filter: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 860px){
|
|
||||||
.verbs-hero{
|
|
||||||
position: static;
|
|
||||||
border-radius: 22px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 14px 14px 16px;
|
|
||||||
row-gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-intro{
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-more{
|
|
||||||
max-height: none;
|
|
||||||
opacity: 1;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verbs-hero-toggle{
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body.is-verbes-de-la-scene-page.verbs-follow-on .verbs-hero){
|
|
||||||
border-radius: 22px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 14px 14px 16px;
|
|
||||||
row-gap: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
@media (prefers-color-scheme: dark){
|
||||||
.verbs-card,
|
.verbs-card{
|
||||||
.verbs-aside__block{
|
|
||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255,255,255,0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,4 +468,50 @@ const totalCount = sections.reduce((sum, section) => sum + section.items.length,
|
|||||||
background: rgba(255,255,255,0.07);
|
background: rgba(255,255,255,0.07);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px){
|
||||||
|
.verbs-cards{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: landscape) and (max-width: 920px) and (max-height: 520px){
|
||||||
|
.verbs-cards{
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow){
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px){
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow),
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-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-glossary-portal-page #reading-follow),
|
||||||
|
:global(body.is-glossary-portal-page #reading-follow .reading-follow__inner){
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(body.is-glossary-portal-page){
|
||||||
|
--followbar-h: 0px !important;
|
||||||
|
--sticky-offset-px: calc(var(--sticky-header-h, 0px) + var(--page-gap, 12px)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user