identité 4 : plus de paire ni de colonne en marge, chaque oiseau sur une ligne visible ; la console arrête un curseur qui descendait
Relecture de fb8c71f..16d6607 (03/11 13h10, relayée par la session orch) : - /economique : la balance sort de derrière le bloc du livre à mi-hauteur, loin du sol de la maraîchère ; - authentification-wot : la toile de confiance, petite, en marge sur la dernière ligne des étapes (le bloc n'a pas de fond) ; - chapitres : le filet au-dessus de précédent / suivant est tracé (border-t seul n'a pas de style ici) ; le cartonnier s'y pose ; - /evenement : l'acrobate passe au bout de la ligne du leitmotiv, le régisseur reste seul près de « Format & lieu » ; - sommaire du livre : empileur plus loin, illustratrice moins sortie : plus de bande commune. Trouvés par le contrôle étendu : le débogueur (logiciel-libre) sur la dernière ligne des étapes, la vigneronne (monnaie-libre) derrière le bloc de texte, qui a un fond. Console, décision d'orch du 03/11 à 13h10 : au premier geste, un curseur non touché que la rotation faisait descendre s'arrête là où il est ; un curseur qui montait finit sa montée. docs/consignes-yvv.md (« Ce que fait le code ») et docs/da-oiseaux.md suivent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
role="tab"
|
role="tab"
|
||||||
class="fader"
|
class="fader"
|
||||||
:class="{ 'fader--active': axis.key === active, 'fader--held': held.has(axis.key), 'fader--rising': rising.has(axis.key) }"
|
:class="{ 'fader--active': axis.key === active, 'fader--held': held.has(axis.key), 'fader--rising': rising.has(axis.key), 'fader--stopped': stopped.has(axis.key) }"
|
||||||
:style="{ '--hue': `var(${axis.hue})`, '--level': levels[axis.key] ?? 0, '--i': i }"
|
:style="{ '--hue': `var(${axis.hue})`, '--level': levels[axis.key] ?? 0, '--i': i }"
|
||||||
:data-axis="axis.key"
|
:data-axis="axis.key"
|
||||||
:aria-selected="axis.key === active"
|
:aria-selected="axis.key === active"
|
||||||
@@ -142,10 +142,11 @@ const current = computed(() => props.axes.find(a => a.key === active.value) ?? p
|
|||||||
// The visitor's hand takes over for good (03/11): from the first hover,
|
// The visitor's hand takes over for good (03/11): from the first hover,
|
||||||
// keyboard focus or tap on a cursor, the rotation stops. The touched cursor
|
// keyboard focus or tap on a cursor, the rotation stops. The touched cursor
|
||||||
// replays its rise, from the bottom to its own graduation, and its panel
|
// replays its rise, from the bottom to its own graduation, and its panel
|
||||||
// shows. The others are never lowered by the hand: a cursor already touched
|
// shows. The others are never lowered by the hand (orch decision, 03/11
|
||||||
// stays at its graduation; a cursor never touched finishes, gently, the move
|
// 13h10): a cursor already touched stays at its graduation; a cursor never
|
||||||
// the rotation had begun (up to its graduation, or down to its low level),
|
// touched that the rotation was taking down stops where it is at the first
|
||||||
// then stays there. None stays frozen mid-course.
|
// gesture; one it was taking up finishes, gently, its rise to the level the
|
||||||
|
// rotation gave it, then stays there.
|
||||||
const BEAT_MS = 2600
|
const BEAT_MS = 2600
|
||||||
const BEATS_PER_AXIS = 3
|
const BEATS_PER_AXIS = 3
|
||||||
/** Graduation of each axis, from asservissement (0) to émancipation (1) */
|
/** Graduation of each axis, from asservissement (0) to émancipation (1) */
|
||||||
@@ -158,6 +159,8 @@ const levels = reactive<Partial<Record<AxisKey, number>>>({})
|
|||||||
const held = reactive(new Set<AxisKey>())
|
const held = reactive(new Set<AxisKey>())
|
||||||
/** Cursors replaying their rise (fast transition) */
|
/** Cursors replaying their rise (fast transition) */
|
||||||
const rising = reactive(new Set<AxisKey>())
|
const rising = reactive(new Set<AxisKey>())
|
||||||
|
/** Untouched cursors the first gesture stopped on their way down */
|
||||||
|
const stopped = reactive(new Set<AxisKey>())
|
||||||
const reduced = ref(false)
|
const reduced = ref(false)
|
||||||
const visible = ref(true)
|
const visible = ref(true)
|
||||||
const engaged = ref(false)
|
const engaged = ref(false)
|
||||||
@@ -188,17 +191,30 @@ function faderEl(key: AxisKey) {
|
|||||||
return root.value?.querySelector<HTMLElement>(`[data-axis="${key}"]`) ?? null
|
return root.value?.querySelector<HTMLElement>(`[data-axis="${key}"]`) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** First gesture: the rotation stops for good. The untouched cursors keep the target the
|
/** First gesture: the rotation stops for good. An untouched cursor on its way down stops
|
||||||
* rotation gave them and finish their glide to it (no freeze mid-course) */
|
* where it is drawn; one on its way up finishes its glide to the target the rotation gave it.
|
||||||
function engage() {
|
* `touched` is the cursor of this gesture: it replays its rise anyway */
|
||||||
|
function engage(touched?: AxisKey) {
|
||||||
if (engaged.value) return
|
if (engaged.value) return
|
||||||
engaged.value = true
|
engaged.value = true
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
|
for (const axis of props.axes) {
|
||||||
|
const key = axis.key
|
||||||
|
if (key === touched || held.has(key)) continue
|
||||||
|
const el = faderEl(key)
|
||||||
|
const drawn = el ? Number.parseFloat(getComputedStyle(el).getPropertyValue('--level')) : Number.NaN
|
||||||
|
const target = levels[key] ?? 0
|
||||||
|
if (Number.isFinite(drawn) && drawn > target) {
|
||||||
|
stopped.add(key)
|
||||||
|
levels[key] = drawn
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The touched cursor replays its rise: back to the bottom, then up to its graduation */
|
/** The touched cursor replays its rise: back to the bottom, then up to its graduation */
|
||||||
async function rise(key: AxisKey) {
|
async function rise(key: AxisKey) {
|
||||||
held.add(key)
|
held.add(key)
|
||||||
|
stopped.delete(key)
|
||||||
const target = GRADUATION[key] ?? 0.75
|
const target = GRADUATION[key] ?? 0.75
|
||||||
if (reduced.value) {
|
if (reduced.value) {
|
||||||
levels[key] = target
|
levels[key] = target
|
||||||
@@ -220,14 +236,14 @@ async function rise(key: AxisKey) {
|
|||||||
/** A cursor under the visitor's hand: it rises and its panel shows. Every rollover replays
|
/** A cursor under the visitor's hand: it rises and its panel shows. Every rollover replays
|
||||||
* the rise, however soon after the previous one (Yvv, 03/11) */
|
* the rise, however soon after the previous one (Yvv, 03/11) */
|
||||||
function touch(key: AxisKey) {
|
function touch(key: AxisKey) {
|
||||||
engage()
|
engage(key)
|
||||||
active.value = key
|
active.value = key
|
||||||
rise(key)
|
rise(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The panel of a cursor already raised by this same gesture: no second rise */
|
/** The panel of a cursor already raised by this same gesture: no second rise */
|
||||||
function select(key: AxisKey) {
|
function select(key: AxisKey) {
|
||||||
engage()
|
engage(key)
|
||||||
active.value = key
|
active.value = key
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,8 +420,10 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* A cursor the hand has touched no longer glides: it drops to the bottom at once, then
|
/* A cursor the hand has touched no longer glides: it drops to the bottom at once, then
|
||||||
replays its rise. The untouched ones finish their glide, then the rotation is over */
|
replays its rise. At the first gesture, an untouched cursor on its way down stops where it
|
||||||
.fader--held {
|
is; one on its way up finishes its glide, then the rotation is over */
|
||||||
|
.fader--held,
|
||||||
|
.fader--stopped {
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,10 @@
|
|||||||
|
|
||||||
<!-- Modèle économique — bloc livre -->
|
<!-- Modèle économique — bloc livre -->
|
||||||
<div class="book-block">
|
<div class="book-block">
|
||||||
<!-- The balance (the measure of the gift) peeks out from behind the book -->
|
<!-- The balance (the measure of the gift) peeks out from behind the book, on the left and
|
||||||
<UiOiseauPose nom="la-balance" pose="derriere" left="-150px" bottom="-20px" :w="240" />
|
halfway up: the market gardener stands low on the right, never at its height, and the
|
||||||
|
four birds of the page do not alternate at an even step -->
|
||||||
|
<UiOiseauPose nom="la-balance" pose="derriere" left="-150px" bottom="calc(100% - 240px)" :w="240" />
|
||||||
<!-- Not by the Productions card: with the beekeeper, a pair at the same height -->
|
<!-- Not by the Productions card: with the beekeeper, a pair at the same height -->
|
||||||
<UiOiseauPose nom="maraichere" pose="marge-d" ecart="46px" :w="108" retourne />
|
<UiOiseauPose nom="maraichere" pose="marge-d" ecart="46px" :w="108" retourne />
|
||||||
<HomeBookSection
|
<HomeBookSection
|
||||||
|
|||||||
@@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
<BookChapterContent :content="chapter" />
|
<BookChapterContent :content="chapter" />
|
||||||
|
|
||||||
<!-- Prev / Next navigation -->
|
<!-- Prev / Next navigation. The rule above it is drawn (border-t alone sets no style here):
|
||||||
<nav class="relative mt-16 flex items-center justify-between border-t border-white/8 pt-8">
|
the box maker stands on it -->
|
||||||
|
<nav class="relative mt-16 flex items-center justify-between border-t border-t-solid border-white/8 pt-8">
|
||||||
<UiOiseauPose nom="cartonnier" pose="perche" left="calc(50% - 38px)" :w="76" />
|
<UiOiseauPose nom="cartonnier" pose="perche" left="calc(50% - 38px)" :w="76" />
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-if="prevChapter"
|
v-if="prevChapter"
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ const OISEAUX_CHAPITRE: Record<string, OiseauPlace[]> = {
|
|||||||
'01-introduction': [{ nom: 'conteuse', pose: 'marge-g', ecart: '50px', w: 122 }],
|
'01-introduction': [{ nom: 'conteuse', pose: 'marge-g', ecart: '50px', w: 122 }],
|
||||||
'03-mesure': [{ nom: 'la-balance', pose: 'marge-d', ecart: '40px', w: 112, retourne: true }],
|
'03-mesure': [{ nom: 'la-balance', pose: 'marge-d', ecart: '40px', w: 112, retourne: true }],
|
||||||
'07-echanger': [{ nom: 'colporteur', pose: 'marge-g', ecart: '44px', w: 116 }],
|
'07-echanger': [{ nom: 'colporteur', pose: 'marge-g', ecart: '44px', w: 116 }],
|
||||||
'08-institution': [{ nom: 'empileur', pose: 'marge-d', ecart: '48px', w: 128, retourne: true }],
|
'08-institution': [{ nom: 'empileur', pose: 'marge-d', ecart: '90px', w: 104, retourne: true }],
|
||||||
'11-annexes': [{ nom: 'illustratrice', pose: 'derriere', left: 'calc(100% - 90px)', bottom: '-40px', w: 220 }],
|
'11-annexes': [{ nom: 'illustratrice', pose: 'derriere', left: 'calc(100% - 110px)', bottom: '-40px', w: 220 }],
|
||||||
}
|
}
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
|
|||||||
@@ -65,6 +65,8 @@
|
|||||||
class="prose-block relative mb-8 max-w-2xl mx-auto section-anchor"
|
class="prose-block relative mb-8 max-w-2xl mx-auto section-anchor"
|
||||||
>
|
>
|
||||||
<UiOiseauPose nom="boulangere" pose="marge-g" ecart="56px" :w="96" />
|
<UiOiseauPose nom="boulangere" pose="marge-g" ecart="56px" :w="96" />
|
||||||
|
<!-- Behind the top of the text block, which has a background (the links stand apart) -->
|
||||||
|
<UiOiseauPose nom="vigneronne" pose="derriere" left="-140px" bottom="calc(100% - 220px)" :w="210" />
|
||||||
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
|
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
|
||||||
{{ content.content }}
|
{{ content.content }}
|
||||||
</p>
|
</p>
|
||||||
@@ -76,7 +78,6 @@
|
|||||||
id="section-links"
|
id="section-links"
|
||||||
class="relative flex flex-col gap-3 mb-10 max-w-2xl mx-auto section-anchor"
|
class="relative flex flex-col gap-3 mb-10 max-w-2xl mx-auto section-anchor"
|
||||||
>
|
>
|
||||||
<UiOiseauPose nom="vigneronne" pose="derriere" left="-140px" bottom="-24px" :w="210" />
|
|
||||||
<a
|
<a
|
||||||
v-for="link in content.links"
|
v-for="link in content.links"
|
||||||
:key="link.href"
|
:key="link.href"
|
||||||
|
|||||||
@@ -26,8 +26,11 @@
|
|||||||
|
|
||||||
<!-- Leitmotiv -->
|
<!-- Leitmotiv -->
|
||||||
<div v-if="evtContent?.leitmotiv" class="mt-8 flex flex-col items-center gap-3">
|
<div v-if="evtContent?.leitmotiv" class="mt-8 flex flex-col items-center gap-3">
|
||||||
<p class="font-display text-xl font-bold" style="color: hsl(var(--color-text))">
|
<p class="relative font-display text-xl font-bold" style="color: hsl(var(--color-text))">
|
||||||
« {{ evtContent.leitmotiv }} »
|
« {{ evtContent.leitmotiv }} »
|
||||||
|
<!-- The acrobat on the line of the leitmotiv, before it: by « Format & lieu », the stage
|
||||||
|
manager stands alone (two birds there would stand at the same height) -->
|
||||||
|
<UiOiseauPose nom="acrobate" pose="perche" right="calc(100% + 14px)" bottom="0px" :w="72" />
|
||||||
</p>
|
</p>
|
||||||
<p v-if="evtContent?.tagline" class="font-mono text-sm tracking-widest uppercase" style="color: hsl(var(--color-primary))">
|
<p v-if="evtContent?.tagline" class="font-mono text-sm tracking-widest uppercase" style="color: hsl(var(--color-primary))">
|
||||||
{{ evtContent.tagline }}
|
{{ evtContent.tagline }}
|
||||||
@@ -129,7 +132,6 @@ const evtContent = computed(() => content.value as Record<string, any> | null)
|
|||||||
const OISEAUX_CARTE: Record<string, OiseauPlace[]> = {
|
const OISEAUX_CARTE: Record<string, OiseauPlace[]> = {
|
||||||
'Économique': [{ nom: 'jongleur', pose: 'perche', right: '22px', w: 76 }],
|
'Économique': [{ nom: 'jongleur', pose: 'perche', right: '22px', w: 76 }],
|
||||||
'Ğ(marché)': [{ nom: 'cracheur-de-feu', pose: 'perche', right: '18px', w: 76, ton: 'accent', seuil: 1200 }],
|
'Ğ(marché)': [{ nom: 'cracheur-de-feu', pose: 'perche', right: '18px', w: 76, ton: 'accent', seuil: 1200 }],
|
||||||
'100 à 200 personnes': [{ nom: 'acrobate', pose: 'perche', right: '14px', w: 72 }],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useSeoPage({
|
useSeoPage({
|
||||||
|
|||||||
@@ -439,7 +439,8 @@ const OISEAUX_PAGE: Record<string, OiseauxPage> = {
|
|||||||
'logiciel-libre': {
|
'logiciel-libre': {
|
||||||
projet: [{ nom: 'cafeine', pose: 'derriere', left: '-130px', bottom: '-30px', w: 200 }],
|
projet: [{ nom: 'cafeine', pose: 'derriere', left: '-130px', bottom: '-30px', w: 200 }],
|
||||||
sections: {
|
sections: {
|
||||||
1: [{ nom: 'debogueur', pose: 'marge-g', ecart: '24px', w: 132 }],
|
// feet on the last line of the steps: the block ends with the step's padding (16 px)
|
||||||
|
1: [{ nom: 'debogueur', pose: 'marge-g', ecart: '24px', bottom: '16px', w: 132 }],
|
||||||
// sections 2 (and cloud-libre 1 and 5) are wide: 152 px of margin at 1200 px
|
// sections 2 (and cloud-libre 1 and 5) are wide: 152 px of margin at 1200 px
|
||||||
2: [{ nom: 'le-manchot', pose: 'marge-g', ecart: '40px', w: 84 }],
|
2: [{ nom: 'le-manchot', pose: 'marge-g', ecart: '40px', w: 84 }],
|
||||||
3: [{ nom: 'canard-en-plastique', pose: 'marge-g', ecart: '110px', w: 76 }],
|
3: [{ nom: 'canard-en-plastique', pose: 'marge-g', ecart: '110px', w: 76 }],
|
||||||
@@ -448,7 +449,9 @@ const OISEAUX_PAGE: Record<string, OiseauxPage> = {
|
|||||||
'authentification-wot': {
|
'authentification-wot': {
|
||||||
projet: [{ nom: 'porteur-de-serveur', pose: 'derriere', left: '-130px', bottom: '-30px', w: 210 }],
|
projet: [{ nom: 'porteur-de-serveur', pose: 'derriere', left: '-130px', bottom: '-30px', w: 210 }],
|
||||||
sections: {
|
sections: {
|
||||||
1: [{ nom: 'toile-de-confiance', pose: 'derriere', left: '-120px', bottom: '-30px', w: 220 }],
|
// the steps have no background: in the margin, on their last line, small and close to the
|
||||||
|
// text, out of the band shared by the server carrier and the pump
|
||||||
|
1: [{ nom: 'toile-de-confiance', pose: 'marge-g', ecart: '24px', bottom: '16px', w: 76 }],
|
||||||
// not right under the server carrier and the web of trust: no column of three
|
// not right under the server carrier and the web of trust: no column of three
|
||||||
2: [{ nom: 'cryptographe', pose: 'marge-g', ecart: '96px', w: 84 }],
|
2: [{ nom: 'cryptographe', pose: 'marge-g', ecart: '96px', w: 84 }],
|
||||||
4: [{ nom: 'pompeur-de-g1', pose: 'marge-g', ecart: '72px', w: 120 }],
|
4: [{ nom: 'pompeur-de-g1', pose: 'marge-g', ecart: '72px', w: 120 }],
|
||||||
|
|||||||
@@ -41,7 +41,14 @@ Ce que fait le code :
|
|||||||
- Le curseur touché repart d'en bas et monte en 1,1 s à son cran : numérique 0,75, économique 0,50,
|
- Le curseur touché repart d'en bas et monte en 1,1 s à son cran : numérique 0,75, économique 0,50,
|
||||||
citoyenne 0,667. Il y reste.
|
citoyenne 0,667. Il y reste.
|
||||||
- Le panneau de l'axe s'affiche au même geste.
|
- Le panneau de l'axe s'affiche au même geste.
|
||||||
- Les autres curseurs ne bougent pas. Un curseur jamais touché reste là où il était.
|
- La main ne fait descendre aucun autre curseur :
|
||||||
|
- un curseur déjà touché reste à son cran ;
|
||||||
|
- au premier geste, un curseur jamais touché que la rotation faisait descendre s'arrête là où il
|
||||||
|
est ;
|
||||||
|
- un curseur jamais touché que la rotation faisait monter finit sa montée, au niveau que la
|
||||||
|
rotation lui donnait (le cran pour l'axe mis en avant), puis il y reste.
|
||||||
|
|
||||||
|
Décision d'orch du 03/11 à 13h10, qui découle de « ne fait pas descendre les autres ».
|
||||||
- Un nouveau survol rejoue la montée.
|
- Un nouveau survol rejoue la montée.
|
||||||
- Avant tout geste, l'animation du 29/09 continue : la rotation et la dérive des curseurs bas. L'axe
|
- Avant tout geste, l'animation du 29/09 continue : la rotation et la dérive des curseurs bas. L'axe
|
||||||
mis en avant monte à son cran, et non plus vers 0,9. C'est une décision d'orch du 03/11 à 05h51, qui
|
mis en avant monte à son cran, et non plus vers 0,9. C'est une décision d'orch du 03/11 à 05h51, qui
|
||||||
|
|||||||
@@ -55,3 +55,31 @@ Ce que fait le code depuis :
|
|||||||
- Commande : un seul côté par carte. Le cycliste est à gauche de la première, le libraire en grand
|
- Commande : un seul côté par carte. Le cycliste est à gauche de la première, le libraire en grand
|
||||||
derrière la seconde, à droite. La lectrice se tient sur le sac de l'icône. Le cartonnier est parti
|
derrière la seconde, à droite. La lectrice se tient sur le sac de l'icône. Le cartonnier est parti
|
||||||
sur la ligne qui clôt chaque chapitre, l'empileur sur le sommaire du livre.
|
sur la ligne qui clôt chaque chapitre, l'empileur sur le sommaire du livre.
|
||||||
|
|
||||||
|
### 03/11/2026, 13h10 : relecture (relayée par la session orch, ce ne sont pas les mots d'Yvv)
|
||||||
|
|
||||||
|
La relecture de fb8c71f à 16d6607 conclut « à reprendre », avec cinq constats :
|
||||||
|
- /economique : la maraîchère et la balance font une paire, aux sols presque à la même hauteur ;
|
||||||
|
- /numerique/authentification-wot : la toile de confiance est « derrière » un bloc sans fond, et du
|
||||||
|
texte la traverse ;
|
||||||
|
- les chapitres : le cartonnier est posé sur un filet que rien ne trace ;
|
||||||
|
- /evenement : le régisseur et l'acrobate font une paire ;
|
||||||
|
- le sommaire du livre : trois oiseaux dans une même bande de la marge droite.
|
||||||
|
|
||||||
|
Trois règles en découlent :
|
||||||
|
- pas deux oiseaux de part et d'autre dont les sols sont à moins de 40 px l'un de l'autre ;
|
||||||
|
- une ligne visible, c'est une bordure, un fond différent de ce qu'il y a dessous, le bas d'une
|
||||||
|
carte qui a un fond, ou une ligne de texte ;
|
||||||
|
- « derrière une carte » demande une carte au fond opaque.
|
||||||
|
|
||||||
|
Ce que fait le code depuis :
|
||||||
|
- /economique : la balance sort de derrière le bloc du livre, à gauche, à mi-hauteur.
|
||||||
|
- Authentification : la toile de confiance est petite, en marge, sur la dernière ligne des étapes.
|
||||||
|
- Logiciel libre : le débogueur se tient aussi sur la dernière ligne des étapes.
|
||||||
|
- Chapitres : le filet au-dessus de précédent et suivant est tracé ; le cartonnier s'y pose.
|
||||||
|
- /evenement : le régisseur reste seul près de « Format & lieu ». L'acrobate se tient au bout de la
|
||||||
|
ligne du leitmotiv, dans l'en-tête.
|
||||||
|
- Sommaire du livre : l'empileur est plus loin dans la marge, l'illustratrice dépasse moins de sa
|
||||||
|
carte.
|
||||||
|
- Monnaie libre : la vigneronne sort de derrière le haut du bloc de texte, qui a un fond.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user