diff --git a/app/app.config.ts b/app/app.config.ts index f899a6e..4cab6a7 100644 --- a/app/app.config.ts +++ b/app/app.config.ts @@ -21,9 +21,9 @@ export default defineAppConfig({ }, }, libredecision: { - url: import.meta.dev ? 'http://localhost:3002' : 'https://decision.librodrome.org', + url: 'https://decision.librodrome.org', }, sejeteral0: { - url: import.meta.dev ? 'http://localhost:3009' : 'https://collectivites.librodrome.org', + url: 'https://collectivites.librodrome.org', }, }) diff --git a/app/assets/css/main.css b/app/assets/css/main.css index c20a663..fb2a669 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -16,7 +16,7 @@ --sidebar-width: 280px; --font-display: 'Bricolage Grotesque', system-ui, sans-serif; - --font-sans: 'Atkinson Hyperlegible', system-ui, sans-serif; + --font-sans: 'Public Sans', system-ui, sans-serif; --font-logo: 'Syne', sans-serif; /* One hue per axis — overridden by each palette (stores/palette.ts) */ @@ -29,6 +29,13 @@ --ease-in-out-expo: cubic-bezier(0.87, 0, 0.13, 1); } +/* Fader level of the home console — registered so it can transition smoothly */ +@property --level { + syntax: ''; + inherits: true; + initial-value: 0; +} + *, *::before, *::after { diff --git a/app/components/book/BookPlayer.vue b/app/components/book/BookPlayer.vue index 5ac31a5..3e8cf4e 100644 --- a/app/components/book/BookPlayer.vue +++ b/app/components/book/BookPlayer.vue @@ -378,6 +378,15 @@ function onTouchEnd(e: TouchEvent) { } // ── Lifecycle ── +// While the reader is open, the persistent mini player (above it) lifts up +// so it does not cover the reader navigation. +if (import.meta.client) { + watch(isOpen, (open) => { + document.documentElement.classList.toggle('book-player-open', open) + }, { immediate: true }) + onUnmounted(() => document.documentElement.classList.remove('book-player-open')) +} + watch(isOpen, async (open) => { if (open) { showSommaire.value = false diff --git a/app/components/home/AxisBlock.vue b/app/components/home/AxisBlock.vue deleted file mode 100644 index a235edc..0000000 --- a/app/components/home/AxisBlock.vue +++ /dev/null @@ -1,379 +0,0 @@ - - - - - diff --git a/app/components/home/AxisGrid.vue b/app/components/home/AxisGrid.vue deleted file mode 100644 index 92ea63b..0000000 --- a/app/components/home/AxisGrid.vue +++ /dev/null @@ -1,237 +0,0 @@ - - - - - diff --git a/app/components/home/BookSection.vue b/app/components/home/BookSection.vue index 5ebe77c..ac835ae 100644 --- a/app/components/home/BookSection.vue +++ b/app/components/home/BookSection.vue @@ -89,9 +89,9 @@ const titleLine2 = computed(() => titleParts.value[1]) .book-cover-3d { width: 100%; max-width: 360px; - aspect-ratio: 3 / 4; - background-size: 200% auto; - background-position: right center; + aspect-ratio: 1756 / 2480; + background-size: cover; + background-position: center; background-repeat: no-repeat; border-radius: 0.75rem; overflow: hidden; diff --git a/app/components/home/HeroSection.vue b/app/components/home/HeroSection.vue deleted file mode 100644 index 99fcb82..0000000 --- a/app/components/home/HeroSection.vue +++ /dev/null @@ -1,120 +0,0 @@ - - - - - diff --git a/app/components/home/HomeConsole.vue b/app/components/home/HomeConsole.vue index 00574f4..d74fba4 100644 --- a/app/components/home/HomeConsole.vue +++ b/app/components/home/HomeConsole.vue @@ -1,17 +1,25 @@ + + {{ action.note }} + @@ -113,16 +116,15 @@ a.tool-name:hover { color: hsl(var(--hue)); } -.tool-state { +.tool-status { margin-left: 0.4rem; - font-family: var(--font-mono); - font-size: 0.64rem; - color: hsl(var(--color-text) / 0.5); - white-space: nowrap; } -.tool-state::before { - content: '◌ '; +.tool-note { + align-self: center; + font-family: var(--font-mono); + font-size: 0.66rem; + color: hsl(var(--axis-cit)); } .tool-desc { diff --git a/app/components/home/HomeToolbox.vue b/app/components/home/HomeToolbox.vue index f24a9f9..cc67fa5 100644 --- a/app/components/home/HomeToolbox.vue +++ b/app/components/home/HomeToolbox.vue @@ -23,14 +23,14 @@ - + - {{ lpk.name }} {{ lpk.fullName }} — {{ lpk.text }} + {{ lpk.name }} {{ lpk.text }} {{ s.name }} @@ -65,7 +65,7 @@ import type { HomeAxis } from '~/composables/useHomeData' withDefaults(defineProps<{ axes: HomeAxis[] - lpk?: { name: string, fullName: string, text: string, to: string } + lpk?: { name: string, text: string, to: string } bouquet?: { title: string, inService: { name?: string }[], stacks: unknown[] } | null gratewizard?: { title: string, subtitle: string } showPromise?: boolean @@ -153,7 +153,7 @@ function onAction(id: string) { gap: 0.5rem; } -/* LPK */ +/* LaPlanK */ .toolbox-lpk { display: flex; flex-direction: column; diff --git a/app/components/home/HomeVariantEtabli.vue b/app/components/home/HomeVariantEtabli.vue deleted file mode 100644 index 34cd621..0000000 --- a/app/components/home/HomeVariantEtabli.vue +++ /dev/null @@ -1,492 +0,0 @@ - - - - - diff --git a/app/components/home/HomeVariantParcours.vue b/app/components/home/HomeVariantParcours.vue deleted file mode 100644 index d59dff9..0000000 --- a/app/components/home/HomeVariantParcours.vue +++ /dev/null @@ -1,321 +0,0 @@ - - - - - diff --git a/app/components/home/HomeVariantSwitch.vue b/app/components/home/HomeVariantSwitch.vue deleted file mode 100644 index 6d0b85b..0000000 --- a/app/components/home/HomeVariantSwitch.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - - - diff --git a/app/components/home/TypewriterText.vue b/app/components/home/TypewriterText.vue deleted file mode 100644 index 49e82ca..0000000 --- a/app/components/home/TypewriterText.vue +++ /dev/null @@ -1,279 +0,0 @@ - - - - - diff --git a/app/components/layout/TheHeader.vue b/app/components/layout/TheHeader.vue index e2ddaf1..0742f6d 100644 --- a/app/components/layout/TheHeader.vue +++ b/app/components/layout/TheHeader.vue @@ -3,22 +3,7 @@
- + {{ site?.identity.name }} @@ -88,9 +73,19 @@ const AXIS_HUES = ['--axis-num', '--axis-eco', '--axis-cit'] } .logo-icon { - width: 1.6rem; - height: 2rem; + width: auto; + height: 2.1rem; flex-shrink: 0; + transform: rotate(-8deg); + transition: transform 0.2s ease; +} + +.logo-link:hover .logo-icon { + transform: rotate(0deg) scale(1.08); +} + +@media (prefers-reduced-motion: reduce) { + .logo-icon { transition: none; } } .logo-text { diff --git a/app/components/player/PlayerPersistent.vue b/app/components/player/PlayerPersistent.vue index 1d8acb1..77e9602 100644 --- a/app/components/player/PlayerPersistent.vue +++ b/app/components/player/PlayerPersistent.vue @@ -179,6 +179,7 @@ onClickOutside(widgetRef, () => { .mini-player { position: fixed; bottom: 1rem; + transition: bottom 0.3s ease; right: max(1rem, calc((100vw - 80rem) / 2)); z-index: 70; display: flex; @@ -186,6 +187,11 @@ onClickOutside(widgetRef, () => { align-items: flex-end; } +/* Book player open: stay above its navigation bar */ +:global(html.book-player-open .mini-player) { + bottom: 5.5rem; +} + /* ═══════════════════════════════════════ PILL ═══════════════════════════════════════ */ diff --git a/app/components/ui/SectionSign.vue b/app/components/ui/SectionSign.vue new file mode 100644 index 0000000..a8f0302 --- /dev/null +++ b/app/components/ui/SectionSign.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/components/ui/StatusBadge.vue b/app/components/ui/StatusBadge.vue new file mode 100644 index 0000000..f205656 --- /dev/null +++ b/app/components/ui/StatusBadge.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/app/composables/useAudioPlayer.ts b/app/composables/useAudioPlayer.ts index f4f455b..4a9ed53 100644 --- a/app/composables/useAudioPlayer.ts +++ b/app/composables/useAudioPlayer.ts @@ -71,11 +71,9 @@ export function useAudioPlayer() { store.setSong(song) firedMilestones.clear() - // Try OGG first, fall back to MP3 - const oggPath = song.file.replace(/\.mp3$/, '.ogg') - const canOgg = el.canPlayType('audio/ogg; codecs=vorbis') - - el.src = canOgg ? oggPath : song.file + // Only MP3 files are published (no .ogg on disk nor in production): + // asking for OGG first cost a 404 and a delay on every track. + el.src = song.file el.volume = store.volume try { @@ -84,20 +82,8 @@ export function useAudioPlayer() { startTimeUpdate() trackAudioPlay(song.id, song.title) } - catch { - // If OGG failed, try MP3 - if (el.src !== song.file) { - el.src = song.file - try { - await el.play() - store.play() - startTimeUpdate() - trackAudioPlay(song.id, song.title) - } - catch (err) { - console.error('Playback failed:', err) - } - } + catch (err) { + console.error('Playback failed:', err) } } diff --git a/app/composables/useHomeData.ts b/app/composables/useHomeData.ts index 9c23c11..cabc236 100644 --- a/app/composables/useHomeData.ts +++ b/app/composables/useHomeData.ts @@ -13,6 +13,8 @@ export interface HomeAction { secondary?: boolean to?: string href?: string + /** Short status line shown under the button (e.g. the v1 in production) */ + note?: string } export interface HomeTool { @@ -21,6 +23,9 @@ export interface HomeTool { to?: string href?: string gestation?: boolean + /** « En production », « En développement »… — wins over `gestation` */ + status?: string + since?: string icon?: string presentation?: { title: string, text: string } actions?: HomeAction[] @@ -86,9 +91,9 @@ export async function useHomeData() { }) const lpk = computed(() => (site.value as any)?.lpk as - { name: string, fullName: string, text: string, role: string, to: string } | undefined) + { name: string, text: string, role: string, to: string } | undefined) - /** Bouquet sweethomeCloud, flattened — the stacks served by LPK */ + /** Bouquet sweetHome, flattened — the stacks served by LaPlanK */ const bouquet = computed(() => { const section = ((cloud.value as any)?.sections ?? []).find((s: any) => s.type === 'territoire') const b = section?.bouquet @@ -139,6 +144,8 @@ export async function useHomeData() { evenement, book: computed(() => (home.value as any)?.book), format: computed(() => (home.value as any)?.format as { title: string, text: string } | undefined), + toolboxTitle: computed(() => (home.value as any)?.toolbox?.title as string | undefined), + consoleLabels: computed(() => (home.value as any)?.console as { prefix: string, top: string, bottom: string } | undefined), gratewizard: computed(() => (home.value as any)?.gratewizard), } } diff --git a/app/composables/useSiteContent.ts b/app/composables/useSiteContent.ts index 40cd199..4416fbe 100644 --- a/app/composables/useSiteContent.ts +++ b/app/composables/useSiteContent.ts @@ -16,7 +16,6 @@ interface SiteContent { } lpk?: { name: string - fullName: string text: string role: string to: string diff --git a/app/pages/citoyenne/[slug].vue b/app/pages/citoyenne/[slug].vue index 636d00d..62b8d9e 100644 --- a/app/pages/citoyenne/[slug].vue +++ b/app/pages/citoyenne/[slug].vue @@ -86,10 +86,7 @@

{{ content.project.text }}

- -
- En gestation - +
diff --git a/app/pages/citoyenne/index.vue b/app/pages/citoyenne/index.vue index 9769066..ba23bca 100644 --- a/app/pages/citoyenne/index.vue +++ b/app/pages/citoyenne/index.vue @@ -352,6 +352,7 @@

Décision collective

+

Se donner les moyens de la décision collective. @@ -376,10 +377,7 @@

Tarifs de l'eau

- -
- En gestation - +

Application pour obtenir justice sociale et incitation dynamique à la réduction. @@ -404,6 +402,10 @@ definePageMeta({ }) const { data: content } = await usePageContent('citoyenne') +const statusOf = (id: string) => { + const item = ((content.value as any)?.items ?? []).find((i: any) => i.id === id) ?? {} + return { status: item.status, since: item.since, gestation: item.gestation } +} const appConfig = useAppConfig() const decisionUrl = (appConfig.libredecision as { url: string })?.url ?? '#' @@ -449,6 +451,7 @@ useSeoPage({ .item-header { display: flex; + flex-wrap: wrap; align-items: center; gap: 0.75rem; } diff --git a/app/pages/economique/index.vue b/app/pages/economique/index.vue index 819ef1a..b1de775 100644 --- a/app/pages/economique/index.vue +++ b/app/pages/economique/index.vue @@ -396,6 +396,7 @@

Monnaie libre

+

La Ğ1 (June) : une monnaie co-créée par ses membres, sans dette ni intérêt. Le dividende universel comme base. @@ -424,10 +425,7 @@

Productions collectives

- -
- En gestation - +

Une plateforme pour faciliter la création d'équipes et la réalisation de productions à l'échelle des bassins de vie. Passer la seconde. @@ -451,6 +449,10 @@ definePageMeta({ }) const { data: content } = await usePageContent('economique') +const statusOf = (id: string) => { + const item = ((content.value as any)?.items ?? []).find((i: any) => i.id === id) ?? {} + return { status: item.status, since: item.since, gestation: item.gestation } +} useSeoPage({ title: content.value?.meta?.title ?? 'Autonomie économique', @@ -484,6 +486,7 @@ const showPdfReader = ref(false) .item-header { display: flex; + flex-wrap: wrap; align-items: center; gap: 0.75rem; } diff --git a/app/pages/economique/monnaie-libre.vue b/app/pages/economique/monnaie-libre.vue index 64cabff..de52be7 100644 --- a/app/pages/economique/monnaie-libre.vue +++ b/app/pages/economique/monnaie-libre.vue @@ -17,6 +17,7 @@

{{ content?.description }}

+ diff --git a/app/pages/economique/productions-collectives.vue b/app/pages/economique/productions-collectives.vue index ebe62e6..c3b8932 100644 --- a/app/pages/economique/productions-collectives.vue +++ b/app/pages/economique/productions-collectives.vue @@ -18,10 +18,9 @@ {{ content?.description }}

- -
- En gestation - +
+ +
diff --git a/app/pages/evenement.vue b/app/pages/evenement.vue index 641c063..ba82940 100644 --- a/app/pages/evenement.vue +++ b/app/pages/evenement.vue @@ -332,20 +332,16 @@

{{ content?.kicker }}

{{ content?.title }}

+

+ {{ evtContent.format }} +

{{ evtContent.subtitle }}

@@ -447,6 +443,14 @@ useSeoPage({