Files
wondif_vue/app/pages/concerts/concert-[id].vue
2026-05-25 18:48:32 +02:00

1161 lines
35 KiB
Vue

<template>
<div class="concert--page">
<section v-if="pending" aria-busy="true" aria-live="polite">
<p>en cours de chargement...</p>
</section>
<template v-else>
<PageSection tone="" content-size="default" class="breadcrum_wp">
<Breadcrumb :current-label="concert?.titre_concert || ''" />
</PageSection>
<section class="fiche_concert_wp">
<div class="fiche_header_inner">
<div class="fiche_header_titres">
<div>
<DsHeading as="h1" tone="default" textcase="uppercase" class="concert-card__title">
{{ concert.titre_concert }}
</DsHeading>
</div>
<div>
<DsText as="p" size="md" tone="default" class="" v-if="concert.sous_titre_concert">
{{ concert.sous_titre_concert }}
</DsText>
</div>
</div>
<div class="fiche_header_img">
<DsMedia
v-if="illustration?.url"
:src="illustration.url"
:alt="illustration.alternativeText || concert?.titre_concert || ''"
ratio="3-4"
/>
<div v-else class="img_placeholder" aria-hidden="true" />
</div>
<div class="fiche_header_distrib_wp">
<div class="programme_list">
<template v-if="directionsOndif.length">
<div v-for="d in directionsOndif" :key="d.id" class="programme_item" >
<DsText as="p" tone="default" size="lg" spacing="space-0" class="programme_compositeur">
{{ d.postes_artiste_ondif.map((p) => p.nom_poste).join(', ') }}
</DsText>
<button type="button" class="programme_artist_button" @click="openArtistOverlay(d, 'ondif')">
<DsText as="span" tone="default" size="lg" spacing="space-0" weight="semibold" class="programme_oeuvre">
{{ d.nom_artiste_ondif }}
</DsText>
</button>
</div>
</template>
<template v-if="directionsInvite.length">
<div v-for="d in directionsInvite" :key="d.id" class="programme_item" >
<DsText as="p" tone="default" size="lg" spacing="space-0" v-if="d.postes_artiste_invite?.length" class="programme_compositeur direction">
{{ d.postes_artiste_invite.map((p) => p.nom_poste).join(', ') }}
</DsText>
<button type="button" class="programme_artist_button" @click="openArtistOverlay(d, 'invite')">
<DsText as="span" tone="default" size="lg" spacing="space-0" weight="semibold" class="programme_oeuvre">
{{ d.nom_artiste_invite }}
</DsText>
</button>
</div>
</template>
<template v-if="artistesOndif.length">
<div v-for="d in artistesOndif" :key="d.id" class="programme_item" >
<DsText as="p" tone="default" size="lg" spacing="space-0" v-if="d.postes_artiste_ondif?.length" class="programme_compositeur">
{{ d.postes_artiste_ondif.map((p) => p.nom_poste).join(', ') }}
</DsText>
<button type="button" class="programme_artist_button" @click="openArtistOverlay(d, 'ondif')">
<DsText as="span" tone="default" size="lg" spacing="space-0" weight="semibold" class="programme_oeuvre">
{{ d.nom_artiste_ondif }}
</DsText>
</button>
</div>
</template>
<template v-if="artistesInvite.length">
<div v-for="d in artistesInvite" :key="d.id" class="programme_item" >
<DsText as="p" tone="default" size="lg" spacing="space-0" v-if="d.postes_artiste_invite?.length" class="programme_compositeur">
{{ d.postes_artiste_invite.map((p) => p.nom_poste).join(', ') }}
</DsText>
<button type="button" class="programme_artist_button" @click="openArtistOverlay(d, 'invite')">
<DsText as="span" tone="default" size="lg" spacing="space-0" weight="semibold" class="programme_oeuvre">
{{ d.nom_artiste_invite }}
</DsText>
</button>
</div>
</template>
</div>
</div>
<div v-if="representations.length" class="fiche_header_representation_wp">
<div v-for="(r, i) in representations" :key="r.id || i" class="representation_item">
<div>
<DsHeading as="h6" tone="default" v-if="r.date_debut_representation">
{{ formatDateLong(r.date_debut_representation) }} <span v-if="r.date_fin_representation">- {{ formatDateLong(r.date_fin_representation) }}</span>
</DsHeading>
</div>
<div>
<DsHeading as="h5" tone="default" v-if="r.lieu_representation?.nom_lieu" class="representation_item_lieu">
{{ r.lieu_representation.nom_lieu }}
</DsHeading>
</div>
<div>
<DsText as="p" tone="default" spacing="space-0" v-if="r.lieu_representation?.adresse_lieu">
{{ r.lieu_representation.adresse_lieu }}
</DsText>
</div>
<div class="representation_item_comment_wp">
<DsText as="p" tone="default" spacing="space-0" v-if="r.commentaire_representation" class="representation_item_comment">
{{ r.commentaire_representation }}
</DsText>
</div>
<div class="representation_cta">
<a
v-if="r.lien_billetterie_representation"
:href="r.lien_billetterie_representation"
target="_blank"
rel="noopener noreferrer"
>
Réserver
</a>
</div>
</div>
</div>
<div class="fiche_header_infos">
<div>
<DsHeading as="h2" tone="invert" textcase="uppercase" class="fiche_header_infos_genre" v-if="genreLabel">
{{ genreLabel }}
</DsHeading>
</div>
<div class="programme_list">
<div v-for="(p, i) in programmes" :key="p.id || i" class="programme_item" >
<DsText as="p" tone="default" size="lg" spacing="space-0" weight="semibold" class="programme_compositeur">
{{ p.compositeur_programme }}
</DsText>
<DsText as="p" tone="default" size="lg" spacing="space-0" class="programme_oeuvre">
{{ p.oeuvre_programme }}
</DsText>
<DsText as="p" tone="default" size="lg" class="" v-if="p.piece_programme">
{{ p.piece_programme }}
</DsText>
</div>
</div>
<div v-if="concert.duree_concert">
<DsText as="p" tone="invert" weight="bold" spacing="space-0" class="">
DURÉE {{ concert.duree_concert }}
</DsText>
<DsText as="p" tone="invert" class="" v-if="concert.duree_entracte">
Entracte {{ concert.duree_entracte }}
</DsText>
</div>
<div v-if="concert.production_concert">
<DsText as="p" tone="invert" class="">
{{ concert.production_concert }}
</DsText>
</div>
</div>
</div>
</section>
<PageSection tone="" content-size="default">
<section v-if="concert.description_concert" class="description_wp">
<StrapiBlocksConvert :blocks="concert?.description_concert" />
</section>
<section v-if="imagesConcert.length" class="img-gallery_wp">
<div class="img-gallery">
<DsMedia
v-for="img in imagesConcert"
:key="img.id || img.url"
:src="img.url"
:alt="img.alternativeText || concert?.titre_concert || ''"
/>
</div>
</section>
<section v-if="youtubeEmbeds.length" class="youtube_wp">
<div class="youtube-list">
<div v-for="v in youtubeEmbeds" :key="v.id" class="youtube-item">
<iframe
:src="v.src"
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>
</PageSection>
<PageSection
v-if="selectedArtist"
padded_size=""
:content="false"
class="artist-overlay-section"
@click="closeArtistOverlay"
>
<aside class="actus-overlay artist-overlay" aria-label="Fiche artiste" @click.stop>
<button
type="button"
class="actus-overlay--close"
aria-label="Fermer la fiche artiste"
@click="closeArtistOverlay"
>
<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>
</button>
<div class="actus-overlay--content">
<div v-if="selectedArtist.postesLabel" class="actus-overlay--metas">
<DsText as="p" weight="bold" tone="default" class="uppercase">
{{ selectedArtist.postesLabel }}
</DsText>
</div>
<DsHeading ref="artistOverlayTitle" as="h1" tone="default" class="uppercase" tabindex="-1">
{{ selectedArtist.name }}
</DsHeading>
</div>
<section v-if="selectedArtist.illustration?.url" class="artist-overlay--image">
<DsMedia
:src="selectedArtist.illustration.url"
:alt="selectedArtist.illustration.alternativeText || selectedArtist.name"
ratio="3-4"
/>
</section>
<div class="actus-overlay--content">
<p v-if="selectedArtist.website">
<a :href="selectedArtist.website" target="_blank" rel="noopener noreferrer">Site internet</a>
</p>
<StrapiBlocksConvert v-if="selectedArtist.descriptionBlocks?.length" :blocks="selectedArtist.descriptionBlocks" />
</div>
<section v-if="selectedArtist.galleryImages.length" class="img-gallery_wp">
<div class="img-gallery">
<DsMedia
v-for="img in selectedArtist.galleryImages"
:key="img.id || img.url"
:src="img.url"
:alt="img.alternativeText || selectedArtist.name"
/>
</div>
</section>
<section v-if="selectedArtist.videos.length" class="youtube_wp">
<div class="youtube-list">
<div v-for="v in selectedArtist.videos" :key="v.id" class="youtube-item">
<iframe
:src="v.src"
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">
<button
type="button"
class="actus-overlay--close actus-overlay--close-bottom"
aria-label="Fermer la fiche artiste"
@click="closeArtistOverlay"
>
<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>
</button>
</div>
</aside>
</PageSection>
</template>
</div>
</template>
<script setup>
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
import { formatDateLong } from "@/utils/dateFormat.js"
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'
const route = useRoute()
const selectedArtistRequest = ref(null)
const artistOverlayTitle = ref(null)
//////////////////////////////////////////////////////////////
// RÉCUPÉRATION DU CONTENU
//////////////////////////////////////////////////////////////
const concertSlug = computed(() => String(route.params.id || ''))
const artisteOndifPopulate = {
postes_artiste_ondif: true,
image_illustration_artiste_ondif: true,
}
const artisteInvitePopulate = {
postes_artiste_invite: true,
image_illustration_artiste_invite: true,
}
const populate = {
saison_concert: true,
genre_concert: true,
type_audience_concert: true,
direction_ondif_concert: { postes_artiste_ondif: true },
direction_invite_concert: { postes_artiste_invite: true },
artistes_ondif_concert: { postes_artiste_ondif: true },
artistes_invite_concert: { postes_artiste_invite: true },
image_illustration_concert: true,
images_concert: true,
videos_concert: true,
audios_concert: true,
programme_concert: true,
representation_concert: { lieu_representation: true },
liens_youtube_concert: true,
}
const filters = computed(() => ({
slug_concert: {
$eq: concertSlug.value,
},
}))
const { concerts, pending, error } = useConcerts({
locale: 'fr-FR',
populate,
filters,
limit: 1,
upcomingOnly: false,
})
const { items: artistesOndifItems } = useStrapi(
"/api/__strapi__/artistes",
{
locale: "fr-FR",
populate: artisteOndifPopulate,
fetchAll: true,
}
)
const { items: artistesInviteItems } = useStrapi(
"/api/__strapi__/artistesinvitees",
{
locale: "fr-FR",
populate: artisteInvitePopulate,
fetchAll: true,
}
)
const selectedArtist = computed(() => {
if (!selectedArtistRequest.value) return null
const { artist, type } = selectedArtistRequest.value
return normalizeArtist(findFullArtist(artist, type) || artist, type)
})
const concert = computed(() => concerts.value?.[0] || {})
useSeoMeta({
title: () => concert.value?.titre_concert || 'Concert',
description: () => concert.value?.resume_concert || undefined,
})
const genreLabel = computed(() => {
const g = concert.value?.genre_concert
// Strapi relation classique
if (Array.isArray(g?.data)) return g.data.map(x => x?.attributes?.nom_genre).filter(Boolean).join(', ')
if (g?.data) return g.data?.attributes?.nom_genre || ''
// Si déjà normalisé/flat
if (Array.isArray(g)) return g.map(x => x?.nom_genre).filter(Boolean).join(', ')
return g?.nom_genre || ''
})
const directionsOndif = computed(() => {
const value = concert.value?.direction_ondif_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
const directionsInvite = computed(() => {
const value = concert.value?.direction_invite_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
const artistesOndif = computed(() => {
const value = concert.value?.artistes_ondif_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
const artistesInvite = computed(() => {
const value = concert.value?.artistes_invite_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
const programmes = computed(() => {
const value = concert.value?.programme_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
const representations = computed(() => {
const value = concert.value?.representation_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
const illustration = computed(() => {
const m = concert.value?.image_illustration_concert
if (!m) return null
if (m.url) return m
return null
})
const imagesConcert = computed(() => {
const value = concert.value?.images_concert
if (!value) return []
if (Array.isArray(value) && value[0]?.url) return value
return Array.isArray(value) ? value : []
})
const youtube = computed(() => {
const value = concert.value?.liens_youtube_concert
if (!value) return []
return Array.isArray(value) ? value : [value]
})
function getYoutubeId(url = '') {
try {
const u = new URL(url)
if (u.hostname.includes('youtu.be')) return u.pathname.slice(1)
if (u.pathname.startsWith('/shorts/')) return u.pathname.split('/')[2]
if (u.pathname.startsWith('/embed/')) return u.pathname.split('/')[2]
return u.searchParams.get('v')
} catch {
return null
}
}
const youtubeEmbeds = computed(() =>
youtube.value
.map((item) => {
const id = getYoutubeId(item?.lien_youtube)
if (!id) return null
return {
id: item.id || id,
src: `https://www.youtube-nocookie.com/embed/${id}?rel=0&modestbranding=1&iv_load_policy=3&playsinline=1`,
}
})
.filter(Boolean)
)
function openArtistOverlay(artist, type) {
selectedArtistRequest.value = { artist, type }
}
function closeArtistOverlay() {
selectedArtistRequest.value = null
}
function normalizeArtist(artist, type) {
const isInvite = type === 'invite'
const name = isInvite ? artist?.nom_artiste_invite : artist?.nom_artiste_ondif
const postes = extractStrapiList(isInvite ? artist?.postes_artiste_invite : artist?.postes_artiste_ondif)
const illustration = normalizeStrapiMedia(isInvite ? artist?.image_illustration_artiste_invite : artist?.image_illustration_artiste_ondif)
const galleryImages = extractStrapiList(isInvite ? artist?.images_artiste_invite : artist?.images_artiste_ondif)
.map(normalizeStrapiMedia)
.filter(Boolean)
const youtubeItems = extractStrapiList(isInvite ? artist?.liens_youtube_artiste_invite : artist?.liens_youtube_artiste_ondif)
return {
id: artist?.id || artist?.documentId || name,
type,
name: name || '',
postesLabel: postes.map((p) => p?.nom_poste).filter(Boolean).join(', '),
website: isInvite ? artist?.url_artiste_invite : artist?.url_artiste_ondif,
descriptionBlocks: isInvite ? artist?.description_artiste_invite || [] : artist?.description_artiste_ondif || [],
illustration,
galleryImages,
videos: youtubeItems
.map((item) => {
const id = getYoutubeId(item?.lien_youtube)
if (!id) return null
return {
id: item.id || id,
src: `https://www.youtube-nocookie.com/embed/${id}?rel=0&modestbranding=1&iv_load_policy=3&playsinline=1`,
}
})
.filter(Boolean),
}
}
function findFullArtist(artist, type) {
const rows = type === 'invite' ? artistesInviteItems.value : artistesOndifItems.value
const slug = type === 'invite' ? artist?.slug_artiste_invite : artist?.slug_artiste_ondif
const name = type === 'invite' ? artist?.nom_artiste_invite : artist?.nom_artiste_ondif
return rows.find((item) => {
if (artist?.id && item.id === artist.id) return true
if (slug && (type === 'invite' ? item.slug_artiste_invite : item.slug_artiste_ondif) === slug) return true
if (name && (type === 'invite' ? item.nom_artiste_invite : item.nom_artiste_ondif) === name) return true
return false
})
}
function extractStrapiList(value) {
if (!value) return []
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
if (value?.data) {
const rows = Array.isArray(value.data) ? value.data : [value.data]
return rows.map(normalizeStrapiItem).filter(Boolean)
}
if (typeof value === 'object') return [normalizeStrapiItem(value)].filter(Boolean)
return []
}
function normalizeStrapiItem(item) {
if (!item || typeof item !== 'object') return null
if (item.attributes && typeof item.attributes === 'object') {
return { id: item.id, ...item.attributes }
}
return item
}
function normalizeStrapiMedia(media) {
if (media?.data) {
const mediaItem = Array.isArray(media.data) ? media.data[0] : media.data
return normalizeStrapiMedia(mediaItem)
}
const item = normalizeStrapiItem(media)
if (!item?.url) return null
return {
id: item.id || item.documentId || item.url,
url: item.url,
alternativeText: item.alternativeText || item.caption || '',
}
}
watch(
selectedArtist,
async (artist) => {
if (import.meta.client) {
document.body.style.overflow = artist ? 'hidden' : ''
}
if (!artist) return
await nextTick()
const titleElement = artistOverlayTitle.value?.$el || artistOverlayTitle.value
titleElement?.focus?.({ preventScroll: true })
}
)
onBeforeUnmount(() => {
if (import.meta.client) {
document.body.style.overflow = ''
}
})
</script>
<style lang="scss">
.breadcrum_wp {
padding-top: 30px;
}
.fiche_concert_wp {
display: grid;
@media (min-width: 0px) and (max-width: 700px) {
grid-template-columns: 1fr;
grid-template-rows: auto auto;
padding-top: 40px;
}
@media (min-width: 700px) {
grid-template-columns: minmax(10px, 10px) 660px 0px;
grid-template-rows: 70px auto;
}
@media (min-width: 800px) {
grid-template-columns: minmax(10px, 10px) 780px minmax(10px, 10px);
grid-template-rows: 60px auto;
}
@media (min-width: 900px) {
grid-template-columns: minmax(10px, 10px) 860px minmax(10px, 10px);
grid-template-rows: 90px auto;
}
@media (min-width: 1000px) {
grid-template-columns: minmax(20px, auto) 950px minmax(10px, auto);
grid-template-rows: 90px auto;
}
@media (min-width: 1100px) {
grid-template-columns: minmax(20px, auto) 1020px minmax(20px, auto);
grid-template-rows: 90px auto;
}
@media (min-width: 1200px) {
grid-template-columns: minmax(20px, auto) 1100px minmax(20px, auto);
grid-template-rows: 90px auto;
}
@media (min-width: 1300px) {
grid-template-columns: minmax(20px, auto) 1200px minmax(20px, auto);
grid-template-rows: 90px auto;
}
@media (min-width: 1400px) {
grid-template-columns: minmax(20px, auto) 1300px minmax(20px, auto);
grid-template-rows: 90px auto;
}
@media (min-width: 1500px) {
grid-template-columns: minmax(20px, auto) 1400px minmax(20px, auto);
grid-template-rows: 90px auto;
}
.fiche_header_inner {
@media (min-width: 0px) and (max-width: 700px) {
grid-column: 1;
grid-row: 1/3;
}
@media (min-width: 700px) {
grid-column: 2;
grid-row: 1/3;
}
display: grid;
@media (min-width: 0px) and (max-width: 700px) {
grid-template-columns: 1fr;
grid-template-rows: auto auto min-content auto auto;
}
@media (min-width: 700px) {
width: 675px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 70px auto min-content auto auto;
}
@media (min-width: 800px) {
width: 780px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 60px auto min-content auto auto;
}
@media (min-width: 900px) {
width: 860px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
@media (min-width: 1000px) {
width: 950px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
@media (min-width: 1100px) {
width: 1020px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
@media (min-width: 1200px) {
width: 1100px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
@media (min-width: 1300px) {
width: 1200px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
@media (min-width: 1400px) {
width: 1300px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
@media (min-width: 1500px) {
width: 1400px;
grid-template-columns: 4fr 4fr;
grid-template-rows: 90px auto min-content auto auto;
}
}
.fiche_header_titres {
//background-color: rgba(255, 166, 0, 0.674);
@media (min-width: 0px) and (max-width: 700px) {
grid-column: 1;
grid-row: 1;
padding-bottom: 20px;
padding-left: 10px;
}
@media (min-width: 700px) {
grid-column: 1;
grid-row: 2;
}
display: grid;
align-content: start;
gap: 0.75rem;
padding-right: 10px;
padding-bottom: 10px;
h1 {
font-size: 55px;
@media (min-width: 0px) and (max-width: 700px) {
font-size: 25px;
}
@media (min-width: 700px) {
font-size: 30px;
}
@media (min-width: 800px) {
font-size: 30px;
}
@media (min-width: 900px) {
font-size: 40px;
}
@media (min-width: 1000px) {
font-size: 40px;
}
@media (min-width: 1100px) {
font-size: 40px;
}
@media (min-width: 1200px) {
font-size: 50px;
}
@media (min-width: 1300px) {
font-size: 55px;
}
@media (min-width: 1400px) {
font-size: 55px;
}
@media (min-width: 1500px) {
font-size: 55px;
}
@media (min-width: 1600px) {
font-size: 55px;
}
@media (min-width: 1700px) {
font-size: 55px;
}
@media (min-width: 1800px) {
font-size: 55px;
}
}
}
.fiche_header_img {
@media (min-width: 0px) and (max-width: 700px) {
grid-column: 1;
grid-row: 2;
}
@media (min-width: 700px) {
grid-column: 2;
grid-row: 1 / 5;
}
overflow: hidden;
.ds-media {
height: 100%;
}
}
.fiche_header_infos {
background-color: var(--c-text);
@media (min-width: 0px) and (max-width: 700px) {
grid-column: 1;
grid-row: 4;
}
@media (min-width: 700px) {
grid-column: 2;
grid-row: 5;
}
display: grid;
align-content: start;
justify-content: end;
padding-top: 20px;
padding-bottom: 20px;
padding-right: 20px;
padding-left: 10px;
width: 96%;
@media (min-width: 0px) and (max-width: 700px) {
width: 100%;
}
margin-top: -18px;
@media (min-width: 0px) and (max-width: 700px) {
gap: 7px;
margin-top: 0px;
}
@media (min-width: 700px) {
gap: 20px;
}
text-align: right;
.fiche_header_infos_genre {
font-weight: 900;
}
.programme_list {
display: flex;
flex-wrap: wrap;
column-gap: 20px;
row-gap: 20px;
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
padding-right: 20px;
}
.programme_item {
flex: 1 0 auto;
max-width: 100%;
background-color: var(--c-surface);
padding-top: 14px;
padding-right: 20px;
padding-left: 18px;
padding-bottom: 10px;
}
}
.fiche_header_distrib_wp {
background-color: var(--c-backgroud-brandreverse);
grid-column: 1;
grid-row: 3;
@media (min-width: 0px) and (max-width: 700px) {
width: 96%;
}
.programme_list {
display: flex;
flex-wrap: wrap;
column-gap: 20px;
row-gap: 20px;
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
padding-right: 20px;
}
.programme_item {
flex: 1 0 200px;
background-color: var(--c-surface);
padding-top: 14px;
padding-right: 20px;
padding-left: 18px;
padding-bottom: 10px;
}
.programme_artist_button {
display: inline;
padding: 0;
border: 0;
background: transparent;
color: inherit;
text-align: left;
cursor: pointer;
&:hover,
&:focus-visible {
text-decoration: underline;
text-underline-offset: 3px;
}
&:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
}
}
.fiche_header_representation_wp {
//background-color: aqua;
grid-column: 1;
grid-row: 5;
display: flex;
flex-wrap: wrap;
align-self: start;
column-gap: 20px;
row-gap: 20px;
padding-top: 20px;
padding-right: 20px;
padding-left: 20px;
@media (min-width: 0px) and (max-width: 700px) {
padding-left: 20px;
padding-right: 5px;
}
.representation_item {
@media (min-width: 0px) and (max-width: 500px) {
width: 100%;
}
@media (min-width: 500px) {
max-width: 215px;
}
@media (min-width: 600px) {
max-width: 262px;
}
@media (min-width: 700px) {
max-width: 300px;
}
flex: 1 1 230px;
display: grid;
border: 2px var(--c-brand_rouge) solid;
padding-top: 20px;
> * {
padding-left: 20px;
padding-right: 20px;
}
.representation_item_lieu {
font-size: 20px !important;
}
.representation_item_comment_wp {
padding-top: 5px;
}
.representation_item_comment {
background-color: lightgray;
padding: 5px;
}
}
.representation_cta {
color: var(--c-surface);
background-color: var(--c-brand_rouge);
margin-top: 15px;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
a {
font-family: var(--font-roboto);
font-weight: 600;
font-size: 18px;
}
}
}
}
.artist-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;
padding: 0;
border: 0;
background: transparent;
color: inherit;
text-decoration: none;
cursor: pointer;
&-icon {
width: 4rem;
height: 4rem;
fill: currentColor;
flex: 0 0 auto;
}
}
&--close-bottom {
display: inline-flex;
margin-top: 2rem;
margin-bottom: 0;
}
&--content {
max-width: 680px;
}
&--content h1:focus {
outline: none;
}
&--metas {
display: flex;
column-gap: 25px;
padding-bottom: 10px;
}
}
.artist-overlay {
&--image {
max-width: 320px;
margin-top: 1rem;
margin-bottom: 1.5rem;
}
.img-gallery {
grid-template-columns: repeat(2, minmax(0, 300px));
justify-content: left;
}
}
@media (max-width: 700px) {
.actus-overlay {
width: 100%;
margin-left: 0;
}
}
/* ============================ */
/* GALERIES */
/* ============================ */
.img-gallery_wp {
padding-bottom: 50px;
}
.img-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 502px));
gap: 1rem;
justify-content: center;
margin-top: 10px;
width: 100%;
}
.img-gallery > * {
display: block;
width: 100%;
overflow: hidden;
border-radius: 5px;
}
.img-gallery :deep(.ds-media) {
display: block;
width: 100%;
height: auto;
background: transparent;
}
.img-gallery :deep(.ds-media__img) {
display: block;
width: 100%;
max-width: 100%;
height: auto;
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.img-gallery :deep(.ds-media__img:hover) {
transform: scale(1.02);
}
@media (max-width: 1100px) {
.img-gallery {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
}
@media (max-width: 820px) {
.img-gallery {
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.75rem;
}
}
@media (max-width: 520px) {
.img-gallery {
grid-template-columns: 1fr;
}
}
.youtube_wp {
margin-bottom: 70px;
}
.youtube-list {
display: grid;
justify-content: center;
/* flex-wrap: wrap; */
gap: 20px;
}
.youtube-item {
@media (min-width: 0px) and (max-width: 300px) {
min-width: 290px;
}
@media (min-width: 300px) {
min-width: 298px;
}
@media (min-width: 400px) {
min-width: 398px;
}
@media (min-width: 500px) {
min-width: 480px;
}
@media (min-width: 600px) {
min-width: 580px;
}
@media (min-width: 700px) {
min-width: 670px;
}
}
.youtube-item iframe {
aspect-ratio: 16 / 9;
border: 0;
}
// =======================
// SPÉCIFIQUE À CETTE PAGE
// =======================
/* ============================ */
/* DESCRIPTION */
/* ============================ */
.concert--page {
margin-bottom: 80px;
.description_wp {
display: flex;
justify-content: center;
margin-top: 80px;
padding-bottom: 40px;
padding-left: 10px;
padding-right: 10px;
> * {
max-width: 570px;
display: flex;
flex-direction: column;
}
}
}
</style>