Restructure Engagement Forgeron + fix GenesisBlock + InertiaSlider

- Seed: restructure Engagement Forgeron (51→59 items) avec 3 nouvelles
  sections: Engagements fondamentaux (EF1-EF3), Engagements techniques
  (ET1-ET3), Qualification (Q0-Q1) liée au protocole Embarquement
- Seed: ajout protocole Embarquement Forgeron (5 jalons: candidature,
  miroir, évaluation, certification Smith, mise en ligne)
- GenesisBlock: fix lisibilité — fond mood-surface teinté accent au lieu
  de mood-text inversé, texte mood-aware au lieu de rgba blanc hardcodé
- InertiaSlider: mini affiche "Inertie" sous le curseur, compact en
  width:fit-content pour s'adapter au label
- Frontend: ajout section qualification dans SECTION_META/SECTION_ORDER
- Pages, composants et tests des sprints précédents

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-03-03 03:44:33 +01:00
parent 4212e847d4
commit c19c1aa55e
16 changed files with 3002 additions and 361 deletions

View File

@@ -37,7 +37,6 @@ const steps = [
<template>
<div>
<UButton
label="Comment ça marche ?"
icon="i-lucide-circle-help"
variant="ghost"
color="neutral"

View File

@@ -257,17 +257,17 @@ function navigateToItem() {
}
.engagement-card__body {
padding: 0.75rem 1rem 1rem;
padding: 0.5rem 1rem 0.625rem;
cursor: pointer;
font-size: 0.9375rem;
line-height: 1.7;
font-size: 0.875rem;
line-height: 1.5;
color: var(--mood-text);
}
@media (min-width: 640px) {
.engagement-card__body {
font-size: 1rem;
line-height: 1.75;
font-size: 0.9375rem;
line-height: 1.55;
}
}
@@ -284,7 +284,7 @@ function navigateToItem() {
}
.engagement-card__inertia {
padding: 0.375rem 1rem;
padding: 0.25rem 1rem 0.5rem;
opacity: 0.6;
transition: opacity 0.2s;
}

View File

@@ -50,15 +50,6 @@ const genesis = computed((): GenesisData | null => {
}
})
const statusColor = (status: string) => {
switch (status) {
case 'rejected': return 'error'
case 'in_progress': return 'warning'
case 'reference': return 'info'
default: return 'neutral'
}
}
const statusLabel = (status: string) => {
switch (status) {
case 'rejected': return 'Rejetée'
@@ -67,6 +58,15 @@ const statusLabel = (status: string) => {
default: return status
}
}
const statusClass = (status: string) => {
switch (status) {
case 'rejected': return 'genesis-status--rejected'
case 'in_progress': return 'genesis-status--progress'
case 'reference': return 'genesis-status--reference'
default: return 'genesis-status--default'
}
}
</script>
<template>
@@ -81,18 +81,17 @@ const statusLabel = (status: string) => {
<UIcon name="i-lucide-file-archive" class="text-lg" />
</div>
<div class="text-left">
<h3 class="text-sm font-bold uppercase tracking-wide" style="color: var(--mood-accent)">
<h3 class="text-sm font-bold uppercase tracking-wide genesis-accent">
Bloc de genèse
</h3>
<p class="text-xs" style="color: var(--mood-text-muted)">
<p class="text-xs genesis-text-muted">
Sources, références et formule de dépôt
</p>
</div>
</div>
<UIcon
:name="expanded ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
class="text-lg"
style="color: var(--mood-text-muted)"
class="text-lg genesis-muted-icon"
/>
</button>
@@ -108,13 +107,12 @@ const statusLabel = (status: string) => {
</h4>
<UIcon
:name="sectionOpen.source ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
class="text-sm"
style="color: var(--mood-text-muted)"
class="text-sm genesis-muted-icon"
/>
</button>
<div v-if="sectionOpen.source" class="genesis-section__content">
<div class="genesis-card">
<p class="font-medium text-sm" style="color: var(--mood-text)">
<p class="font-medium text-sm genesis-text">
{{ genesis.source_document.title }}
</p>
<div class="flex flex-col gap-1 mt-2">
@@ -150,8 +148,7 @@ const statusLabel = (status: string) => {
</h4>
<UIcon
:name="sectionOpen.tools ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
class="text-sm"
style="color: var(--mood-text-muted)"
class="text-sm genesis-muted-icon"
/>
</button>
<div v-if="sectionOpen.tools" class="genesis-section__content">
@@ -164,10 +161,10 @@ const statusLabel = (status: string) => {
rel="noopener"
class="genesis-card genesis-card--tool"
>
<span class="text-xs font-semibold capitalize" style="color: var(--mood-text)">
<span class="text-xs font-semibold capitalize genesis-text">
{{ name.replace(/_/g, ' ') }}
</span>
<UIcon name="i-lucide-external-link" class="text-xs" style="color: var(--mood-text-muted)" />
<UIcon name="i-lucide-external-link" class="text-xs genesis-text-muted" />
</a>
</div>
</div>
@@ -182,8 +179,7 @@ const statusLabel = (status: string) => {
</h4>
<UIcon
:name="sectionOpen.forum ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
class="text-sm"
style="color: var(--mood-text-muted)"
class="text-sm genesis-muted-icon"
/>
</button>
<div v-if="sectionOpen.forum" class="genesis-section__content">
@@ -197,19 +193,17 @@ const statusLabel = (status: string) => {
class="genesis-card genesis-card--forum"
>
<div class="flex items-start justify-between gap-2">
<span class="text-xs font-medium" style="color: var(--mood-text)">
<span class="text-xs font-medium genesis-text">
{{ topic.title }}
</span>
<UBadge
:color="statusColor(topic.status)"
variant="subtle"
size="xs"
class="shrink-0"
<span
class="genesis-status shrink-0"
:class="statusClass(topic.status)"
>
{{ statusLabel(topic.status) }}
</UBadge>
</span>
</div>
<span v-if="topic.posts" class="text-xs" style="color: var(--mood-text-muted)">
<span v-if="topic.posts" class="text-xs genesis-text-muted">
{{ topic.posts }} messages
</span>
</a>
@@ -226,13 +220,12 @@ const statusLabel = (status: string) => {
</h4>
<UIcon
:name="sectionOpen.process ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
class="text-sm"
style="color: var(--mood-text-muted)"
class="text-sm genesis-muted-icon"
/>
</button>
<div v-if="sectionOpen.process" class="genesis-section__content">
<div class="genesis-card">
<p class="text-xs leading-relaxed" style="color: var(--mood-text)">
<p class="text-xs leading-relaxed genesis-text">
{{ genesis.formula_trigger }}
</p>
</div>
@@ -248,8 +241,7 @@ const statusLabel = (status: string) => {
</h4>
<UIcon
:name="sectionOpen.contributors ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
class="text-sm"
style="color: var(--mood-text-muted)"
class="text-sm genesis-muted-icon"
/>
</button>
<div v-if="sectionOpen.contributors" class="genesis-section__content">
@@ -259,8 +251,8 @@ const statusLabel = (status: string) => {
:key="c.name"
class="genesis-contributor"
>
<span class="font-semibold text-xs" style="color: var(--mood-text)">{{ c.name }}</span>
<span class="text-xs" style="color: var(--mood-text-muted)">{{ c.role }}</span>
<span class="font-semibold text-xs genesis-text">{{ c.name }}</span>
<span class="text-xs genesis-text-muted">{{ c.role }}</span>
</div>
</div>
</div>
@@ -272,10 +264,10 @@ const statusLabel = (status: string) => {
<style scoped>
.genesis-block {
background: var(--mood-surface);
background: color-mix(in srgb, var(--mood-accent) 8%, var(--mood-surface));
border: 1px solid color-mix(in srgb, var(--mood-accent) 15%, transparent);
border-radius: 16px;
overflow: hidden;
border: 1px solid color-mix(in srgb, var(--mood-accent) 15%, transparent);
}
.genesis-block__header {
@@ -290,7 +282,15 @@ const statusLabel = (status: string) => {
}
.genesis-block__header:hover {
background: color-mix(in srgb, var(--mood-accent) 5%, transparent);
background: color-mix(in srgb, var(--mood-accent) 4%, transparent);
}
.genesis-block__header h3 {
color: var(--mood-accent) !important;
}
.genesis-block__header p {
color: var(--mood-text-muted) !important;
}
.genesis-block__icon {
@@ -300,7 +300,7 @@ const statusLabel = (status: string) => {
align-items: center;
justify-content: center;
border-radius: 10px;
background: color-mix(in srgb, var(--mood-accent) 12%, transparent);
background: color-mix(in srgb, var(--mood-accent) 15%, transparent);
color: var(--mood-accent);
}
@@ -314,7 +314,7 @@ const statusLabel = (status: string) => {
.genesis-section {
border-radius: 10px;
overflow: hidden;
background: color-mix(in srgb, var(--mood-accent) 2%, transparent);
background: color-mix(in srgb, var(--mood-accent) 4%, var(--mood-bg));
}
.genesis-section__toggle {
@@ -330,7 +330,7 @@ const statusLabel = (status: string) => {
}
.genesis-section__toggle:hover {
background: color-mix(in srgb, var(--mood-accent) 5%, transparent);
background: color-mix(in srgb, var(--mood-accent) 6%, transparent);
}
.genesis-section__title {
@@ -345,6 +345,10 @@ const statusLabel = (status: string) => {
margin: 0;
}
.genesis-section__toggle .text-sm {
color: var(--mood-text-muted) !important;
}
.genesis-section__content {
padding: 0 0.75rem 0.75rem;
}
@@ -352,7 +356,13 @@ const statusLabel = (status: string) => {
.genesis-card {
padding: 0.75rem;
border-radius: 10px;
background: color-mix(in srgb, var(--mood-accent) 4%, var(--mood-bg));
background: color-mix(in srgb, var(--mood-accent) 5%, var(--mood-surface));
}
.genesis-card .font-medium,
.genesis-card .text-xs,
.genesis-text {
color: var(--mood-text) !important;
}
.genesis-card--tool {
@@ -363,8 +373,12 @@ const statusLabel = (status: string) => {
transition: background 0.15s;
}
.genesis-card--tool .text-xs {
color: var(--mood-text) !important;
}
.genesis-card--tool:hover {
background: color-mix(in srgb, var(--mood-accent) 10%, var(--mood-bg));
background: color-mix(in srgb, var(--mood-accent) 10%, var(--mood-surface));
}
.genesis-card--forum {
@@ -376,7 +390,7 @@ const statusLabel = (status: string) => {
}
.genesis-card--forum:hover {
background: color-mix(in srgb, var(--mood-accent) 10%, var(--mood-bg));
background: color-mix(in srgb, var(--mood-accent) 10%, var(--mood-surface));
}
.genesis-link {
@@ -398,7 +412,64 @@ const statusLabel = (status: string) => {
flex-direction: column;
padding: 0.5rem 0.75rem;
border-radius: 8px;
background: color-mix(in srgb, var(--mood-accent) 4%, var(--mood-bg));
background: color-mix(in srgb, var(--mood-accent) 5%, var(--mood-surface));
}
.genesis-contributor .font-semibold {
color: var(--mood-text) !important;
}
.genesis-contributor .text-xs:not(.font-semibold) {
color: var(--mood-text-muted) !important;
}
/* Status badges — palette-aware */
.genesis-status {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 20px;
font-size: 0.625rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.genesis-status--reference {
background: color-mix(in srgb, var(--mood-accent) 20%, transparent);
color: var(--mood-accent);
}
.genesis-status--progress {
background: color-mix(in srgb, var(--mood-warning) 20%, transparent);
color: var(--mood-warning);
}
.genesis-status--rejected {
background: color-mix(in srgb, var(--mood-error) 20%, transparent);
color: var(--mood-error);
}
.genesis-status--default {
background: color-mix(in srgb, var(--mood-text) 8%, transparent);
color: var(--mood-text-muted);
}
/* Genesis-context text utilities */
.genesis-accent {
color: var(--mood-accent) !important;
}
.genesis-text {
color: var(--mood-text) !important;
}
.genesis-text-muted {
color: var(--mood-text-muted) !important;
}
.genesis-muted-icon {
color: var(--mood-text-muted) !important;
}
/* Expand/collapse transition */

View File

@@ -7,8 +7,10 @@
const props = withDefaults(defineProps<{
preset: string
compact?: boolean
mini?: boolean
}>(), {
compact: false,
mini: false,
})
interface InertiaLevel {
@@ -105,7 +107,7 @@ const allCurves = computed(() => {
</script>
<template>
<div class="inertia" :class="{ 'inertia--compact': compact }">
<div class="inertia" :class="{ 'inertia--compact': compact, 'inertia--mini': mini }">
<!-- Slider track -->
<div class="inertia__track">
<div class="inertia__fill" :style="{ width: `${level.position}%`, background: level.color }" />
@@ -124,7 +126,12 @@ const allCurves = computed(() => {
</div>
<!-- Label row -->
<div class="inertia__info">
<div v-if="mini" class="inertia__info">
<span class="inertia__label inertia__label--mini" :style="{ color: level.color }">
Inertie
</span>
</div>
<div v-else class="inertia__info">
<span class="inertia__label" :style="{ color: level.color }">
{{ level.label }}
</span>
@@ -223,6 +230,23 @@ const allCurves = computed(() => {
.inertia--compact {
gap: 0.25rem;
width: fit-content;
}
.inertia--mini {
gap: 0.125rem;
width: fit-content;
min-width: 3rem;
}
.inertia--mini .inertia__track {
height: 3px;
}
.inertia--mini .inertia__thumb {
width: 8px;
height: 8px;
border-width: 2px;
}
.inertia__track {
@@ -295,6 +319,13 @@ const allCurves = computed(() => {
font-size: 0.625rem;
}
.inertia__label--mini {
font-size: 0.5625rem;
font-weight: 600;
text-transform: none;
letter-spacing: 0;
}
.inertia__params {
font-size: 0.625rem;
font-family: monospace;