about : extract team carousel into TeamCarousel component (swiper)
Replace inline carousel logic with a dedicated TeamCarousel.svelte component. Uses SwiperJS for mobile peek (1.4 slides), tablet (2) and desktop (4) layouts, with touch swipe, pagination dots and prev/next buttons. related to #53 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6ec32dd82a
commit
4ccbad9663
4 changed files with 238 additions and 238 deletions
20
package-lock.json
generated
20
package-lock.json
generated
|
|
@ -13,6 +13,7 @@
|
||||||
"gsap": "^3.14.2",
|
"gsap": "^3.14.2",
|
||||||
"navaid": "^1.2.0",
|
"navaid": "^1.2.0",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
|
"swiper": "^12.1.3",
|
||||||
"vite": "7.0.4"
|
"vite": "7.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -1278,6 +1279,25 @@
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/swiper": {
|
||||||
|
"version": "12.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/swiper/-/swiper-12.1.3.tgz",
|
||||||
|
"integrity": "sha512-XcWlVmkHFICI4fuoJKgbp8PscDcS4i7pBH8nwJRBi3dpQvhCySwsWRYm4bOf/BzKVWkHOYaFw7qz9uBSrY3oug==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/swiperjs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "open_collective",
|
||||||
|
"url": "http://opencollective.com/swiper"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
"gsap": "^3.14.2",
|
"gsap": "^3.14.2",
|
||||||
"navaid": "^1.2.0",
|
"navaid": "^1.2.0",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
|
"swiper": "^12.1.3",
|
||||||
"vite": "7.0.4"
|
"vite": "7.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
214
src/components/ui/TeamCarousel.svelte
Normal file
214
src/components/ui/TeamCarousel.svelte
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte'
|
||||||
|
import { t } from '@i18n'
|
||||||
|
import Swiper from 'swiper'
|
||||||
|
import { Navigation, Pagination } from 'swiper/modules'
|
||||||
|
import 'swiper/css'
|
||||||
|
import 'swiper/css/pagination'
|
||||||
|
|
||||||
|
let { members = [] } = $props()
|
||||||
|
|
||||||
|
let swiperContainerEl = $state(null)
|
||||||
|
let swiper = null
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
// Petit délai pour laisser le layout se stabiliser
|
||||||
|
// (le composant est monté même quand le slide est hors écran)
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
swiper = new Swiper(swiperContainerEl, {
|
||||||
|
modules: [Navigation, Pagination],
|
||||||
|
|
||||||
|
slidesPerView: 1.4,
|
||||||
|
centeredSlides: true,
|
||||||
|
spaceBetween: 16,
|
||||||
|
|
||||||
|
pagination: {
|
||||||
|
el: swiperContainerEl.parentElement.querySelector('.team-pagination'),
|
||||||
|
clickable: true,
|
||||||
|
},
|
||||||
|
navigation: {
|
||||||
|
prevEl: swiperContainerEl.parentElement.querySelector('.team-prev'),
|
||||||
|
nextEl: swiperContainerEl.parentElement.querySelector('.team-next'),
|
||||||
|
},
|
||||||
|
|
||||||
|
breakpoints: {
|
||||||
|
701: {
|
||||||
|
slidesPerView: 2,
|
||||||
|
centeredSlides: false,
|
||||||
|
spaceBetween: 20,
|
||||||
|
},
|
||||||
|
913: {
|
||||||
|
slidesPerView: 4,
|
||||||
|
centeredSlides: false,
|
||||||
|
spaceBetween: 30,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}, 100)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timer)
|
||||||
|
swiper?.destroy(true, true)
|
||||||
|
swiper = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="team-carousel">
|
||||||
|
<div class="swiper" bind:this={swiperContainerEl}>
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
{#each members as member}
|
||||||
|
<div class="swiper-slide">
|
||||||
|
{#if member.link}
|
||||||
|
<a href={member.link} target="_blank" rel="noopener noreferrer" class="team-member">
|
||||||
|
{#if member.photo}
|
||||||
|
<img src={member.photo} alt={member.name} class="team-member-image" draggable="false" />
|
||||||
|
{/if}
|
||||||
|
<h4 class="team-member-name">{member.name}</h4>
|
||||||
|
<p class="team-member-title">{member.role}</p>
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<div class="team-member">
|
||||||
|
{#if member.photo}
|
||||||
|
<img src={member.photo} alt={member.name} class="team-member-image" draggable="false" />
|
||||||
|
{/if}
|
||||||
|
<h4 class="team-member-name">{member.name}</h4>
|
||||||
|
<p class="team-member-title">{member.role}</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="team-nav">
|
||||||
|
<button class="team-prev nav-button">{t('prev_slide')}</button>
|
||||||
|
<div class="team-pagination"></div>
|
||||||
|
<button class="team-next nav-button">{t('next_slide')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.team-carousel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swiper container */
|
||||||
|
.swiper {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Items --- */
|
||||||
|
.team-member {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.team-member:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-member-image {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
object-fit: contain;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.team-member .team-member-image:hover {
|
||||||
|
transform: scale(1.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-member-name {
|
||||||
|
font-family: "Danzza Bold", sans-serif;
|
||||||
|
font-size: var(--font-size-paragraph-small);
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-member-title {
|
||||||
|
font-family: "Danzza", sans-serif;
|
||||||
|
font-size: var(--font-size-caption);
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Nav buttons --- */
|
||||||
|
.team-nav {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-button {
|
||||||
|
color: #04fea0;
|
||||||
|
font-family: "Danzza", sans-serif;
|
||||||
|
font-size: var(--font-size-paragraph-small);
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: transform 0.3s ease, background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-button:hover:not(:disabled) {
|
||||||
|
transform: scale(1.05);
|
||||||
|
background-color: rgba(4, 254, 160, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-button:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Pagination (Swiper-injected, needs :global) --- */
|
||||||
|
:global(.team-pagination) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.team-pagination .swiper-pagination-bullet) {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
opacity: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.3s ease, background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.team-pagination .swiper-pagination-bullet-active) {
|
||||||
|
background: #04fea0;
|
||||||
|
transform: scale(1.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
:global(.team-pagination) {
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.team-pagination .swiper-pagination-bullet) {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte'
|
|
||||||
import { slides } from '@state/slides.svelte'
|
import { slides } from '@state/slides.svelte'
|
||||||
import { navigation } from '@state/navigation.svelte'
|
import { navigation } from '@state/navigation.svelte'
|
||||||
|
|
||||||
import { t } from '@i18n'
|
import { t } from '@i18n'
|
||||||
|
import TeamCarousel from '@components/ui/TeamCarousel.svelte'
|
||||||
|
|
||||||
let { data } = $props()
|
let { data } = $props()
|
||||||
|
|
||||||
|
|
@ -13,66 +12,11 @@
|
||||||
const members = $derived(data?.team ?? [])
|
const members = $derived(data?.team ?? [])
|
||||||
const isActive = $derived(slides.active?.id === 'about')
|
const isActive = $derived(slides.active?.id === 'about')
|
||||||
|
|
||||||
let sectionEl = $state(null)
|
let sectionEl = $state(null)
|
||||||
|
|
||||||
// --- Carousel state ---
|
|
||||||
let currentSlide = $state(0)
|
|
||||||
let visibleItems = $state(3)
|
|
||||||
let isTransitioning = $state(false)
|
|
||||||
let touchStartX = $state(null)
|
|
||||||
|
|
||||||
const totalSlides = $derived(Math.max(1, Math.ceil(members.length / visibleItems)))
|
|
||||||
|
|
||||||
const carouselOffset = $derived(
|
|
||||||
members.length === 0 ? 0 :
|
|
||||||
currentSlide === totalSlides - 1
|
|
||||||
? Math.max(0, (members.length - visibleItems) * 300)
|
|
||||||
: currentSlide * visibleItems * 300
|
|
||||||
)
|
|
||||||
|
|
||||||
function updateVisibleItems() {
|
|
||||||
if (window.matchMedia('(max-width: 700px)').matches) visibleItems = 1
|
|
||||||
else if (window.matchMedia('(max-width: 912px)').matches) visibleItems = 2
|
|
||||||
else visibleItems = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
function prevSlide() {
|
|
||||||
if (isTransitioning || currentSlide <= 0) return
|
|
||||||
isTransitioning = true
|
|
||||||
currentSlide--
|
|
||||||
setTimeout(() => { isTransitioning = false }, 800)
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextSlide() {
|
|
||||||
if (isTransitioning || currentSlide >= totalSlides - 1) return
|
|
||||||
isTransitioning = true
|
|
||||||
currentSlide++
|
|
||||||
setTimeout(() => { isTransitioning = false }, 800)
|
|
||||||
}
|
|
||||||
|
|
||||||
function goToSlide(i) {
|
|
||||||
if (isTransitioning || i === currentSlide) return
|
|
||||||
isTransitioning = true
|
|
||||||
currentSlide = i
|
|
||||||
setTimeout(() => { isTransitioning = false }, 800)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset scroll when slide leaves view
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (!isActive) sectionEl?.scrollTo(0, 0)
|
if (!isActive) sectionEl?.scrollTo(0, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Reset carousel when number of visible items changes
|
|
||||||
$effect(() => {
|
|
||||||
void visibleItems
|
|
||||||
currentSlide = 0
|
|
||||||
})
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
updateVisibleItems()
|
|
||||||
window.addEventListener('resize', updateVisibleItems)
|
|
||||||
return () => window.removeEventListener('resize', updateVisibleItems)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="about golden-grid page-scrollable" bind:this={sectionEl} onscroll={() => navigation.setScrolled(sectionEl.scrollTop > 100)}>
|
<div class="about golden-grid page-scrollable" bind:this={sectionEl} onscroll={() => navigation.setScrolled(sectionEl.scrollTop > 100)}>
|
||||||
|
|
@ -103,68 +47,7 @@
|
||||||
{#if members.length > 0}
|
{#if members.length > 0}
|
||||||
<section class="about-team">
|
<section class="about-team">
|
||||||
<h2 class="about-team-heading">{t('our_team')}</h2>
|
<h2 class="about-team-heading">{t('our_team')}</h2>
|
||||||
|
<TeamCarousel {members} />
|
||||||
<div class="team-carousel-container">
|
|
||||||
<div
|
|
||||||
class="team-grid"
|
|
||||||
role="list"
|
|
||||||
style="transform: translateX(-{carouselOffset}px)"
|
|
||||||
ontouchstart={(e) => { touchStartX = e.touches[0].clientX }}
|
|
||||||
ontouchend={(e) => {
|
|
||||||
if (touchStartX === null) return
|
|
||||||
const delta = touchStartX - e.changedTouches[0].clientX
|
|
||||||
if (Math.abs(delta) > 50) delta > 0 ? nextSlide() : prevSlide()
|
|
||||||
touchStartX = null
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#each members as member}
|
|
||||||
{#if member.link}
|
|
||||||
<a href={member.link} target="_blank" rel="noopener noreferrer" class="team-member">
|
|
||||||
{#if member.photo}
|
|
||||||
<img src={member.photo} alt={member.name} class="team-member-image" draggable="false" />
|
|
||||||
{/if}
|
|
||||||
<h4 class="team-member-name">{member.name}</h4>
|
|
||||||
<p class="team-member-title">{member.role}</p>
|
|
||||||
</a>
|
|
||||||
{:else}
|
|
||||||
<div class="team-member" role="listitem">
|
|
||||||
{#if member.photo}
|
|
||||||
<img src={member.photo} alt={member.name} class="team-member-image" draggable="false" />
|
|
||||||
{/if}
|
|
||||||
<h4 class="team-member-name">{member.name}</h4>
|
|
||||||
<p class="team-member-title">{member.role}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="nav-buttons">
|
|
||||||
<button
|
|
||||||
class="nav-button"
|
|
||||||
disabled={currentSlide === 0}
|
|
||||||
onclick={prevSlide}
|
|
||||||
>{t('prev_slide')}</button>
|
|
||||||
|
|
||||||
<ul class="pagination-indicator">
|
|
||||||
{#each { length: totalSlides } as _, i}
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
class="pagination-dot"
|
|
||||||
class:active={i === currentSlide}
|
|
||||||
aria-label="Slide {i + 1}"
|
|
||||||
onclick={() => goToSlide(i)}
|
|
||||||
></button>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="nav-button"
|
|
||||||
disabled={currentSlide === totalSlides - 1}
|
|
||||||
onclick={nextSlide}
|
|
||||||
>{t('next_slide')}</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -285,124 +168,6 @@
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-carousel-container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 1200px;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 10px 0;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-grid {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
transition: transform 0.8s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
||||||
padding: 10px 0;
|
|
||||||
will-change: transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-member {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: 250px;
|
|
||||||
margin: 0 25px;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.team-member:hover {
|
|
||||||
transform: translateY(-5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-member-image {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
aspect-ratio: 1 / 1;
|
|
||||||
object-fit: contain;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.team-member .team-member-image:hover {
|
|
||||||
transform: scale(1.03);
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-member-name {
|
|
||||||
font-family: "Danzza Bold", sans-serif;
|
|
||||||
font-size: var(--font-size-paragraph-small);
|
|
||||||
text-align: center;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-member-title {
|
|
||||||
font-family: "Danzza", sans-serif;
|
|
||||||
font-size: var(--font-size-caption);
|
|
||||||
text-align: center;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination-indicator li {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nav */
|
|
||||||
.nav-buttons {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-button {
|
|
||||||
color: #04fea0;
|
|
||||||
font-family: "Danzza", sans-serif;
|
|
||||||
font-size: var(--font-size-paragraph-small);
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: transform 0.3s ease, background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-button:hover:not(:disabled) {
|
|
||||||
transform: scale(1.05);
|
|
||||||
background-color: rgba(4, 254, 160, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-button:disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination-indicator {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination-dot {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0;
|
|
||||||
transition: transform 0.3s ease, background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination-dot.active {
|
|
||||||
background: #04fea0;
|
|
||||||
transform: scale(1.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Mobile (≤700px) ── */
|
/* ── Mobile (≤700px) ── */
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue