/* Moduland — styles */

/* ---------- Font ---------- */
@font-face {
  font-family: "Arial Narrow";
  src: url("../fonts/arial-narrow-bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Design tokens ---------- */
:root {
  --pink: #fe52b4;
  --green: #4aa664;
  --black: #000;

  /* Proportional scaling: 1u = 1 Figma pixel */
  --design-width: 402;       /* Figma frame width */
  --max-width: 600px;       /* column stops growing here */
  --u: calc(min(100vw, var(--max-width)) / var(--design-width));

  --text-size: calc(26 * var(--u));  /* Figma: 26 */
  --text-leading: 1.07;              /* 27.8 / 26, scales by itself */

  --marge-page: 20;                          /* page side margins, in Figma px */
  --margin: calc(var(--marge-page) * var(--u));
  --gap-tagline: calc(20 * var(--u));        /* logo → tagline */

  /* Section spacing */
  --gap-titre-section: calc(40 * var(--u)); /* section title (PROGRAMME…) → first section */
  --gap-sections: calc(80 * var(--u)); /* after each section */
  --gap-section: calc(20 * var(--u));  /* inside a section: info bar, title, blocks */
  --gap-paragraphes: calc(8 * var(--u)); /* between paragraphs of a text block */
  --gap-images: calc(8 * var(--u));    /* between images (grid gutter + spacers) */
  --gap-lignes: calc(8 * var(--u));    /* between price lines */
  --legende-avant: calc(0 * var(--u)); /* image → caption */
  --legende-apres: calc(10 * var(--u)); /* caption → next image */

  --haut-overlay: calc(20 * var(--u));      /* space above overlay content */

  /* Animated titles (timing is in main.js) */
  --stroke-bleed: calc(3.5 * var(--u)); /* title canvas extends this far past the letters */
}

/* Desktop (550px and wider) */
@media (min-width: 550px) {
  :root {
    --text-size: calc(22 * var(--u));     /* smaller body text */
    --marge-page: 8;                      /* desktop side margins */
    --gap-tagline: calc(8 * var(--u));    /* desktop logo → tagline */
  }
}

/* ---------- Base ---------- */
body {
  margin: 0;
  font-family: "Arial Narrow", "Arial", sans-serif;
  font-weight: 700;
  font-size: var(--text-size);
  line-height: var(--text-leading);
  color: var(--black);
  background: var(--pink);   /* side fill on desktop (temporary) */
}

.column {
  /* Background colour + its contrast colour (overlays will swap them) */
  --fond: var(--green);
  --contraste: var(--pink);
  max-width: var(--max-width);
  margin: 0 auto;
  background: var(--fond);
  min-height: 100vh;
  box-sizing: border-box;
}

.content {
  display: flow-root;           /* keeps the last section's gap inside the column */
  padding: 0 var(--margin);
}

/* Hidden text for screen readers and search engines */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Sticky date + city box ---------- */
.date-lieu {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--pink);
  padding: var(--margin);
  padding-top: calc(var(--margin) + env(safe-area-inset-top, 0px));
}

.date-lieu p {
  margin: 0;
}

/* Wider than 500px (desktop, tablet, phone held sideways): not enough
   height for two sticky elements, so the box scrolls away with the page. */
@media (min-width: 550px) {
  .date-lieu {
    position: static;
  }
}

/* ---------- SVG titles ---------- */
/* Every title SVG = letters + 3.5 on each side (room for the thickest
   stroke). The whole SVG, stroke room included, sits inside the margins,
   and spacing is measured from its edge.
   To go back to "letters on the margins, stroke overflowing": replace the
   width and margin lines below with
     width: calc(100% + 2 * var(--stroke-bleed));
     margin: calc(-1 * var(--stroke-bleed));  */
.titre {
  display: block;
  width: 100%;
  height: auto;
  margin: 0;
  overflow: visible;            /* accents overflow above the letters */
}

/* Variant: the whole title, stroke included, sits inside the margins
   (the outer edge of the thickest stroke aligns with margins and gaps). */
.titre--contour {
  width: 100%;
  margin: 0;
}

/* The element holding a title keeps those negative margins inside it
   (otherwise they merge with neighbouring margins and gaps drift). */
:has(> .titre) {
  display: flow-root;
}

/* Sub-titles: coloured letters on a black box.
   The box (not the letters) aligns with the margins. */
.sous-titre {
  color: var(--contraste, var(--pink));   /* letters = contrast colour (pink on the page, green on overlays); the box stays black */
}

/* ---------- Main title ---------- */
.logo {
  margin: calc(20 * var(--u)) 0 0;   /* Figma: 20 under the sticky box */
}

/* ---------- Tagline ---------- */
.tagline {
  margin: var(--gap-tagline) 0 0;  /* under the logo (see :root) */
}

/* ---------- Intro ---------- */
.intro {
  margin: calc(40 * var(--u)) 0 0;  /* Figma: 40 under the tagline */
}

/* ---------- Section titles (Programme, Infos pratiques…) ---------- */
.titre-section {
  margin: calc(40 * var(--u)) 0 var(--gap-titre-section);  /* 40 under the previous item */
}

/* ---------- Programme sections ---------- */
.section {
  margin-bottom: var(--gap-sections);
}

/* Info bar: pink "highlighter" behind the text, line by line */
.section-infos {
  margin: 0;
}

.section-infos span {
  background: var(--pink);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.section-titre {
  margin: var(--gap-section) 0 0;
}

/* Every block (text, images, button, map) */
.bloc {
  margin-top: var(--gap-section);
}

/* ---------- Text blocks ---------- */
.texte p {
  margin: 0;
}

.texte p + p {
  margin-top: var(--gap-paragraphes);
}

.texte a {
  color: inherit;
  text-decoration: underline;
}

/* ---------- Image blocks ---------- */
/* .pile = images stacked vertically (grid columns, column / edge-to-edge blocks) */
.grille {
  display: flex;
  align-items: flex-start;      /* columns keep their own height */
  gap: var(--gap-images);
}

.grille > .pile {
  flex: 1 1 0;
  min-width: 0;
}

/* Edge to edge: cancel the page margins */
.images-bord {
  margin-inline: calc(-1 * var(--margin));
}

.vignette--sans-legende:not(:last-child) {
  margin-bottom: var(--gap-images);
}

.vignette {
  display: block;
  color: inherit;
  text-decoration: none;
}

.vignette-legende {
  display: block;
  margin: var(--legende-avant) 0 var(--legende-apres);
}

.vignette:last-child .vignette-legende {
  margin-bottom: 0;
}

/* ---------- Dithered images ---------- */
/* Files are black & white. The white takes the background colour
   (multiply), the black stays black: exact 2-colour result.
   Colour: pink by default; set --image-couleur to change it (e.g. overlays). */
.image-tramee {
  display: block;
  background: var(--image-couleur, var(--pink));
  isolation: isolate;           /* blend only with this background */
}

.image-tramee picture {
  display: block;
}

.image-tramee img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;          /* "image" shape */
  object-fit: cover;            /* safety if a fallback file has another shape */
  image-rendering: pixelated;   /* keep the dither crisp when scaled */
  mix-blend-mode: multiply;
}

.image-tramee--miniature img {
  aspect-ratio: 1;              /* "miniature" shape: square */
}

/* Linked images: exact negative on mouse hover (desktop) and keyboard focus */
.vignette--lien:focus-visible {
  outline: none;
}

.vignette--lien:focus-visible .image-tramee img {
  filter: invert(1);
}

@media (hover: hover) and (pointer: fine) {
  .vignette--lien:hover .image-tramee img {
    filter: invert(1);
  }
}

/* ---------- Price lines (Billetterie) ---------- */
/* Name on the left (wraps), price on the right, level with the name's
   last line. Dots (title-font dots, assets/svg/point.svg) fill the gap
   from the end of that last line: main.js measures the gap, then CSS fits
   as many whole dots as possible and stretches them slightly to fill it. */
.tarif {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;             /* price on the last line of the name */
  margin: 0;
}

.tarif + .tarif {
  margin-top: var(--gap-lignes);
}

.tarif-prix {
  white-space: nowrap;
}

.tarif-points {
  --largeur: 0px;               /* set by main.js */
  --marge: calc(6 * var(--u));  /* space before and after the dots */
  --etirement: 2;               /* horizontal stretch of each dot (1 = round) */
  --taille: 4;                /* dot size in u (Figma: 3.5) */
  display: inline-block;
  width: var(--largeur);
  height: calc(var(--taille) * var(--u));
  /* sits on the baseline, extends to the left without moving the price */
  margin-left: calc(-1 * (var(--largeur) + var(--marge)));
  margin-right: var(--marge);
  background: url("../svg/point.svg") left center / calc(var(--taille) * 4.05 / 3.5 * var(--etirement) * var(--u)) 100% round no-repeat;
}

/* ---------- Map ---------- */
.carte {
  aspect-ratio: 4 / 5;          /* keep in sync with carte-style.js (format) */
  margin-inline: calc(-1 * var(--margin));   /* full width, no margins */
  position: relative;
  z-index: 0;                   /* keeps the map's layers under the sticky elements */
  background: var(--fond, var(--green));
}

/* Venue pins (size, colour, shape: carte-style.js) + name next to them */
.carte-point-bloc {
  display: flex;
  align-items: center;
  gap: calc(6 * var(--u));
  cursor: pointer;
}

.carte-point-nom {
  font: inherit;
  font-size: calc(18 * var(--u));
  line-height: 1;
  background: var(--pink);
  padding: calc(2 * var(--u)) calc(4 * var(--u));
  white-space: nowrap;
}

/* Pop-up (venue name + address) */
.carte .maplibregl-popup-content {
  font: inherit;
  padding: calc(8 * var(--u)) calc(10 * var(--u));
  background: var(--pink);
  border: calc(3 * var(--u)) solid var(--black);
  border-radius: 0;
  box-shadow: none;
}

.carte .maplibregl-popup-tip {
  display: none;
}

/* Fallback when the map can't be drawn: plain list of venues */
.carte--texte {
  aspect-ratio: auto;
  padding: 0 var(--margin);
}

.carte--texte p {
  margin: 0 0 var(--gap-paragraphes);
}

/* ---------- Buttons ---------- */
/* Colour = same as the background; the sticky button uses the contrast
   colour. Force a colour with .bouton--rose / .bouton--vert.
   Label SVG = button width minus 16 on each side (inside the stroke). */
.bouton {
  --bouton-couleur: var(--fond, var(--green));
  display: block;
  box-sizing: border-box;
  width: 100%;
  padding: calc(16 * var(--u));
  border: calc(3.5 * var(--u)) solid var(--black);
  border-radius: calc(15 * var(--u));
  background: var(--bouton-couleur);
  color: var(--black);            /* label colour */
  font: inherit;                  /* for <button> elements */
  text-align: inherit;
  cursor: pointer;
}

.bouton--vert {
  --bouton-couleur: var(--green);
}

.bouton--rose {
  --bouton-couleur: var(--pink);
}

.barre-bas .bouton {
  --bouton-couleur: var(--contraste, var(--pink));
}

/* Inverted: on mouse hover (desktop only) and keyboard focus */
.bouton:focus-visible {
  outline: none;
  background: var(--black);
  color: var(--bouton-couleur);
}

@media (hover: hover) and (pointer: fine) {
  .bouton:hover {
    background: var(--black);
    color: var(--bouton-couleur);
  }
}

/* ---------- Sticky bottom bar ---------- */
/* Stays at the bottom of the screen; at the end of the page it sits
   in the flow, so it never hides the last content. */
.barre-bas {
  position: sticky;
  bottom: 0;
  z-index: 10;
  padding: 0 var(--margin) calc(var(--margin) + env(safe-area-inset-bottom, 0px));
  pointer-events: none;           /* the empty strip lets clicks through */
}

.barre-bas > * {
  pointer-events: auto;
}

/* ---------- Overlays ---------- */
/* Full screen, scrolls on its own. Opened / closed by main.js. */
.overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  overflow-y: auto;
  overscroll-behavior: contain;   /* scrolling never leaks to the page */
  background: var(--green);       /* side bands on desktop */
  outline: none;
}

.overlay[hidden] {
  display: none;
}

/* Pink column: colours swapped (buttons pink, FERMER green, images green) */
.overlay-colonne {
  --fond: var(--pink);
  --contraste: var(--green);
  --image-couleur: var(--green);
  display: flex;
  flex-direction: column;
  max-width: var(--max-width);
  min-height: 100%;
  margin: 0 auto;
  background: var(--fond);
}

.overlay-contenu {
  flex: 1 0 auto;
  display: flow-root;
  padding: calc(var(--haut-overlay) + env(safe-area-inset-top, 0px)) var(--margin) var(--gap-sections);
}

/* First and last items: no extra outer gap inside an overlay */
.overlay-contenu > :first-child {
  margin-top: 0;
}

.overlay-contenu > :last-child {
  margin-bottom: 0;
}

/* Page behind an open overlay: no scrolling */
html.overlay-ouvert {
  overflow: hidden;
}

/* Detail overlay (Artiste / Exposant / Atelier) */
.detail-titre {
  margin: 0;
  font: inherit;
  text-align: center;
}

.detail-image {
  margin: var(--gap-images) calc(-1 * var(--margin)) 0;   /* 8 under the title, edge to edge */
}

/* Galerie overlay: normal photos, edge to edge */
.galerie-photos {
  display: flex;
  flex-direction: column;
  gap: var(--gap-images);
  margin-inline: calc(-1 * var(--margin));
}

.galerie-photos picture,
.galerie-photos img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------- Animated background + characters (fond.js) ---------- */
/* Both are drawn on canvases fixed to the screen. Once the background is
   drawn ("fond-actif"), the column and the overlays let it show through. */
#fond,
#persos {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  height: 100lvh;               /* full height even when the phone's address bar hides */
  display: block;
  pointer-events: none;
  image-rendering: pixelated;   /* canvas enlarged without smoothing: stays crisp */
}

#fond {
  z-index: -1;                  /* behind everything */
}

#persos {
  z-index: 5;                   /* in front of the content, behind the sticky date box and button */
}

html.fond-actif body {
  background: var(--green);     /* same as the background's page colour (visible when over-scrolling) */
}

html.fond-actif .column,
html.fond-actif .overlay,
html.fond-actif .overlay-colonne {
  background: none;
}

/* Overlay open: hide the page so the background (in overlay colours) shows */
html.fond-actif.overlay-ouvert .column {
  visibility: hidden;
}

/* ---------- 404 page ---------- */
.page-404 {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: var(--margin);
  text-align: center;
}

.page-404 p {
  margin: 0;
}

.page-404 a {
  color: inherit;
}

/* ---------- Animated titles (frames in one SVG) ---------- */
/* Each <g> is a frame. main.js cycles them when a speed is set below;
   otherwise frame 1 shows, static. */
.titre-anime {
  color: var(--black);
}

/* Speeds (ms). Remove a line to make that title static. */
.logo:not(.logo--fixe) .titre-anime {   /* switch "Animer le logo" in the admin */
  --vitesse: 120;               /* ms per frame */
}
/* Example for the date box: .date-lieu .titre-anime { --vitesse: 100; --pause: 3000; } */

.titre-anime > g {
  opacity: 0;
}

.titre-anime > g:nth-of-type(1) {
  opacity: 1;
}

.titre-anime.anime > g:nth-of-type(1) {
  opacity: 0;
}

.titre-anime.anime > g.actif {
  opacity: 1;
}
