/* ==========================================================================
   Design system — course à pied d'abord, déclinable aux autres sports
   Style direction: performance. Pure black, pure white, one volt accent --
   the palette of a start list and a finish clock, not of a consumer app.
   Maximum contrast everywhere: true #000 on true #fff, square corners, heavy
   condensed capitals. Nothing is tinted for comfort.

   THE ONE RULE ABOUT VOLT: it is a *fill*, never small text. #d6ff00 on white
   is roughly 1.4:1 -- illegible. So volt paints surfaces (buttons, progress,
   badges, the found-match marker) with black type on top, and it is only ever
   used as a text colour on dark surfaces. Wherever the accent used to be
   small red text on a light background, it is now black: on a black / white /
   volt palette that reads as deliberate, not as a missing colour.
   Type: Archivo (headlines & labels, uppercase) / Inter (body).
   ========================================================================== */

:root {
  --ink: #000000;
  --ink-raised: #121214;
  --ink-soft: #52525b;
  --accent: #d6ff00;
  --accent-deep: #b4d900;   /* volt hover -- still a fill, still not text */
  --accent-soft: #e9ff66;   /* volt on dark surfaces only */
  --tint: #f2ffbf;
  --tint-2: #f4f4f5;
  --paper: #ffffff;
  --line: #e4e4e7;
  --white: #ffffff;
  --success: #1f8a5f;
  --success-bg: rgba(31, 138, 95, 0.12);
  --warning: #b3690a;
  --warning-bg: rgba(179, 105, 10, 0.12);
  --error: #dc2626;
  --error-bg: rgba(220, 38, 38, 0.08);
  /* Near-square: a 2px radius still softens the pixel edge but reads as a
     machined rectangle rather than a rounded card. */
  --radius-lg: 4px;
  --radius-md: 3px;
  --radius-sm: 2px;
  --shadow-soft: 0 16px 34px -16px rgba(0, 0, 0, 0.4);
  --shadow-card: 0 1px 0 rgba(0, 0, 0, 0.05), 0 14px 28px -20px rgba(0, 0, 0, 0.3);
  --max-width: 1180px;
  --font-display: "Archivo", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.04;
  margin: 0 0 0.5em;
  letter-spacing: -0.02em;
  color: var(--ink);
}
/* Capitals on the display headlines only -- the big statements. Card titles
   (h3) stay sentence case: a paragraph's worth of French in uppercase stops
   being readable. */
.hero h1, .section-title, .cta-final h2 {
  text-transform: uppercase;
  font-weight: 900;
  letter-spacing: -0.015em;
}

p { margin: 0 0 1em; color: var(--ink-soft); }
a { color: inherit; }

img { max-width: 100%; display: block; }

.lead { font-size: 1.15rem; color: var(--ink-soft); max-width: 46ch; }

/* Black label, volt square. The square is how the accent gets onto a white
   page at all: as a solid 8px fill it reads instantly, where volt text would
   disappear. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  color: var(--ink);
  font-weight: 800;
  margin: 0 0 0.9em;
}
.eyebrow::before {
  content: "";
  width: 9px;
  height: 9px;
  flex-shrink: 0;
  background: var(--accent);
}
.eyebrow a { color: inherit; text-decoration: none; }

/* Used inside the hero headline, i.e. always on the dark photo -- the one
   place the accent is allowed to be type rather than a fill. */
.accent { color: var(--accent); }

/* --- Pulse mark (logo) --------------------------------------------------
   A minimal three-bar glyph -- short / tall / medium -- inside a viewfinder.
   An asymmetric "pulse" -- effort, cadence, a heartbeat on a screen. It read
   for a while as the three disciplines of a triathlon; now that the product
   targets plain road races, the original reading simply comes back, and the
   mark needs no redrawing. One inline SVG, styled
   with currentColor, so it drops cleanly into any context: dark header on
   the hero photo, plain ink on white pages, light on the footer. --------- */

.pulse-mark { display: inline-block; width: 22px; height: 22px; flex-shrink: 0; }
.pulse-mark.small { width: 16px; height: 16px; }
.pulse-mark svg { display: block; width: 100%; height: 100%; }
/* Four corner brackets -- a viewfinder/focus reticle, symbolic of what the
   product actually does (detect and lock onto a face) -- framing three
   small pulse bars at the center. */
.pulse-mark path {
  fill: none;
  stroke: var(--pulse-fill, var(--ink));
  stroke-width: 2.4;
  stroke-linecap: round;
}
.pulse-mark rect {
  /* A dedicated custom property, not `currentColor` -- several containers
     that use this mark (the demo arrow, etc.) set `color` for
     unrelated text, and that must never leak into the mark's fill. */
  fill: var(--pulse-fill, var(--ink));
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: pulse-bar 1.6s ease-in-out infinite;
}
.pulse-mark rect:nth-of-type(1) { animation-delay: 0s; }
.pulse-mark rect:nth-of-type(2) { animation-delay: 0.15s; }
.pulse-mark rect:nth-of-type(3) { animation-delay: 0.3s; }
/* The one highlighted bar follows the same rule as everything else: volt is a
   fill, and on a white header a 2.6px volt bar would vanish -- so it stays ink
   there and only turns volt on the dark surfaces that can carry it. */
.pulse-mark .pulse-accent { fill: var(--pulse-accent-fill, var(--ink)); }
.page-landing .site-header .pulse-mark,
.footer-brand .pulse-mark,
.processing-card .pulse-mark {
  --pulse-fill: var(--white);
  --pulse-accent-fill: var(--accent);
}
@keyframes pulse-bar {
  0%, 100% { transform: scaleY(0.62); opacity: 0.7; }
  50% { transform: scaleY(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .pulse-mark rect { animation: none; }
}

/* --- Header / footer ----------------------------------------------------- */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px clamp(20px, 5vw, 56px);
  max-width: var(--max-width);
  margin: 0 auto;
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--ink);
}
.wordmark-text {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 500;
}
/* La moitié en gras se colore par variable, et non par une règle réécrite
   surface par surface. Sans ça, chaque fond sombre ajouté redonne du noir
   sur noir : c'est exactement ce qui arrivait au pied de page, dont le
   `background` vaut lui aussi --ink. Par défaut l'encre, pour les pages
   blanches ; les surfaces sombres redéfinissent --wordmark-strong. */
.wordmark-text strong { font-weight: 800; color: var(--wordmark-strong, var(--ink)); }
.site-nav { display: flex; align-items: center; gap: 22px; }
.site-nav a:not(.btn) { text-decoration: none; color: var(--ink-soft); font-weight: 500; font-size: 0.95rem; }
.site-nav a:not(.btn):hover { color: var(--ink); }
.nav-logout { margin: 0; display: inline-flex; }

/* On the landing page the header floats over the hero photo instead of
   sitting on its own white bar above it -- no seam between nav and photo. */
.page-landing .site-header { position: absolute; top: 0; left: 0; right: 0; z-index: 10; }
/* A soft scrim behind the header only -- keeps the logo readable no matter
   how bright the photo is at the very top, without darkening the whole hero. */
.page-landing .site-header::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 150px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.5), transparent);
  z-index: -1;
  pointer-events: none;
}
.page-landing .site-header { --wordmark-strong: var(--accent); }
.page-landing .site-header .wordmark,
.page-landing .site-header .wordmark-text,
.page-landing .site-header .site-nav a:not(.btn) { color: var(--white); }
.page-landing .site-header .site-nav a:not(.btn):hover { color: var(--white); opacity: 0.8; }
.page-landing .site-header .btn-ghost { color: var(--white); border-color: rgba(255, 255, 255, 0.4); }
.page-landing .site-header .btn-ghost:hover { border-color: var(--white); }
/* Subtle emboss so the mark reads as a deliberate, integrated overlay
   rather than flat text pasted on top of a photo. */
.page-landing .site-header .wordmark {
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, 0.12)) drop-shadow(0 2px 6px rgba(0, 0, 0, 0.55));
}

/* Fond encre : la moitié en gras du logotype passe à l'accent, comme dans
   l'en-tête de la page d'accueil. Même traitement pour toute surface sombre. */
.site-footer { --wordmark-strong: var(--accent); background: var(--ink); color: #a1a1aa; padding: 48px clamp(20px, 5vw, 56px) 32px; margin-top: 64px; }
.footer-inner { max-width: var(--max-width); margin: 0 auto; }
.footer-brand { display: flex; align-items: center; gap: 10px; color: var(--white); margin-bottom: 14px; }
.footer-brand .wordmark-text { color: var(--white); }
.footer-tagline { font-family: var(--font-display); font-size: 1.05rem; color: var(--white); max-width: 40ch; }
/* #71717a sur le noir du pied de page ne donne que 4,35:1, sous le seuil AA
   de 4,5 pour du petit texte -- et c'est ici un lien, pas de la mention
   décorative. Même gris que le reste du pied de page, soit 8,19:1. */
.footer-legal { font-size: 0.85rem; color: #a1a1aa; margin: 18px 0 0; }
.footer-legal a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.footer-legal a:hover { color: var(--white); }

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 26px;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
  font-family: var(--font-display);
}
.btn:hover { transform: translateY(-1px); }
/* Volt fill, black type: the highest-contrast pair in the palette, and the
   only combination that lets the accent survive on a white page. */
.btn-primary { background: var(--accent); color: var(--ink); box-shadow: var(--shadow-soft); }
.btn-primary:hover { background: var(--accent-deep); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn-ghost:hover { background: var(--ink); color: var(--white); }
.btn-ghost-invert { background: transparent; color: var(--white); border-color: rgba(255,255,255,0.4); }
.btn-ghost-invert:hover { border-color: var(--white); }
.btn-lg { padding: 15px 30px; font-size: 1.02rem; }
.btn-sm { padding: 8px 16px; font-size: 0.82rem; }
.btn:disabled { opacity: 0.6; cursor: default; transform: none; }

.btn-glow { animation: btn-glow-pulse 2.8s ease-in-out infinite; }
@keyframes btn-glow-pulse {
  0%, 100% { box-shadow: var(--shadow-soft), 0 0 0 0 rgba(214, 255, 0, 0.35); }
  50% { box-shadow: var(--shadow-soft), 0 0 0 8px rgba(214, 255, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .btn-glow { animation: none; }
}

/* --- Layout helpers -------------------------------------------------------- */

.section { padding: 76px clamp(20px, 5vw, 56px); }
.section-inner { max-width: var(--max-width); margin: 0 auto; }
.section-inner-narrow { max-width: 560px; }
.section-title { font-size: clamp(2rem, 4vw, 2.6rem); }

/* --- Hero: full-bleed event photo, broadcast-style overlay ------------------ */

.hero {
  position: relative;
  min-height: 620px;
  display: flex;
  align-items: center;
  background-color: var(--ink);
  background-image:
    linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.72) 65%, rgba(0, 0, 0, 0.94) 100%),
    var(--hero-photo, none);
  background-size: cover;
  background-position: center 30%;
  padding: 100px clamp(20px, 5vw, 56px) 64px;
}
.hero-inner { max-width: 640px; margin: 0 auto 0 0; padding-left: clamp(0px, 3vw, 40px); }
.hero h1 { color: var(--white); font-size: clamp(2.5rem, 5.4vw, 3.8rem); }
.hero-sub { color: #e4e4e7; font-size: 1.12rem; max-width: 42ch; }
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; margin: 30px 0 0; }

/* --- Live demo section -------------------------------------------------- */

.demo-chips { display: flex; flex-wrap: wrap; gap: 10px; margin: 28px 0 36px; }
.demo-chip {
  padding: 11px 22px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--ink);
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.88rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.demo-chip:hover { background: var(--tint); transform: translateY(-1px); }
.demo-chip.is-active {
  background: var(--accent);
  border-color: var(--ink);
  color: var(--ink);
  transform: translateY(-1px);
}

.demo-panel {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: clamp(28px, 5vw, 56px);
}

.showcase {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 48px;
}
.showcase::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 560px;
  height: 320px;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse, rgba(214, 255, 0, 0.08), transparent 70%);
  z-index: -1;
}
.showcase.is-loading { opacity: 0.85; transition: opacity 0.2s ease; }
.showcase.is-loading .phone-frame img,
.showcase.is-loading .sheet-frame img {
  opacity: 0.25;
  filter: grayscale(0.5);
  transition: opacity 0.2s ease, filter 0.2s ease;
}

.showcase-side { display: flex; flex-direction: column; align-items: center; gap: 18px; }
.showcase-caption { max-width: 24ch; text-align: center; font-weight: 600; color: var(--ink); font-size: 0.98rem; margin: 0; }
.showcase-arrow { position: relative; display: flex; flex-direction: column; align-items: center; gap: 10px; color: var(--ink); }
.showcase-arrow-caption { margin: 0; font-family: var(--font-display); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-soft); white-space: nowrap; }
.demo-footnote { text-align: center; margin: 28px 0 0; font-size: 0.85rem; color: var(--ink-soft); }

/* Index scan: a small grid standing in for "a large gallery of faces",
   scanned left-to-right/top-to-bottom (staggered via --j), with a few
   cells flashing red as matches turn up along the way. */
.index-scan {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 3px;
  width: 78px;
  height: 65px;
}
.index-scan span {
  background: var(--line);
  border-radius: 2px;
  animation: index-wave 2.6s ease-in-out infinite;
  animation-delay: calc(var(--j, 0) * 0.05s);
}
.index-scan span.is-match { animation-name: index-match; }
@keyframes index-wave {
  0%, 100% { opacity: 0.25; }
  45%, 55% { opacity: 0.9; }
}
@keyframes index-match {
  0%, 100% { opacity: 0.3; background: var(--line); box-shadow: none; }
  45%, 55% { opacity: 1; background: var(--ink); box-shadow: 0 0 0 2px var(--accent); }
}
@media (prefers-reduced-motion: reduce) {
  .index-scan span { animation: none; opacity: 0.5; }
  .index-scan span.is-match { opacity: 1; background: var(--ink); }
}

.phone-frame {
  width: 96px;
  aspect-ratio: 9 / 17.5;
  border-radius: 18px;
  border: 5px solid var(--ink);
  background: var(--ink);
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-soft);
}
.phone-frame::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 3px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.28);
  z-index: 2;
}
.phone-frame img { width: 100%; height: 100%; object-fit: cover; }

/* Contact sheet: the found photos laid out the way a photographer lays out
   a shoot -- one black block, hairline gutters, every frame numbered. The
   column count comes from the photo count (two up to four photos, three
   beyond) so the sheet is always a full rectangle and never a last row with
   holes in it. */
.contact-sheet {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), 1fr);
  gap: 3px;
  padding: 3px;
  background: var(--ink);
  width: 372px;
  /* The hovered frame grows out of the sheet -- nothing here may clip it. */
}
.sheet-frame {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--ink-raised);
  cursor: pointer;
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s ease;
}
.sheet-frame img { width: 100%; height: 100%; object-fit: cover; }
.sheet-frame figcaption {
  position: absolute;
  left: 0; bottom: 0;
  display: flex; align-items: center; gap: 5px;
  padding: 4px 7px;
  font-family: var(--font-display);
  font-weight: 800; font-size: 0.6rem; letter-spacing: 0.1em;
  color: var(--white);
  background: rgba(0, 0, 0, 0.7);
}
.sheet-frame figcaption::before { content: ""; width: 5px; height: 5px; background: var(--accent); }
/* Scales from its own centre, so the pointer that triggered the hover is
   still inside the frame once it has grown -- that is what stops the hover
   flip-flopping between two neighbours along their shared edge. */
.sheet-frame:hover {
  transform: scale(1.5);
  z-index: 5;
  box-shadow: 0 26px 50px -16px rgba(0, 0, 0, 0.65);
}
@media (prefers-reduced-motion: reduce) {
  .sheet-frame { transition: none; }
}

/* --- Camera "face lock" scan effect (selfie phone frame) ------------------------ */

.scan-frame { position: relative; display: inline-block; }
.scan-frame .phone-frame { position: relative; overflow: hidden; }
.scan-frame .phone-frame::after {
  content: "";
  position: absolute;
  left: 6%; right: 6%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent-soft), var(--accent), var(--accent-soft), transparent);
  box-shadow: 0 0 10px 1px rgba(214, 255, 0, 0.7);
  animation: scan-sweep 2.6s ease-in-out infinite;
}
@keyframes scan-sweep {
  0%, 100% { top: 12%; opacity: 0; }
  10% { opacity: 1; }
  50% { top: 88%; opacity: 1; }
  60% { opacity: 0; }
}
.scan-corner {
  position: absolute;
  width: 22px; height: 22px;
  border: 2px solid var(--ink);
  opacity: 0.85;
  animation: corner-pulse 2.6s ease-in-out infinite;
}
.scan-corner-tl { top: -8px; left: -8px; border-right: none; border-bottom: none; border-radius: 6px 0 0 0; }
.scan-corner-tr { top: -8px; right: -8px; border-left: none; border-bottom: none; border-radius: 0 6px 0 0; }
.scan-corner-bl { bottom: -8px; left: -8px; border-right: none; border-top: none; border-radius: 0 0 0 6px; }
.scan-corner-br { bottom: -8px; right: -8px; border-left: none; border-top: none; border-radius: 0 0 6px 0; }
@keyframes corner-pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .scan-frame .phone-frame::after, .scan-corner { animation: none; }
}

/* --- Steps (compact single row) -------------------------------------------- */

.step-row { display: flex; gap: 44px; margin-top: 36px; flex-wrap: wrap; }
.step-item { flex: 1 1 200px; border-top: 2px solid var(--ink); padding-top: 18px; }
.step-item .step-number {
  display: block; font-family: var(--font-display); color: var(--ink);
  font-weight: 800; font-size: 0.8rem; text-transform: uppercase;
  letter-spacing: 0.1em; margin-bottom: 10px;
}
.step-item h3 { font-size: 1.15rem; margin-bottom: 6px; }
.step-item p { margin: 0; font-size: 0.94rem; }

/* --- Pain / offer / payoff ------------------------------------------------ */
/* Reuses .step-row / .step-item: the three columns carry "aujourd'hui",
   "avec nous" and "ce que ça change" rather than numbered steps, so the
   label slot holds a word instead of 01/02/03. Tinted to separate it from
   the demo above it. */

.pitch-section { background: var(--tint-2); }

/* --- Final CTA ---------------------------------------------------------------- */

.cta-final { background: var(--tint-2); }
.cta-final-inner { text-align: center; max-width: 620px; }
.cta-final h2 { font-size: clamp(1.8rem, 3.4vw, 2.4rem); }

/* --- Badges ------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.76rem;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: var(--radius-sm);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-neutral { background: var(--tint-2); color: var(--ink-soft); }
.badge-demo { background: var(--accent); color: var(--ink); }

/* --- Organizer app pages -------------------------------------------------------- */

.organizer-page, .participant-page { padding-top: 56px; }
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 40px; flex-wrap: wrap; }
.event-list { display: flex; flex-direction: column; gap: 10px; }
.event-row {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 18px 22px; text-decoration: none; color: var(--ink); transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.event-row:hover { box-shadow: var(--shadow-card); transform: translateY(-1px); }
.event-row h3 { margin: 0 0 4px; font-size: 1.05rem; }
.event-row-date { margin: 0; font-size: 0.85rem; color: var(--ink-soft); }
.empty-state { text-align: center; padding: 60px 20px; color: var(--ink-soft); }

.form-card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 30px; box-shadow: var(--shadow-card); display: flex; flex-direction: column; gap: 18px; margin-top: 28px;
}
.field { display: flex; flex-direction: column; gap: 6px; font-weight: 600; font-size: 0.9rem; }
.field input, select {
  font-family: var(--font-body); font-size: 1rem; padding: 12px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--paper);
}
.field input:focus, select:focus, input[type=file]:focus { outline: 2px solid var(--ink); outline-offset: 1px; }

/* Avancement de l'enrichissement (lecture des dossards), côté organisateur. */
.enrichment-card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 22px 24px; box-shadow: var(--shadow-card); margin-top: 20px;
  display: flex; flex-direction: column; gap: 10px;
}
.enrichment-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.enrichment-head h3 { margin: 0; font-size: 1.05rem; }
.enrichment-line { margin: 0; font-size: 0.92rem; color: var(--ink-soft); }
.enrichment-line strong { color: var(--ink); }
.progress-track {
  height: 8px; border-radius: 999px; background: var(--tint); overflow: hidden;
}
.progress-fill {
  height: 100%; background: var(--ink); border-radius: 999px;
  transition: width 0.4s ease;
}

/* Participant search: bib number and/or reference photos, either alone. */
.field-block { display: flex; flex-direction: column; gap: 8px; }
.field-label { font-weight: 600; font-size: 0.95rem; }
.field-input {
  font-family: var(--font-body); font-size: 1.05rem; letter-spacing: 0.04em;
  padding: 13px 15px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--paper); width: 100%;
}
.field-input:focus { outline: 2px solid var(--ink); outline-offset: 1px; }
.field-separator {
  display: flex; align-items: center; gap: 14px;
  color: var(--ink-soft); font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.08em;
}
.field-separator::before, .field-separator::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}

.results-summary { color: var(--ink-soft); font-size: 0.95rem; margin: 0 0 18px; }
.results-summary strong { color: var(--ink); }
.group-block { margin-top: 40px; padding-top: 28px; border-top: 1px solid var(--line); }
.group-title { font-size: 1.15rem; margin: 0 0 4px; }
.group-block .gallery-grid { margin-top: 16px; }

/* How a photo was found -- a bib read is an exact identifier, a face match
   is a similarity, so they are labelled differently rather than merged. */
.match-badges { position: absolute; top: 8px; left: 8px; display: flex; gap: 4px; flex-wrap: wrap; z-index: 2; }
.match-badge {
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.03em;
  padding: 3px 7px; border-radius: 999px; background: rgba(0, 0, 0, 0.62); color: var(--white);
  backdrop-filter: blur(2px);
}
.match-badge-bib { background: var(--accent); color: var(--ink); }

.dropzone-card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 30px; box-shadow: var(--shadow-card); margin-bottom: 28px;
}
.dropzone-card-compact { padding: 20px; }
.dropzone {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  border: 2px dashed var(--line); border-radius: var(--radius-md); padding: 40px 20px;
  cursor: pointer; margin-top: 16px; text-align: center; transition: border-color 0.15s ease;
}
/* The native file input must not be able to receive the drop itself: a
   plain (non-webkitdirectory) <input type=file> natively refuses a
   dropped folder before our own drop handler ever runs. Visually hidden
   but still reachable -- clicking the label still opens its picker. */
.dropzone input[type=file] {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
}
.dropzone:hover { border-color: var(--ink); }
.dropzone.is-dragover { border-color: var(--ink); background: var(--tint); border-style: solid; }
.dropzone-compact { padding: 22px; margin-top: 10px; }
.dropzone-label { font-weight: 600; }
.dropzone-hint { font-size: 0.82rem; color: var(--ink-soft); }
.dropzone-status { min-height: 1.2em; font-size: 0.88rem; color: var(--ink); font-weight: 600; }

.processing-card {
  background: var(--ink); color: var(--white); border-radius: var(--radius-lg);
  padding: 48px 30px; text-align: center; margin-bottom: 28px;
}
.processing-card h2 { color: var(--white); margin-top: 16px; }
.processing-card .lead { color: #d4d4d8; margin: 0 auto; }

.mock-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.mock-stats div { display: flex; flex-direction: column; gap: 2px; }
.mock-stats strong { font-family: var(--font-display); font-size: 1.6rem; }
.mock-stats span { font-size: 0.78rem; }
.stats-real { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 26px; box-shadow: var(--shadow-card); margin: 28px 0; }
.stats-real strong { color: var(--ink); }
.stats-real span { color: var(--ink-soft); }

.share-card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 30px; box-shadow: var(--shadow-card); display: flex; flex-direction: column; gap: 16px; align-items: flex-start;
}
.share-link-row { display: flex; gap: 10px; width: 100%; }
.share-link-row input {
  flex: 1; padding: 12px 14px; border-radius: var(--radius-sm); border: 1px solid var(--line);
  font-family: monospace; font-size: 0.9rem; background: var(--tint-2);
}

/* --- Participant pages ---------------------------------------------------------- */

.alert { padding: 14px 18px; border-radius: var(--radius-sm); margin: 20px 0; font-size: 0.92rem; }
.alert-error { background: var(--error-bg); color: var(--error); }

.upload-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 12px; margin-top: 8px; }
.upload-slot {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  aspect-ratio: 1; border: 2px dashed var(--line); border-radius: var(--radius-md);
  cursor: pointer; text-align: center; font-size: 0.78rem; color: var(--ink-soft); overflow: hidden;
  transition: border-color 0.15s ease;
}
.upload-slot:hover { border-color: var(--ink); }
.upload-slot.is-dragover { border-color: var(--ink); background: var(--tint); border-style: solid; }
.upload-slot-plus { font-size: 1.5rem; color: var(--ink); font-weight: 800; }
.upload-slot .preview-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.upload-slot-preview { cursor: default; border-style: solid; border-color: var(--line); }
.upload-slot-remove {
  position: absolute; top: 4px; right: 4px; z-index: 1;
  width: 22px; height: 22px; border-radius: 50%; border: none;
  background: rgba(0, 0, 0, 0.6); color: var(--white);
  font-size: 1rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.upload-slot-remove:hover { background: var(--accent); color: var(--ink); }
.form-hint { font-size: 0.84rem; color: var(--ink-soft); margin-top: 4px; }
.consent-row { display: flex; align-items: flex-start; gap: 10px; font-size: 0.86rem; color: var(--ink-soft); }
.consent-row input { margin-top: 3px; }

.results-header {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}

.pagination { display: flex; align-items: center; justify-content: center; gap: 18px; margin: 36px 0; }
.pagination-count { font-family: var(--font-display); font-size: 0.85rem; color: var(--ink-soft); }

.dashboard-photos-link { display: inline-flex; margin-bottom: 28px; }

.gallery-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; margin: 30px 0;
}
.gallery-item {
  position: relative;
  border-radius: var(--radius-md); overflow: hidden; aspect-ratio: 1;
  background: var(--tint-2);
  box-shadow: var(--shadow-card);
}
.gallery-item-open {
  display: block; width: 100%; height: 100%; padding: 0; border: none; background: none; cursor: pointer;
}
.gallery-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s ease; }
.gallery-item:hover img { transform: scale(1.06); }
.gallery-item::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(0, 0, 0, 0.55) 100%);
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}
.gallery-item:hover::after { opacity: 1; }
.gallery-download {
  position: absolute; bottom: 10px; right: 10px;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.92); color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transform: translateY(6px);
  transition: opacity 0.2s ease, transform 0.2s ease, background 0.15s ease, color 0.15s ease;
}
.gallery-item:hover .gallery-download { opacity: 1; transform: none; }
.gallery-download:hover { background: var(--accent); color: var(--ink); }

/* --- Lightbox ------------------------------------------------------------- */

.lightbox {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(11, 11, 13, 0.92);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.lightbox[hidden] { display: none; }
.lightbox-img { max-width: min(88vw, 900px); max-height: 74vh; border-radius: var(--radius-sm); box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6); }
.lightbox-close {
  position: absolute; top: 20px; right: 24px;
  width: 40px; height: 40px; border-radius: 50%; border: none;
  background: rgba(255, 255, 255, 0.12); color: var(--white);
  font-size: 1.6rem; line-height: 1; cursor: pointer;
}
.lightbox-close:hover { background: rgba(255, 255, 255, 0.22); }
.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 48px; height: 48px; border-radius: 50%; border: none;
  background: rgba(255, 255, 255, 0.12); color: var(--white);
  font-size: 1.8rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.lightbox-nav:hover { background: rgba(255, 255, 255, 0.22); }
.lightbox-prev { left: 16px; }
.lightbox-next { right: 16px; }
.lightbox-download {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
}
@media (max-width: 560px) {
  .lightbox-nav { width: 40px; height: 40px; font-size: 1.5rem; }
  .lightbox-prev { left: 6px; }
  .lightbox-next { right: 6px; }
}

.privacy-panel {
  border-top: 1px solid var(--line); margin-top: 36px; padding-top: 24px;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap; color: var(--ink-soft); font-size: 0.9rem;
}

/* --- Scroll-reveal (progressive enhancement, see reveal.js) -------------------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: var(--reveal-delay, 0s);
}
[data-reveal].is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* --- Responsive --------------------------------------------------------------- */

@media (max-width: 900px) {
  .hero { min-height: 520px; }
  .hero-inner { max-width: 100%; padding-left: 0; }
  .showcase { flex-direction: column; gap: 36px; }
  .showcase::before { width: 320px; height: 320px; }
}
@media (max-width: 560px) {
  .site-nav { gap: 12px; }
  .site-nav a:not(.btn) { display: none; }
  .upload-slots { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .share-link-row { flex-direction: column; }
  .step-row { flex-direction: column; gap: 24px; }
  .demo-panel { padding: 24px; border-radius: var(--radius-lg); }
  .contact-sheet { width: 268px; }
  .sheet-frame:hover { transform: scale(1.35); }
}

/* --- Pages de texte contractuel ----------------------------------------
   Largeur de lecture, pas largeur de grille : au-delà d'environ 75 caractères
   par ligne l'œil perd la ligne suivante, et un contrat se lit mal en
   diagonale. Volontairement sobre -- rien à vendre sur cette page. */
.legal { max-width: 74ch; margin: 0 auto; }
.legal h1 { font-size: clamp(1.8rem, 3.5vw, 2.4rem); margin-bottom: 8px; }
.legal .lead { margin-bottom: 40px; }
.legal h2 {
  font-family: var(--font-display);
  font-size: 1.25rem;
  margin: 44px 0 12px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.legal h3 { font-size: 1rem; margin: 26px 0 8px; }
.legal p { margin: 0 0 14px; line-height: 1.65; }
.legal dl { margin: 0 0 14px; }
.legal dt { font-weight: 700; margin-top: 12px; }
.legal dd { margin: 2px 0 0; padding-left: 16px; border-left: 2px solid var(--accent); }
.legal-table { width: 100%; border-collapse: collapse; margin: 16px 0 20px; font-size: 0.95rem; }
.legal-table th, .legal-table td {
  text-align: left; vertical-align: top; padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}
.legal-table th { font-family: var(--font-display); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; }
.legal-footnote { margin-top: 44px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 0.88rem; color: var(--ink-soft); }
