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>
133 lines
3.5 KiB
Vue
133 lines
3.5 KiB
Vue
<template>
|
|
<header class="mb-8">
|
|
<div class="mb-2 flex items-center gap-2">
|
|
<span class="font-mono text-sm text-primary/70">
|
|
Chapitre {{ order }}
|
|
</span>
|
|
<span v-if="readingTime" class="text-xs text-white/30">
|
|
· {{ readingTime }}
|
|
</span>
|
|
</div>
|
|
<h1 class="chapter-title relative font-display font-bold leading-tight tracking-tight text-white">
|
|
{{ title }}
|
|
<!-- The calligrapher in the left margin, feet on the title's rule (rule e) -->
|
|
<UiOiseauPose nom="calligraphe" pose="marge-g" ecart="40px" :w="112" />
|
|
</h1>
|
|
<p v-if="description" class="mt-3 text-lg text-white/60">
|
|
{{ description }}
|
|
</p>
|
|
|
|
<!-- Songs + PDF actions row. The box maker in the right margin, feet at the bottom of the
|
|
buttons (every chapter has its PDF page) -->
|
|
<div class="relative mt-4 flex flex-wrap items-center gap-2">
|
|
<UiOiseauPose nom="cartonnier" pose="marge-d" ecart="40px" :w="76" retourne />
|
|
<!-- Associated songs badges -->
|
|
<button
|
|
v-for="song in songs"
|
|
:key="song.id"
|
|
class="song-badge-btn"
|
|
@click="playSong(song)"
|
|
>
|
|
<div class="i-lucide-music h-3 w-3" />
|
|
{{ song.title }}
|
|
</button>
|
|
|
|
<!-- PDF button -->
|
|
<button v-if="pdfPage" class="pdf-btn" @click="showPdf = true">
|
|
<div class="i-lucide-book-open h-3.5 w-3.5" />
|
|
<span>Lire dans le PDF</span>
|
|
<span class="pdf-page-badge">p.{{ pdfPage }}</span>
|
|
</button>
|
|
</div>
|
|
|
|
<LazyBookPdfReader v-if="showPdf" v-model="showPdf" :page="pdfPage" />
|
|
</header>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Song } from '~/types/song'
|
|
|
|
const props = defineProps<{
|
|
title: string
|
|
description?: string
|
|
order: number
|
|
readingTime?: string
|
|
chapterSlug: string
|
|
}>()
|
|
|
|
const bookData = useBookData()
|
|
const { loadAndPlay } = useAudioPlayer()
|
|
|
|
bookData.init()
|
|
|
|
const songs = computed(() => bookData.getChapterSongs(props.chapterSlug))
|
|
const pdfPage = computed(() => bookData.getChapterPage(props.chapterSlug))
|
|
|
|
const showPdf = ref(false)
|
|
|
|
function playSong(song: Song) {
|
|
loadAndPlay(song)
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.chapter-title {
|
|
font-size: clamp(2rem, 5vw, 2.75rem);
|
|
padding-bottom: 0.75rem;
|
|
border-bottom: 2px solid hsl(var(--color-primary) / 0.4);
|
|
}
|
|
|
|
.song-badge-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.375rem;
|
|
border-radius: 9999px;
|
|
padding: 0.375rem 0.875rem;
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
background: hsl(var(--color-primary) / 0.12);
|
|
color: hsl(var(--color-primary) / 0.85);
|
|
border: 1px solid hsl(var(--color-primary) / 0.25);
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.song-badge-btn:hover {
|
|
background: hsl(var(--color-primary) / 0.2);
|
|
border-color: hsl(var(--color-primary) / 0.4);
|
|
box-shadow: 0 2px 8px hsl(var(--color-primary) / 0.15);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.pdf-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
border-radius: 0.5rem;
|
|
background: hsl(0 0% 96%);
|
|
color: hsl(0 0% 15%);
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
border: 1px solid hsl(0 0% 88%);
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.pdf-btn:hover {
|
|
background: white;
|
|
box-shadow: 0 2px 12px hsl(0 0% 100% / 0.25);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.pdf-page-badge {
|
|
font-family: var(--font-mono, monospace);
|
|
font-size: 0.7rem;
|
|
font-weight: 500;
|
|
padding: 0.1rem 0.4rem;
|
|
border-radius: 0.25rem;
|
|
background: hsl(0 0% 88%);
|
|
color: hsl(0 0% 35%);
|
|
}
|
|
</style>
|