Refonte UI complète : palettes saisonnières, typo moderne, paroles nettoyées, Shadoks
- Nettoyage paroles : suppression instructions Suno AI, corrections prononciation (11 fichiers) - 4 palettes saisonnières (Automne/Hiver dark, Printemps/Été light) avec sélecteur - Typographie modernisée : Outfit (display) + Inter (sans) remplacent Syne + Space Grotesk - Styles adaptatifs : CSS vars pour couleurs, overrides light mode complets - Mini-player : bouton Next ajouté, flèche expand plus visible - BookPlayer : fix scroll mode paginé, croix de fermeture visible - Illustrations Shadoks inline SVG dans 11 composants/pages - Suppression soulignés navigation, reset boutons, bordures propres Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ export default defineAppConfig({
|
||||
],
|
||||
},
|
||||
gratewizard: {
|
||||
url: 'https://gratewizard.ml',
|
||||
url: import.meta.dev ? 'http://localhost:3009' : 'https://gratewizard.ml',
|
||||
popup: {
|
||||
width: 420,
|
||||
height: 720,
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const paletteStore = usePaletteStore()
|
||||
onMounted(() => paletteStore.applyToDOM())
|
||||
|
||||
useHead({
|
||||
titleTemplate: (title) => {
|
||||
return title ? `${title} — Le Librodrome` : 'Le librodrome'
|
||||
|
||||
@@ -60,10 +60,10 @@
|
||||
|
||||
@keyframes glow-pulse {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 8px hsl(12 76% 48% / 0.3);
|
||||
box-shadow: 0 0 8px hsl(var(--color-primary) / 0.3);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 24px hsl(12 76% 48% / 0.6);
|
||||
box-shadow: 0 0 24px hsl(var(--color-primary) / 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
/* This file provides fallback and utility classes */
|
||||
|
||||
.font-display {
|
||||
font-family: 'Syne', system-ui, sans-serif;
|
||||
font-family: 'Outfit', system-ui, sans-serif;
|
||||
}
|
||||
|
||||
.font-sans {
|
||||
font-family: 'Space Grotesk', system-ui, sans-serif;
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
|
||||
.font-mono {
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
@import './typography.css';
|
||||
|
||||
:root {
|
||||
--color-primary: 12 76% 48%;
|
||||
--color-accent: 36 80% 52%;
|
||||
--color-bg: 20 8% 3.5%;
|
||||
--color-surface: 20 8% 8%;
|
||||
--color-surface-light: 20 8% 13%;
|
||||
--color-primary: 18 80% 45%;
|
||||
--color-accent: 32 85% 50%;
|
||||
--color-bg: 16 12% 4%;
|
||||
--color-surface: 16 12% 9%;
|
||||
--color-surface-light: 16 10% 14%;
|
||||
--color-text: 0 0% 100%;
|
||||
--color-text-muted: 0 0% 100% / 0.6;
|
||||
--color-text-muted: 0 0% 60%;
|
||||
|
||||
--header-height: 4rem;
|
||||
--player-height: 0rem;
|
||||
--sidebar-width: 280px;
|
||||
|
||||
--font-display: 'Syne', sans-serif;
|
||||
--font-sans: 'Space Grotesk', sans-serif;
|
||||
--font-display: 'Outfit', sans-serif;
|
||||
--font-sans: 'Inter', sans-serif;
|
||||
--font-mono: 'JetBrains Mono', monospace;
|
||||
|
||||
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
@@ -43,9 +43,22 @@ body {
|
||||
min-height: 100dvh;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: hsl(var(--color-primary) / 0.3);
|
||||
color: white;
|
||||
color: hsl(var(--color-text));
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
@@ -72,6 +85,78 @@ body {
|
||||
background: hsl(var(--color-text) / 0.25);
|
||||
}
|
||||
|
||||
/* ═══ Light mode overrides ═══ */
|
||||
.palette-light {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
.palette-light,
|
||||
.palette-light .text-white {
|
||||
color: hsl(var(--color-text));
|
||||
}
|
||||
|
||||
/* white with opacity → dark text with same opacity */
|
||||
.palette-light .text-white\/20 { color: hsl(var(--color-text) / 0.2); }
|
||||
.palette-light .text-white\/30 { color: hsl(var(--color-text) / 0.3); }
|
||||
.palette-light .text-white\/40 { color: hsl(var(--color-text) / 0.4); }
|
||||
.palette-light .text-white\/45 { color: hsl(var(--color-text) / 0.45); }
|
||||
.palette-light .text-white\/50 { color: hsl(var(--color-text) / 0.5); }
|
||||
.palette-light .text-white\/60 { color: hsl(var(--color-text) / 0.6); }
|
||||
.palette-light .text-white\/70 { color: hsl(var(--color-text) / 0.7); }
|
||||
.palette-light .text-white\/80 { color: hsl(var(--color-text) / 0.8); }
|
||||
.palette-light .text-white\/85 { color: hsl(var(--color-text) / 0.85); }
|
||||
|
||||
/* white backgrounds → surface tones */
|
||||
.palette-light .bg-white\/5 { background-color: hsl(var(--color-text) / 0.04); }
|
||||
.palette-light .bg-white\/8 { background-color: hsl(var(--color-text) / 0.06); }
|
||||
.palette-light .bg-white\/10 { background-color: hsl(var(--color-text) / 0.07); }
|
||||
|
||||
/* borders */
|
||||
.palette-light .border-white\/8 { border-color: hsl(var(--color-text) / 0.1); }
|
||||
|
||||
/* hover overrides */
|
||||
.palette-light .hover\:text-white:hover,
|
||||
.palette-light .hover\:text-white\/70:hover,
|
||||
.palette-light .hover\:text-white\/80:hover {
|
||||
color: hsl(var(--color-text));
|
||||
}
|
||||
.palette-light .hover\:text-white\/60:hover {
|
||||
color: hsl(var(--color-text) / 0.6);
|
||||
}
|
||||
.palette-light .hover\:bg-white\/5:hover {
|
||||
background-color: hsl(var(--color-text) / 0.04);
|
||||
}
|
||||
.palette-light .hover\:bg-white\/10:hover {
|
||||
background-color: hsl(var(--color-text) / 0.07);
|
||||
}
|
||||
|
||||
/* placeholder overrides */
|
||||
.palette-light .placeholder\:text-white\/30::placeholder {
|
||||
color: hsl(var(--color-text) / 0.3);
|
||||
}
|
||||
|
||||
/* Prose/content in light mode */
|
||||
.palette-light .prose { color: hsl(var(--color-text)); }
|
||||
.palette-light .prose :where(h1,h2,h3,h4,h5,h6) { color: hsl(var(--color-text)); }
|
||||
|
||||
/* Active states */
|
||||
.palette-light .text-white\! { color: hsl(var(--color-text)) !important; }
|
||||
.palette-light .active-class .text-white\! { color: hsl(var(--color-text)) !important; }
|
||||
|
||||
/* text-gradient in light mode */
|
||||
.palette-light .text-gradient {
|
||||
background-image: linear-gradient(to right, hsl(var(--color-primary)), hsl(var(--color-accent)));
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* card surfaces */
|
||||
.palette-light .card-surface {
|
||||
background: hsl(var(--color-surface));
|
||||
border-color: hsl(var(--color-text) / 0.1);
|
||||
}
|
||||
|
||||
/* Page transitions */
|
||||
.page-enter-active,
|
||||
.page-leave-active {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.8;
|
||||
color: hsl(0 0% 100% / 0.90);
|
||||
color: hsl(var(--color-text) / 0.90);
|
||||
max-width: 65ch;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
font-weight: 800;
|
||||
line-height: 1.25;
|
||||
letter-spacing: -0.02em;
|
||||
color: white;
|
||||
color: hsl(var(--color-text));
|
||||
margin-top: 0;
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
border-bottom: 2px solid hsl(12 76% 48% / 0.4);
|
||||
border-bottom: 2px solid hsl(var(--color-primary) / 0.4);
|
||||
}
|
||||
|
||||
.prose h2 {
|
||||
@@ -26,11 +26,11 @@
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
letter-spacing: -0.01em;
|
||||
color: white;
|
||||
color: hsl(var(--color-text));
|
||||
margin-top: 3.5rem;
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 0.75rem;
|
||||
border-left: 3px solid hsl(12 76% 48% / 0.5);
|
||||
border-left: 3px solid hsl(var(--color-primary) / 0.5);
|
||||
}
|
||||
|
||||
.prose h3 {
|
||||
@@ -38,7 +38,7 @@
|
||||
font-size: clamp(1.25rem, 3vw, 1.625rem);
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
color: hsl(0 0% 100% / 0.92);
|
||||
color: hsl(var(--color-text) / 0.92);
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
@@ -49,7 +49,7 @@
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 50%;
|
||||
background: hsl(36 80% 52%);
|
||||
background: hsl(var(--color-accent));
|
||||
margin-right: 0.625rem;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
@@ -61,7 +61,7 @@
|
||||
font-size: clamp(1.065rem, 2.5vw, 1.25rem);
|
||||
font-weight: 600;
|
||||
line-height: 1.45;
|
||||
color: hsl(0 0% 100% / 0.85);
|
||||
color: hsl(var(--color-text) / 0.85);
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 0.625rem;
|
||||
}
|
||||
@@ -69,7 +69,7 @@
|
||||
.prose h4::before {
|
||||
content: '//';
|
||||
font-family: var(--font-mono);
|
||||
color: hsl(36 80% 52%);
|
||||
color: hsl(var(--color-accent));
|
||||
margin-right: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -78,7 +78,7 @@
|
||||
.prose h2 + p,
|
||||
.prose h3 + p {
|
||||
font-size: 1.175rem;
|
||||
color: hsl(0 0% 100% / 0.75);
|
||||
color: hsl(var(--color-text) / 0.75);
|
||||
line-height: 1.85;
|
||||
}
|
||||
|
||||
@@ -88,25 +88,25 @@
|
||||
}
|
||||
|
||||
.prose a {
|
||||
color: hsl(12 76% 68%);
|
||||
color: hsl(var(--color-primary) / 0.85);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: hsl(12 76% 58% / 0.3);
|
||||
text-decoration-color: hsl(var(--color-primary) / 0.3);
|
||||
text-underline-offset: 3px;
|
||||
transition: text-decoration-color 0.2s;
|
||||
}
|
||||
|
||||
.prose a:hover {
|
||||
text-decoration-color: hsl(12 76% 58%);
|
||||
text-decoration-color: hsl(var(--color-primary));
|
||||
}
|
||||
|
||||
.prose blockquote {
|
||||
margin: 2rem 0;
|
||||
padding: 1rem 1.5rem;
|
||||
border-left: 3px solid hsl(12 76% 58%);
|
||||
background: hsl(240 10% 8%);
|
||||
border-left: 3px solid hsl(var(--color-primary));
|
||||
background: hsl(var(--color-surface));
|
||||
border-radius: 0 0.5rem 0.5rem 0;
|
||||
font-style: italic;
|
||||
color: hsl(0 0% 100% / 0.75);
|
||||
color: hsl(var(--color-text) / 0.75);
|
||||
}
|
||||
|
||||
.prose blockquote p:last-child {
|
||||
@@ -116,17 +116,17 @@
|
||||
.prose code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.875em;
|
||||
background: hsl(240 10% 12%);
|
||||
background: hsl(var(--color-surface-light));
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 0.25rem;
|
||||
color: hsl(31 97% 66%);
|
||||
color: hsl(var(--color-accent));
|
||||
}
|
||||
|
||||
.prose pre {
|
||||
margin: 2rem 0;
|
||||
padding: 1.5rem;
|
||||
background: hsl(240 10% 6%);
|
||||
border: 1px solid hsl(0 0% 100% / 0.08);
|
||||
background: hsl(var(--color-bg));
|
||||
border: 1px solid hsl(var(--color-text) / 0.08);
|
||||
border-radius: 0.75rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
@@ -134,7 +134,7 @@
|
||||
.prose pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: hsl(0 0% 100% / 0.87);
|
||||
color: hsl(var(--color-text) / 0.87);
|
||||
}
|
||||
|
||||
.prose ul,
|
||||
@@ -149,22 +149,22 @@
|
||||
}
|
||||
|
||||
.prose li::marker {
|
||||
color: hsl(12 76% 58%);
|
||||
color: hsl(var(--color-primary));
|
||||
}
|
||||
|
||||
.prose hr {
|
||||
margin: 3rem 0;
|
||||
border: none;
|
||||
border-top: 1px solid hsl(0 0% 100% / 0.1);
|
||||
border-top: 1px solid hsl(var(--color-text) / 0.1);
|
||||
}
|
||||
|
||||
.prose strong {
|
||||
color: white;
|
||||
color: hsl(var(--color-text));
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.prose em {
|
||||
color: hsl(0 0% 100% / 0.9);
|
||||
color: hsl(var(--color-text) / 0.9);
|
||||
}
|
||||
|
||||
.prose img {
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<template v-if="isScrollMode">{{ scrollPercent }}%</template>
|
||||
<template v-else>{{ currentPage + 1 }}<span class="op-40">/</span>{{ totalPages }}</template>
|
||||
</span>
|
||||
<button class="reader-bar-btn" @click="close" aria-label="Fermer">
|
||||
<button class="reader-bar-btn reader-bar-close" @click="close" aria-label="Fermer">
|
||||
<div class="i-lucide-x h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -633,6 +633,14 @@ onUnmounted(() => {
|
||||
color: white;
|
||||
background: hsl(0 0% 100% / 0.06);
|
||||
}
|
||||
.reader-bar-close {
|
||||
color: hsl(0 0% 100% / 0.7);
|
||||
background: hsl(0 0% 100% / 0.08);
|
||||
}
|
||||
.reader-bar-close:hover {
|
||||
color: white;
|
||||
background: hsl(0 70% 55% / 0.3);
|
||||
}
|
||||
.reader-bar-title {
|
||||
flex: 1;
|
||||
font-family: var(--font-display, 'Syne', sans-serif);
|
||||
@@ -744,7 +752,7 @@ onUnmounted(() => {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
overflow: hidden auto;
|
||||
border-radius: 0.75rem;
|
||||
background: hsl(20 8% 5% / 0.4);
|
||||
backdrop-filter: blur(16px);
|
||||
@@ -796,12 +804,16 @@ onUnmounted(() => {
|
||||
.reader-columns :deep(h3) {
|
||||
break-after: avoid;
|
||||
}
|
||||
.reader-columns :deep(p),
|
||||
.reader-columns :deep(blockquote),
|
||||
.reader-columns :deep(ul),
|
||||
.reader-columns :deep(ol) {
|
||||
break-inside: avoid;
|
||||
}
|
||||
/* p with pre-line (lyrics) can be taller than a column — allow break */
|
||||
.reader-columns :deep(p) {
|
||||
break-inside: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Page-turn shadow overlay */
|
||||
.reader-shadow {
|
||||
|
||||
@@ -57,6 +57,6 @@ function playSong(song: Song) {
|
||||
.chapter-title {
|
||||
font-size: clamp(2rem, 5vw, 2.75rem);
|
||||
padding-bottom: 0.75rem;
|
||||
border-bottom: 2px solid hsl(12 76% 48% / 0.4);
|
||||
border-bottom: 2px solid hsl(var(--color-primary) / 0.4);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
<template>
|
||||
<section class="section-padding">
|
||||
<section class="relative overflow-hidden section-padding">
|
||||
<!-- Shadok thinker: ovoid character sitting, hand on chin, thinking bubble -->
|
||||
<svg class="shadok-thinker" viewBox="0 0 220 280" fill="none" aria-hidden="true">
|
||||
<!-- Body (seated, leaning forward) -->
|
||||
<ellipse cx="100" cy="160" rx="42" ry="50" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head (tilted) -->
|
||||
<ellipse cx="110" cy="95" rx="25" ry="24" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Neck -->
|
||||
<path d="M100 118 Q105 110 108 105" stroke="currentColor" stroke-width="6" stroke-linecap="round" opacity="0.6" fill="none"/>
|
||||
<!-- Eyes (contemplative) -->
|
||||
<circle cx="103" cy="90" r="4.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="120" cy="90" r="4.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="104" cy="89" r="1.8" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="121" cy="89" r="1.8" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Arm to chin -->
|
||||
<line x1="140" y1="145" x2="130" y2="108" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Hand on chin -->
|
||||
<circle cx="130" cy="105" r="5" fill="currentColor" opacity="0.45"/>
|
||||
<!-- Seated legs (crossed/bent) -->
|
||||
<path d="M75 205 Q60 230 50 240" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6" fill="none"/>
|
||||
<path d="M120 205 Q140 220 145 240" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6" fill="none"/>
|
||||
<!-- Feet -->
|
||||
<path d="M50 240 L38 243 M50 240 L45 246" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<path d="M145 240 L133 243 M145 240 L140 246" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Thinking bubbles -->
|
||||
<circle cx="150" cy="78" r="5" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="165" cy="62" r="8" fill="currentColor" opacity="0.25"/>
|
||||
<circle cx="185" cy="42" r="12" fill="currentColor" opacity="0.2"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content">
|
||||
<div class="grid items-center gap-12 md:grid-cols-2">
|
||||
<!-- Book cover -->
|
||||
@@ -63,10 +92,10 @@ const { data: content } = await usePageContent('home')
|
||||
aspect-ratio: 3 / 4;
|
||||
border-radius: 0.75rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid hsl(20 8% 18%);
|
||||
border: 1px solid hsl(var(--color-text) / 0.1);
|
||||
box-shadow:
|
||||
0 12px 40px hsl(0 0% 0% / 0.5),
|
||||
0 0 0 1px hsl(20 8% 15%);
|
||||
0 12px 40px hsl(var(--color-text) / 0.15),
|
||||
0 0 0 1px hsl(var(--color-text) / 0.08);
|
||||
transition: transform 0.5s cubic-bezier(0.645, 0.045, 0.355, 1),
|
||||
box-shadow 0.5s ease;
|
||||
max-width: 360px;
|
||||
@@ -75,8 +104,8 @@ const { data: content } = await usePageContent('home')
|
||||
.book-cover-3d:hover {
|
||||
transform: rotateY(-8deg) rotateX(3deg) scale(1.02);
|
||||
box-shadow:
|
||||
12px 16px 48px hsl(0 0% 0% / 0.6),
|
||||
0 0 0 1px hsl(12 76% 48% / 0.2);
|
||||
12px 16px 48px hsl(var(--color-text) / 0.2),
|
||||
0 0 0 1px hsl(var(--color-primary) / 0.2);
|
||||
}
|
||||
|
||||
.book-cover-img {
|
||||
@@ -89,4 +118,24 @@ const { data: content } = await usePageContent('home')
|
||||
.heading-section {
|
||||
font-size: clamp(1.625rem, 4vw, 2.125rem);
|
||||
}
|
||||
|
||||
.shadok-thinker {
|
||||
position: absolute;
|
||||
right: 3%;
|
||||
bottom: 8%;
|
||||
width: clamp(90px, 12vw, 170px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-accent));
|
||||
animation: shadok-float-thinker 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-thinker {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-8px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-thinker { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,24 @@
|
||||
<div class="grid items-center gap-12 md:grid-cols-2">
|
||||
<!-- Book cover -->
|
||||
<UiScrollReveal>
|
||||
<div class="book-cover-wrapper">
|
||||
<div class="book-cover-wrapper relative">
|
||||
<!-- Shadok pumper -->
|
||||
<svg class="shadok-pumper" viewBox="0 0 200 240" fill="none" aria-hidden="true">
|
||||
<ellipse cx="100" cy="130" rx="55" ry="65" fill="currentColor" opacity="0.9"/>
|
||||
<ellipse cx="100" cy="60" rx="30" ry="28" fill="currentColor" opacity="0.85"/>
|
||||
<circle cx="88" cy="54" r="6" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="112" cy="54" r="6" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="90" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="114" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<polygon points="100,68 115,78 85,78" fill="currentColor" opacity="0.6"/>
|
||||
<line x1="80" y1="192" x2="70" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
|
||||
<line x1="120" y1="192" x2="130" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
|
||||
<line x1="70" y1="230" x2="55" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="130" y1="230" x2="145" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="155" y1="110" x2="190" y2="90" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="190" y1="90" x2="190" y2="120" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
|
||||
<rect x="180" y="118" width="18" height="40" rx="3" fill="currentColor" opacity="0.4"/>
|
||||
</svg>
|
||||
<div class="book-cover-3d">
|
||||
<img
|
||||
:src="content?.book.coverImage"
|
||||
@@ -68,10 +85,10 @@ const { data: content } = await usePageContent('home')
|
||||
aspect-ratio: 3 / 4;
|
||||
border-radius: 0.75rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid hsl(20 8% 18%);
|
||||
border: 1px solid hsl(var(--color-text) / 0.1);
|
||||
box-shadow:
|
||||
0 12px 40px hsl(0 0% 0% / 0.5),
|
||||
0 0 0 1px hsl(20 8% 15%);
|
||||
0 12px 40px hsl(var(--color-text) / 0.15),
|
||||
0 0 0 1px hsl(var(--color-text) / 0.08);
|
||||
transition: transform 0.5s cubic-bezier(0.645, 0.045, 0.355, 1),
|
||||
box-shadow 0.5s ease;
|
||||
max-width: 360px;
|
||||
@@ -80,8 +97,8 @@ const { data: content } = await usePageContent('home')
|
||||
.book-cover-3d:hover {
|
||||
transform: rotateY(-8deg) rotateX(3deg) scale(1.02);
|
||||
box-shadow:
|
||||
12px 16px 48px hsl(0 0% 0% / 0.6),
|
||||
0 0 0 1px hsl(12 76% 48% / 0.2);
|
||||
12px 16px 48px hsl(var(--color-text) / 0.2),
|
||||
0 0 0 1px hsl(var(--color-primary) / 0.2);
|
||||
}
|
||||
|
||||
.book-cover-img {
|
||||
@@ -94,4 +111,25 @@ const { data: content } = await usePageContent('home')
|
||||
.heading-section {
|
||||
font-size: clamp(1.625rem, 4vw, 2.125rem);
|
||||
}
|
||||
|
||||
.shadok-pumper {
|
||||
position: absolute;
|
||||
right: -15%;
|
||||
bottom: 5%;
|
||||
width: clamp(60px, 10vw, 120px);
|
||||
opacity: 0.12;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float 10s ease-in-out infinite;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@keyframes shadok-float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-pumper { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
<template>
|
||||
<section class="section-padding">
|
||||
<section class="relative overflow-hidden section-padding">
|
||||
<!-- Shadok scale: balance with absurd objects -->
|
||||
<svg class="shadok-scale" viewBox="0 0 260 280" fill="none" aria-hidden="true">
|
||||
<!-- Vertical pole -->
|
||||
<line x1="130" y1="40" x2="130" y2="240" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.8"/>
|
||||
<!-- Base triangle -->
|
||||
<polygon points="100,240 160,240 130,220" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Horizontal beam -->
|
||||
<line x1="40" y1="80" x2="220" y2="60" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.7"/>
|
||||
<!-- Pivot circle -->
|
||||
<circle cx="130" cy="70" r="8" fill="currentColor" opacity="0.6"/>
|
||||
<!-- Left pan (chain lines) -->
|
||||
<line x1="40" y1="80" x2="30" y2="120" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="40" y1="80" x2="70" y2="120" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Left pan dish -->
|
||||
<path d="M20 120 Q50 135 80 120" stroke="currentColor" stroke-width="2.5" fill="currentColor" opacity="0.35"/>
|
||||
<!-- Absurd object on left: a snail -->
|
||||
<ellipse cx="50" cy="112" rx="14" ry="8" fill="currentColor" opacity="0.5"/>
|
||||
<path d="M60 108 Q68 95 58 92 Q48 90 52 100" stroke="currentColor" stroke-width="2" fill="none" opacity="0.4"/>
|
||||
<!-- Right pan (chain lines) -->
|
||||
<line x1="220" y1="60" x2="210" y2="100" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="220" y1="60" x2="250" y2="100" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Right pan dish -->
|
||||
<path d="M200 100 Q230 115 260 100" stroke="currentColor" stroke-width="2.5" fill="currentColor" opacity="0.35"/>
|
||||
<!-- Absurd object on right: a star/coin -->
|
||||
<circle cx="230" cy="92" r="10" fill="currentColor" opacity="0.4"/>
|
||||
<circle cx="230" cy="92" r="5" fill="currentColor" opacity="0.2"/>
|
||||
<!-- Tiny Shadok perched on top -->
|
||||
<ellipse cx="130" cy="35" rx="12" ry="10" fill="currentColor" opacity="0.6"/>
|
||||
<circle cx="130" cy="22" r="7" fill="currentColor" opacity="0.55"/>
|
||||
<circle cx="133" cy="20" r="2" fill="currentColor" opacity="0.3"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content">
|
||||
<div class="mx-auto max-w-3xl text-center">
|
||||
<UiScrollReveal>
|
||||
@@ -41,4 +73,24 @@ const { data: content } = await usePageContent('home')
|
||||
.heading-section {
|
||||
font-size: clamp(1.625rem, 4vw, 2.125rem);
|
||||
}
|
||||
|
||||
.shadok-scale {
|
||||
position: absolute;
|
||||
left: 2%;
|
||||
top: 10%;
|
||||
width: clamp(100px, 14vw, 200px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float-scale 9s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-scale {
|
||||
0%, 100% { transform: translateY(0) rotate(0deg); }
|
||||
50% { transform: translateY(-10px) rotate(2deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-scale { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,8 +2,20 @@
|
||||
<section class="section-padding">
|
||||
<div class="container-content">
|
||||
<UiScrollReveal>
|
||||
<div class="gw-card">
|
||||
<div class="flex flex-col items-center text-center gap-4 md:flex-row md:text-left md:gap-8">
|
||||
<div class="gw-card relative overflow-hidden">
|
||||
<!-- Shadok blob -->
|
||||
<svg class="shadok-blob" viewBox="0 0 200 180" fill="none" aria-hidden="true">
|
||||
<path d="M60 90 Q30 50 70 30 Q110 10 140 40 Q180 60 170 100 Q165 140 130 155 Q90 170 55 145 Q25 125 60 90Z" fill="currentColor" opacity="0.12"/>
|
||||
<path d="M60 90 Q30 50 70 30 Q110 10 140 40 Q180 60 170 100 Q165 140 130 155 Q90 170 55 145 Q25 125 60 90Z" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
|
||||
<circle cx="100" cy="80" r="8" fill="currentColor" opacity="0.08"/>
|
||||
<circle cx="120" cy="110" r="6" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="80" cy="105" r="5" fill="currentColor" opacity="0.07"/>
|
||||
<circle cx="95" cy="72" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="108" cy="70" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="96" cy="71" r="1.2" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="109" cy="69" r="1.2" fill="currentColor" opacity="0.5"/>
|
||||
</svg>
|
||||
<div class="flex flex-col items-center text-center gap-4 md:flex-row md:text-left md:gap-8 relative z-1">
|
||||
<!-- Icon -->
|
||||
<div class="gw-icon-wrapper">
|
||||
<div class="i-lucide-sparkles h-8 w-8 text-amber-400" />
|
||||
@@ -75,4 +87,24 @@ const { data: content } = await usePageContent('home')
|
||||
border: 1px solid hsl(40 80% 50% / 0.15);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.shadok-blob {
|
||||
position: absolute;
|
||||
right: -2%;
|
||||
top: -20%;
|
||||
width: clamp(100px, 15vw, 180px);
|
||||
opacity: 0.15;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-accent));
|
||||
animation: shadok-drift 12s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-drift {
|
||||
0%, 100% { transform: translateY(0) rotate(0deg); }
|
||||
50% { transform: translateY(-8px) rotate(3deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-blob { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,6 +4,25 @@
|
||||
<div class="absolute inset-0 bg-gradient-to-b from-primary/10 via-transparent to-surface-bg" />
|
||||
<div class="absolute inset-0 bg-[radial-gradient(ellipse_at_top,hsl(12_76%_48%/0.15),transparent_70%)]" />
|
||||
|
||||
<!-- Shadok bird decoration -->
|
||||
<svg class="shadok-bird" viewBox="0 0 180 260" fill="none" aria-hidden="true">
|
||||
<ellipse cx="90" cy="100" rx="45" ry="40" fill="currentColor" opacity="0.85"/>
|
||||
<circle cx="130" cy="60" r="22" fill="currentColor" opacity="0.8"/>
|
||||
<path d="M110 85 Q125 70 128 63" stroke="currentColor" stroke-width="8" stroke-linecap="round" opacity="0.7" fill="none"/>
|
||||
<circle cx="136" cy="55" r="5" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="137" cy="54" r="2" fill="currentColor" opacity="0.6"/>
|
||||
<polygon points="150,58 175,50 152,65" fill="currentColor" opacity="0.6"/>
|
||||
<line x1="75" y1="138" x2="60" y2="230" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="105" y1="138" x2="115" y2="230" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<circle cx="66" cy="190" r="4" fill="currentColor" opacity="0.4"/>
|
||||
<circle cx="111" cy="190" r="4" fill="currentColor" opacity="0.4"/>
|
||||
<path d="M60 230 L45 233 M60 230 L55 236 M60 230 L65 235" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<path d="M115 230 L100 233 M115 230 L110 236 M115 230 L120 235" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<path d="M48 95 Q20 80 15 65" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5" fill="none"/>
|
||||
<path d="M48 100 Q22 92 10 85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4" fill="none"/>
|
||||
<path d="M48 105 Q25 102 12 100" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3" fill="none"/>
|
||||
</svg>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="container-content relative z-10 px-4">
|
||||
<div class="mx-auto max-w-3xl text-center">
|
||||
@@ -54,4 +73,25 @@ const { data: content } = await usePageContent('home')
|
||||
.hero-title {
|
||||
font-size: clamp(2.25rem, 7vw, 4rem);
|
||||
}
|
||||
|
||||
.shadok-bird {
|
||||
position: absolute;
|
||||
right: 5%;
|
||||
top: 15%;
|
||||
width: clamp(80px, 12vw, 160px);
|
||||
opacity: 0.12;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float 8s ease-in-out infinite;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@keyframes shadok-float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-12px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-bird { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -106,8 +106,8 @@ function formatDate(iso: string) {
|
||||
|
||||
<style scoped>
|
||||
.message-form-card {
|
||||
background: hsl(20 8% 6%);
|
||||
border: 1px solid hsl(20 8% 14%);
|
||||
background: hsl(var(--color-surface));
|
||||
border: 1px solid hsl(var(--color-text) / 0.1);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
@@ -116,25 +116,25 @@ function formatDate(iso: string) {
|
||||
width: 100%;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid hsl(20 8% 18%);
|
||||
background: hsl(20 8% 4%);
|
||||
color: white;
|
||||
border: 1px solid hsl(var(--color-text) / 0.12);
|
||||
background: hsl(var(--color-bg));
|
||||
color: hsl(var(--color-text));
|
||||
font-size: 0.875rem;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.msg-input::placeholder {
|
||||
color: hsl(20 8% 40%);
|
||||
color: hsl(var(--color-text) / 0.35);
|
||||
}
|
||||
|
||||
.msg-input:focus {
|
||||
outline: none;
|
||||
border-color: hsl(12 76% 48% / 0.5);
|
||||
border-color: hsl(var(--color-primary) / 0.5);
|
||||
}
|
||||
|
||||
.message-card {
|
||||
background: hsl(20 8% 6%);
|
||||
border: 1px solid hsl(20 8% 14%);
|
||||
background: hsl(var(--color-surface));
|
||||
border: 1px solid hsl(var(--color-text) / 0.1);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1rem 1.25rem;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
<template>
|
||||
<section class="section-padding bg-surface-600/50">
|
||||
<section class="relative overflow-hidden section-padding bg-surface-600/50">
|
||||
<!-- Shadok musician: round character playing a trumpet -->
|
||||
<svg class="shadok-musician" viewBox="0 0 220 280" fill="none" aria-hidden="true">
|
||||
<!-- Body (ovoid) -->
|
||||
<ellipse cx="100" cy="150" rx="45" ry="55" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head -->
|
||||
<circle cx="100" cy="80" r="28" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Eyes -->
|
||||
<circle cx="90" cy="74" r="5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="110" cy="74" r="5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="91" cy="73" r="2" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="111" cy="73" r="2" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Mouth (blowing) -->
|
||||
<circle cx="125" cy="86" r="4" fill="currentColor" opacity="0.3"/>
|
||||
<!-- Trumpet -->
|
||||
<line x1="128" y1="86" x2="185" y2="78" stroke="currentColor" stroke-width="5" stroke-linecap="round" opacity="0.7"/>
|
||||
<path d="M185 68 Q200 78 185 88" stroke="currentColor" stroke-width="3" fill="currentColor" opacity="0.45"/>
|
||||
<!-- Trumpet valves -->
|
||||
<circle cx="155" cy="80" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="165" cy="79" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<!-- Music notes floating -->
|
||||
<circle cx="205" cy="60" r="4" fill="currentColor" opacity="0.4"/>
|
||||
<line x1="209" y1="60" x2="209" y2="42" stroke="currentColor" stroke-width="1.5" opacity="0.4"/>
|
||||
<circle cx="195" cy="45" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<line x1="198" y1="45" x2="198" y2="30" stroke="currentColor" stroke-width="1.5" opacity="0.3"/>
|
||||
<!-- Legs -->
|
||||
<line x1="82" y1="202" x2="72" y2="255" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="118" y1="202" x2="128" y2="255" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Feet -->
|
||||
<path d="M72 255 L58 258 M72 255 L66 261" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<path d="M128 255 L114 258 M128 255 L122 261" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content">
|
||||
<UiScrollReveal>
|
||||
<div class="text-center mb-12">
|
||||
@@ -48,4 +80,24 @@ const featuredSongs = computed(() => bookData.getSongs().slice(0, 6))
|
||||
.heading-section {
|
||||
font-size: clamp(1.625rem, 4vw, 2.125rem);
|
||||
}
|
||||
|
||||
.shadok-musician {
|
||||
position: absolute;
|
||||
right: 3%;
|
||||
top: 5%;
|
||||
width: clamp(90px, 12vw, 170px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float-musician 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-musician {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-musician { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,45 @@
|
||||
<template>
|
||||
<footer class="border-t border-white/8 bg-surface-600">
|
||||
<div class="container-content px-4 py-8">
|
||||
<footer class="footer-wrap border-t border-white/8 bg-surface-600">
|
||||
<!-- Shadok pattern -->
|
||||
<svg class="footer-shadok-pattern" viewBox="0 0 400 80" fill="none" aria-hidden="true">
|
||||
<g transform="translate(20,10)">
|
||||
<ellipse cx="15" cy="25" rx="12" ry="14" fill="currentColor" opacity="0.08"/>
|
||||
<circle cx="15" cy="10" r="7" fill="currentColor" opacity="0.06"/>
|
||||
<line x1="10" y1="38" x2="8" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
<line x1="20" y1="38" x2="22" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
</g>
|
||||
<g transform="translate(80,15)">
|
||||
<ellipse cx="15" cy="22" rx="10" ry="12" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="15" cy="8" r="6" fill="currentColor" opacity="0.05"/>
|
||||
<line x1="10" y1="33" x2="8" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
<line x1="20" y1="33" x2="22" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
</g>
|
||||
<g transform="translate(140,8)">
|
||||
<ellipse cx="15" cy="25" rx="11" ry="13" fill="currentColor" opacity="0.07"/>
|
||||
<circle cx="15" cy="10" r="6.5" fill="currentColor" opacity="0.06"/>
|
||||
<line x1="10" y1="37" x2="7" y2="54" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
<line x1="20" y1="37" x2="23" y2="54" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
</g>
|
||||
<g transform="translate(210,18)">
|
||||
<ellipse cx="15" cy="20" rx="10" ry="11" fill="currentColor" opacity="0.05"/>
|
||||
<circle cx="15" cy="7" r="5.5" fill="currentColor" opacity="0.04"/>
|
||||
<line x1="10" y1="30" x2="9" y2="44" stroke="currentColor" stroke-width="1.5" opacity="0.04"/>
|
||||
<line x1="20" y1="30" x2="21" y2="44" stroke="currentColor" stroke-width="1.5" opacity="0.04"/>
|
||||
</g>
|
||||
<g transform="translate(270,12)">
|
||||
<ellipse cx="15" cy="24" rx="12" ry="14" fill="currentColor" opacity="0.07"/>
|
||||
<circle cx="15" cy="9" r="7" fill="currentColor" opacity="0.06"/>
|
||||
<line x1="10" y1="37" x2="7" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
<line x1="20" y1="37" x2="23" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
</g>
|
||||
<g transform="translate(340,16)">
|
||||
<ellipse cx="15" cy="22" rx="10" ry="12" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="15" cy="8" r="6" fill="currentColor" opacity="0.05"/>
|
||||
<line x1="10" y1="33" x2="8" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
<line x1="20" y1="33" x2="22" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="container-content px-4 py-8 relative z-1">
|
||||
<div class="flex flex-col items-center gap-4 md:flex-row md:justify-between">
|
||||
<!-- Credits -->
|
||||
<p class="text-sm text-white/40">
|
||||
@@ -26,3 +65,21 @@
|
||||
<script setup lang="ts">
|
||||
const { data: site } = await useSiteContent()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.footer-wrap {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.footer-shadok-pattern {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<header class="sticky top-0 z-40 border-b border-white/8 bg-surface-bg/80 backdrop-blur-xl">
|
||||
<div class="container-content flex h-[var(--header-height)] items-center justify-between px-4">
|
||||
<!-- Logo -->
|
||||
<NuxtLink to="/" class="flex items-center gap-2 font-display text-lg font-bold tracking-tight">
|
||||
<NuxtLink to="/" class="flex items-center gap-2 text-lg tracking-tight">
|
||||
<div class="i-lucide-book-open h-6 w-6 text-primary" />
|
||||
<span class="text-gradient">{{ site?.identity.name }}</span>
|
||||
<span class="font-calligraphy font-bold text-gradient text-xl italic">{{ site?.identity.name }}</span>
|
||||
</NuxtLink>
|
||||
|
||||
<!-- Desktop navigation -->
|
||||
@@ -18,6 +18,7 @@
|
||||
>
|
||||
{{ item.label }}
|
||||
</NuxtLink>
|
||||
<UiPaletteSelector />
|
||||
</nav>
|
||||
|
||||
<!-- Mobile menu button -->
|
||||
|
||||
@@ -99,13 +99,18 @@
|
||||
<div :class="store.isPlaying ? 'i-lucide-pause' : 'i-lucide-play'" class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<!-- Next -->
|
||||
<button class="pill-next" aria-label="Suivant" @click.stop="playNext" :disabled="!store.hasNext">
|
||||
<div class="i-lucide-skip-forward h-3.5 w-3.5" />
|
||||
</button>
|
||||
|
||||
<!-- Expand -->
|
||||
<button
|
||||
class="pill-expand"
|
||||
:aria-label="isExpanded ? 'Réduire' : 'Développer'"
|
||||
@click.stop="toggleExpanded"
|
||||
>
|
||||
<div :class="isExpanded ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'" class="h-3.5 w-3.5" />
|
||||
<div :class="isExpanded ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'" class="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -116,7 +121,7 @@
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
|
||||
const store = usePlayerStore()
|
||||
const { setVolume, togglePlayPause } = useAudioPlayer()
|
||||
const { setVolume, togglePlayPause, playNext } = useAudioPlayer()
|
||||
|
||||
useMediaSession()
|
||||
|
||||
@@ -235,22 +240,40 @@ onClickOutside(widgetRef, () => {
|
||||
.pill-play:hover { transform: scale(1.08); }
|
||||
.pill-play:active { transform: scale(0.94); }
|
||||
|
||||
/* Next */
|
||||
.pill-next {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: hsl(0 0% 100% / 0.6);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.pill-next:hover { color: white; }
|
||||
.pill-next:disabled { opacity: 0.3; cursor: default; }
|
||||
|
||||
/* Expand chevron */
|
||||
.pill-expand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
background: hsl(0 0% 100% / 0.08);
|
||||
border: none;
|
||||
color: hsl(0 0% 100% / 0.3);
|
||||
color: hsl(0 0% 100% / 0.5);
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
transition: all 0.2s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.pill-expand:hover { color: hsl(0 0% 100% / 0.7); }
|
||||
.pill-expand:hover { color: hsl(0 0% 100% / 0.9); background: hsl(0 0% 100% / 0.15); }
|
||||
|
||||
/* ═══════════════════════════════════════
|
||||
PANEL
|
||||
|
||||
261
app/components/ui/PaletteSelector.vue
Normal file
261
app/components/ui/PaletteSelector.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<div class="settings-selector" ref="selectorRef">
|
||||
<button
|
||||
class="settings-trigger"
|
||||
aria-label="Réglages d'affichage"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<div class="i-lucide-settings h-5 w-5" />
|
||||
</button>
|
||||
|
||||
<Transition name="settings-dropdown">
|
||||
<div v-if="isOpen" class="settings-dropdown">
|
||||
<h4 class="settings-title">Affichage</h4>
|
||||
|
||||
<!-- Palette grid : 4 saisons -->
|
||||
<div class="settings-section">
|
||||
<span class="settings-label">Ambiance</span>
|
||||
<div class="settings-palette-grid">
|
||||
<button
|
||||
v-for="name in paletteNames"
|
||||
:key="name"
|
||||
class="settings-palette-btn"
|
||||
:class="{
|
||||
'settings-palette-btn--active': paletteStore.currentPalette === name,
|
||||
'settings-palette-btn--light': paletteStore.palettes[name].isLight,
|
||||
}"
|
||||
:title="paletteStore.palettes[name].label"
|
||||
@click="paletteStore.setPalette(name)"
|
||||
>
|
||||
<span class="settings-palette-preview">
|
||||
<span class="settings-palette-dot" :style="{ background: `hsl(${paletteStore.palettes[name].primary})` }" />
|
||||
<span class="settings-palette-dot" :style="{ background: `hsl(${paletteStore.palettes[name].accent})` }" />
|
||||
</span>
|
||||
<span class="settings-palette-info">
|
||||
<span class="settings-palette-name">{{ paletteStore.palettes[name].label }}</span>
|
||||
<span class="settings-palette-mode">{{ paletteStore.palettes[name].isLight ? 'Clair' : 'Sombre' }}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Font size -->
|
||||
<div class="settings-section">
|
||||
<span class="settings-label">Taille texte</span>
|
||||
<div class="settings-toggle-group">
|
||||
<button
|
||||
v-for="size in fontSizes"
|
||||
:key="size.value"
|
||||
class="settings-toggle"
|
||||
:class="{ 'settings-toggle--active': currentFontSize === size.value }"
|
||||
@click="setFontSize(size.value)"
|
||||
>
|
||||
{{ size.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import type { PaletteName } from '~/stores/palette'
|
||||
|
||||
const paletteStore = usePaletteStore()
|
||||
const selectorRef = ref<HTMLElement>()
|
||||
const isOpen = ref(false)
|
||||
|
||||
const paletteNames: PaletteName[] = ['automne', 'hiver', 'printemps', 'ete']
|
||||
|
||||
const currentFontSize = ref(
|
||||
(import.meta.client && localStorage.getItem('fontSize')) || 'normal',
|
||||
)
|
||||
|
||||
const fontSizes = [
|
||||
{ label: 'A-', value: 'small' },
|
||||
{ label: 'A', value: 'normal' },
|
||||
{ label: 'A+', value: 'large' },
|
||||
]
|
||||
|
||||
function setFontSize(size: string) {
|
||||
currentFontSize.value = size
|
||||
if (import.meta.client) {
|
||||
localStorage.setItem('fontSize', size)
|
||||
const root = document.documentElement
|
||||
const map: Record<string, string> = { small: '14px', normal: '16px', large: '18px' }
|
||||
root.style.fontSize = map[size] || '16px'
|
||||
}
|
||||
}
|
||||
|
||||
// Apply font size on mount
|
||||
onMounted(() => {
|
||||
const saved = localStorage.getItem('fontSize')
|
||||
if (saved) setFontSize(saved)
|
||||
})
|
||||
|
||||
onClickOutside(selectorRef, () => { isOpen.value = false })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.settings-selector {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.settings-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
border-radius: 0.5rem;
|
||||
color: hsl(var(--color-text) / 0.7);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.settings-trigger:hover {
|
||||
color: hsl(var(--color-text));
|
||||
background: hsl(var(--color-text) / 0.1);
|
||||
}
|
||||
|
||||
.settings-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% + 0.5rem);
|
||||
right: 0;
|
||||
width: 260px;
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.75rem;
|
||||
background: hsl(var(--color-surface));
|
||||
backdrop-filter: blur(16px);
|
||||
border: 1px solid hsl(var(--color-text) / 0.08);
|
||||
box-shadow: 0 8px 32px hsl(0 0% 0% / 0.3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.settings-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: hsl(var(--color-text) / 0.4);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
.settings-label {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--color-text) / 0.5);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.settings-toggle-group {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
background: hsl(var(--color-text) / 0.04);
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.125rem;
|
||||
}
|
||||
|
||||
.settings-toggle {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.375rem 0.5rem;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: hsl(var(--color-text) / 0.5);
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.settings-toggle:hover {
|
||||
color: hsl(var(--color-text) / 0.8);
|
||||
}
|
||||
.settings-toggle--active {
|
||||
background: hsl(var(--color-primary));
|
||||
color: white;
|
||||
box-shadow: 0 1px 4px hsl(var(--color-primary) / 0.3);
|
||||
}
|
||||
|
||||
.settings-palette-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
.settings-palette-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
transition: all 0.2s;
|
||||
color: hsl(var(--color-text) / 0.6);
|
||||
background: hsl(var(--color-text) / 0.02);
|
||||
}
|
||||
.settings-palette-btn:hover {
|
||||
background: hsl(var(--color-text) / 0.06);
|
||||
color: hsl(var(--color-text) / 0.9);
|
||||
}
|
||||
.settings-palette-btn--active {
|
||||
background: hsl(var(--color-text) / 0.1);
|
||||
color: hsl(var(--color-text));
|
||||
box-shadow: inset 0 0 0 1.5px hsl(var(--color-primary) / 0.5);
|
||||
}
|
||||
|
||||
.settings-palette-preview {
|
||||
display: flex;
|
||||
gap: 0.125rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.settings-palette-dot {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 1px 3px hsl(0 0% 0% / 0.25);
|
||||
}
|
||||
|
||||
.settings-palette-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.settings-palette-name {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.settings-palette-mode {
|
||||
font-size: 0.6rem;
|
||||
opacity: 0.5;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.settings-dropdown-enter-active {
|
||||
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
.settings-dropdown-leave-active {
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
.settings-dropdown-enter-from,
|
||||
.settings-dropdown-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px) scale(0.96);
|
||||
}
|
||||
</style>
|
||||
@@ -35,7 +35,7 @@
|
||||
top: var(--header-height);
|
||||
height: calc(100dvh - var(--header-height));
|
||||
overflow-y: auto;
|
||||
border-right: 1px solid hsl(0 0% 100% / 0.08);
|
||||
border-right: 1px solid hsl(var(--color-text) / 0.08);
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
<template>
|
||||
<div class="section-padding">
|
||||
<div class="relative overflow-hidden section-padding">
|
||||
<!-- Shadok philosopher: character sitting cross-legged, floating -->
|
||||
<svg class="shadok-philosopher" viewBox="0 0 220 280" fill="none" aria-hidden="true">
|
||||
<!-- Body (round, serene) -->
|
||||
<ellipse cx="110" cy="150" rx="48" ry="55" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head -->
|
||||
<ellipse cx="110" cy="82" rx="26" ry="25" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Closed eyes (meditating) -->
|
||||
<path d="M96 80 Q100 84 105 80" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.4"/>
|
||||
<path d="M115 80 Q119 84 124 80" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.4"/>
|
||||
<!-- Serene smile -->
|
||||
<path d="M102 93 Q110 98 118 93" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
|
||||
<!-- Arms resting on knees -->
|
||||
<path d="M64 155 Q55 180 70 200" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
|
||||
<path d="M156 155 Q165 180 150 200" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
|
||||
<!-- Hands on knees -->
|
||||
<circle cx="70" cy="200" r="5" fill="currentColor" opacity="0.4"/>
|
||||
<circle cx="150" cy="200" r="5" fill="currentColor" opacity="0.4"/>
|
||||
<!-- Crossed legs -->
|
||||
<path d="M80 205 Q90 230 120 235" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
|
||||
<path d="M140 205 Q130 230 100 235" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
|
||||
<!-- Floating aura lines -->
|
||||
<path d="M50 245 Q110 260 170 245" stroke="currentColor" stroke-width="1.5" stroke-dasharray="4 4" fill="none" opacity="0.25"/>
|
||||
<path d="M60 255 Q110 268 160 255" stroke="currentColor" stroke-width="1" stroke-dasharray="3 5" fill="none" opacity="0.18"/>
|
||||
<!-- Small sparkles around -->
|
||||
<circle cx="55" cy="110" r="2.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="170" cy="95" r="2" fill="currentColor" opacity="0.18"/>
|
||||
<circle cx="160" cy="130" r="3" fill="currentColor" opacity="0.15"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content mx-auto max-w-3xl">
|
||||
<ContentRenderer v-if="page" :value="page" class="prose" />
|
||||
</div>
|
||||
@@ -19,3 +48,25 @@ const { data: page } = await useAsyncData('about', () =>
|
||||
queryCollection('pages').path('/pages/about').first(),
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.shadok-philosopher {
|
||||
position: absolute;
|
||||
right: 3%;
|
||||
bottom: 8%;
|
||||
width: clamp(90px, 13vw, 180px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float-philosopher 11s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-philosopher {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-12px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-philosopher { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
<template>
|
||||
<div class="section-padding">
|
||||
<div class="relative overflow-hidden section-padding">
|
||||
<!-- Shadok DJ: character with headphones behind a turntable -->
|
||||
<svg class="shadok-dj" viewBox="0 0 260 300" fill="none" aria-hidden="true">
|
||||
<!-- Body -->
|
||||
<ellipse cx="130" cy="155" rx="42" ry="50" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head -->
|
||||
<circle cx="130" cy="88" r="26" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Headphones band -->
|
||||
<path d="M104 78 Q130 55 156 78" stroke="currentColor" stroke-width="4" stroke-linecap="round" fill="none" opacity="0.6"/>
|
||||
<!-- Headphone ear pads -->
|
||||
<ellipse cx="102" cy="85" rx="8" ry="12" fill="currentColor" opacity="0.5"/>
|
||||
<ellipse cx="158" cy="85" rx="8" ry="12" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Eyes (cool, half-lidded) -->
|
||||
<ellipse cx="120" cy="85" rx="5" ry="3" fill="currentColor" opacity="0.25"/>
|
||||
<ellipse cx="140" cy="85" rx="5" ry="3" fill="currentColor" opacity="0.25"/>
|
||||
<circle cx="121" cy="86" r="1.8" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="141" cy="86" r="1.8" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Mouth (grin) -->
|
||||
<path d="M122 98 Q130 104 138 98" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.35"/>
|
||||
<!-- Arms reaching to turntable -->
|
||||
<line x1="90" y1="150" x2="55" y2="195" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="170" y1="150" x2="205" y2="195" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Turntable body -->
|
||||
<rect x="30" y="200" width="200" height="18" rx="4" fill="currentColor" opacity="0.4"/>
|
||||
<!-- Turntable platter (ellipse for perspective) -->
|
||||
<ellipse cx="130" cy="200" rx="55" ry="15" fill="currentColor" opacity="0.25"/>
|
||||
<ellipse cx="130" cy="200" rx="55" ry="15" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.35"/>
|
||||
<!-- Record center -->
|
||||
<circle cx="130" cy="200" r="5" fill="currentColor" opacity="0.4"/>
|
||||
<!-- Tone arm -->
|
||||
<line x1="195" y1="188" x2="150" y2="195" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<circle cx="195" cy="188" r="3" fill="currentColor" opacity="0.35"/>
|
||||
<!-- Legs -->
|
||||
<line x1="115" y1="202" x2="105" y2="260" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="145" y1="202" x2="155" y2="260" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content">
|
||||
<header class="mb-12 text-center">
|
||||
<p class="mb-2 font-mono text-sm tracking-widest text-accent uppercase">{{ content?.kicker }}</p>
|
||||
@@ -107,4 +143,24 @@ const filteredSongs = computed(() => {
|
||||
.page-title {
|
||||
font-size: clamp(2rem, 5vw, 2.75rem);
|
||||
}
|
||||
|
||||
.shadok-dj {
|
||||
position: absolute;
|
||||
right: 2%;
|
||||
top: 3%;
|
||||
width: clamp(100px, 14vw, 190px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-accent));
|
||||
animation: shadok-float-dj 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-dj {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-dj { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,48 @@
|
||||
<template>
|
||||
<NuxtLayout>
|
||||
<div class="section-padding">
|
||||
<div class="relative overflow-hidden section-padding">
|
||||
<!-- Shadok alchemist: character stirring a cauldron with sparkles -->
|
||||
<svg class="shadok-alchemist" viewBox="0 0 240 320" fill="none" aria-hidden="true">
|
||||
<!-- Body -->
|
||||
<ellipse cx="120" cy="145" rx="40" ry="48" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head -->
|
||||
<circle cx="120" cy="82" r="24" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Wizard hat -->
|
||||
<polygon points="120,30 100,80 140,80" fill="currentColor" opacity="0.5"/>
|
||||
<line x1="100" y1="80" x2="140" y2="80" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.45"/>
|
||||
<!-- Hat star -->
|
||||
<circle cx="118" cy="55" r="3" fill="currentColor" opacity="0.25"/>
|
||||
<!-- Eyes (mischievous) -->
|
||||
<circle cx="111" cy="78" r="4.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="129" cy="78" r="4.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="112" cy="77" r="2" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="130" cy="77" r="2" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Grin -->
|
||||
<path d="M112 92 Q120 98 128 92" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.35"/>
|
||||
<!-- Arm holding spoon/stick -->
|
||||
<line x1="158" y1="140" x2="175" y2="210" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Other arm -->
|
||||
<path d="M82 145 Q65 165 70 185" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
|
||||
<!-- Cauldron -->
|
||||
<path d="M60 220 Q60 260 120 260 Q180 260 180 220" fill="currentColor" opacity="0.4"/>
|
||||
<ellipse cx="120" cy="220" rx="60" ry="15" fill="currentColor" opacity="0.3"/>
|
||||
<ellipse cx="120" cy="220" rx="60" ry="15" stroke="currentColor" stroke-width="2" fill="none" opacity="0.4"/>
|
||||
<!-- Cauldron legs -->
|
||||
<line x1="80" y1="258" x2="75" y2="280" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="160" y1="258" x2="165" y2="280" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Bubbles from cauldron -->
|
||||
<circle cx="100" cy="210" r="5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="135" cy="205" r="4" fill="currentColor" opacity="0.18"/>
|
||||
<circle cx="115" cy="198" r="3" fill="currentColor" opacity="0.15"/>
|
||||
<!-- Sparkles -->
|
||||
<circle cx="90" cy="190" r="2" fill="currentColor" opacity="0.25"/>
|
||||
<circle cx="150" cy="195" r="2.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="105" cy="185" r="1.5" fill="currentColor" opacity="0.2"/>
|
||||
<!-- Character legs -->
|
||||
<line x1="105" y1="190" x2="95" y2="225" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="135" y1="190" x2="145" y2="225" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.5"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content max-w-3xl mx-auto">
|
||||
<!-- Back link -->
|
||||
<UiScrollReveal>
|
||||
@@ -77,14 +119,14 @@ const { url, launch } = useGrateWizard()
|
||||
.gw-feature-card {
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid hsl(20 8% 18%);
|
||||
background: hsl(20 8% 8% / 0.5);
|
||||
border: 1px solid hsl(var(--color-text) / 0.1);
|
||||
background: hsl(var(--color-surface) / 0.5);
|
||||
transition: border-color 0.3s ease, background 0.3s ease;
|
||||
}
|
||||
|
||||
.gw-feature-card:hover {
|
||||
border-color: hsl(40 80% 50% / 0.25);
|
||||
background: hsl(20 8% 10% / 0.5);
|
||||
background: hsl(var(--color-surface-light) / 0.5);
|
||||
}
|
||||
|
||||
code {
|
||||
@@ -94,4 +136,24 @@ code {
|
||||
border-radius: 0.25em;
|
||||
background: hsl(40 80% 50% / 0.1);
|
||||
}
|
||||
|
||||
.shadok-alchemist {
|
||||
position: absolute;
|
||||
right: 2%;
|
||||
top: 15%;
|
||||
width: clamp(100px, 14vw, 190px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-accent));
|
||||
animation: shadok-float-alchemist 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-alchemist {
|
||||
0%, 100% { transform: translateY(0) rotate(0deg); }
|
||||
50% { transform: translateY(-10px) rotate(1deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-alchemist { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,54 @@
|
||||
<template>
|
||||
<div class="section-padding">
|
||||
<div class="relative overflow-hidden section-padding">
|
||||
<!-- Shadok reader: character with big glasses reading a book -->
|
||||
<svg class="shadok-reader" viewBox="0 0 240 300" fill="none" aria-hidden="true">
|
||||
<!-- Body -->
|
||||
<ellipse cx="120" cy="170" rx="45" ry="55" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head -->
|
||||
<circle cx="120" cy="100" r="28" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Big round glasses -->
|
||||
<circle cx="107" cy="94" r="11" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.5"/>
|
||||
<circle cx="133" cy="94" r="11" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.5"/>
|
||||
<line x1="118" y1="94" x2="122" y2="94" stroke="currentColor" stroke-width="2" opacity="0.5"/>
|
||||
<!-- Eyes behind glasses -->
|
||||
<circle cx="108" cy="93" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="134" cy="93" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Arms holding book -->
|
||||
<line x1="78" y1="155" x2="60" y2="180" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="162" y1="155" x2="180" y2="180" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Book (open) -->
|
||||
<rect x="55" y="175" width="55" height="40" rx="2" fill="currentColor" opacity="0.35"/>
|
||||
<rect x="110" y="175" width="55" height="40" rx="2" fill="currentColor" opacity="0.3"/>
|
||||
<line x1="110" y1="175" x2="110" y2="215" stroke="currentColor" stroke-width="2" opacity="0.5"/>
|
||||
<!-- Book lines (text) -->
|
||||
<line x1="65" y1="188" x2="100" y2="188" stroke="currentColor" stroke-width="1" opacity="0.2"/>
|
||||
<line x1="65" y1="195" x2="95" y2="195" stroke="currentColor" stroke-width="1" opacity="0.2"/>
|
||||
<line x1="65" y1="202" x2="98" y2="202" stroke="currentColor" stroke-width="1" opacity="0.2"/>
|
||||
<!-- Legs -->
|
||||
<line x1="105" y1="222" x2="95" y2="270" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="135" y1="222" x2="145" y2="270" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
</svg>
|
||||
|
||||
<!-- Shadok stack: pile of books tilting -->
|
||||
<svg class="shadok-stack" viewBox="0 0 160 220" fill="none" aria-hidden="true">
|
||||
<!-- Bottom book -->
|
||||
<rect x="20" y="170" width="120" height="22" rx="3" fill="currentColor" opacity="0.5" transform="rotate(-2 80 181)"/>
|
||||
<!-- Second book -->
|
||||
<rect x="30" y="145" width="100" height="20" rx="3" fill="currentColor" opacity="0.45" transform="rotate(3 80 155)"/>
|
||||
<!-- Third book -->
|
||||
<rect x="25" y="120" width="110" height="18" rx="3" fill="currentColor" opacity="0.4" transform="rotate(-4 80 129)"/>
|
||||
<!-- Fourth book -->
|
||||
<rect x="35" y="97" width="90" height="18" rx="3" fill="currentColor" opacity="0.35" transform="rotate(5 80 106)"/>
|
||||
<!-- Fifth book (tilting more) -->
|
||||
<rect x="40" y="74" width="80" height="17" rx="3" fill="currentColor" opacity="0.3" transform="rotate(-7 80 82)"/>
|
||||
<!-- Top book (really tilting) -->
|
||||
<rect x="45" y="52" width="70" height="16" rx="3" fill="currentColor" opacity="0.25" transform="rotate(10 80 60)"/>
|
||||
<!-- Tiny Shadok sitting on top -->
|
||||
<ellipse cx="85" cy="42" rx="10" ry="8" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="85" cy="30" r="6" fill="currentColor" opacity="0.45"/>
|
||||
<circle cx="87" cy="29" r="1.5" fill="currentColor" opacity="0.3"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-content">
|
||||
<header class="mb-12 text-center">
|
||||
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
|
||||
@@ -68,4 +117,41 @@ const { data: chapters } = await useAsyncData('book-toc', () =>
|
||||
.page-title {
|
||||
font-size: clamp(2rem, 5vw, 2.75rem);
|
||||
}
|
||||
|
||||
.shadok-reader {
|
||||
position: absolute;
|
||||
right: 2%;
|
||||
top: 5%;
|
||||
width: clamp(90px, 13vw, 180px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float-reader 9s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.shadok-stack {
|
||||
position: absolute;
|
||||
left: 2%;
|
||||
bottom: 5%;
|
||||
width: clamp(80px, 11vw, 150px);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-accent));
|
||||
animation: shadok-float-stack 11s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes shadok-float-reader {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
@keyframes shadok-float-stack {
|
||||
0%, 100% { transform: translateY(0) rotate(0deg); }
|
||||
50% { transform: translateY(-8px) rotate(-2deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-reader { display: none; }
|
||||
.shadok-stack { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -42,8 +42,8 @@ function formatDate(iso: string) {
|
||||
|
||||
<style scoped>
|
||||
.message-card {
|
||||
background: hsl(20 8% 6%);
|
||||
border: 1px solid hsl(20 8% 14%);
|
||||
background: hsl(var(--color-surface));
|
||||
border: 1px solid hsl(var(--color-text) / 0.1);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.25rem 1.5rem;
|
||||
}
|
||||
|
||||
118
app/stores/palette.ts
Normal file
118
app/stores/palette.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
export type PaletteName = 'automne' | 'hiver' | 'printemps' | 'ete'
|
||||
|
||||
interface PaletteColors {
|
||||
primary: string
|
||||
accent: string
|
||||
surface: string
|
||||
bg: string
|
||||
surfaceLight: string
|
||||
text: string
|
||||
textMuted: string
|
||||
isLight: boolean
|
||||
label: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
const palettes: Record<PaletteName, PaletteColors> = {
|
||||
// ══════ DARK THEMES ══════
|
||||
|
||||
// Automne : cuivre chaud, feuilles mortes, terre brûlée
|
||||
automne: {
|
||||
primary: '18 80% 45%', // cuivre profond
|
||||
accent: '32 85% 50%', // ambre doré
|
||||
surface: '16 12% 9%', // écorce sombre
|
||||
bg: '16 12% 4%', // terre noire
|
||||
surfaceLight: '16 10% 14%', // bois fumé
|
||||
text: '0 0% 100%',
|
||||
textMuted: '0 0% 60%',
|
||||
isLight: false,
|
||||
label: 'Automne',
|
||||
icon: 'i-lucide-leaf',
|
||||
},
|
||||
|
||||
// Hiver : bleu nuit, givre, argent lunaire
|
||||
hiver: {
|
||||
primary: '215 55% 52%', // bleu nuit étoilé
|
||||
accent: '195 40% 65%', // givre argenté
|
||||
surface: '220 15% 10%', // ciel de minuit
|
||||
bg: '225 18% 5%', // nuit polaire
|
||||
surfaceLight: '220 12% 15%', // brume nocturne
|
||||
text: '0 0% 100%',
|
||||
textMuted: '210 10% 60%',
|
||||
isLight: false,
|
||||
label: 'Hiver',
|
||||
icon: 'i-lucide-snowflake',
|
||||
},
|
||||
|
||||
// ══════ LIGHT THEMES ══════
|
||||
|
||||
// Printemps : vert tendre, rose cerisier, lumière fraîche
|
||||
printemps: {
|
||||
primary: '145 50% 38%', // vert bourgeon
|
||||
accent: '340 65% 55%', // rose cerisier
|
||||
surface: '120 12% 93%', // rosée du matin
|
||||
bg: '100 15% 96%', // clarté verte
|
||||
surfaceLight: '120 8% 87%', // feuille pâle
|
||||
text: '150 15% 12%', // vert profond
|
||||
textMuted: '140 8% 42%', // mousse
|
||||
isLight: true,
|
||||
label: 'Printemps',
|
||||
icon: 'i-lucide-flower-2',
|
||||
},
|
||||
|
||||
// Été : doré solaire, turquoise mer, lumineux chaleureux
|
||||
ete: {
|
||||
primary: '25 85% 52%', // soleil couchant
|
||||
accent: '175 55% 42%', // turquoise marin
|
||||
surface: '40 25% 92%', // sable clair
|
||||
bg: '42 30% 96%', // lumière dorée
|
||||
surfaceLight: '38 18% 86%', // dune
|
||||
text: '30 20% 12%', // terre chaude
|
||||
textMuted: '30 10% 40%', // ombre estivale
|
||||
isLight: true,
|
||||
label: 'Été',
|
||||
icon: 'i-lucide-sun',
|
||||
},
|
||||
}
|
||||
|
||||
export const usePaletteStore = defineStore('palette', () => {
|
||||
const currentPalette = ref<PaletteName>(
|
||||
(import.meta.client && localStorage.getItem('palette') as PaletteName) || 'automne',
|
||||
)
|
||||
|
||||
const colors = computed(() => palettes[currentPalette.value])
|
||||
const isLight = computed(() => colors.value.isLight)
|
||||
|
||||
function applyToDOM() {
|
||||
if (!import.meta.client) return
|
||||
const c = colors.value
|
||||
const root = document.documentElement
|
||||
const s = root.style
|
||||
s.setProperty('--color-primary', c.primary)
|
||||
s.setProperty('--color-accent', c.accent)
|
||||
s.setProperty('--color-surface', c.surface)
|
||||
s.setProperty('--color-bg', c.bg)
|
||||
s.setProperty('--color-surface-light', c.surfaceLight)
|
||||
s.setProperty('--color-text', c.text)
|
||||
s.setProperty('--color-text-muted', c.textMuted)
|
||||
// Toggle light/dark class for CSS overrides
|
||||
root.classList.toggle('palette-light', c.isLight)
|
||||
root.classList.toggle('palette-dark', !c.isLight)
|
||||
s.setProperty('color-scheme', c.isLight ? 'light' : 'dark')
|
||||
}
|
||||
|
||||
function setPalette(name: PaletteName) {
|
||||
currentPalette.value = name
|
||||
if (import.meta.client) localStorage.setItem('palette', name)
|
||||
applyToDOM()
|
||||
}
|
||||
|
||||
return {
|
||||
currentPalette,
|
||||
colors,
|
||||
palettes,
|
||||
isLight,
|
||||
setPalette,
|
||||
applyToDOM,
|
||||
}
|
||||
})
|
||||
@@ -7,18 +7,16 @@ readingTime: "25 min"
|
||||
|
||||
Coder un rêve
|
||||
|
||||
\[Verse\]
|
||||
Dans l'ombre des géants big tek
|
||||
Des lignes poussent discrètes
|
||||
Tourné vers la grande ourse
|
||||
Je coule open source
|
||||
|
||||
\[Prechorus\]
|
||||
Balance ton Jiz Onne
|
||||
Balance ton Json
|
||||
mon shell résonne
|
||||
Coup de dés Py - thon Runtime Upgrade, ninja blayde
|
||||
Ça bilt, Docker compose. Devant l'écran je pose. Ca biilt.
|
||||
shhhhhhh... it com paille ...llss,
|
||||
Coup de dés Python Runtime Upgrade, ninja blade
|
||||
Ça build, Docker compose. Devant l'écran je pose. Ça build.
|
||||
shhhhhhh... it compiles ...llss,
|
||||
tapis dans une typo sans serif, je check les certif
|
||||
merde ça lag,
|
||||
mate mes log,
|
||||
@@ -26,14 +24,13 @@ j'ai la langue qui bog.
|
||||
Mon café est tout froid
|
||||
Je ne perds pas la foi.
|
||||
|
||||
\[Chorus\]
|
||||
Codeurs de rêv
|
||||
Codeurs de rêve
|
||||
Rime pour les dèvs
|
||||
dans les réseaux, où que j'aille
|
||||
vous êtes mes sudo,
|
||||
mes samouraï
|
||||
Hackers, Admin,
|
||||
Dèvop, développ
|
||||
Devop, develop
|
||||
Vous décentralisez
|
||||
Vous open sourcez
|
||||
Un monde moins obscur
|
||||
@@ -41,7 +38,6 @@ Duniterre bien sûr.
|
||||
Notre toil fiduciaire
|
||||
Nous pouvez être fiers
|
||||
|
||||
\[Verse 2\]
|
||||
Appel aux ressources
|
||||
Donner vie au code source
|
||||
Léger besoin de finance
|
||||
@@ -53,7 +49,6 @@ Du fuel pour les applis
|
||||
tous vos dons ... les mettent à l'abri
|
||||
Merci
|
||||
|
||||
\[Bridge\]
|
||||
Crash à minuit
|
||||
Je reste éveillé
|
||||
Le bug fatal
|
||||
@@ -63,14 +58,13 @@ Je vais le basher
|
||||
Le café est-il prêt ?
|
||||
C'est bientôt aujourd'hui
|
||||
|
||||
\[Chorus\]
|
||||
Codeurs de rêv
|
||||
Codeurs de rêve
|
||||
Rime pour les dèvs
|
||||
dans les réseaux, où que j'aille
|
||||
vous êtes mes sudo,
|
||||
mes samouraï
|
||||
Hackers, Admin,
|
||||
Dèvop, développ
|
||||
Devop, develop
|
||||
Vous décentralisez
|
||||
Vous open sourcez
|
||||
Un monde moins obscur
|
||||
|
||||
@@ -7,12 +7,6 @@ readingTime: "15 min"
|
||||
|
||||
Inverser les flux
|
||||
|
||||
\[Intro\]
|
||||
\[Guitar vibraphone : Accords riches et harmoniques\]
|
||||
\[Basse : Une ligne très ronde qui glisse\]
|
||||
\[Cut Brass swell\]
|
||||
\[Articulte, french\]
|
||||
|
||||
Tu choisis ... ta monnaie,
|
||||
son économie,
|
||||
Tu passes de l'une à l'autre
|
||||
@@ -23,22 +17,18 @@ Tu peux aussi ne plus l'appeler monnaie du tout.
|
||||
Changer de lunettes, (mais pas les rose)
|
||||
c'est un ruban-mètre, posé sur la planète.
|
||||
|
||||
\[Chorus\]
|
||||
(Groove s'intensifie, la batterie claque)
|
||||
Le D.U, c'est une mesure.
|
||||
(Choir: La mesure...)
|
||||
Pour ne plus obliger. Pour ne plus devoir.
|
||||
Je donne à mon économie, j'alimente le réservoir.
|
||||
\[break\]
|
||||
Si je t'aime, j'y mets mon affect.
|
||||
Si je ne t'aime pas, du moins je te respecte.
|
||||
Je compte sur les autres, sur mon économie,
|
||||
Pour y trouver ma pleine mesure.
|
||||
La solidarité organique, pas de paniK
|
||||
La solidarité organique, pas de panique
|
||||
Elle franchit les limites.
|
||||
(Choir: Organique...)
|
||||
|
||||
\[Verse 1\]
|
||||
"Je ne veux rien en retour", c'est ce que tu dis.
|
||||
Mais tu m'obliges.
|
||||
Tu crées une dette non dite,
|
||||
@@ -47,7 +37,6 @@ La solidarité mécanique est complexe
|
||||
Elle a ses limites.
|
||||
(Whisper: C'est horrible pour les mites)
|
||||
|
||||
\[Le rythme devient plus sec, plus percussif. Flow rapide\]
|
||||
Alors j'opère un retournement.
|
||||
Je choisis mes mots, c'est un glissement.
|
||||
(...)
|
||||
@@ -65,10 +54,9 @@ La "dépossession monétaire" n'a plus lieu d'être.
|
||||
Ce n'est plus mortifère, ni délétère.
|
||||
(...)
|
||||
Je rentre du marché, nouveau vocabulaire :
|
||||
\[Male\]- "Hey - j'ai reçu une semaine de cour-ss."
|
||||
\[Female\]- "Wow, t'as mis gratitude max à la source ?"
|
||||
(Male) - "Hey - j'ai reçu une semaine de cours."
|
||||
(Female) - "Wow, t'as mis gratitude max à la source ?"
|
||||
|
||||
\[Bridge - Duet Call & Response\]
|
||||
(Male) Je ne paye plus.
|
||||
(Female) Je mesure. J'estime...
|
||||
(Male) Je négocie détendu. (c'est un virage)
|
||||
@@ -77,16 +65,13 @@ Je rentre du marché, nouveau vocabulaire :
|
||||
(Female) De la masse.
|
||||
(Both) Ou une température.
|
||||
L'économie, c'est de l'énergie, de la chaleur c'est sûr.
|
||||
\[break\] Je grave ma gratitude dans la chaîne.
|
||||
Je grave ma gratitude dans la chaîne.
|
||||
C'est une trans-action. Au sens noble du terme.
|
||||
|
||||
\[Chorus - Ensemble\]
|
||||
(Groove s'intensifie, la batterie claque)
|
||||
Le D.U, c'est une mesure.
|
||||
(Choir: La mesure...)
|
||||
Pour ne plus obliger. Pour ne plus devoir.
|
||||
Je donne à mon économie, j'alimente le réservoir.
|
||||
\[break\]
|
||||
Si je t'aime, j'y mets mon affect.
|
||||
Si je ne t'aime pas, du moins je te respecte.
|
||||
Je compte sur les autres, sur mon économie,
|
||||
@@ -95,8 +80,6 @@ La solidarité organique, pas de panique
|
||||
Elle franchit les limites.
|
||||
(Choir: Organique...)
|
||||
|
||||
\[Verse 3 - Male Lead\]
|
||||
\[Musique s'épure, Basse et Claquements de doigts. Question tone\]
|
||||
Dis,... et quand c'est la course ? Si c'est une buvette ?
|
||||
Pas le temps des discours, philosopher sur la canette ?
|
||||
(Female : Faut qu'ça dépote !)
|
||||
@@ -107,21 +90,14 @@ Ils ont posé leurs références.
|
||||
Tu prends ou pas, tu vois si c'est bon,
|
||||
tu entres dans la danse.
|
||||
Tu peux gratifier plus, si le cœur t'en dit.
|
||||
Plaider un co-eff. relatif aussi...
|
||||
Plaider un coeff. relatif aussi...
|
||||
Mais la mesure est là, autour d'un bel invariant, on sait où on va.
|
||||
(...)
|
||||
Au delà d'un simple théorème
|
||||
C'est le cadeau de la T.R.M.
|
||||
|
||||
\[Outro\]
|
||||
(Female ad-libs: Équilibre... Invariant...)
|
||||
\[Rhodes solo, jazzy and improvised\]
|
||||
\[Male spoken sexy\]
|
||||
On frotte nos échelles.
|
||||
On construit avec les autres.
|
||||
(Fade out on the warm bass line)
|
||||
\[Female sexy\]
|
||||
Construction culturelle.
|
||||
\[break smooth\]
|
||||
J'évalue mon degré de gratitude
|
||||
Pour que ça devienne une habitude.
|
||||
|
||||
@@ -7,12 +7,6 @@ readingTime: "25 min"
|
||||
|
||||
Inverser les flux
|
||||
|
||||
\[Intro\]
|
||||
\[Guitar vibraphone : Accords riches et harmoniques\]
|
||||
\[Basse : Une ligne très ronde qui glisse\]
|
||||
\[Cut Brass swell\]
|
||||
\[Articulte, french\]
|
||||
|
||||
Tu choisis ... ta monnaie,
|
||||
son économie,
|
||||
Tu passes de l'une à l'autre
|
||||
@@ -23,22 +17,18 @@ Tu peux aussi ne plus l'appeler monnaie du tout.
|
||||
Changer de lunettes, (mais pas les rose)
|
||||
c'est un ruban-mètre, posé sur la planète.
|
||||
|
||||
\[Chorus\]
|
||||
(Groove s'intensifie, la batterie claque)
|
||||
Le D.U, c'est une mesure.
|
||||
(Choir: La mesure...)
|
||||
Pour ne plus obliger. Pour ne plus devoir.
|
||||
Je donne à mon économie, j'alimente le réservoir.
|
||||
\[break\]
|
||||
Si je t'aime, j'y mets mon affect.
|
||||
Si je ne t'aime pas, du moins je te respecte.
|
||||
Je compte sur les autres, sur mon économie,
|
||||
Pour y trouver ma pleine mesure.
|
||||
La solidarité organique, pas de paniK
|
||||
La solidarité organique, pas de panique
|
||||
Elle franchit les limites.
|
||||
(Choir: Organique...)
|
||||
|
||||
\[Verse 1\]
|
||||
"Je ne veux rien en retour", c'est ce que tu dis.
|
||||
Mais tu m'obliges.
|
||||
Tu crées une dette non dite,
|
||||
@@ -47,7 +37,6 @@ La solidarité mécanique est complexe
|
||||
Elle a ses limites.
|
||||
(Whisper: C'est horrible pour les mites)
|
||||
|
||||
\[Le rythme devient plus sec, plus percussif. Flow rapide\]
|
||||
Alors j'opère un retournement.
|
||||
Je choisis mes mots, c'est un glissement.
|
||||
(...)
|
||||
@@ -65,10 +54,9 @@ La "dépossession monétaire" n'a plus lieu d'être.
|
||||
Ce n'est plus mortifère, ni délétère.
|
||||
(...)
|
||||
Je rentre du marché, nouveau vocabulaire :
|
||||
\[Male\]- "Hey - j'ai reçu une semaine de cour-ss."
|
||||
\[Female\]- "Wow, t'as mis gratitude max à la source ?"
|
||||
(Male) - "Hey - j'ai reçu une semaine de cours."
|
||||
(Female) - "Wow, t'as mis gratitude max à la source ?"
|
||||
|
||||
\[Bridge - Duet Call & Response\]
|
||||
(Male) Je ne paye plus.
|
||||
(Female) Je mesure. J'estime...
|
||||
(Male) Je négocie détendu. (c'est un virage)
|
||||
@@ -77,16 +65,13 @@ Je rentre du marché, nouveau vocabulaire :
|
||||
(Female) De la masse.
|
||||
(Both) Ou une température.
|
||||
L'économie, c'est de l'énergie, de la chaleur c'est sûr.
|
||||
\[break\] Je grave ma gratitude dans la chaîne.
|
||||
Je grave ma gratitude dans la chaîne.
|
||||
C'est une trans-action. Au sens noble du terme.
|
||||
|
||||
\[Chorus - Ensemble\]
|
||||
(Groove s'intensifie, la batterie claque)
|
||||
Le D.U, c'est une mesure.
|
||||
(Choir: La mesure...)
|
||||
Pour ne plus obliger. Pour ne plus devoir.
|
||||
Je donne à mon économie, j'alimente le réservoir.
|
||||
\[break\]
|
||||
Si je t'aime, j'y mets mon affect.
|
||||
Si je ne t'aime pas, du moins je te respecte.
|
||||
Je compte sur les autres, sur mon économie,
|
||||
@@ -95,8 +80,6 @@ La solidarité organique, pas de panique
|
||||
Elle franchit les limites.
|
||||
(Choir: Organique...)
|
||||
|
||||
\[Verse 3 - Male Lead\]
|
||||
\[Musique s'épure, Basse et Claquements de doigts. Question tone\]
|
||||
Dis,... et quand c'est la course ? Si c'est une buvette ?
|
||||
Pas le temps des discours, philosopher sur la canette ?
|
||||
(Female : Faut qu'ça dépote !)
|
||||
@@ -107,21 +90,14 @@ Ils ont posé leurs références.
|
||||
Tu prends ou pas, tu vois si c'est bon,
|
||||
tu entres dans la danse.
|
||||
Tu peux gratifier plus, si le cœur t'en dit.
|
||||
Plaider un co-eff. relatif aussi...
|
||||
Plaider un coeff. relatif aussi...
|
||||
Mais la mesure est là, autour d'un bel invariant, on sait où on va.
|
||||
(...)
|
||||
Au delà d'un simple théorème
|
||||
C'est le cadeau de la T.R.M.
|
||||
|
||||
\[Outro\]
|
||||
(Female ad-libs: Équilibre... Invariant...)
|
||||
\[Rhodes solo, jazzy and improvised\]
|
||||
\[Male spoken sexy\]
|
||||
On frotte nos échelles.
|
||||
On construit avec les autres.
|
||||
(Fade out on the warm bass line)
|
||||
\[Female sexy\]
|
||||
Construction culturelle.
|
||||
\[break smooth\]
|
||||
J'évalue mon degré de gratitude
|
||||
Pour que ça devienne une habitude.
|
||||
|
||||
@@ -7,9 +7,6 @@ readingTime: "20 min"
|
||||
|
||||
Les asymétries
|
||||
|
||||
\[Intro\]
|
||||
(Cello and Bowed Bass: low, scraping texture)
|
||||
(Piano: Single discordant note repeated)
|
||||
(Male: Voix très posée, grave, proche)
|
||||
Entre soi... Connivence fait loi.
|
||||
On est entre nous On se rassure.
|
||||
@@ -19,12 +16,10 @@ Nous sommes trop convaincus.
|
||||
Cela nous endort. Ce que je crois peut-être à tord ... tue.
|
||||
(Females: Pseudo-isolés... Pseudo-isolés...)
|
||||
|
||||
\[Verse 1\]
|
||||
(Drums enter: intricate brushwork, soft but fast)
|
||||
J'ai vu des collectifs, plus ou moins dissruptifs.
|
||||
Parfois prônant le don, par exemple Solariss.
|
||||
J'ai vu des collectifs, plus ou moins disruptifs.
|
||||
Parfois prônant le don, par exemple Solaris.
|
||||
J'y ai vu de l'usure, le sentiment d'abus.
|
||||
Des abandons moribons, ...
|
||||
Des abandons moribonds, ...
|
||||
Ha bon ?
|
||||
|
||||
Malgré quelques notifs, et les esprits attentifs
|
||||
@@ -32,8 +27,6 @@ Parfois nous le savons, dans les violons on pisse
|
||||
J'ai vu aussi bien sûr, quelques trous du cul
|
||||
Mais ! Est-ce là une bonne raison ?
|
||||
|
||||
\[Bridge 1\]
|
||||
(Rhythm becomes jagged, syncopated stops)
|
||||
Rien n'est symétrique, ce n'est pas magique.
|
||||
(Females: ) Rien.
|
||||
Une pomme aujourd'hui, n'est pas la même demain.
|
||||
@@ -42,10 +35,7 @@ Et s'il y a une cagette, ce n'est pas cinq palettes.
|
||||
Six heures assis à parler bien à l'aise...
|
||||
Six heures à genoux sur un toit...ho ! balaise
|
||||
(Females:) Est-ce le même geste, ou une ascèse ? mmmhh.
|
||||
(Silence - 1 second)
|
||||
|
||||
\[Chorus\]
|
||||
(Music swells slightly, singing questions)
|
||||
Alors que faire ? On désespère, on baisse les bras ?
|
||||
on légifère ? On écrit des lois ?
|
||||
On réglemente, on décide de l'issue ?
|
||||
@@ -54,8 +44,6 @@ Mieux vaut peut-être un protocole avec quelques bémol.
|
||||
Une façon de traiter, d'éviter de juger, préfigurer.
|
||||
(suspension) Ne pas tranchez les sorts, à leur insu.
|
||||
|
||||
\[Verse 2\]
|
||||
(Bass is now plucked, heavy groove)
|
||||
Pour limiter le ressentiment,
|
||||
la lassitude, l'envenime-ment.
|
||||
Il suffit d'une mesure.
|
||||
@@ -68,7 +56,6 @@ Qui célèbre le mérite ? - Dans l'ombre du monde ;
|
||||
Pas celui des héritages ? - Ce s'rait possible ça ?
|
||||
Qui réellement, récompense et compense ? sans dépense ni dispense ?
|
||||
|
||||
\[Bridge 2\]
|
||||
Une communauté ne peut pas tout écrire.
|
||||
La loi, ne peut pas tout régler.
|
||||
même si c'est toi qui la fait
|
||||
@@ -77,8 +64,6 @@ Une belle et grande morale ? - c'est bancal :
|
||||
Il est utile de prévenir, se souvenir, ...
|
||||
C'est le pire.
|
||||
|
||||
\[Chorus\]
|
||||
(Music swells slightly)
|
||||
Alors que faire ? On désespère, on baisse les bras ?
|
||||
on légifère ? On écrit des lois ?
|
||||
On réglemente, on décide de l'issue ?
|
||||
@@ -88,23 +73,18 @@ Une façon de traiter, d'éviter de juger, préfigurer.
|
||||
(suspension) Ne pas tranchez les sorts, à leur insu.
|
||||
(suspension) Ne tranchez pas mon sort, à mon insu.
|
||||
|
||||
\[Bridge 1\]
|
||||
(Rhythm becomes jagged, syncopated stops)
|
||||
Rien n'est symétrique. Ce n'est pas magique.
|
||||
(Females:) Rien.
|
||||
Pour se rétablir, retomber sur nos pieds
|
||||
Il existe un outil qui s'appelle, ... "la monnaie".
|
||||
|
||||
\[Verse 3\]
|
||||
C'est elle en permanence qui résout le "schmilblick".
|
||||
Même sans qu'on y pense, faut avouer, c'est pratique
|
||||
C'est elle qui compense, récompense ou dispense
|
||||
Mais attention, délit de pleine flagrance ! (drum, suspension)
|
||||
Mais attention, délit de pleine flagrance !
|
||||
Chaque monnaie programme sa propre engence.
|
||||
Ne t'y méprends pas, son pouvoir est immense.
|
||||
|
||||
\[Outro\]
|
||||
(Piano flowing arpeggios, fading)
|
||||
Résoudre le problème des asymétries.
|
||||
Réduire le besoin de légiférer.
|
||||
Pour une simple coloc... ou pour un monde entier.
|
||||
|
||||
@@ -7,7 +7,6 @@ readingTime: "18 min"
|
||||
|
||||
Désir des arts
|
||||
|
||||
\[Intro\]
|
||||
La matière est peu docile
|
||||
L'esprit est agile
|
||||
Il désire l'art
|
||||
@@ -15,19 +14,16 @@ Les mains sont habiles
|
||||
précieuses et volubiles
|
||||
Elles façonnent des amarres
|
||||
|
||||
\[Pont\]
|
||||
C'est reparti pour un tour
|
||||
Pour le désir des arts
|
||||
Nous voilà de retour
|
||||
Vous nous avez manqué
|
||||
|
||||
\[Refrain\]
|
||||
Les mains habiles
|
||||
L'esprit agile
|
||||
La matière plus docile
|
||||
Sous le geste de l'émotion
|
||||
|
||||
\[Couplet 1\]
|
||||
Les structures sont solides
|
||||
Les intentions fluides
|
||||
Notre équipe est unie
|
||||
@@ -35,13 +31,11 @@ Prête pour l'inédit
|
||||
Nous serons à vos côtés
|
||||
En ce lieu de toute beauté
|
||||
|
||||
\[Refrain\]
|
||||
Les mains habiles
|
||||
L'esprit agile
|
||||
La matière plus docile
|
||||
Sous le geste de l'émotion
|
||||
|
||||
\[Couplet 2\]
|
||||
Qu'ils soient cent
|
||||
Qu'ils soient mille
|
||||
Curieux ou passionnés
|
||||
@@ -51,13 +45,11 @@ Partout est l'attrait
|
||||
Touchez sans les gants
|
||||
Ici le désir vrille
|
||||
|
||||
\[Refrain\]
|
||||
Les mains habiles
|
||||
L'esprit agile
|
||||
La matière plus docile
|
||||
Sous le geste de l'émotion
|
||||
|
||||
\[Outro\]
|
||||
L'Art est de retour
|
||||
Il célèbre l'amour
|
||||
Demain un autre jour
|
||||
|
||||
@@ -7,14 +7,9 @@ readingTime: "8 min"
|
||||
|
||||
Ainsi soit-il
|
||||
|
||||
\[Intro\]
|
||||
\[Vinyl Crackle Sound\]
|
||||
\[Minimalist Piano Loop\]
|
||||
Fiat...
|
||||
Fiat Lux… Fiat Euro.
|
||||
|
||||
\[Verse 1\]
|
||||
\[Spoken Word, Calm and Clear\]
|
||||
Fiat. Ce n'est pas une marque.
|
||||
C'est du latin.
|
||||
Ça veut dire : "Que cela soit".
|
||||
@@ -25,15 +20,11 @@ Un monopole déclaré.
|
||||
Une clé de voûte qui tient tout l'édifice.
|
||||
Si la clé casse... tout s'écroule.
|
||||
|
||||
\[Chorus\]
|
||||
\[Melodic Hook, Softly Sung\]
|
||||
Mais la monnaie n'est pas la richesse.
|
||||
C'est juste le mètre... pas le tissu.
|
||||
C'est le baromètre... pas le climat.
|
||||
Ne confondons pas la carte et le territoire.
|
||||
|
||||
\[Verse 2\]
|
||||
\[Rhythmic Spoken, Slightly Faster\]
|
||||
Message aux pionniers :
|
||||
Faire tourner la monnaie en rond, ce n'est pas créer.
|
||||
Se faire des virements autour d'une table...
|
||||
@@ -45,19 +36,12 @@ L'économie, c'est "passer la seconde".
|
||||
C'est produire. Transformer.
|
||||
Le reste ? C'est de la comptabilité.
|
||||
|
||||
\[Bridge\]
|
||||
\[Bass Line Drops\]
|
||||
\[Pause\]
|
||||
Notre monnaie-dette a un code génétique.
|
||||
Elle programme le manque. Elle programme la course.
|
||||
Mais le DU...
|
||||
Le DU change le code source.
|
||||
|
||||
\[Outro\]
|
||||
\[Fading Music\]
|
||||
\[Whispered\]
|
||||
Même accès pour tous.
|
||||
Même pouvoir de création.
|
||||
Ce n'est plus "Que la dette soit".
|
||||
C'est "Que l'équilibre soit".
|
||||
\[Silence\]
|
||||
|
||||
@@ -5,7 +5,6 @@ order: 1
|
||||
readingTime: "15 min"
|
||||
---
|
||||
|
||||
\[Intro\]
|
||||
Ce livre est un essai.
|
||||
Une proposition.
|
||||
Une intention.
|
||||
@@ -13,16 +12,14 @@ Une invitation.
|
||||
(...)
|
||||
Une façon.
|
||||
|
||||
\[bridge\]
|
||||
Deux mille vingt'-quatre j'écris tout l'été, ...
|
||||
Deux mille vingt'-cinq je mûris toute l'année, ...
|
||||
Deux mille vingt'-siss la sortie... mmmmhh,
|
||||
Deux mille vingt-quatre j'écris tout l'été, ...
|
||||
Deux mille vingt-cinq je mûris toute l'année, ...
|
||||
Deux mille vingt-six la sortie... mmmmhh,
|
||||
Le temps pass
|
||||
Est-ce une menace ?
|
||||
|
||||
\[Verse 1\]
|
||||
Pour éviter tout quiproquo :
|
||||
Pour mieux zaimer le propos
|
||||
Pour mieux aimer le propos
|
||||
Ce n'est pas une théorie.
|
||||
Pas d'u-niversalité.
|
||||
Loin s'en faut.
|
||||
@@ -34,20 +31,17 @@ Civile et artistique
|
||||
Mais si ça reste à ton échelle... c'est symbolique.
|
||||
Viser mon bassin de vie ? ça se complique.
|
||||
|
||||
\[Chorus\]
|
||||
Ce livre n'est pas un guiDe,
|
||||
Ce livre n'est pas un guide,
|
||||
davantage un guit'.
|
||||
Ce n'est pas un Kit.
|
||||
Ce n'est pas un kit.
|
||||
Ça ne dit pas quoi faire lundi.
|
||||
|
||||
\[Bridge\]
|
||||
Tu veux une baguette magique ?
|
||||
Supprimer la pression, l'oppression ? - Ce s'rait pas con...
|
||||
Si je ne résous pas mes problèmes d'aujourd'hui... à quoi bon ?
|
||||
Naviguer dans le ciel des idées...
|
||||
C'est fini !
|
||||
|
||||
\[Verse 2\]
|
||||
Créer une économie ?
|
||||
On en a déjà une. Tu veux décrocher la lune ?
|
||||
Elle couvre mes besoins vitaux. De facto.
|
||||
@@ -62,33 +56,29 @@ restez là sans mot dire,
|
||||
"restez des enfants !"...
|
||||
mmh, suspect et sans avenir.
|
||||
|
||||
\[Bridge\]
|
||||
Deux mille vingt-six. L'année des défis.
|
||||
Ne plus subir les agendas. Créer les nôtr'.
|
||||
On manque de repères ?... Entre autres, ...
|
||||
Faut les trouver,...
|
||||
En produisant, les inventer.
|
||||
|
||||
\[Chorus\]
|
||||
Ce livre n'est pas un guiDe,
|
||||
Ce livre n'est pas un guide,
|
||||
davantage un guit'.
|
||||
Ce n'est pas un Kit.
|
||||
Ce n'est pas un kit.
|
||||
Ça ne dit pas quoi faire lundi.
|
||||
|
||||
\[Bridge 2\]
|
||||
C'est un os à ronger.
|
||||
Une cartographie. Quelques boussoles.
|
||||
Dans une jungle à défricher.
|
||||
Ce n'est pas encore l'heure...
|
||||
Du prêtà-porter.
|
||||
Du prêt-à-porter.
|
||||
A nous de tailler.
|
||||
|
||||
\[outro\]
|
||||
On tourne une page pour voir ?
|
||||
Décline le rôle de la bonne poire...
|
||||
Je n'ai pas que l'espoir
|
||||
J'ai un pouvoir
|
||||
Tu as bien mieux que l'espoir,
|
||||
Nous - zavons un grand pouvoir.
|
||||
Nous avons un grand pouvoir.
|
||||
|
||||
(whisper :) hey, on tourne une page ?
|
||||
|
||||
@@ -5,17 +5,12 @@ order: 3
|
||||
readingTime: "8 min"
|
||||
---
|
||||
|
||||
\[Intro\]
|
||||
(Piano Rhodes : accords jazzy)
|
||||
(Basse : Ligne ronde et enveloppante)
|
||||
|
||||
Une économie du don ?
|
||||
Mais de quel don nous parlons ?
|
||||
Ce mariage fait peur. Il claque.
|
||||
Un oxymore, on l'apprend juste après l'bac.
|
||||
Une contradiction pour l'esprit.
|
||||
|
||||
\[Verse 1\]
|
||||
On évacue tout de suite le spirituel.
|
||||
Désolé pour le karma, désolé pour le ciel.
|
||||
Je ne parle pas du "centuple divin".
|
||||
@@ -25,7 +20,6 @@ Ici, c'est un geste. Juste un geste.
|
||||
Qui sert de base, qui sert de fondation,
|
||||
À une autre forme de construction.
|
||||
|
||||
\[Chorus\]
|
||||
Ce n'est pas l'image d'Épinal, le don gratuit, le don idéal.
|
||||
Marcel Mauss nous l'a dit, dans son essai radical.
|
||||
Ce n'est pas un cadeau, c'est un cycle vital.
|
||||
@@ -35,7 +29,6 @@ C'est un pacte, une tension, parfois même un combat.
|
||||
Si tu ne redonnes pas, si tu enfreins le protocole...
|
||||
Ça ne pardonne pas.
|
||||
|
||||
\[Verse 2\]
|
||||
J'entends les rêves de brûler la monnaie.
|
||||
"Le troc", "la gratuité", "Mocica", le grand projet.
|
||||
La monnaie serait le vice, la corruption mentale.
|
||||
@@ -46,8 +39,6 @@ La monnaie-dette, celle qui nous tient, celle qui nous guette.
|
||||
Mais si la monnaie est libre ? Elle permet les équilibres.
|
||||
Si elle devient notre outil ? Elle change le récit.
|
||||
|
||||
\[Bridge\]
|
||||
(Music strips down. Just Bass and Snare rimshots)
|
||||
Le don qui se mesure, donne la mesure.
|
||||
C'est quand tu donnes ton temps, ton énergie, ta sueur,
|
||||
Que tu crées ton propre étalon de valeur.
|
||||
@@ -56,7 +47,6 @@ Puis silence. Le geste pose un nouveau décor.
|
||||
Le don — c'est pas une perte.
|
||||
Le don — c'est le début d'un accord.
|
||||
|
||||
\[Chorus 2\]
|
||||
Ce n'est pas l'image d'Épinal, le don gratuit, le don idéal.
|
||||
Marcel Mauss nous l'a dit, dans son essai radical.
|
||||
Ce n'est pas un cadeau, c'est un cycle vital.
|
||||
@@ -64,7 +54,6 @@ Ce n'est pas un cadeau, c'est un cycle vital.
|
||||
Le don qui se mesure, donne la mesure.
|
||||
Le don qui se mesure, donne la mesure.
|
||||
|
||||
\[Outro\]
|
||||
De quel don nous parlons ?
|
||||
...Celui qui construit.
|
||||
Celui qui nous relie.
|
||||
|
||||
@@ -7,7 +7,6 @@ readingTime: "35 min"
|
||||
|
||||
Hymne à la monnaie libre
|
||||
|
||||
\[Verse\]
|
||||
Des cercles qui se croisent
|
||||
Sans les regards qui toisent
|
||||
Des poings qui se détendent
|
||||
@@ -18,7 +17,6 @@ Un futur qui s'écrit
|
||||
Un souffle tout petit
|
||||
Pas de chaînes pour les pensées
|
||||
|
||||
\[Chorus\]
|
||||
Construire des vies
|
||||
Nos cœurs qui grossissent
|
||||
Couvrir nos besoins
|
||||
@@ -34,7 +32,6 @@ Y consacrer nos vies
|
||||
Si tu en as la fibre
|
||||
C'est l'hymne à la monnaie libre
|
||||
|
||||
\[Verse 2\]
|
||||
Les jours se lèvent sur des rêves partagés
|
||||
Quelques champs pour les possibles
|
||||
Des ponts à imaginer
|
||||
@@ -43,7 +40,6 @@ Pas de trône
|
||||
Juste l'humanité
|
||||
Est-elle si pénible ?
|
||||
|
||||
\[Bridge\]
|
||||
Ni maîtres ni esclaves
|
||||
Juste un écho
|
||||
Des esprits qui dansent
|
||||
@@ -51,7 +47,6 @@ Dans des corps qui pensent
|
||||
Un chant nouveau
|
||||
Surmontent les entraves
|
||||
|
||||
\[Chorus\]
|
||||
Construire des vies
|
||||
Nos cœurs qui grossissent
|
||||
Couvrir nos besoins
|
||||
|
||||
@@ -7,7 +7,6 @@ readingTime: "30 min"
|
||||
|
||||
Hymne à la monnaie libre
|
||||
|
||||
\[Verse\]
|
||||
Des cercles qui se croisent
|
||||
Sans les regards qui toisent
|
||||
Des poings qui se détendent
|
||||
@@ -18,7 +17,6 @@ Un futur qui s'écrit
|
||||
Un souffle tout petit
|
||||
Pas de chaînes pour les pensées
|
||||
|
||||
\[Chorus\]
|
||||
Construire des vies
|
||||
Nos cœurs qui grossissent
|
||||
Couvrir nos besoins
|
||||
@@ -34,7 +32,6 @@ Y consacrer nos vies
|
||||
Si tu en as la fibre
|
||||
C'est l'hymne à la monnaie libre
|
||||
|
||||
\[Verse 2\]
|
||||
Les jours se lèvent sur des rêves partagés
|
||||
Quelques champs pour les possibles
|
||||
Des ponts à imaginer
|
||||
@@ -43,7 +40,6 @@ Pas de trône
|
||||
Juste l'humanité
|
||||
Est-elle si pénible ?
|
||||
|
||||
\[Bridge\]
|
||||
Ni maîtres ni esclaves
|
||||
Juste un écho
|
||||
Des esprits qui dansent
|
||||
@@ -51,7 +47,6 @@ Dans des corps qui pensent
|
||||
Un chant nouveau
|
||||
Surmontent les entraves
|
||||
|
||||
\[Chorus\]
|
||||
Construire des vies
|
||||
Nos cœurs qui grossissent
|
||||
Couvrir nos besoins
|
||||
|
||||
@@ -7,14 +7,9 @@ readingTime: "20 min"
|
||||
|
||||
Ainsi soit-il
|
||||
|
||||
\[Intro\]
|
||||
\[Vinyl Crackle Sound\]
|
||||
\[Minimalist Piano Loop\]
|
||||
Fiat...
|
||||
Fiat Lux… Fiat Euro.
|
||||
|
||||
\[Verse 1\]
|
||||
\[Spoken Word, Calm and Clear\]
|
||||
Fiat. Ce n'est pas une marque.
|
||||
C'est du latin.
|
||||
Ça veut dire : "Que cela soit".
|
||||
@@ -25,15 +20,11 @@ Un monopole déclaré.
|
||||
Une clé de voûte qui tient tout l'édifice.
|
||||
Si la clé casse... tout s'écroule.
|
||||
|
||||
\[Chorus\]
|
||||
\[Melodic Hook, Softly Sung\]
|
||||
Mais la monnaie n'est pas la richesse.
|
||||
C'est juste le mètre... pas le tissu.
|
||||
C'est le baromètre... pas le climat.
|
||||
Ne confondons pas la carte et le territoire.
|
||||
|
||||
\[Verse 2\]
|
||||
\[Rhythmic Spoken, Slightly Faster\]
|
||||
Message aux pionniers :
|
||||
Faire tourner la monnaie en rond, ce n'est pas créer.
|
||||
Se faire des virements autour d'une table...
|
||||
@@ -45,19 +36,12 @@ L'économie, c'est "passer la seconde".
|
||||
C'est produire. Transformer.
|
||||
Le reste ? C'est de la comptabilité.
|
||||
|
||||
\[Bridge\]
|
||||
\[Bass Line Drops\]
|
||||
\[Pause\]
|
||||
Notre monnaie-dette a un code génétique.
|
||||
Elle programme le manque. Elle programme la course.
|
||||
Mais le DU...
|
||||
Le DU change le code source.
|
||||
|
||||
\[Outro\]
|
||||
\[Fading Music\]
|
||||
\[Whispered\]
|
||||
Même accès pour tous.
|
||||
Même pouvoir de création.
|
||||
Ce n'est plus "Que la dette soit".
|
||||
C'est "Que l'équilibre soit".
|
||||
\[Silence\]
|
||||
|
||||
26
public/images/shadoks/shadok-bird.svg
Normal file
26
public/images/shadoks/shadok-bird.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 260" fill="none">
|
||||
<!-- Body: round absurd bird -->
|
||||
<ellipse cx="90" cy="100" rx="45" ry="40" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Head: tilted -->
|
||||
<circle cx="130" cy="60" r="22" fill="currentColor" opacity="0.8"/>
|
||||
<!-- Neck -->
|
||||
<path d="M110 85 Q125 70 128 63" stroke="currentColor" stroke-width="8" stroke-linecap="round" opacity="0.7" fill="none"/>
|
||||
<!-- Eye -->
|
||||
<circle cx="136" cy="55" r="5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="137" cy="54" r="2" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Beak: long, absurd -->
|
||||
<polygon points="150,58 175,50 152,65" fill="currentColor" opacity="0.6"/>
|
||||
<!-- Long legs -->
|
||||
<line x1="75" y1="138" x2="60" y2="230" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="105" y1="138" x2="115" y2="230" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Knees (knobby) -->
|
||||
<circle cx="66" cy="190" r="4" fill="currentColor" opacity="0.4"/>
|
||||
<circle cx="111" cy="190" r="4" fill="currentColor" opacity="0.4"/>
|
||||
<!-- Feet -->
|
||||
<path d="M60 230 L45 233 M60 230 L55 236 M60 230 L65 235" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<path d="M115 230 L100 233 M115 230 L110 236 M115 230 L120 235" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Tail feathers -->
|
||||
<path d="M48 95 Q20 80 15 65" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5" fill="none"/>
|
||||
<path d="M48 100 Q22 92 10 85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4" fill="none"/>
|
||||
<path d="M48 105 Q25 102 12 100" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
14
public/images/shadoks/shadok-blob.svg
Normal file
14
public/images/shadoks/shadok-blob.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 180" fill="none">
|
||||
<!-- Amorphous blob shape -->
|
||||
<path d="M60 90 Q30 50 70 30 Q110 10 140 40 Q180 60 170 100 Q165 140 130 155 Q90 170 55 145 Q25 125 60 90Z" fill="currentColor" opacity="0.12"/>
|
||||
<path d="M60 90 Q30 50 70 30 Q110 10 140 40 Q180 60 170 100 Q165 140 130 155 Q90 170 55 145 Q25 125 60 90Z" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
|
||||
<!-- Inner texture -->
|
||||
<circle cx="100" cy="80" r="8" fill="currentColor" opacity="0.08"/>
|
||||
<circle cx="120" cy="110" r="6" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="80" cy="105" r="5" fill="currentColor" opacity="0.07"/>
|
||||
<!-- Tiny eyes (personality) -->
|
||||
<circle cx="95" cy="72" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="108" cy="70" r="3" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="96" cy="71" r="1.2" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="109" cy="69" r="1.2" fill="currentColor" opacity="0.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 977 B |
45
public/images/shadoks/shadok-pattern.svg
Normal file
45
public/images/shadoks/shadok-pattern.svg
Normal file
@@ -0,0 +1,45 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 80" fill="none">
|
||||
<!-- Repeating mini-shadok pattern -->
|
||||
<!-- Shadok 1 -->
|
||||
<g transform="translate(20,10)">
|
||||
<ellipse cx="15" cy="25" rx="12" ry="14" fill="currentColor" opacity="0.08"/>
|
||||
<circle cx="15" cy="10" r="7" fill="currentColor" opacity="0.06"/>
|
||||
<line x1="10" y1="38" x2="8" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
<line x1="20" y1="38" x2="22" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
</g>
|
||||
<!-- Shadok 2 -->
|
||||
<g transform="translate(80,15)">
|
||||
<ellipse cx="15" cy="22" rx="10" ry="12" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="15" cy="8" r="6" fill="currentColor" opacity="0.05"/>
|
||||
<line x1="10" y1="33" x2="8" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
<line x1="20" y1="33" x2="22" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
</g>
|
||||
<!-- Shadok 3 -->
|
||||
<g transform="translate(140,8)">
|
||||
<ellipse cx="15" cy="25" rx="11" ry="13" fill="currentColor" opacity="0.07"/>
|
||||
<circle cx="15" cy="10" r="6.5" fill="currentColor" opacity="0.06"/>
|
||||
<line x1="10" y1="37" x2="7" y2="54" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
<line x1="20" y1="37" x2="23" y2="54" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
</g>
|
||||
<!-- Shadok 4 -->
|
||||
<g transform="translate(210,18)">
|
||||
<ellipse cx="15" cy="20" rx="10" ry="11" fill="currentColor" opacity="0.05"/>
|
||||
<circle cx="15" cy="7" r="5.5" fill="currentColor" opacity="0.04"/>
|
||||
<line x1="10" y1="30" x2="9" y2="44" stroke="currentColor" stroke-width="1.5" opacity="0.04"/>
|
||||
<line x1="20" y1="30" x2="21" y2="44" stroke="currentColor" stroke-width="1.5" opacity="0.04"/>
|
||||
</g>
|
||||
<!-- Shadok 5 -->
|
||||
<g transform="translate(270,12)">
|
||||
<ellipse cx="15" cy="24" rx="12" ry="14" fill="currentColor" opacity="0.07"/>
|
||||
<circle cx="15" cy="9" r="7" fill="currentColor" opacity="0.06"/>
|
||||
<line x1="10" y1="37" x2="7" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
<line x1="20" y1="37" x2="23" y2="55" stroke="currentColor" stroke-width="1.5" opacity="0.06"/>
|
||||
</g>
|
||||
<!-- Shadok 6 -->
|
||||
<g transform="translate(340,16)">
|
||||
<ellipse cx="15" cy="22" rx="10" ry="12" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="15" cy="8" r="6" fill="currentColor" opacity="0.05"/>
|
||||
<line x1="10" y1="33" x2="8" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
<line x1="20" y1="33" x2="22" y2="48" stroke="currentColor" stroke-width="1.5" opacity="0.05"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
17
public/images/shadoks/shadok-planet.svg
Normal file
17
public/images/shadoks/shadok-planet.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" fill="none">
|
||||
<!-- Planet body -->
|
||||
<circle cx="100" cy="100" r="70" fill="currentColor" opacity="0.15"/>
|
||||
<circle cx="100" cy="100" r="70" stroke="currentColor" stroke-width="2" opacity="0.3"/>
|
||||
<!-- Craters -->
|
||||
<circle cx="80" cy="75" r="15" fill="currentColor" opacity="0.08"/>
|
||||
<circle cx="120" cy="110" r="20" fill="currentColor" opacity="0.06"/>
|
||||
<circle cx="90" cy="130" r="10" fill="currentColor" opacity="0.1"/>
|
||||
<!-- Ring / orbit -->
|
||||
<ellipse cx="100" cy="100" rx="95" ry="25" stroke="currentColor" stroke-width="1.5" opacity="0.2" transform="rotate(-20 100 100)"/>
|
||||
<!-- Small moons -->
|
||||
<circle cx="30" cy="50" r="8" fill="currentColor" opacity="0.25"/>
|
||||
<circle cx="175" cy="140" r="5" fill="currentColor" opacity="0.2"/>
|
||||
<!-- Surface features -->
|
||||
<path d="M65 90 Q75 85 85 90" stroke="currentColor" stroke-width="1.5" opacity="0.15" fill="none"/>
|
||||
<path d="M105 120 Q115 115 125 118" stroke="currentColor" stroke-width="1.5" opacity="0.12" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
24
public/images/shadoks/shadok-pumper.svg
Normal file
24
public/images/shadoks/shadok-pumper.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 240" fill="none">
|
||||
<!-- Body: ovoid shape -->
|
||||
<ellipse cx="100" cy="130" rx="55" ry="65" fill="currentColor" opacity="0.9"/>
|
||||
<!-- Head: smaller oval on top -->
|
||||
<ellipse cx="100" cy="60" rx="30" ry="28" fill="currentColor" opacity="0.85"/>
|
||||
<!-- Eyes -->
|
||||
<circle cx="88" cy="54" r="6" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="112" cy="54" r="6" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="90" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="114" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<!-- Beak -->
|
||||
<polygon points="100,68 115,78 85,78" fill="currentColor" opacity="0.6"/>
|
||||
<!-- Legs -->
|
||||
<line x1="80" y1="192" x2="70" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
|
||||
<line x1="120" y1="192" x2="130" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
|
||||
<!-- Feet -->
|
||||
<line x1="70" y1="230" x2="55" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="130" y1="230" x2="145" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Pump handle -->
|
||||
<line x1="155" y1="110" x2="190" y2="90" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="190" y1="90" x2="190" y2="120" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
|
||||
<!-- Pump body -->
|
||||
<rect x="180" y="118" width="18" height="40" rx="3" fill="currentColor" opacity="0.4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -20,9 +20,10 @@ export default defineConfig({
|
||||
presetWebFonts({
|
||||
provider: 'bunny',
|
||||
fonts: {
|
||||
display: 'Syne:400,500,600,700,800',
|
||||
sans: 'Space Grotesk:300,400,500,600,700',
|
||||
display: 'Outfit:400,500,600,700,800',
|
||||
sans: 'Inter:300,400,500,600,700',
|
||||
mono: 'JetBrains Mono:400,500,700',
|
||||
calligraphy: 'Playfair Display:400,700',
|
||||
},
|
||||
}),
|
||||
],
|
||||
@@ -33,47 +34,47 @@ export default defineConfig({
|
||||
theme: {
|
||||
colors: {
|
||||
primary: {
|
||||
DEFAULT: 'hsl(12, 76%, 48%)',
|
||||
50: 'hsl(12, 76%, 95%)',
|
||||
100: 'hsl(12, 76%, 88%)',
|
||||
200: 'hsl(12, 76%, 76%)',
|
||||
300: 'hsl(12, 76%, 64%)',
|
||||
400: 'hsl(12, 76%, 56%)',
|
||||
500: 'hsl(12, 76%, 48%)',
|
||||
600: 'hsl(12, 76%, 40%)',
|
||||
700: 'hsl(12, 76%, 33%)',
|
||||
800: 'hsl(12, 76%, 26%)',
|
||||
900: 'hsl(12, 76%, 18%)',
|
||||
DEFAULT: 'hsl(var(--color-primary))',
|
||||
50: 'hsl(18, 80%, 95%)',
|
||||
100: 'hsl(18, 80%, 88%)',
|
||||
200: 'hsl(18, 80%, 76%)',
|
||||
300: 'hsl(18, 80%, 64%)',
|
||||
400: 'hsl(18, 80%, 56%)',
|
||||
500: 'hsl(var(--color-primary))',
|
||||
600: 'hsl(18, 80%, 38%)',
|
||||
700: 'hsl(18, 80%, 30%)',
|
||||
800: 'hsl(18, 80%, 24%)',
|
||||
900: 'hsl(18, 80%, 16%)',
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: 'hsl(36, 80%, 52%)',
|
||||
50: 'hsl(36, 80%, 95%)',
|
||||
100: 'hsl(36, 80%, 88%)',
|
||||
200: 'hsl(36, 80%, 76%)',
|
||||
300: 'hsl(36, 80%, 66%)',
|
||||
400: 'hsl(36, 80%, 58%)',
|
||||
500: 'hsl(36, 80%, 52%)',
|
||||
600: 'hsl(36, 80%, 44%)',
|
||||
700: 'hsl(36, 80%, 36%)',
|
||||
800: 'hsl(36, 80%, 28%)',
|
||||
900: 'hsl(36, 80%, 20%)',
|
||||
DEFAULT: 'hsl(var(--color-accent))',
|
||||
50: 'hsl(32, 85%, 95%)',
|
||||
100: 'hsl(32, 85%, 88%)',
|
||||
200: 'hsl(32, 85%, 76%)',
|
||||
300: 'hsl(32, 85%, 66%)',
|
||||
400: 'hsl(32, 85%, 58%)',
|
||||
500: 'hsl(var(--color-accent))',
|
||||
600: 'hsl(32, 85%, 42%)',
|
||||
700: 'hsl(32, 85%, 34%)',
|
||||
800: 'hsl(32, 85%, 26%)',
|
||||
900: 'hsl(32, 85%, 18%)',
|
||||
},
|
||||
surface: {
|
||||
DEFAULT: 'hsl(20, 8%, 8%)',
|
||||
50: 'hsl(20, 8%, 22%)',
|
||||
100: 'hsl(20, 8%, 18%)',
|
||||
200: 'hsl(20, 8%, 13%)',
|
||||
300: 'hsl(20, 8%, 10%)',
|
||||
400: 'hsl(20, 8%, 8%)',
|
||||
500: 'hsl(20, 8%, 6%)',
|
||||
600: 'hsl(20, 8%, 4%)',
|
||||
bg: 'hsl(20, 8%, 3.5%)',
|
||||
DEFAULT: 'hsl(var(--color-surface))',
|
||||
50: 'hsl(16, 12%, 22%)',
|
||||
100: 'hsl(16, 12%, 18%)',
|
||||
200: 'hsl(16, 12%, 13%)',
|
||||
300: 'hsl(16, 12%, 10%)',
|
||||
400: 'hsl(var(--color-surface))',
|
||||
500: 'hsl(16, 12%, 6%)',
|
||||
600: 'hsl(16, 12%, 4%)',
|
||||
bg: 'hsl(var(--color-bg))',
|
||||
},
|
||||
},
|
||||
},
|
||||
shortcuts: {
|
||||
'btn-primary': 'inline-flex items-center justify-center px-6 py-3 rounded-lg bg-primary text-white font-display font-semibold tracking-wide transition-all duration-200 hover:bg-primary-600 hover:scale-105 active:scale-95',
|
||||
'btn-accent': 'inline-flex items-center justify-center px-6 py-3 rounded-lg bg-accent text-surface-bg font-display font-semibold tracking-wide transition-all duration-200 hover:bg-accent-600 hover:scale-105 active:scale-95',
|
||||
'btn-primary': 'inline-flex items-center justify-center px-6 py-3 rounded-lg bg-primary text-white font-display font-semibold tracking-wide border-none transition-all duration-200 hover:bg-primary-600 hover:scale-105 active:scale-95',
|
||||
'btn-accent': 'inline-flex items-center justify-center px-6 py-3 rounded-lg bg-accent text-surface-bg font-display font-semibold tracking-wide border-none transition-all duration-200 hover:bg-accent-600 hover:scale-105 active:scale-95',
|
||||
'btn-ghost': 'inline-flex items-center justify-center px-4 py-2 rounded-lg border-none text-white/70 font-sans transition-all duration-200 hover:bg-white/10 hover:text-white',
|
||||
'card-surface': 'rounded-xl bg-surface border border-white/8 p-6 transition-all duration-300 hover:border-primary/30 hover:shadow-lg hover:shadow-primary/5',
|
||||
'text-gradient': 'bg-gradient-to-r from-primary-300 to-accent bg-clip-text text-transparent',
|
||||
|
||||
Reference in New Issue
Block a user