Files
YvvandClaude Opus 5.5 67ddee28b2 v3 : socle Rust (moteur pur, accès trustinWallet, serveur) ; maquette Nuxt rangée dans maquette/
- crates/ld-engine : formule inertielle (parité avec la maquette, garde C),
  coquille / changement de fond, assistant d'édition à règles, composition
  d'un document sous vote permanent (adoptions, aperçus, rivales).
- crates/trustin-access : qui voit, qui ouvre, qui gère les accès.
- crates/ld-server : API axum + SQLite, connexion Ğ1 (client OAuth2 de
  connect.monnaie-libre.fr), invitations, entrée en vigueur automatique,
  signalements de contradiction, traductions éditoriales, publication git,
  taille de la toile lue sur la chaîne.
- seeds/acte-engagement-certification.json : 33 articles, fr + en + es ;
  en vigueur : préambule, E1, E2 (seed a minima).
- maquette/ : frontend, backend et docker v2 déplacés tels quels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 02:04:42 +02:00

160 lines
5.2 KiB
Vue

<script setup lang="ts">
/**
* /textes/formules — l'Atelier des formules : la pédagogie du seuil,
* seule maison des lettres W/T/M/B/G/C. Query params ?W=&T=&M=&B=&G=&C=(&S=)
* pré-règlent l'établi — les liens « comprendre ce seuil » arrivent ici.
*/
import { BINARY_DESCRIPTION, BINARY_COST, METHOD_LABELS } from '~/lexicon'
import type { AtelierInit } from '~/components/texts/textsModel'
const route = useRoute()
function numParam(name: string): number | undefined {
const raw = route.query[name]
const value = Number(Array.isArray(raw) ? raw[0] : raw)
return Number.isFinite(value) ? value : undefined
}
const initial = computed((): AtelierInit => {
const init: AtelierInit = {}
const W = numParam('W')
const T = numParam('T')
const M = numParam('M')
const B = numParam('B')
const G = numParam('G')
const C = numParam('C')
const S = numParam('S')
if (W !== undefined) init.W = W
if (T !== undefined) init.T = T
if (M !== undefined) init.M = M
if (B !== undefined) init.B = B
if (G !== undefined) init.G = G
if (C !== undefined) init.C = C
if (S !== undefined) init.S = S
return init
})
</script>
<template>
<!-- ld-v2 -->
<div class="atelier">
<NuxtLink to="/textes" class="ld-btn ld-btn--quiet atelier__back">
<UIcon name="i-lucide-arrow-left" />
Tous les textes
</NuxtLink>
<header class="atelier__header">
<h1 class="atelier__title">L'Atelier des formules</h1>
<p class="atelier__subtitle">
La pédagogie du seuil — c'est ici, et seulement ici, que vivent les lettres.
Partout ailleurs, l'outil parle français.
</p>
</header>
<!-- L'établi -->
<AtelierFormulaLab :key="JSON.stringify(initial)" :initial="initial" />
<!-- Le pour/contre, présenté pour ce qu'il est -->
<section class="atelier__card ld-card">
<div class="atelier__card-head">
<span class="atelier__card-icon atelier__card-icon--binary">
<UIcon name="i-lucide-scale" />
</span>
<div>
<h2 class="atelier__card-title">{{ METHOD_LABELS.binary }}</h2>
<p class="atelier__card-sub">{{ BINARY_DESCRIPTION }}</p>
</div>
</div>
<p class="atelier__prose">
Cette formule inertielle est un héritage de la Toile de Confiance Ğ1 : quand
des milliers de membres sont éligibles et que peu s'expriment, elle exige
presque l'unanimité ; quand la participation monte, le seuil descend vers la
majorité cible. C'est une protection remarquable pour les très grands corps —
et un outil d'exception : son coût reste « {{ BINARY_COST }} ».
Pour la vie courante d'un collectif, le consentement, le vote nuancé et le
réglage collectif font mieux vivre le désaccord.
</p>
</section>
<!-- Le Réglage collectif : la médiane basse expliquée -->
<section class="atelier__card ld-card">
<div class="atelier__card-head">
<span class="atelier__card-icon atelier__card-icon--parametric">
<UIcon name="i-lucide-sliders-horizontal" />
</span>
<div>
<h2 class="atelier__card-title">{{ METHOD_LABELS.parametric }}</h2>
<p class="atelier__card-sub">décider au curseur — la médiane basse, expliquée en jouant</p>
</div>
</div>
<p class="atelier__prose">
Quand la question est un nombre — un montant, un taux, une répartition —
voter pour ou contre appauvrit la question. Chacun pose son curseur, et le
collectif retient la médiane basse. Bouge les cinq curseurs-votes ci-dessous :
tire un vote vers l'extrême, la médiane bouge à peine.
</p>
<AtelierMedianDemo />
</section>
</div>
</template>
<style scoped>
.atelier {
display: flex;
flex-direction: column;
gap: clamp(1rem, 3vw, 1.5rem);
max-width: 56rem;
margin: 0 auto;
padding-bottom: 4rem;
}
.atelier__back { align-self: flex-start; font-size: 0.8125rem; text-decoration: none; }
.atelier__header { display: flex; flex-direction: column; gap: 0.35rem; }
.atelier__title {
font-size: clamp(1.5rem, 5vw, 1.9rem);
font-weight: 800;
letter-spacing: -0.02em;
color: var(--mood-text);
}
.atelier__subtitle {
font-size: 0.875rem;
color: var(--mood-text-muted);
line-height: 1.55;
max-width: 38rem;
}
.atelier__card {
padding: clamp(1rem, 3vw, 1.4rem);
display: flex;
flex-direction: column;
gap: 0.9rem;
}
.atelier__card-head { display: flex; align-items: center; gap: 0.8rem; }
.atelier__card-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.75rem;
height: 2.75rem;
border-radius: var(--r-icon);
font-size: 1.3rem;
flex-shrink: 0;
}
.atelier__card-icon--binary {
background: color-mix(in srgb, var(--mood-secondary) 12%, transparent);
color: var(--mood-secondary);
}
.atelier__card-icon--parametric {
background: color-mix(in srgb, var(--mood-tertiary) 12%, transparent);
color: var(--mood-tertiary);
}
.atelier__card-title { font-size: 1.05rem; font-weight: 800; color: var(--mood-text); }
.atelier__card-sub { font-size: 0.8125rem; color: var(--mood-text-muted); }
.atelier__prose {
font-size: 0.875rem;
line-height: 1.65;
color: var(--mood-text);
}
</style>