This commit is contained in:
2026-05-20 00:45:23 +02:00
parent fb6a0c7968
commit 107093f7bb
16 changed files with 866 additions and 22 deletions

View File

@@ -111,7 +111,7 @@
</SectionContent>
<SquareCardBlocTextList >
<SquareCardBlocText
v-for="actuscard in actuscards"
v-for="actuscard in homeActuscards"
:key="actuscard.id"
:id="actuscard.id"
:imgSrc="actuscard.imgSrc"
@@ -331,17 +331,55 @@
description: ``,
url:"/mediation/petite-enfance",
},
{
id: '4',
imgSrc: '/contenus/pablo_gonzalez.jpg',
imgAlt: "Pablo González, nouveau directeur musical pour la saison 27.28",
title: "Pablo González, nouveau directeur musical pour la saison 27.28",
description: ``,
url:"",
},
])
const { items: actualitesAccueilItems } = useStrapi(
"/api/__strapi__/actualites",
{
locale: "fr-FR",
sort: "date_actu:desc",
fetchAll: true,
filters: {
accueil_actu: {
$eq: true,
},
},
populate: {
image_illustration_actu: true,
},
}
)
const actualitesAccueilCards = computed(() => {
return actualitesAccueilItems.value.map((actu) => {
const image = normalizeStrapiMedia(actu.image_illustration_actu)
return {
id: `actualite-${actu.id || actu.documentId || actu.slug_actu}`,
imgSrc: image?.url || "",
imgAlt: image?.alternativeText || actu.titre_actu || "",
title: actu.titre_actu || "",
description: actu.sous_titre_actu || "",
url: actu.slug_actu ? `/orchestre/actus?actu=${actu.slug_actu}` : "/orchestre/actus",
}
})
})
const homeActuscards = computed(() => [
...actuscards.value,
...actualitesAccueilCards.value,
])
function normalizeStrapiMedia(media) {
if (!media?.url) return null
return {
id: media.id || media.documentId || media.url,
url: media.url,
alternativeText: media.alternativeText || media.caption || media.name || "",
}
}
//--------------------
// DONNÉES POUR ONDIF MAG
//--------------------

View File

@@ -128,7 +128,7 @@
nom="Vanessa Gasztowtt"
poste="Responsable de laction éducative et culturelle
et de la programmation jeune public"
numero="01 41 79 03 43"
numero=""
mail="vanessa.gasztowtt@orchestre-ile.com"
adresse=""
/>

View File

@@ -112,7 +112,7 @@
nom="Vanessa Gasztowtt"
poste="Responsable de laction éducative et culturelle
et de la programmation jeune public"
numero="01 41 79 03 43"
numero=""
mail="vanessa.gasztowtt@orchestre-ile.com"
adresse=""
/>

View File

@@ -112,7 +112,7 @@
nom="Vanessa Gasztowtt"
poste="Responsable de laction éducative et culturelle
et de la programmation jeune public"
numero="01 41 79 03 43"
numero=""
mail="vanessa.gasztowtt@orchestre-ile.com"
adresse=""
/>

View File

@@ -112,7 +112,7 @@
nom="Vanessa Gasztowtt"
poste="Responsable de laction éducative et culturelle
et de la programmation jeune public"
numero="01 41 79 03 43"
numero=""
mail="vanessa.gasztowtt@orchestre-ile.com"
adresse=""
/>

View File

@@ -122,7 +122,7 @@
nom="Vanessa Gasztowtt"
poste="Responsable de laction éducative et culturelle
et de la programmation jeune public"
numero="01 41 79 03 43"
numero=""
mail="vanessa.gasztowtt@orchestre-ile.com"
adresse=""
/>

View File

@@ -112,7 +112,7 @@
nom="Vanessa Gasztowtt"
poste="Responsable de laction éducative et culturelle
et de la programmation jeune public"
numero="01 41 79 03 43"
numero=""
mail="vanessa.gasztowtt@orchestre-ile.com"
adresse=""
/>

View File

@@ -0,0 +1,182 @@
<template>
<div class="actus--page">
<!-- ================== -->
<!-- FILS D'ARIANE -->
<!-- ================== -->
<PageSection tone="" content-size="default" class="breadcrum_wp">
<Breadcrumb/>
</PageSection>
<!-- ================== -->
<!-- EN-TêTE -->
<!-- ================== -->
<PageSection padded_size="md" position="relative" overflow="hidden" class="">
<SectionContent>
<SectionTitle tone="" pad="xs">
ACTUALITÉS
</SectionTitle>
</SectionContent>
</PageSection>
<!-- ================== -->
<!-- LISTE DES ACTUS -->
<!-- ================== -->
<PageSection padded_size="md" position="relative" overflow="hidden" class="">
<SectionContent>
<div class="grid_3">
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
<article class="card">
<div class="card--img">
<DsMedia :src="imgSrc" :alt="imgAlt" ratio="square" />
</div>
<div class="card--content">
<h2>Titre</h2>
<p>Description</p>
</div>
</article>
</div>
</SectionContent>
</PageSection>
</div>
</template>
<script setup>
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
import DsText from '@root/design-system/primitives/DsText.vue'
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
import { computed } from 'vue'
// ======================================
// RÉCUPÉRATION DES DONNÉES DANS STRAPI
// ======================================
// ======================================
// PRÉPARATION DES DONNÉES POUR AFFICHAGE DANS LA PAGE
// ======================================
const imgSrc= '/contenus/pablo_gonzalez.jpg'
</script>
<style lang="scss">
// =======================
// SPÉCIFIQUE À CETTE PAGE
// =======================
.actus--page {
.grid_3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 4%;
}
.card {
display: flex;
background: white;
&--content {
background: #e5e5e5;
}
}
.fiche_description {
display: flex;
justify-content: center;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
> * {
max-width: 640px;
display: flex;
flex-direction: column;
}
}
.strapi-blocks {
h2 {
color: var(--c-bleu);
}
}
}
/* ============================ */
/* GALERIES */
/* ============================ */
</style>

View File

@@ -0,0 +1,614 @@
<template>
<div class="actus--page">
<!-- ================== -->
<!-- FILS D'ARIANE -->
<!-- ================== -->
<PageSection tone="" content-size="default" class="breadcrum_wp">
<Breadcrumb/>
</PageSection>
<!-- ================== -->
<!-- EN-TêTE -->
<!-- ================== -->
<PageSection padded_size="" position="relative" overflow="hidden" class="">
<SectionContent>
<SectionTitle tone="" pad="xs">
ACTUALITÉS
</SectionTitle>
</SectionContent>
</PageSection>
<div ref="actusMainZone" class="actus-main-zone">
<!-- ================== -->
<!-- ACTUS FOCUS -->
<!-- ================== -->
<PageSection
v-if="focusActu"
padded_size="md"
position="relative"
overflow="hidden"
class=""
>
<SectionContent>
<div class="card_focus">
<article class="grid_3">
<div class="card--img">
<DsMedia :src="getActuCoverSrc(focusActu)" :alt="getActuCoverAlt(focusActu)" ratio="square" />
</div>
<div class="card_focus--content card_focus--titre">
<h2>
<NuxtLink
:to="{ path: '/orchestre/actus', query: { actu: focusActu.slug } }"
class="card--title-link"
>
<SectionTitle tone="" pad="" class="card--title-link">
{{ focusActu.title }}
</SectionTitle>
</NuxtLink>
</h2>
</div>
<div class="card_focus--content card_focus--text">
<DsText v-if="focusActu.subtitle" as="p" tone="default" :clamp="3" class="square-card__description">
{{ focusActu.subtitle }}
</DsText>
</div>
</article>
</div>
</SectionContent>
</PageSection>
<!-- ================== -->
<!-- LISTE DES ACTUS -->
<!-- ================== -->
<PageSection padded_size="md" position="relative" overflow="hidden" class="">
<SectionContent>
<div class="grid_3">
<article
v-for="actu in listedActus"
:key="actu.slug"
class="card"
>
<div class="card--img">
<DsMedia :src="getActuCoverSrc(actu)" :alt="getActuCoverAlt(actu)" ratio="square" />
</div>
<div class="card--content">
<h2>
<NuxtLink
:to="{ path: '/orchestre/actus', query: { actu: actu.slug } }"
class="card--title-link"
>
<DsHeading as="h5" tone="default" class="card--title-link">
{{ actu.title }}
</DsHeading>
</NuxtLink>
</h2>
<DsText as="p" tone="default" :clamp="3" class="">
{{ actu.subtitle }}
</DsText>
</div>
</article>
</div>
</SectionContent>
</PageSection>
<PageSection
v-if="selectedActu"
padded_size=""
:content="false"
class="actus-overlay-section"
@click="closeActuOverlay"
>
<aside class="actus-overlay" aria-label="Fiche actualité" @click.stop>
<NuxtLink
:to="{ path: '/orchestre/actus' }"
class="actus-overlay--close"
aria-label="Fermer la fiche actualité"
>
<svg class="actus-overlay--close-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M3 3h18v18H3V3Zm4.4 5.8 3.2 3.2-3.2 3.2 1.4 1.4 3.2-3.2 3.2 3.2 1.4-1.4-3.2-3.2 3.2-3.2-1.4-1.4-3.2 3.2-3.2-3.2-1.4 1.4Z" />
</svg>
<span class="sr-only">Fermer</span>
</NuxtLink>
<div class="actus-overlay--content">
<div class="actus-overlay--metas">
<DsText as="p" weight="bold" tone="default" class="uppercase">
{{ selectedActu.date }}
</DsText>
<DsText as="p" weight="bold" tone="default" class="uppercase">
{{ selectedActu.categorie }}
</DsText>
</div>
<DsHeading ref="actusOverlayTitle" as="h1" tone="default" class="uppercase" tabindex="-1">
{{ selectedActu.title }}
</DsHeading>
</div>
<section v-if="selectedActuImagesTop.length" class="img-gallery_wp">
<div class="img-gallery">
<DsMedia
v-for="img in selectedActuImagesTop"
:key="img.id || img.url"
:src="img.url"
:alt="img.alternativeText || selectedActu.imgAlt"
/>
</div>
</section>
<div class="actus-overlay--content">
<p v-if="selectedActu.subtitle">{{ selectedActu.subtitle }}</p>
<StrapiBlocksConvert :blocks="selectedActu.descriptionBlocks" />
</div>
<section v-if="selectedActuImagesBottom.length" class="img-gallery_wp">
<div class="img-gallery">
<DsMedia
v-for="img in selectedActuImagesBottom"
:key="img.id || img.url"
:src="img.url"
:alt="img.alternativeText || selectedActu.imgAlt"
/>
</div>
</section>
<section v-if="selectedActuVideos.length" class="youtube_wp">
<div class="youtube-list">
<div v-for="v in selectedActuVideos" :key="v.id" class="youtube-item">
<iframe
:src="v.lien_youtube"
title="Vidéo YouTube"
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
/>
</div>
</div>
</section>
<div class="actus-overlay--content">
<NuxtLink
:to="{ path: '/orchestre/actus' }"
class="actus-overlay--close actus-overlay--close-bottom"
aria-label="Fermer la fiche actualité"
>
<svg class="actus-overlay--close-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M3 3h18v18H3V3Zm4.4 5.8 3.2 3.2-3.2 3.2 1.4 1.4 3.2-3.2 3.2 3.2 1.4-1.4-3.2-3.2 3.2-3.2-1.4-1.4-3.2 3.2-3.2-3.2-1.4 1.4Z" />
</svg>
<span class="sr-only">Fermer</span>
</NuxtLink>
</div>
</aside>
</PageSection>
</div>
</div>
</template>
<script setup>
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
import DsText from '@root/design-system/primitives/DsText.vue'
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
useHead({
link: [
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com',
},
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossorigin: '',
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap',
},
],
})
// ======================================
// RÉCUPÉRATION DES DONNÉES DANS STRAPI
// ======================================
// ======================================
// PRÉPARATION DES DONNÉES POUR AFFICHAGE DANS LA PAGE
// ======================================
const route = useRoute()
const actusOverlayTitle = ref(null)
const { items: actualitesItems } = useStrapi(
"/api/__strapi__/actualites",
{
locale: "fr-FR",
sort: "date_actu:desc",
fetchAll: true,
populate: {
image_illustration_actu: true,
images_actu: true,
liens_youtube_actu: true,
},
}
)
const actus = computed(() => {
return actualitesItems.value.map(normalizeActualite).filter((actu) => actu.slug)
})
const selectedActu = computed(() => {
return actus.value.find((actu) => actu.slug === route.query.actu) || null
})
const focusActu = computed(() => {
return actus.value.find((actu) => actu.focus) || null
})
const listedActus = computed(() => {
return actus.value.filter((actu) => !actu.focus)
})
function normalizeActualite(item) {
const coverImage = normalizeStrapiMedia(item.image_illustration_actu)
const galleryImages = (Array.isArray(item.images_actu) ? item.images_actu : [])
.map(normalizeStrapiMedia)
.filter(Boolean)
return {
slug: item.slug_actu || item.slug || String(item.id || ''),
title: item.titre_actu || item.title || '',
subtitle: item.sous_titre_actu || '',
descriptionBlocks: Array.isArray(item.description_actu) ? item.description_actu : [],
date: formatActuDate(item.date_actu),
categorie: item.categorie_actu || '',
focus: Boolean(item.focus_actu),
accueil: Boolean(item.accueil_actu),
tiroir_videos: Array.isArray(item.liens_youtube_actu) ? item.liens_youtube_actu : [],
coverImage,
galleryImages,
imgAlt: coverImage?.alternativeText || '',
}
}
function normalizeStrapiMedia(media) {
if (!media?.url) return null
return {
id: media.id || media.documentId || media.url,
url: media.url,
alternativeText: media.alternativeText || media.caption || '',
}
}
function formatActuDate(date) {
if (!date) return ''
const parsedDate = new Date(date)
if (Number.isNaN(parsedDate.getTime())) return ''
return new Intl.DateTimeFormat('fr-FR', {
day: 'numeric',
month: 'long',
year: 'numeric',
}).format(parsedDate)
}
const getActuImages = (actu) => {
return Array.isArray(actu?.galleryImages) ? actu.galleryImages : []
}
const getActuCoverSrc = (actu) => {
return actu?.coverImage?.url || ''
}
const getActuCoverAlt = (actu) => {
return actu?.coverImage?.alternativeText || actu?.imgAlt || ''
}
const selectedActuImages = computed(() => {
return getActuImages(selectedActu.value)
})
const selectedActuImagesTop = computed(() => {
return selectedActuImages.value.slice(0, 2)
})
const selectedActuImagesBottom = computed(() => {
return selectedActuImages.value.slice(2)
})
const getYoutubeEmbedUrl = (url = '') => {
if (!url) return ''
try {
const parsedUrl = new URL(url)
const hostname = parsedUrl.hostname.replace(/^www\./, '')
let videoId = ''
if (hostname === 'youtu.be') {
videoId = parsedUrl.pathname.split('/').filter(Boolean)[0] || ''
}
if (hostname === 'youtube.com' || hostname === 'm.youtube.com' || hostname === 'youtube-nocookie.com') {
if (parsedUrl.pathname.startsWith('/embed/')) return url
videoId = parsedUrl.searchParams.get('v') || ''
if (!videoId && parsedUrl.pathname.startsWith('/shorts/')) {
videoId = parsedUrl.pathname.split('/').filter(Boolean)[1] || ''
}
if (!videoId && parsedUrl.pathname.startsWith('/live/')) {
videoId = parsedUrl.pathname.split('/').filter(Boolean)[1] || ''
}
}
return videoId ? `https://www.youtube-nocookie.com/embed/${videoId}` : url
} catch {
return url
}
}
const selectedActuVideos = computed(() => {
return (selectedActu.value?.tiroir_videos || [])
.map((video) => ({
...video,
lien_youtube: getYoutubeEmbedUrl(video.lien_youtube)
}))
.filter((video) => video.lien_youtube)
})
const closeActuOverlay = () => {
navigateTo({ path: '/orchestre/actus' })
}
watch(
selectedActu,
async (actu) => {
if (import.meta.client) {
document.body.style.overflow = actu ? 'hidden' : ''
}
if (!actu) return
await nextTick()
const titleElement = actusOverlayTitle.value?.$el || actusOverlayTitle.value
titleElement?.focus?.({ preventScroll: true })
},
{ immediate: true }
)
onBeforeUnmount(() => {
if (import.meta.client) {
document.body.style.overflow = ''
}
})
</script>
<style lang="scss">
// =======================
// SPÉCIFIQUE À CETTE PAGE
// =======================
.actus--page {
.actus-main-zone {
position: relative;
}
.grid_3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8%;
}
.card_focus {
.grid_3 {
gap: 0px;
}
@media (max-width: 700px) {
.grid_3 {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 500px) {
.grid_3 {
grid-template-columns: repeat(1, 1fr);
}
}
.card_focus--content {
position: relative;
width: 100%;
margin-inline: auto;
padding: 1.5rem;
background: var(--c-gris);
}
}
.card {
position: relative;
display: flex;
flex-direction: column;
background: white;
min-height: 0;
&--content {
position: relative;
width: 84%;
min-height: 200px;
margin-inline: auto;
margin-top: -35px;
@media (max-width: 700px) {
margin-top: -45px;
}
padding: 1.5rem;
background: var(--c-grisclair);
}
&--title-link {
color: inherit;
text-decoration: none;
&:hover,
&:focus-visible {
color: var(--c-bleu);
text-decoration: none;
}
}
}
.card--img {
min-height: 0; /* Crucial pour permettre au flex-item de rétrécir */
background-color: var(--c-gris);
}
.actus-overlay-section {
position: fixed;
inset: 0;
z-index: 1000;
display: flex;
justify-content: flex-end;
overflow: hidden;
background: linear-gradient(
to right,
rgb(0 0 0 / 71%) 0%,
rgb(0 0 0 / 71%) 20%,
transparent 20%,
transparent 100%
);
cursor: pointer;
}
.actus-overlay {
display: flex;
flex-direction: column;
width: 80%;
height: 100vh;
padding: 2rem;
overflow-y: auto;
background: var(--c-backgroud-brandreverse);
box-shadow: 0 0 40px rgb(0 0 0 / 18%);
cursor: auto;
&--close {
display: inline-flex;
align-items: center;
justify-content: center;
align-self: flex-end;
width: 2.5rem;
height: 2.5rem;
margin-bottom: 1.5rem;
color: inherit;
text-decoration: none;
&-icon {
width: 4rem;
height: 4rem;
fill: currentColor;
flex: 0 0 auto;
}
}
&--close-bottom {
display: inline-flex;
margin-top: 2rem;
margin-bottom: 0;
}
&--image {
max-width: 360px;
margin-bottom: 1.5rem;
}
&--content {
max-width: 680px;
}
&--metas {
display: flex;
column-gap: 25px;
padding-bottom: 10px;
}
&--date {
margin-bottom: 0.75rem;
}
}
.img-gallery {
display: grid;
grid-template-columns: repeat(2, minmax(0, 300px));
gap: 1rem;
justify-content:left;
margin-top: 10px;
padding-bottom: 0px;
}
.youtube_wp {
margin-top: 1rem;
margin-bottom: 2rem;
}
.youtube-list {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
justify-content: start;
}
.youtube-item {
max-width: 500px;
iframe {
width: 100%;
aspect-ratio: 16 / 9;
border: 0;
}
}
@media (max-width: 700px) {
.grid_3 {
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
.actus-overlay {
width: 100%;
margin-left: 0;
}
}
@media (max-width: 360px) {
.grid_3 {
grid-template-columns: 1fr;
gap: 2rem;
}
.actus-overlay {
width: 100%;
margin-left: 0;
}
.img-gallery {
grid-template-columns: 1fr;
}
}
.fiche_description {
display: flex;
justify-content: center;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
> * {
max-width: 640px;
display: flex;
flex-direction: column;
}
}
.strapi-blocks {
h2 {
color: var(--c-bleu);
}
}
}
/* ============================ */
/* GALERIES */
/* ============================ */
</style>

View File

@@ -88,7 +88,7 @@
v-if="parc_contenus?.documents?.[0]?.url"
:href="parc_contenus.documents[0].url"
:download="parc_contenus.documents[0].name || true"
class="flex items-center gap-2 px-6 py-2 max-w-[334px] bg-primary-container text-on-primary-container rounded-full font-bold text-sm hover:bg-primary-fixed"
class="flex flex-wrap items-center gap-2 px-6 py-2 max-w-[334px] bg-primary-container text-on-primary-container rounded-full font-bold text-sm hover:bg-primary-fixed"
target="_blank"
rel="noopener noreferrer"
>
@@ -418,7 +418,7 @@
<a
href="https://media.orchestre-ile.com/uploads/parc_attestation_sur_l_honneur_fd039769c5.pdf"
download="https://media.orchestre-ile.com/uploads/parc_attestation_sur_l_honneur_fd039769c5.pdf"
class="flex items-center gap-2 px-6 py-2 max-w-[334px] bg-primary-container text-on-primary-container rounded-full font-bold text-sm hover:bg-primary-fixed"
class="flex flex-wrap items-center gap-2 px-6 py-2 max-w-[334px] bg-primary-container text-on-primary-container rounded-full font-bold text-sm hover:bg-primary-fixed"
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -121,7 +121,7 @@
<!-- Logos -->
<div class="col-span-12 md:col-span-6 lg:col-span-7 bg-surface-container-highest/40 rounded-xl p-8 border border-outline-variant/20">
<div class="col-span-12 lg:col-span-7 bg-surface-container-highest/40 rounded-xl p-8 border border-outline-variant/20">
<div class="flex justify-between items-center gap-x-16 mb-8">
<h4 class="text-xl font-bold">Logos</h4>
<span class="text-xs text-on-surface-variant font-medium">LOrchestre national dÎle-de-France est financé par la Région Île-de-France et la DRAC Île-de-France.</span>
@@ -324,7 +324,7 @@
v-if="categorie.programme_categorie?.url"
:href="categorie.programme_categorie.url"
:download="categorie.programme_categorie.name || true"
class="flex items-center gap-2 px-6 py-2 bg-primary-container text-on-primary-container rounded-full font-bold text-sm hover:bg-primary-fixed transition-colors"
class="flex flex-wrap items-center gap-2 px-6 py-2 bg-primary-container text-on-primary-container rounded-full font-bold text-sm hover:bg-primary-fixed transition-colors"
target="_blank"
rel="noopener noreferrer"
>