Files
librodrome/app/components/home/HomeLanding.vue
T
YvvandClaude Opus 5.5 28a6daf382 identité 6 : la règle f mesurée au-dessus du dessin, les chapitres posés sur leurs filets, les coins arrondis dégagés
Règle f, selon la précision de DA du 03/11 après 17h35 : au-dessus d'un oiseau perché, le vide
se mesure du haut de son dessin jusqu'à la plus basse ligne de texte ou au plus bas bloc qui
passe au-dessus de sa largeur peinte. Les lignes de son propre titre comptent, et l'en-tête
collant aussi en haut de page. Quinze perchés en défaut sur bb8fad9 changent de pose, sans
sortir de la liste fermée :
- accueil :
  - le DJ se tient derrière le pupitre de la console, seule sa tête dépasse ;
  - l'accordéoniste passe en S, visible à partir de 1200 px ;
  - la factrice passe à 76 px ;
  - la lectrice sort 20 px plus bas ;
- au téléphone, l'oiseau de l'intitulé est un oiseau plat : codeuse, maraîchère, potier, et le
  cycliste livreur sur productions collectives ;
- authentification, tarifs de l'eau, commande : en marge droite, sur l'arête haute de la carte ;
- en musique : le danseur passe en S ;
- évènement :
  - l'acrobate se tient avant la devise ;
  - le régisseur passe en S, posé sur l'arête des cartes ;
  - le clown passe en M ;
  - le marionnettiste se tient sur le filet du pied de page (option 1 d'orch). Son décalage
    est tiré de --seal-block, le bloc du sceau défini dans le layout ;
- chapitres : le calligraphe se tient sur le filet du titre, le typographe sur celui de la
  navigation, le cartonnier en marge des boutons. Plus aucune hauteur en %.

Règle g, rectangle du bloc (décision d'orch) : le porteur de serveur et l'administrateur réseau
sortent de la découpe des coins arrondis.

La liste fermée (docs/da-oiseaux.md) reçoit les précisions d'orch :
- e vaut pour un oiseau « libre » dont le centre sort de son bloc ;
- g se mesure sur le rectangle du bloc ;
- un oiseau derrière une carte reste « derrière ».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:24:44 +01:00

238 lines
6.3 KiB
Vue

<template>
<div class="va">
<!-- Hero : the headline, and the three cursors to push -->
<section class="va-hero">
<div class="container-content va-hero-grid">
<div class="va-intro">
<h1 class="va-h1">
<span class="va-h1-a">{{ heading[0] }}</span>
<span class="va-h1-b">{{ heading[1] }}</span>
</h1>
<p class="va-axes">
<template v-for="(seg, i) in axesLine" :key="i">
<span v-if="seg.hue" class="va-axes-word" :style="{ '--hue': `var(${seg.hue})` }">{{ seg.text }}</span>
<template v-else>{{ seg.text }}</template>
</template>
</p>
<p class="va-means">{{ heading[4] }}</p>
<p v-if="hero.approach" class="va-approach">{{ hero.approach }}</p>
</div>
<div class="va-console">
<p class="va-console-title">
{{ heading[2] }}
</p>
<!-- The DJ stands behind the console board, like behind its decks: only its head, with
its headphones, shows over the board. Perched on the board, under the sticky header,
it had no void of its own height above it (rule f, DA 03/11 after 17h35). The scene
keeps it under the board without touching the console -->
<div class="va-console-scene">
<UiOiseauPose nom="dj" pose="derriere" right="24px" top="-95px" :w="150" retourne ton="accent" />
<UiOiseauPose nom="dj" pose="derriere" right="24px" top="-95px" :w="150" retourne ton="accent" mobile-seul :seuil="768" />
<HomeConsole
v-model="active"
:axes="axes"
:prefix="consoleLabels?.prefix"
:top-label="consoleLabels?.top"
:bottom-label="consoleLabels?.bottom"
:stacks="bouquet?.inService"
:stacks-to="lpk?.to"
:stacks-label="lpk ? `En service chez ${lpk.name} :` : 'En service :'"
/>
</div>
</div>
</div>
</section>
<!-- Pourquoi -->
<section class="va-band">
<div class="container-content">
<HomeCitations :lines="hero.citations ?? []" />
</div>
</section>
<!-- Le format -->
<section class="va-section">
<div class="container-content">
<HomeFormat
:format="format"
:book="book"
:evenement="evenement"
:hero="hero"
@open-player="$emit('open-player')"
@open-pdf="$emit('open-pdf')"
/>
</div>
</section>
<!-- La boîte à outils -->
<section class="va-section va-section--tools">
<div class="container-content">
<h2 class="va-h2">{{ toolboxTitle }}</h2>
<HomeToolbox
:oiseaux="toolboxOiseaux"
:axes="axes"
:lpk="lpk"
:bouquet="bouquet"
:gratewizard="gratewizard"
anchors
@open-player="$emit('open-player')"
@open-pdf="$emit('open-pdf')"
/>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import type { AxisKey } from '~/composables/useHomeData'
import type { OiseauPlace } from '~/utils/oiseauPose'
defineEmits<{
'open-player': []
'open-pdf': []
}>()
const { hero, axes, lpk, bouquet, evenement, book, format, gratewizard, consoleLabels, toolboxTitle } = await useHomeData()
const heading = computed<string[]>(() => hero.value.heading ?? [])
// « Autonomie numérique, économique, citoyenne. » — each axis word in its own hue
const AXIS_WORDS: Record<string, string> = {
numérique: '--axis-num',
économique: '--axis-eco',
citoyenne: '--axis-cit',
}
const axesLine = computed(() =>
(heading.value[3] ?? '')
.split(/(numérique|économique|citoyenne)/)
.filter(Boolean)
.map(text => ({ text, hue: AXIS_WORDS[text] })))
const active = ref<AxisKey>('numerique')
// The governance crew stands in the empty space under the citoyenne column of the toolbox
const toolboxOiseaux: Partial<Record<AxisKey, OiseauPlace[]>> = {
politique: [
{ nom: 'capitaine', pose: 'libre', left: 'calc(34% - 75px)', bottom: '-190px', w: 150, op: 0.24 },
{ nom: 'matelot', pose: 'libre', left: 'calc(80% - 40px)', bottom: '-300px', w: 80, op: 0.26, retourne: true },
],
}
</script>
<style scoped>
.va-hero {
position: relative;
overflow: hidden;
padding: clamp(2.5rem, 6vw, 5rem) 1rem clamp(2.5rem, 5vw, 4rem);
}
.va-hero-grid {
position: relative;
z-index: 1;
display: grid;
gap: 2.5rem;
align-items: center;
}
@media (min-width: 1024px) {
.va-hero-grid {
grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
gap: 4rem;
}
}
.va-h1 {
margin: 0;
display: flex;
flex-direction: column;
font-family: var(--font-display);
letter-spacing: -0.035em;
line-height: 0.98;
}
.va-h1-a {
font-weight: 800;
font-size: clamp(2.4rem, 6.4vw, 4.6rem);
color: hsl(var(--color-text));
}
.va-h1-b {
margin-top: 0.3rem;
font-weight: 400;
font-size: clamp(1.6rem, 3.8vw, 2.7rem);
letter-spacing: -0.025em;
color: hsl(var(--color-text) / 0.55);
}
.va-axes {
margin: 1.75rem 0 0;
font-family: var(--font-display);
font-weight: 800;
font-size: clamp(1.3rem, 2.6vw, 1.85rem);
letter-spacing: -0.025em;
line-height: 1.15;
color: hsl(var(--color-text));
}
.va-axes-word {
color: hsl(var(--hue));
}
.va-means {
margin: 0.35rem 0 0;
font-family: var(--font-display);
font-style: italic;
font-size: 1.05rem;
color: hsl(var(--color-text) / 0.6);
}
.va-approach {
margin: 1.75rem 0 0;
max-width: 26rem;
font-size: 1rem;
line-height: 1.5;
color: hsl(var(--color-text) / 0.8);
}
.va-approach::after {
content: ' ↓';
color: hsl(var(--color-primary));
}
@media (min-width: 1024px) {
.va-approach::after { content: ' →'; }
}
.va-console-scene {
position: relative;
isolation: isolate;
}
.va-console-title {
position: relative;
margin: 0 0 0.75rem;
font-family: var(--font-display);
font-weight: 700;
font-size: 1.1rem;
color: hsl(var(--color-accent));
}
.va-band {
padding: clamp(2.5rem, 6vw, 4.5rem) 1rem;
background: hsl(var(--color-surface) / 0.55);
}
.va-section {
padding: clamp(3rem, 7vw, 5.5rem) 1rem 0;
}
.va-h2 {
margin: 0 0 1.5rem;
font-family: var(--font-display);
font-weight: 800;
font-size: clamp(1.75rem, 4.2vw, 2.75rem);
letter-spacing: -0.03em;
line-height: 1.05;
color: hsl(var(--color-text));
}
</style>