/* NubieCloud — socle d'actifs des sites vitrines. Servi a /_nubie/base.css
 *
 * CE FICHIER PORTE LA QUALITE DU PRODUIT, pas le modele.
 *
 * Avec un modele a poids ouverts, le systeme de design ne fait plus seulement le
 * plancher de qualite : il fait aussi le plafond. Plus ce fichier travaille, moins le
 * gout du modele compte -- et c'est ce qui rend l'offre tenable sans modele de pointe.
 *
 * TROIS CONTRAINTES QUI EXPLIQUENT CHAQUE CHOIX CI-DESSOUS :
 *
 * 1. AUCUNE URL EXTERNE. Pas de Google Fonts, pas de CDN, pas d'image distante. C'est
 *    la liste blanche implicite : le modele ne peut referencer que ce que la plateforme
 *    heberge. Les piles de polices sont donc systeme -- ce qui, sur le marche vise, est
 *    aussi le bon choix technique : aucun telechargement, rendu immediat.
 *
 * 2. LE PREMIER RENDU EST SANS PHOTO. L'utilisateur decrit son activite, choisit une
 *    direction et obtient un site AVANT d'avoir rien televerse. Ce n'est pas un cas
 *    degrade, c'est le chemin principal -- d'ou les motifs CSS et les compositions
 *    typographiques ci-dessous, qui doivent avoir l'air VOULUS et non vides.
 *
 * 3. MOBILE D'ABORD. Le marche visé consulte au telephone. Les styles de base sont donc
 *    ceux du petit ecran, et les requetes elargissent.
 */

/* --------------------------------------------------------------------------- *
 * Jetons — la direction artistique les surcharge, rien d'autre
 * --------------------------------------------------------------------------- */

:root {
  /* Couleur. Une direction redefinit ces six variables et change tout le site. */
  --nubie-fond: #fffdf9;
  --nubie-fond-alt: #f4efe6;
  --nubie-encre: #1c1917;
  --nubie-encre-doux: #57534e;
  --nubie-accent: #9a3412;
  --nubie-trait: #e7e0d5;

  /* Typographie. Piles systeme : aucun telechargement, aucune URL externe. */
  --nubie-titre: ui-serif, Georgia, "Times New Roman", serif;
  --nubie-texte: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Echelle fluide. clamp() evite les requetes media pour la taille du texte. */
  --nubie-t-xxl: clamp(2.5rem, 9vw, 5.5rem);
  --nubie-t-xl: clamp(1.9rem, 6vw, 3.2rem);
  --nubie-t-l: clamp(1.3rem, 3.5vw, 1.75rem);
  --nubie-t-m: clamp(1rem, 2.2vw, 1.125rem);
  --nubie-t-s: 0.875rem;

  /* Espace. Une seule echelle, employee partout. */
  --nubie-e-1: 0.5rem;
  --nubie-e-2: 1rem;
  --nubie-e-3: 1.5rem;
  --nubie-e-4: 2.5rem;
  --nubie-e-5: 4rem;
  --nubie-e-6: 6rem;

  --nubie-rayon: 0.75rem;
  --nubie-mesure: 62ch;      /* longueur de ligne lisible */
  --nubie-gouttiere: 1.25rem;
}

/* --------------------------------------------------------------------------- *
 * Reinitialisation — minimale, et seulement ce qui sert
 * --------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  background: var(--nubie-fond);
  color: var(--nubie-encre);
  font-family: var(--nubie-texte);
  font-size: var(--nubie-t-m);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--nubie-titre); line-height: 1.1; text-wrap: balance; }
h1 { font-size: var(--nubie-t-xxl); letter-spacing: -0.02em; }
h2 { font-size: var(--nubie-t-xl); letter-spacing: -0.01em; }
h3 { font-size: var(--nubie-t-l); }

p { text-wrap: pretty; }
img, svg, video { display: block; max-width: 100%; height: auto; }
ul, ol { padding-inline-start: 1.1rem; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }

/* Visible au clavier. Non negociable : c'est la seule facon de naviguer pour
 * certaines personnes, et un `outline: none` sans remplacement les enferme. */
:focus-visible { outline: 2px solid var(--nubie-accent); outline-offset: 3px; }

/* --------------------------------------------------------------------------- *
 * Primitives de mise en page
 * --------------------------------------------------------------------------- */

.nubie-section { padding-block: var(--nubie-e-5); padding-inline: var(--nubie-gouttiere); }
.nubie-section--serre { padding-block: var(--nubie-e-4); }
.nubie-section--alt { background: var(--nubie-fond-alt); }

/* La gouttiere est posee UNE fois, en padding-inline. Jamais un `padding`
 * raccourci qui remettrait les cotes a zero. */
.nubie-contenu { max-width: var(--nubie-mesure); margin-inline: auto; }
.nubie-contenu--large { max-width: 72rem; margin-inline: auto; }

.nubie-pile { display: flex; flex-direction: column; gap: var(--nubie-e-3); }
.nubie-pile--serree { gap: var(--nubie-e-1); }

.nubie-grille {
  display: grid;
  gap: var(--nubie-e-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.nubie-rang { display: flex; flex-wrap: wrap; gap: var(--nubie-e-2); align-items: center; }

/* --------------------------------------------------------------------------- *
 * Compositions SANS PHOTO — le coeur du socle
 *
 * Chacune remplace une image par de la typographie, de la couleur ou un motif CSS.
 * C'est ce qui fait qu'un site sans photo a l'air VOULU et non vide.
 * --------------------------------------------------------------------------- */

/* Heros typographique : le nom de l'activite occupe l'ecran. Aucune image. */
.nubie-heros {
  min-height: min(78svh, 40rem);
  display: grid;
  align-content: center;
  gap: var(--nubie-e-3);
  padding-block: var(--nubie-e-6);
  padding-inline: var(--nubie-gouttiere);
}
.nubie-heros__sur { font-size: var(--nubie-t-s); letter-spacing: 0.14em; text-transform: uppercase; color: var(--nubie-encre-doux); }
.nubie-heros__accroche { font-size: var(--nubie-t-l); color: var(--nubie-encre-doux); max-width: 48ch; }

/* Motifs : des fonds entierement en CSS, a la place d'une photo d'ambiance.
 * Ils tiennent en quelques declarations et ne pesent rien au telechargement. */
.nubie-motif-lignes {
  background-image: repeating-linear-gradient(
    90deg, var(--nubie-trait) 0 1px, transparent 1px 2.5rem);
}
.nubie-motif-points {
  background-image: radial-gradient(var(--nubie-trait) 1.2px, transparent 1.2px);
  background-size: 1.5rem 1.5rem;
}
.nubie-motif-diagonale {
  background-image: repeating-linear-gradient(
    135deg, var(--nubie-fond-alt) 0 0.75rem, transparent 0.75rem 1.5rem);
}
.nubie-motif-lueur {
  background-image: radial-gradient(
    120% 90% at 50% 0%, var(--nubie-fond-alt) 0%, transparent 70%);
}

/* Le chiffre : « 15 ans de metier », « ouvert 7j/7 ». Un commerce a presque
 * toujours deux ou trois chiffres a montrer, et c'est un substitut d'image tres
 * efficace parce qu'il porte une information reelle. */
.nubie-chiffre { display: grid; gap: 0.15rem; }
.nubie-chiffre__valeur {
  font-family: var(--nubie-titre);
  font-size: var(--nubie-t-xl);
  line-height: 1;
  color: var(--nubie-accent);
  font-variant-numeric: tabular-nums;
}
.nubie-chiffre__libelle { font-size: var(--nubie-t-s); color: var(--nubie-encre-doux); }

.nubie-carte {
  padding: var(--nubie-e-3);
  background: var(--nubie-fond);
  border: 1px solid var(--nubie-trait);
  border-radius: var(--nubie-rayon);
}
/* Une barre d'accent au lieu d'une icone : rien a telecharger, rien a inventer. */
.nubie-carte--accent { border-inline-start: 3px solid var(--nubie-accent); }

/* Horaires : une liste de definitions alignee, lisible au telephone. */
.nubie-horaires { display: grid; gap: var(--nubie-e-1); }
.nubie-horaires__ligne {
  display: flex; justify-content: space-between; gap: var(--nubie-e-2);
  padding-block: 0.35rem;
  border-bottom: 1px dashed var(--nubie-trait);
}
.nubie-horaires__jour { font-weight: 600; }
.nubie-horaires__heures { color: var(--nubie-encre-doux); font-variant-numeric: tabular-nums; }

/* Emplacement d'image : ce que remplit une photo televersee plus tard.
 * Sans photo, il garde un motif et un rapport de forme -- donc la page ne saute
 * pas quand l'image arrive. */
.nubie-emplacement {
  aspect-ratio: 4 / 3;
  max-width: 100%;
  border-radius: var(--nubie-rayon);
  background-color: var(--nubie-fond-alt);
  background-image: radial-gradient(var(--nubie-trait) 1.2px, transparent 1.2px);
  background-size: 1.5rem 1.5rem;
  overflow: hidden;
}
.nubie-emplacement > img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------- *
 * Actions — tel:, mailto:, wa.me. Jamais un formulaire.
 * --------------------------------------------------------------------------- */

.nubie-action {
  display: inline-flex; align-items: center; gap: 0.5rem;
  /* 44px de haut : la cible tactile minimale recommandee. */
  min-height: 2.75rem;
  padding: 0.65rem 1.25rem;
  border-radius: 999px;
  font-weight: 600;
  text-decoration: none;
  background: var(--nubie-accent);
  color: var(--nubie-fond);
  transition: transform 160ms ease, opacity 160ms ease;
}
.nubie-action:hover { opacity: 0.9; transform: translateY(-1px); }
.nubie-action--sobre {
  background: transparent; color: var(--nubie-encre);
  border: 1px solid var(--nubie-trait);
}

.nubie-pied {
  padding-block: var(--nubie-e-4);
  padding-inline: var(--nubie-gouttiere);
  border-top: 1px solid var(--nubie-trait);
  font-size: var(--nubie-t-s);
  color: var(--nubie-encre-doux);
}

/* --------------------------------------------------------------------------- *
 * Apparition au defilement — l'etat initial est ici, la bascule dans motion.js
 *
 * `animation-timeline` et les transitions de vue sont inegalement supportees :
 * on s'en tient a IntersectionObserver plus une classe, qui marche partout.
 * --------------------------------------------------------------------------- */

.nubie-apparait { opacity: 0; transform: translateY(0.75rem); transition: opacity 520ms ease, transform 520ms ease; }
.nubie-apparait.nubie-vu { opacity: 1; transform: none; }

/* Le mouvement rend certaines personnes malades. Non negociable : sans JavaScript
 * comme avec, le contenu doit etre visible. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .nubie-apparait { opacity: 1; transform: none; transition: none; }
  .nubie-action { transition: none; }
}

/* Et si le JavaScript ne s'execute pas du tout, rien ne doit rester invisible.
 * C'est la raison du `.nubie-js` pose par motion.js : l'etat cache n'existe QUE
 * lorsque le script a demarre. */
html:not(.nubie-js) .nubie-apparait { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------- *
 * Elargissements — mobile d'abord, donc ce sont les seules requetes de taille
 * --------------------------------------------------------------------------- */

@media (min-width: 48rem) {
  :root { --nubie-gouttiere: 2.5rem; }
  .nubie-section { padding-block: var(--nubie-e-6); }
}

@media (min-width: 72rem) {
  :root { --nubie-gouttiere: 4rem; }
}

@media print {
  .nubie-apparait { opacity: 1; transform: none; }
  .nubie-action { border: 1px solid currentColor; background: none; color: inherit; }
}
