add privacy page as standalone SPA view outside slide navigation

- New Kirby template/blueprint/JSON for privacy page (confidentialite slug)
- Standalone page state in slides store + router handling for non-nav pages
- Privacy.svelte view with background image, text blocks, footer
- Centralize vertical lines in App.svelte as fixed elements with per-slide visibility
- Footer privacy link language-aware (FR/EN)
- Portfolio mockup fix: read from default language for consistent EN display
- menu.php: add privacy page to Kirby panel navigation

refs #44

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-03-30 18:43:35 +02:00
parent b12b839f1b
commit 44af8a9b4e
11 changed files with 259 additions and 50 deletions

123
src/views/Privacy.svelte Normal file
View file

@ -0,0 +1,123 @@
<script>
import { navigation } from '@state/navigation.svelte'
import Footer from '@components/layout/Footer.svelte'
let { data } = $props()
const body = $derived(data?.body ?? [])
const backgroundImage = $derived(data?.backgroundImage ?? null)
let sectionEl = $state(null)
</script>
<div
class="privacy golden-grid page-scrollable"
style={backgroundImage ? `--background-image: url('${backgroundImage}')` : ''}
bind:this={sectionEl}
onscroll={() => navigation.setScrolled(sectionEl.scrollTop > 100)}
>
<div class="page-container">
{#if body.length > 0}
<section class="privacy-body">
{#each body as block}
{#if block.type === 'text'}
<div class="privacy-body-block">
{@html block.html}
</div>
{/if}
{/each}
</section>
{/if}
<Footer />
</div>
</div>
<style>
.privacy {
min-height: 100vh;
color: #fff;
overflow-y: auto;
overflow-x: hidden;
background-image: var(--background-image, none);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.page-container {
grid-area: 6/6 / span 7 / span 10;
display: flex;
flex-direction: column;
align-items: center;
place-self: center;
width: 100%;
overflow: visible;
}
/* ── Body blocks ── */
.privacy-body {
width: 100%;
padding-top: 8rem;
}
.privacy-body-block {
border-left: 2px solid #04fea0;
padding-left: 20px;
margin-top: 3rem;
text-align: left;
font-family: "Danzza", sans-serif;
font-size: var(--font-size-paragraph);
font-weight: normal;
white-space: pre-line;
line-height: 1.6;
}
.privacy-body-block :global(h3) {
font-family: Danzza Medium, sans-serif;
font-size: var(--font-size-paragraph);
margin-bottom: 1rem;
}
.privacy-body-block :global(h3::before) {
content: '';
display: inline-block;
width: .6rem;
height: .6rem;
background-color: var(--color-primary);
margin-right: .6rem;
margin-bottom: .1rem;
}
.privacy-body-block :global(p) {
opacity: 0.9;
margin-bottom: 0.75rem;
}
.privacy-body-block :global(a) {
color: #04fea0;
}
/* ── Mobile (≤700px) ── */
@media (max-width: 700px) {
.page-container {
grid-area: auto;
width: 100vw;
}
.privacy-body {
padding: 6rem 1.25rem 2rem;
}
.privacy-body-block {
font-size: var(--font-size-paragraph-small, 0.875rem);
}
}
/* ── Tablet (701px912px) ── */
@media (min-width: 701px) and (max-width: 912px) {
.privacy-body-block {
font-size: var(--font-size-paragraph);
}
}
</style>

View file

@ -375,15 +375,6 @@
width: 100vw;
max-width: none;
scale: 1.5;
/* position: absolute;
bottom: -10%;
left: 50%;
transform: translateX(-50%);
width: 75%;
max-width: 300px;
z-index: 0;
pointer-events: none; */
}
/* Quand le formulaire est affiché : masque le contenu principal */