/* ============================================================
   BOUTIQUE.

   Valeurs relevees sur store.apple.com/ch-fr le 2026-08-28, pas
   estimees a l'oeil :
     titre de page ..... 80 px / 600 / chasse -1.2 px / interligne 1.05
     titre de section ... 28 px / 600 / chasse +0.196 px / interligne 1.14
     bicolore ........... #1d1d1f puis #6e6e73 — meme corps, meme
                          graisse, seule la couleur change
     fond page .......... #f5f5f7   surface ... #ffffff  (4% d'ecart)
     surface ............ radius 18 px, ombre rgba(0,0,0,.08) 2px 4px 12px

   Deux enseignements que ce releve impose :

   1. La chasse est NEGATIVE a 80 px et POSITIVE a 28 px. Une valeur
      unique pour toutes les tailles est fausse quelque part.
   2. Apple ne borde pas ses surfaces. La separation vient d'un fond a
      peine plus clair que la page. Sur fond sombre on inverse le sens
      mais on garde l'ecart faible : une seule mecanique, pas bordure
      + degrade + ombre empiles.

   TYPOGRAPHIE. SF Pro ne peut pas etre servi depuis ntropyx.com, les
   fichiers sont sous licence Apple. La pile systeme donne le VRAI SF Pro
   sur macOS et iOS, rendu par le systeme, avec ses tables de chasse et
   son corps optique. Portee limitee a .shop : le reste du site ne bouge pas.
   ============================================================ */
.shop {
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text",
          "Segoe UI", Roboto, system-ui, sans-serif;
  --display: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI Variable Display",
             "Segoe UI", Roboto, system-ui, sans-serif;

  /* Une seule surface, un seul ecart. C'est le pendant sombre du
     #fff sur #f5f5f7 d'Apple. */
  --surface: rgba(255, 255, 255, .045);
  --surface-vive: rgba(255, 255, 255, .075);
  --filet: rgba(248, 243, 228, .1);
  --dim: rgba(248, 243, 228, .56);

  font-family: var(--font);
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  padding: clamp(30px, 4vw, 56px) 0 clamp(56px, 7vw, 104px);
}
.shop__shell { width: min(var(--max), calc(100% - 36px)); margin-inline: auto; }

/* ---- Titre de page. Chez Apple il est enorme, a gauche, et la phrase
   qui l'accompagne est calee a droite : deux poids, deux places. ---- */
.shop__tete {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: end; gap: clamp(20px, 4vw, 64px);
  padding-bottom: clamp(28px, 4vw, 52px);
}
.shop__titre {
  margin: 0; font-family: var(--display);
  font-size: clamp(2.9rem, 7vw, 5rem);
  font-weight: 600;
  line-height: 1.05;
  /* -1.2 px sur 80 px releve chez Apple = -0.015 em */
  letter-spacing: -.015em;
}
.shop__dit {
  margin: 0; max-width: 22ch; text-align: right;
  font-family: var(--display);
  font-size: clamp(1.12rem, 1.6vw, 1.5rem);
  font-weight: 600; line-height: 1.28; letter-spacing: -.012em;
  color: var(--dim);
  text-wrap: balance;
}

/* ---- Rail de familles. Vignettes nues, sans cadre : c'est le produit
   qui porte, pas une boite autour de lui. ---- */
.rail {
  display: flex; gap: clamp(10px, 1.8vw, 26px);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  /* Le rail s'aligne exactement sur le conteneur : le retrait negatif qui
     compensait un padding lateral faisait deborder la page de 2 px. */
  padding: 6px 0 clamp(26px, 3.4vw, 44px);
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }

.rail__lien {
  flex: 0 0 auto; width: clamp(104px, 13vw, 148px);
  scroll-snap-align: start;
  display: grid; justify-items: center; gap: 12px;
  padding: 12px 8px; border-radius: 18px;
  color: inherit; text-decoration: none;
  transition:
    background-color 200ms cubic-bezier(.16, 1, .3, 1),
    transform 120ms cubic-bezier(.16, 1, .3, 1);
}
.rail__lien:hover { background: var(--surface); }
/* La reponse est au geste, pas au relachement. */
.rail__lien:active { transform: scale(.97); }

.rail__scene { height: clamp(64px, 8vw, 88px); display: grid; place-items: center; }

/* Les scenes sont des grilles qui contraignent l'image. <picture> n'est qu'une
   enveloppe de selection de format : on la rend transparente pour la mise en
   page, sinon l'image se mesure contre elle et non contre la grille. */
.rail__scene picture,
.produit__scene picture { display: contents; }
.rail__scene img {
  max-width: 100%; max-height: clamp(64px, 8vw, 88px);
  width: auto; height: auto; object-fit: contain;
  filter: drop-shadow(0 8px 12px rgba(0, 0, 0, .5));
}
.rail__nom {
  font-size: .8125rem; line-height: 1.25; text-align: center;
  letter-spacing: -.004em; color: var(--dim);
}

/* ---- Titre de section bicolore. Un seul corps, une seule graisse ;
   c'est la couleur qui separe l'annonce du commentaire. ---- */
.shop__section { padding-top: clamp(34px, 4.4vw, 62px); scroll-margin-top: 84px; }
.shop__h2 {
  margin: 0 0 clamp(18px, 2.4vw, 30px);
  font-family: var(--display);
  font-size: clamp(1.44rem, 2.3vw, 1.75rem);
  font-weight: 600; line-height: 1.14;
  /* +0.196 px sur 28 px releve chez Apple = +0.007 em */
  letter-spacing: .007em;
  text-wrap: balance;
}
.shop__h2 span { color: var(--dim); }

/* ---- Grille. Colonne bornee en haut : sans borne, une famille a un
   seul produit etirerait sa vignette sur toute la largeur. ---- */
.grille {
  display: grid; gap: clamp(12px, 1.5vw, 20px);
  justify-content: start;
  /* auto-FIT et non auto-fill : les colonnes vides se replient, sinon
     une famille de deux produits laissait trois pistes vides et des
     vignettes de 215 px dans un conteneur de 1400. La borne haute evite
     qu'a deux ils s'etirent sur toute la largeur. Mesure dans les 1320 px
     du conteneur : a quatre produits, 468 px donne deux colonnes et un
     carre de 2 x 2 ; une borne plus basse donnerait trois colonnes et
     laisserait le quatrieme seul sur sa rangee. */
  grid-template-columns: repeat(auto-fit, minmax(258px, 468px));
}

/* ---- Le produit mis en avant. Chez Apple le produit phare n'est pas une
   carte de plus dans la grille : il occupe toute la largeur, l'objet a
   gauche, la parole a droite, et son corps monte d'un rang. C'est la
   hierarchie par l'echelle, pas par la couleur. ---- */
.grille--vedette { grid-template-columns: minmax(0, 1fr); }

.produit--vedette {
  /* Deux rangees dans la colonne de droite : le texte, puis le prix et
     l'action juste dessous, alignes sur le nom. L'objet tient la colonne
     de gauche sur toute la hauteur. */
  grid-template-columns: minmax(0, 46%) minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-content: center;
  column-gap: clamp(24px, 4vw, 64px);
  padding: clamp(24px, 3vw, 44px);
}
.produit--vedette .produit__scene { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
.produit--vedette .produit__scene {
  height: clamp(210px, 26vw, 330px);
  margin-bottom: 0;
}
.produit--vedette .produit__prix { margin-top: clamp(18px, 2.2vw, 26px); }
.produit--vedette .produit__scene img { max-height: clamp(210px, 26vw, 330px); }

/* Le corps monte d'un rang, et la chasse se resserre quand il grandit. */
.produit--vedette .produit__nom {
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  line-height: 1.1;
  letter-spacing: -.022em;
}
.produit--vedette .produit__pour {
  margin-top: 9px;
  font-size: clamp(1rem, 1.3vw, 1.125rem);
  line-height: 1.5;
  letter-spacing: -.008em;
}
.produit--vedette .produit__traite { margin-top: 14px; font-size: .9375rem; }
.produit--vedette .produit__prix {
  font-size: clamp(1.6rem, 2.4vw, 2rem);
  letter-spacing: -.022em;
}
@media (max-width: 760px) {
  .produit--vedette {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(14px, 2.4vw, 20px);
  }
  .produit--vedette .produit__scene { height: clamp(180px, 42vw, 240px); }
  .produit--vedette .produit__scene img { max-height: clamp(180px, 42vw, 240px); }
}

/* ---- Un produit. Surface, rien d'autre : pas de bordure, pas de
   degrade, pas d'ombre portee. Une seule mecanique de separation. ---- */
.produit {
  display: grid; grid-template-rows: auto 1fr auto;
  border-radius: 18px;
  background: var(--surface);
  padding: clamp(18px, 2vw, 26px);
  transition:
    background-color 220ms cubic-bezier(.16, 1, .3, 1),
    transform 220ms cubic-bezier(.16, 1, .3, 1);
}
.produit:hover { background: var(--surface-vive); transform: translateY(-2px); }

/* Hauteur ferme : une image de 1275 px de haut imposerait la sienne si
   on s'en remettait a un pourcentage dans une rangee auto-dimensionnee. */
.produit__scene {
  height: clamp(158px, 19vw, 248px);
  display: grid; place-items: center;
  margin-bottom: clamp(14px, 1.6vw, 20px);
}
.produit__scene img {
  max-width: 100%; max-height: clamp(158px, 19vw, 248px);
  width: auto; height: auto; object-fit: contain;
  filter: drop-shadow(0 16px 22px rgba(0, 0, 0, .5));
  transition: transform 320ms cubic-bezier(.16, 1, .3, 1);
}
.produit:hover .produit__scene img { transform: scale(1.03); }

.produit__nom {
  margin: 0; font-size: 1.0625rem; font-weight: 600;
  line-height: 1.3; letter-spacing: -.014em;
}
.produit__pour {
  margin: 5px 0 0; color: var(--dim);
  font-size: .875rem; line-height: 1.45; letter-spacing: -.006em;
}
.produit__traite {
  margin: 11px 0 0; color: var(--dim);
  font-size: .8125rem; letter-spacing: -.004em;
  font-variant-numeric: tabular-nums;
}
.produit__offert {
  margin: 6px 0 0; color: var(--gold-hi);
  font-size: .8125rem; letter-spacing: -.004em;
}

/* ---- Rupture. Le produit reste montre : le retirer ferait croire qu'il
   n'existe plus. Il recule d'un cran — l'objet se decolore, l'etat se dit —
   sans jamais devenir illisible. ---- */
.produit--rupture .produit__scene img { filter: grayscale(1); opacity: .62; }
.produit--rupture:hover .produit__scene img { transform: none; }
.produit__rupture {
  margin: 6px 0 0; color: var(--paper-soft);
  font-size: .8125rem; letter-spacing: -.004em;
}

/* ---- Les hautes concentrations. Les deux bornes empilees, reliees par un
   filet vertical : l'intervalle se lit sans qu'aucun mot ne l'explique. ---- */
.plage {
  margin: 0;
  display: grid; justify-items: center; gap: clamp(9px, 1.1vw, 14px);
  font-family: var(--display);
  font-size: clamp(1.3rem, 2vw, 1.8rem);
  font-weight: 500; line-height: 1.1; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--gold-hi);
  white-space: nowrap;
}
.plage__filet {
  width: 1px; height: clamp(18px, 2.4vw, 30px);
  background: linear-gradient(var(--filet), rgba(216, 192, 113, .55), var(--filet));
}
.produit__prix {
  margin: clamp(14px, 1.6vw, 18px) 0 0;
  font-family: var(--display);
  font-size: 1.16rem; font-weight: 600; letter-spacing: -.016em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.produit__prix--demande { color: var(--dim); }

/* ---- L'action. Pleine largeur, une par produit. Chez Apple on ajoute,
   la quantite se regle dans le panier. ---- */
.action {
  margin-top: clamp(14px, 1.6vw, 18px);
  width: 100%; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--r-control); cursor: pointer;
  font-family: var(--font); font-size: .9375rem; font-weight: 500;
  letter-spacing: -.006em; text-decoration: none;
  transition:
    background-color 170ms cubic-bezier(.16, 1, .3, 1),
    transform 110ms cubic-bezier(.16, 1, .3, 1);
}
.action:active { transform: scale(.97); }
/* Le clavier merite la meme reponse que le doigt : sans cette marque,
   on tabule dans la boutique sans savoir ou l'on est. */
.action:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }

.action--ajouter { background: #f1dda0; color: #08100c; }
.action--ajouter:hover { background: #f7e8bb; }

/* Une demande de prix n'est pas un achat : elle ne porte pas l'habit
   dore, elle emprunte la surface. */
.action--demande { background: var(--surface-vive); color: var(--paper); }
.action--demande:hover { background: rgba(255, 255, 255, .12); }

/* L'etat d'ajout se dit sur place, sans deplacer la mise en page :
   le libelle change, la largeur du bouton ne bouge pas. */
.action--ajouter.fait { background: rgba(255, 255, 255, .12); color: var(--paper); }

@media (max-width: 860px) {
  .shop__tete { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .shop__dit { text-align: left; max-width: 34ch; }

  /* Sur un ecran de 375 px, quatre vignettes de 104 px tombaient juste : la
     quatrieme commencait au pixel ou le rail se termine. Invisible, et rien
     ne disait qu'elle existait — on croyait le catalogue limite a trois
     familles. Les vignettes retrecissent le temps que la suivante depasse
     dans le champ : ce depassement est ce qui dit « fais glisser ». */
  .rail__lien { width: 92px; padding-inline: 4px; }
  .rail { scroll-snap-type: x mandatory; scroll-padding-inline-start: 2px; }
}
@media (max-width: 560px) {
  /* 148 px de plancher donnait deux colonnes des 310 px de conteneur : sur un
     telephone, chaque carte tombait a 164 px et devait y loger l'objet, le nom,
     la description, trois lignes de tarif et le bouton. Tout debordait. Le
     plancher monte a 220 px : un telephone recoit une colonne pleine, une
     petite tablette en garde deux. */
  .grille { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  .produit { padding: 14px; }
  .produit__scene { height: 132px; }
  .produit__scene img { max-height: 132px; }
  .produit__nom { font-size: .9375rem; }
  .produit__pour { font-size: .8125rem; }
}

@media (prefers-reduced-motion: reduce) {
  .rail__lien, .produit, .produit__scene img, .action, .sac { transition: none; }
  .produit:hover { transform: none; }
  .produit:hover .produit__scene img { transform: none; }
  .sac.sursaut { animation: none; }
}
@media (prefers-contrast: more) {
  .shop { --surface: rgba(255, 255, 255, .1); --surface-vive: rgba(255, 255, 255, .16); --dim: rgba(248, 243, 228, .8); --filet: rgba(248, 243, 228, .34); }
}

/* Systeme regle sur transparence reduite : la surface devient opaque et
   le flou disparait. Le texte ne passe jamais sur du flou. */
@media (prefers-reduced-transparency: reduce) {
  .shop { --surface: #101713; --surface-vive: #17201b; }
}

/* Mention de prix. Apple la met en note sous la grille, jamais collee au
   montant : le prix reste lisible d'un coup d'oeil, la precision est a portee
   de regard. L'OIP demande les taxes dans le prix et autorise les frais
   d'expedition a part — c'est exactement ce que dit cette ligne. */
.shop__mention {
  margin: clamp(24px, 2.8vw, 34px) 0 0;
  color: var(--dim);
  font-size: .8125rem; line-height: 1.5; letter-spacing: -.004em;
  max-width: 62ch;
}

/* Le tarif d'un article : hors taxe, la TVA, puis le total. C'est la lecture
   d'une facture, pas une etiquette — le client voit ce qu'il paie et pourquoi.
   Les montants sont alignes a droite et en chiffres tabulaires : les colonnes
   se lisent d'un coup d'oeil d'une carte a l'autre.
   .produit__prix ne sert plus qu'aux articles sans prix (sur demande). */
.produit__tarif {
  margin: clamp(14px, 1.6vw, 18px) 0 0;
  font-variant-numeric: tabular-nums;
}
.produit__tarif-l {
  display: flex; justify-content: space-between; gap: 14px;
  color: var(--dim); font-size: .8125rem; line-height: 1.7;
  letter-spacing: -.004em;
}
.produit__tarif-l--total {
  margin-top: 4px; padding-top: 6px;
  border-top: 1px solid var(--filet);
  color: inherit; font-family: var(--display);
  font-size: 1.16rem; font-weight: 600; letter-spacing: -.016em; line-height: 1.5;
}
