:root{
  --cream:#E3E3C4;
  --cream-50:rgba(227,227,196,.5);
  --cream-25:rgba(227,227,196,.25);
  --ink:#060A10;
  --card:#08141D;
  /* Fond "collectee" : meme profondeur que --card, teinte chaude (olive
     sombre) plutot que bleu nuit, pour que l'oeil distingue une carte
     deja recuperee sans avoir a lire la pastille. */
  --card-got:#171307;
  --w-50:rgba(255,255,255,.5);
  --w-30:rgba(255,255,255,.3);
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  /* géométrie du header, reprise de la maquette */
  --hd-h:89px;      /* hauteur de la barre */
  /* Position et hauteur du selecteur Vue du ciel / Collection. La hauteur
     se deduit du bouton : 15 px de marge, 18 px de texte en interligne
     normal (soit environ 22 px), 15 px de marge, plus 1 px de bordure de
     part et d'autre. Ces deux valeurs servent a poser les filtres de la
     collection a exactement 24 px sous le selecteur. */
  --tg-top:162px;
  --tg-h:54px;
  --notch-d:9px;    /* profondeur de la défonce */
  --notch-w:348px;  /* largeur totale de la défonce */
  /* Supplement de hauteur ajoute par la carte du ciel deployee (actions
     "Collecter"/"En savoir plus" visibles) : pose fleches et zoom juste
     au-dessus, en phase avec la transition de .c-acts. Remis a 0 des que
     la carte est repliee — voir setCardOpen() et renderCard(). */
  --aside-extra:0px;
}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden}
body{
  font-family:'Afacad',system-ui,sans-serif;color:#fff;
  background:linear-gradient(180deg,#000 0%,#0A1931 100%);
  /* Des taps rapprochés (zoom +/-, ouverture/fermeture de carte) pouvaient
     etre lus comme un double-tap par le navigateur, qui zoomait toute la
     page — supprime specifiquement ce geste, sans toucher au reste. */
  touch-action:manipulation;
}
button{font-family:inherit;color:inherit;background:none;border:none;cursor:pointer}

/* ================= SPLASHSCREEN =================
   Fond degrade et champ d'etoiles statique, tracés fins animes (Lottie),
   badge anime au centre (Lottie, 3 s exactement). Le fondu vers
   l'interface est declenche a la fin de l'animation du badge. */
#splash{
  position:fixed;inset:0;z-index:100;overflow:hidden;
  background:linear-gradient(180deg,#000 0%,#0A1931 100%);
  opacity:1;transition:opacity .85s ease;
}
#splash.out{opacity:0;pointer-events:none}
#splash.gone{display:none}
/* Rien de plus a faire ici pour "no-splash" : le JS (voir le bloc
   SPLASHSCREEN) decide seul, une fois la session connue, s'il faut
   reveler la carte (classes out/gone, comme l'animation normale) ou le
   portail (#splash-gate.on) — une regle CSS qui masquerait #splash
   d'office masquerait le portail avec, puisqu'il vit a l'interieur. */
/* Fond etoile fourni : il porte deja le degrade et la lueur turquoise du
   bas. On n'ajoute donc pas l'ellipse en color-dodge par-dessus, elle
   surexposerait la partie basse. Le degrade sous l'image sert de fond
   d'attente pendant son chargement, puis l'image apparait en fondu. */
#splash-bg{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center bottom;
  opacity:0;transition:opacity .45s ease;
}
#splash-bg.ready{opacity:1}
/* Les cercles debordent volontairement du cadre 1920 x 1080 de l'animation :
   on laisse donc le SVG deborder au lieu de le rogner. */
#splash-fond{
  position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);
  width:max(135vw,135vh);aspect-ratio:1920 / 1080;
  pointer-events:none;opacity:.92;
}
#splash-fond svg{overflow:visible!important}
#splash-badge{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(250px,46vw);aspect-ratio:281 / 271;pointer-events:none;
  opacity:1;transition:opacity .4s ease;
}
#splash-badge.hide{opacity:0}
#splash-badge.no-anim-badge{transition:none}
/* Le badge en video. Son fond noir n'est pas une couche alpha : il n'y a
   rien a retirer. On le neutralise par fusion « screen », ou le noir
   n'ajoute rien et seuls les pixels clairs apparaissent — exactement le
   principe du melange additif dont se sert le moteur pour les
   illustrations de constellations. Si un jour la video porte une vraie
   couche alpha (WebM VP9 en yuva420p), remplacez screen par normal. */
#splash-badge video{
  width:100%;height:100%;object-fit:contain;display:block;
}

/* ================= PORTAIL + AUTHENTIFICATION =================
   Portail, inscription, connexion, mot de passe oublie et sa
   reinitialisation : cinq etats d'un seul et meme bloc, pas cinq pages.
   Necessaire pour que la musique ne soit jamais coupee par un
   rechargement, et pour permettre un vrai fondu entre ecrans (demande
   explicite) plutot qu'un blanc de navigation. Le routage (quel etat
   correspond a quelle URL) est gere en JS, voir le bloc ECRANS
   D'AUTHENTIFICATION. */
#splash-gate{
  position:absolute;inset:0;z-index:1;
  display:flex;align-items:center;justify-content:center;overflow-y:auto;
  padding:40px 20px;box-sizing:border-box;
  opacity:0;pointer-events:none;transition:opacity .6s ease;
}
#splash-gate.on{opacity:1;pointer-events:auto}
#splash-gate.no-anim{transition:none}
.sg-inner{width:min(400px,100%);display:flex;flex-direction:column;align-items:center;margin:auto 0}
/* Deux tailles de logo, pas une seule : la maquette du portail montre un
   logo bien plus grand que celui des ecrans de formulaire — cf. Figma
   94:548 (logo ~305px pour un cadre de 1440) contre 94:704 (~153px).
   #splash-gate.form-screen bascule sur la petite taille des que le
   contenu sous le logo n'est plus les deux boutons. */
.sg-logo{width:min(230px,58vw);margin-bottom:40px;flex:none;transition:width .4s ease,margin .4s ease}
#splash-gate.form-screen .sg-logo{width:min(150px,40vw);margin-bottom:28px}
.sg-logo svg,.sg-logo img{width:100%;display:block}
/* Le contenu sous le logo change d'un etat a l'autre : lui seul se
   fond, le logo reste un point fixe pendant toute la traversee. */
#sg-content{width:100%;transition:opacity .32s ease;opacity:1}
#sg-content.fading{opacity:0}
.sg-acts{display:flex;flex-direction:column;gap:14px;align-items:center;width:100%}
/* Le rang bouton+ornements : les decorations Figma (fournies en SVG,
   Left_side/Right_side) vivent A COTE du bouton, pas dedans a la place
   du texte — un bouton qui se laisse prolonger de chaque cote par ces
   ornements, exactement le decoupage Figma. Meme largeur et meme taille
   de texte que les ecrans de formulaire (auth-submit) : demande
   explicite, la maquette elle-meme etait plus etroite mais rendait les
   boutons trop petits a l'usage. */
.sg-btn-row{display:flex;align-items:center;width:100%}
.sg-orn{flex:none;width:23px;height:8px;display:block}
.sg-btn{
  display:flex;align-items:center;justify-content:center;flex:1 1 auto;min-width:0;
  width:100%;padding:15px 30px;border-radius:20000px;box-sizing:border-box;
  text-decoration:none;font-weight:700;font-size:18px;letter-spacing:.02em;
  text-transform:uppercase;color:var(--cream);
  border:1px solid rgba(227,227,196,.5);
  transition:background .2s,border-color .2s;
}
.sg-btn:hover{background:rgba(227,227,196,.1);border-color:#E3E3C4}
.sg-btn.primary{
  border-color:#E3E3C4;
  background:linear-gradient(180deg,rgba(227,227,196,.04) 0%,rgba(227,227,196,.2) 100%);
}
.sg-btn.primary:hover{background:linear-gradient(180deg,rgba(227,227,196,.08) 0%,rgba(227,227,196,.28) 100%)}
.sg-btn .txt{white-space:nowrap}
@media (max-width:420px){
  .sg-btn{font-size:14px;padding:13px 20px}
  .sg-logo{margin-bottom:32px}
}

/* Pied du portail : les deux textes legaux, accessibles depuis l'ecran
   titre comme depuis les formulaires. Discret par defaut, lisible au
   survol — c'est une mention obligatoire, pas un element de navigation
   qu'il faut mettre en avant. */
.sg-legal{
  margin-top:34px;display:flex;align-items:center;justify-content:center;
  gap:6px 14px;flex-wrap:wrap;flex:none;
}
.sg-legal a{
  font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--cream);opacity:.42;text-decoration:none;transition:opacity .2s;
}
.sg-legal a:hover{opacity:.9;text-decoration:underline;text-underline-offset:3px}
.sg-legal .dot{width:3px;height:3px;border-radius:50%;background:var(--cream);opacity:.25;flex:none}
@media (max-width:420px){ .sg-legal{margin-top:26px} }

/* Case de consentement de l'inscription. Obligatoire : elle porte a la
   fois l'age requis (15 ans, age du consentement numerique en droit
   francais) et l'acceptation des deux textes. La case elle-meme est
   dessinee a la main plutot qu'en checkbox native, pour tenir la charte
   — mais c'est bien un input checkbox qui vit dessous, avec son etat
   accessible au clavier et aux lecteurs d'ecran. */
.auth-consent{display:flex;gap:11px;align-items:flex-start;width:100%;cursor:pointer;
  padding:2px 4px}
.auth-consent input{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.auth-consent .bx{
  width:20px;height:20px;flex:none;margin-top:1px;border-radius:5px;
  border:1px solid var(--cream-50);display:grid;place-items:center;
  transition:border-color .18s,background .18s;
}
.auth-consent .bx svg{width:12px;height:12px;opacity:0;transition:opacity .15s}
.auth-consent input:checked + .bx{background:var(--cream);border-color:var(--cream)}
.auth-consent input:checked + .bx svg{opacity:1}
.auth-consent input:focus-visible + .bx{outline:2px solid var(--cream);outline-offset:2px}
.auth-consent .tx{font-size:12.5px;line-height:1.5;color:var(--cream);opacity:.72}
.auth-consent .tx a{color:var(--cream);opacity:1;text-decoration:underline;
  text-underline-offset:2px}
.auth-consent.missing .bx{border-color:#E39A8A}
.auth-consent.missing .tx{opacity:.95}

/* ---------- ecrans d'authentification (titre, formulaire, champs) ----------
   Portes directement depuis l'ancienne feuille partagee assets/css/auth.css
   (les 4 pages autonomes qu'elles remplacent) : memes classes, pour que le
   JS qui construit chaque ecran n'ait rien de nouveau a apprendre. */
.auth-head{width:100%;display:flex;flex-direction:column;align-items:center}
.auth-title{
  font-size:clamp(26px,8vw,42px);font-weight:700;text-transform:uppercase;
  color:var(--cream);text-align:center;width:100%;line-height:1.1;
}
.auth-rule{display:flex;align-items:center;gap:5px;width:100%;margin-top:10px}
.auth-rule .ln{flex:1 1 auto;height:1px;background:var(--cream-50)}
.auth-rule .r7{width:7px;height:7px;border-radius:50%;border:1px solid var(--cream);flex:none}
.auth-rule .d5{width:5px;height:5px;border-radius:50%;background:var(--cream);flex:none}
.auth-drop{width:34px;height:22px;margin:-1px auto 0;flex:none;overflow:visible}
.auth-drop svg{width:100%;height:100%;overflow:visible}

.auth-note{
  margin-top:22px;font-size:14.5px;line-height:1.5;text-align:center;
  color:var(--cream-50);width:100%;
}

/* Deux paliers d'espacement, comme dans la maquette : 60px entre les
   grands blocs (titre / formulaire / bouton), 25px entre les elements
   a l'interieur du bloc formulaire (Google, "ou", champs). Un seul gap
   uniforme aplatissait ces deux echelles en une seule. */
.auth-form{width:100%;display:flex;flex-direction:column;gap:60px;margin-top:60px}
.auth-group{width:100%;display:flex;flex-direction:column;gap:25px}

.g-btn{
  width:100%;background:#fff;border-radius:20000px;padding:15px 30px;
  display:flex;align-items:center;justify-content:center;gap:10px;
  transition:background .2s;border:none;cursor:pointer;
}
.g-btn:hover{background:#EFEFEF}
.g-btn svg{width:24px;height:24px;flex:none;display:block}
.g-btn span{font-weight:700;font-size:18px;text-transform:uppercase;color:var(--ink);white-space:nowrap}

.auth-or{display:flex;align-items:center;gap:14px;width:100%}
.auth-or .ln-wrap{flex:1 1 0;display:flex;align-items:center;gap:5px;height:7px}
.auth-or .ln{flex:1 1 auto;height:1px;background:var(--cream-50)}
.auth-or .r7{width:7px;height:7px;border-radius:50%;border:1px solid var(--cream);flex:none}
.auth-or .d5{width:5px;height:5px;border-radius:50%;background:var(--cream);flex:none}
.auth-or span{font-size:18px;font-weight:700;text-transform:uppercase;color:var(--cream);flex:none}

.auth-fields{display:flex;flex-direction:column;gap:10px;width:100%}
.auth-row{display:flex;gap:5px;width:100%}
.auth-field{
  flex:1 1 0;min-width:0;
  border:1px solid var(--cream);border-radius:20000px;
  background:linear-gradient(180deg,rgba(227,227,196,.02) 0%,rgba(227,227,196,.1) 100%);
  padding:2px 26px;transition:border-color .2s;
}
.auth-field:focus-within{border-color:#fff}
.auth-field input{
  width:100%;background:none;border:none;outline:none;padding:14px 0;
  font-family:inherit;font-weight:700;font-size:18px;text-transform:uppercase;color:var(--cream);
}
.auth-field input::placeholder{color:var(--cream);opacity:.5}
.auth-field input:-webkit-autofill{
  -webkit-text-fill-color:var(--cream);
  transition:background-color 9999s ease-in-out 0s;
}

.auth-inline-link{
  align-self:flex-end;font-size:12px;font-weight:700;letter-spacing:.02em;
  text-transform:uppercase;color:var(--cream-50);text-decoration:underline;
  margin-top:-2px;cursor:pointer;background:none;border:none;
}
.auth-inline-link:hover{color:var(--cream)}

.auth-actions{display:flex;flex-direction:column;gap:20px;align-items:center;width:100%}
.auth-submit{
  position:relative;width:100%;border:1px solid var(--cream);border-radius:20000px;
  background:linear-gradient(180deg,rgba(227,227,196,.04) 0%,rgba(227,227,196,.2) 100%);
  padding:15px 30px;display:flex;align-items:center;justify-content:center;
  transition:background .2s;cursor:pointer;
}
.auth-submit:hover{background:linear-gradient(180deg,rgba(227,227,196,.08) 0%,rgba(227,227,196,.28) 100%)}
.auth-submit:disabled{opacity:.55;pointer-events:none}
.auth-submit .txt{font-weight:700;font-size:18px;text-transform:uppercase;color:var(--cream);white-space:nowrap}
.auth-submit .spin{
  width:16px;height:16px;border-radius:50%;border:2px solid var(--c20);border-top-color:var(--cream);
  animation:auth-spin .7s linear infinite;display:none;
}
.auth-submit.loading .txt{opacity:.5}
.auth-submit.loading .spin{display:block;margin-left:10px}
@keyframes auth-spin{to{transform:rotate(360deg)}}

.auth-switch{font-size:14px;font-weight:700;text-transform:uppercase;color:#fff;text-decoration:underline;
  cursor:pointer;background:none;border:none;font-family:inherit}
.auth-switch:hover{opacity:.8}

.auth-msg{
  width:100%;padding:12px 18px;border-radius:14px;font-size:13.5px;line-height:1.4;
  text-align:center;display:none;box-sizing:border-box;
}
.auth-msg.on{display:block}
.auth-msg.err{background:rgba(200,70,70,.14);border:1px solid rgba(200,70,70,.4);color:#F0B8B8}
.auth-msg.ok{background:rgba(227,227,196,.08);border:1px solid var(--c20);color:var(--cream)}

@media (max-width:480px){
  .auth-row{flex-direction:column}
  .auth-form{margin-top:28px;gap:18px}
}

/* ================= CIEL ================= */
/* Aucun filtre CSS sur le canvas : le ciel garde ses couleurs vraies.
   Le moteur code en dur le cyan des tracés de constellations, dans
   src/modules/constellations.c :
       vec4_set(lines_color, 0.65, 1.0, 1.0, 0.4);
   Aucun filtre global ne peut le convertir en #E3E3C4 sans abîmer le
   reste : préserver les gris impose que chaque ligne de la matrice somme
   à 1, et sous cette contrainte décyaniser les tracés revient à vider le
   canal rouge, donc à détruire Mars, Saturne et les étoiles orangées.
   La seule vraie solution est de recompiler le moteur avec la couleur
   crème — une seule ligne à changer. */
#stel-canvas{
  position:fixed;inset:0;width:100%;height:100%;z-index:1;touch-action:none;
}
#fallback-stars{position:fixed;inset:0;z-index:0;pointer-events:none;transition:opacity 1.2s}
/* Ellipse 297 de la maquette : 2178 x 943 px dans un cadre de 1440 x 1024,
   posée à 403 px du haut — elle dépasse donc de 322 px sous le bas de page.
   Ramené en unités relatives : 151vw x 92vh, bottom -31.4vh. Fusion
   color-dodge, comme dans Figma. */
.horizon-glow{
  position:fixed;left:50%;bottom:-31.4vh;transform:translateX(-50%);
  width:151vw;height:92vh;z-index:2;pointer-events:none;
  mix-blend-mode:color-dodge;
  background:radial-gradient(50% 50% at 50% 50%,
    rgba(96,170,196,.62) 0%,
    rgba(58,118,146,.34) 34%,
    rgba(30,68,92,.14) 58%,
    transparent 74%);
}

/* ================= HEADER ================= */
.hd-bg{
  position:fixed;top:0;left:0;right:0;height:calc(var(--hd-h) + var(--safe-t));z-index:9;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(4,7,12,.97) 0%,
    rgba(5,9,15,.94) 42%,
    rgba(8,18,33,.86) 78%,
    rgba(10,25,49,.74) 100%);
}
header{
  position:fixed;top:0;left:0;right:0;z-index:11;
  height:calc(var(--hd-h) + var(--safe-t));
  padding:calc(27px + var(--safe-t)) 80px 27px;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:20px;
}
/* Deux colonnes laterales de largeur egale (1fr chacune) : le logo au
   centre reste toujours parfaitement centre sur l'ecran, quel que soit
   ce qu'on met a gauche ou a droite. Plus robuste que l'ancien bloc
   miroir invisible, qui devait deviner a l'avance la largeur exacte du
   bouton compte pour compenser. */
header > :first-child{justify-self:start;min-width:0}
header > :last-child{justify-self:end}

/* ---------- recherche (en-tete, en haut a gauche) ----------
   Desktop/tablette large : champ visible directement dans l'en-tete,
   suggestions ancrees dessous. Mobile : l'icone seule ; au tap, une
   recherche plein ecran s'ouvre par-dessus tout (#search-overlay, plus
   bas) — rien ne change jamais de taille dans l'en-tete lui-meme, le
   logo ne peut donc pas se decaler pendant une recherche.

   Deuxieme passe sur cet ecran : le premier jet etait juge pas assez
   integre au reste de l'app — typos trop petites, resultats trop nus.
   Les puces, le medaillon et la pastille de statut sont maintenant
   exactement ceux des cartes (voir searchItemHTML plus bas), pas une
   reinterpretation — c'est ce qui les fait ressembler a l'app plutot
   qu'a un widget rapporte. */
.search-toggle{
  width:40px;height:40px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--c20);background:none;transition:background .2s,border-color .2s;
}
.search-toggle:hover{background:rgba(227,227,196,.08);border-color:var(--cream)}
.search-toggle svg{width:18px;height:18px;display:block}

.search-field{
  position:relative;display:flex;align-items:center;gap:12px;
  border:1px solid var(--cream);border-radius:20000px;
  background:linear-gradient(180deg,rgba(227,227,196,.04) 0%,rgba(227,227,196,.11) 100%);
  padding:13px 24px;width:270px;transition:border-color .2s,background .2s;
}
.search-field:focus-within{border-color:#fff;background:linear-gradient(180deg,rgba(227,227,196,.06) 0%,rgba(227,227,196,.15) 100%)}
.search-field .s-ico{width:19px;height:19px;flex:none;opacity:.75;display:block}
.search-field input{
  flex:1 1 auto;min-width:0;background:none;border:none;outline:none;
  color:var(--cream);font-family:inherit;font-size:17px;font-weight:700;text-transform:uppercase;
}
.search-field input::placeholder{color:var(--cream);opacity:.48;font-weight:400;text-transform:none}

/* Fond entierement opaque : un premier essai translucide avec flou se
   lisait mal par-dessus le ciel — un rendu franc, comme les autres
   panneaux de l'app (menu du compte, carte). */
.search-results{
  position:absolute;top:calc(100% + 10px);left:0;width:360px;
  background:#0A121F;border:1px solid var(--c20);border-radius:18px;
  padding:8px;display:none;max-height:420px;overflow-y:auto;
  box-shadow:0 24px 48px rgba(0,0,0,.55);
}
.search-results.on{display:block}

.search-item{
  display:flex;align-items:center;gap:14px;padding:12px;border-radius:14px;
  cursor:pointer;transition:background .15s;
}
.search-item:hover,.search-item.active{background:rgba(227,227,196,.1)}
.search-item + .search-item{margin-top:2px}
.si-medallion{width:56px;height:56px;flex:none;opacity:.85}
.si-medallion svg{width:100%;height:100%;display:block}
.si-mid{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:7px}
.si-name{font-weight:700;font-size:16.5px;text-transform:uppercase;color:var(--cream);line-height:1.15}
.si-chips{display:flex;flex-wrap:wrap;gap:5px}
.si-pill{
  display:inline-flex;align-items:center;gap:4px;align-self:flex-start;
  border:1px solid var(--c20);border-radius:2000px;padding:2px 10px;
  font-weight:700;font-size:10px;line-height:1.5;text-transform:uppercase;color:var(--cream);white-space:nowrap;
}
.si-pill svg{width:9px;height:9px;display:block;flex:none}
.si-pill.got{border-color:var(--cream);background:var(--cream);color:var(--ink)}
.si-pill.reminder{border-color:var(--c50)}

.search-empty{padding:20px 12px;text-align:center;font-size:14px;color:var(--c50)}

/* ---------- recherche plein ecran (mobile/tablette) ----------
   Un vrai calque a part, pas un champ qui s'etire dans l'en-tete :
   c'est ce qui garantit que rien dans l'en-tete ne bouge pendant que la
   recherche est ouverte. */
#search-overlay{
  position:fixed;inset:0;z-index:60;
  background:linear-gradient(180deg,#04070c 0%,#0A1931 100%);
  opacity:0;pointer-events:none;transition:opacity .25s ease;
  display:flex;flex-direction:column;
}
#search-overlay.open{opacity:1;pointer-events:auto}
.so-top{
  display:flex;align-items:center;gap:12px;flex:none;
  padding:calc(20px + var(--safe-t)) 20px 16px;
  border-bottom:1px solid var(--c20);
}
.so-top .search-field{flex:1 1 auto;width:auto}
.so-close{
  width:40px;height:40px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--c50);background:none;color:var(--cream);
}
.so-close svg{width:16px;height:16px}
.so-results{flex:1 1 auto;overflow-y:auto;padding:10px 16px calc(24px + var(--sb))}
.so-results .search-item{padding:14px 10px}
.so-results .si-medallion{width:60px;height:60px}
.so-results .si-name{font-size:17.5px}
.so-results .search-empty{padding-top:60px;font-size:14px}

/* Bref eclat sur la carte de collection visee par un resultat de recherche. */
.search-flash{animation:search-flash-kf 1.4s ease}
@keyframes search-flash-kf{
  0%,100%{box-shadow:none}
  20%{box-shadow:0 0 0 3px rgba(227,227,196,.55)}
}

@media (min-width:900px){
  .search-toggle{display:none}
  #search-overlay{display:none!important}
}
@media (max-width:899px){
  #search-field-desktop{display:none}
}
.account{display:flex;align-items:center;gap:15px;flex:none}
.account .ico{width:30px;height:30px;flex:none;display:block}
.account .ico svg{width:100%;height:100%;display:block;overflow:visible}
.account .ico img{width:100%;height:100%;display:block;object-fit:contain}
a.account{text-decoration:none}
.account .lbl{font-weight:700;font-size:18px;line-height:normal;text-transform:uppercase;color:var(--cream);white-space:nowrap}
.logo{width:324.7px;height:45px;flex:none;display:block}
.logo svg{width:100%;height:100%;display:block}

/* ---- la défonce : hairline + tab centré ---- */
.hd-edge{
  position:fixed;left:0;right:0;top:calc(var(--hd-h) + var(--safe-t) + 1px);
  height:var(--notch-d);z-index:11;pointer-events:none;
  display:flex;align-items:flex-start;justify-content:center;
}
.hd-edge .side{flex:1 1 auto;height:1px;background:var(--cream-50)}
.hd-edge .notch{flex:none;width:var(--notch-w);height:auto;display:block;overflow:visible}
/* la forme suspendue sous le logo (arc + point + filet) */
.hd-drop{
  position:fixed;left:50%;transform:translateX(-50%);
  top:calc(var(--hd-h) + var(--safe-t) + var(--notch-d) + 1px);
  width:68px;height:53px;z-index:11;pointer-events:none;overflow:hidden;
}
.hd-drop svg{width:100%;height:100%;display:block;overflow:visible}

/* ================= TOGGLE ================= */
.toggle-wrap{
  position:fixed;left:50%;transform:translateX(-50%);
  top:calc(var(--tg-top) + var(--safe-t));z-index:11;
  display:flex;align-items:center;
}
.orn{display:flex;align-items:center;gap:5px;flex:none}
.orn .d5{width:5px;height:5px;border-radius:50%;background:var(--cream);flex:none}
.orn .r7{width:7px;height:7px;border-radius:50%;border:1px solid var(--cream);flex:none}
.orn .ln{width:20px;height:1px;background:var(--cream-50);flex:none}
.toggle{
  display:flex;align-items:stretch;flex:none;
  border:1px solid var(--cream-50);border-radius:20000px;
  background:linear-gradient(180deg,rgba(227,227,196,.03) 0%,rgba(227,227,196,.10) 100%);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
.tg{
  display:flex;align-items:center;justify-content:center;
  padding:15px 50px;border-radius:20000px;
  font-weight:700;font-size:18px;line-height:normal;text-transform:uppercase;text-align:center;
  color:var(--cream);opacity:.5;white-space:nowrap;transition:opacity .2s,background .2s;
}
.tg + .tg{padding-left:40px}
.tg.on{background:var(--cream);color:var(--ink);opacity:1;padding-left:50px;padding-right:50px}
.tg:not(.on):hover{opacity:.75}

/* ================= ZOOM ================= */
.zoom{position:fixed;right:39.7px;bottom:calc(40px + var(--safe-b));z-index:11;display:flex;flex-direction:column;gap:5px;transition:bottom .28s ease}
.zbtn{
  width:50px;height:50px;border-radius:50%;flex:none;
  border:1.064px solid var(--cream);
  background:linear-gradient(180deg,rgba(227,227,196,.04) 0%,rgba(227,227,196,.2) 100%);
  display:flex;align-items:center;justify-content:center;transition:background .2s}
.zbtn:active{background:rgba(227,227,196,.32)}
.zbtn svg{width:24px;height:24px;display:block}
/* Mode boussole actif : fond dore plein, pictogramme fonce — l'inverse
   du bouton au repos, pour que l'etat "en train de suivre le geste"
   saute aux yeux plutot que de se deviner au seul contour "active" du
   bouton (voir useRealOrientation/exitCompassMode plus bas). */
#z-compass.active{
  background:linear-gradient(180deg,#E3E3C4 0%,#EDEDD8 100%);
  border-color:#E3E3C4;
}
#z-compass.active svg{stroke:#050B14}
#z-compass.active svg path{fill:#050B14}
#z-compass.active svg circle:last-child{fill:#E3E3C4}
/* Reserve au tactile (mobile/tablette) : sur un poste a souris, il n'y a
   pas de boussole a lire, le bouton n'a donc rien a faire. */
@media (hover:hover) and (pointer:fine){
  #z-compass{display:none}
}

/* ================= CARTE ================= */
.card-row{
  position:fixed;left:0;right:0;
  bottom:calc(40px + var(--safe-b));z-index:11;
  display:flex;justify-content:center;align-items:center;
  /* La rangee tient toute la largeur de l'ecran mais n'est pleine qu'en
     son centre (la carte fait 560px). Sans la regle ci-dessous, ses
     zones vides captaient clics et molette sur TOUTE la largeur, dans
     une bande de la hauteur de la carte a 40px du bas.

     En desktop, cette bande recouvrait exactement .zoom : meme
     z-index, mais .card-row est placee plus loin dans le document,
     donc dessus. Les boutons + et - devenaient inertes, et la molette
     n'atteignait plus le canvas dans cette bande. En mobile le
     probleme ne se voyait pas : .zoom remonte a 196px du bas, au-dessus
     de la rangee.

     Les evenements traversent donc desormais le vide, et seuls les
     enfants reels — les fleches et la carte — les recoivent. */
  pointer-events:none;
}
.card-row > *{pointer-events:auto}
.nav-side{display:flex;align-items:center;gap:5px;height:54px;flex:none}
.nav-side .ln{width:40px;height:1px;background:var(--w-50);flex:none}
.nav-side .d5{width:5px;height:5px;border-radius:50%;background:#fff;flex:none}
.nav-side .r7{width:7px;height:7px;border-radius:50%;border:1px solid #fff;flex:none}
.nav-btn{
  width:50px;height:50px;border-radius:50%;flex:none;
  border:1px solid var(--w-50);background:rgba(6,10,16,.45);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  display:flex;align-items:center;justify-content:center;transition:border-color .2s,background .2s}
.nav-btn:active{background:rgba(227,227,196,.16);border-color:var(--cream)}
.nav-btn svg{width:16px;height:16px;display:block}
.card{
  width:560px;flex:none;position:relative;cursor:pointer;
  border:1px solid var(--w-50);border-radius:8px;
  padding:20px 30px;display:flex;gap:30px;align-items:center;
  background:
    radial-gradient(118% 150% at 88% -28%,rgba(46,82,104,.55) 0%,rgba(20,42,58,.18) 46%,transparent 72%),
    var(--card);
  box-shadow:0 20px 54px rgba(0,0,0,.5);
  transition:background .3s ease,border-color .3s ease;
}
/* Ekko deja collecte : bascule sur une teinte chaude plutot que le bleu
   nuit habituel — le but explicite est de distinguer une carte deja
   recuperee au premier coup d'oeil, pas seulement via la pastille. */
.card.got{
  border-color:rgba(227,227,196,.35);
  background:
    radial-gradient(118% 150% at 88% -28%,rgba(108,96,58,.4) 0%,rgba(58,50,28,.16) 46%,transparent 72%),
    var(--card-got);
}
.medallion{width:100px;height:100px;flex:none;opacity:.75;position:relative}
.medallion svg{width:100%;height:100%;display:block}
.card-body{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:7px}
.chips{display:flex;align-items:center;justify-content:space-between;gap:10px}
.chip{
  display:inline-flex;align-items:center;justify-content:center;gap:5px;
  padding:2px 10px;border-radius:2000px;
  font-weight:700;font-size:10px;line-height:1.5;text-transform:uppercase;color:#fff;white-space:nowrap;flex:none}
.chip.cat{background:var(--w-30);opacity:.75}
.chip.vis{border:1px solid #fff}
.chip.vis svg{width:9.5px;height:10px;display:block;flex:none}
.card-txt{display:flex;flex-direction:column;align-items:flex-start;opacity:.75;width:100%}
.c-title{font-weight:700;font-size:22px;line-height:normal;text-transform:uppercase;width:100%}
.c-desc{font-weight:400;font-size:14px;line-height:1.2;width:100%;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.c-state{display:flex;align-items:center;gap:5px;width:368px;max-width:100%;margin-top:0}
.c-state .ln{flex:1 1 0;min-width:0;height:1px;background:var(--w-50)}
.c-state .r7{width:7px;height:7px;border-radius:50%;border:1px solid #fff;flex:none}
.c-state .d5{width:5px;height:5px;border-radius:50%;background:#fff;flex:none}
.c-state .pill{
  display:inline-flex;align-items:center;gap:4px;
  border:1px solid var(--w-30);border-radius:2000px;padding:2px 10px;flex:none;
  font-weight:700;font-size:10px;line-height:1.5;text-transform:uppercase;color:#fff;white-space:nowrap}
.c-state .pill svg{width:9px;height:9px;display:block;flex:none}
/* Collectee : pastille pleine, comme le bouton principal — le meme signal
   « c'est acquis » que « Collecter l'ekko » utilisait pour attirer l'oeil. */
.c-state .pill.got{border-color:var(--cream);background:var(--cream);color:var(--ink)}
.c-state .pill.reminder{border-color:var(--cream-50);color:var(--cream)}

.c-pos{
  position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(152px + var(--safe-b));z-index:11;
  font-weight:700;font-size:11px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--cream-50);pointer-events:none;white-space:nowrap}

/* ================= FONDU VERS LE PLAYER =================
   Moitié sortante de la transition : la carte s'efface, le player s'ouvre
   sur son propre fondu entrant. Seule l'opacité est animée, donc tout se
   joue sur le compositeur. */
#curtain{position:fixed;inset:0;z-index:200;background:#000;
  opacity:0;pointer-events:none;will-change:opacity;
  transition:opacity .32s cubic-bezier(.4,0,1,1)}
#curtain.on{opacity:1;pointer-events:auto}
@media (prefers-reduced-motion:reduce){ #curtain{transition-duration:1ms} }

/* ================= SOUS-MENU DU COMPTE ================= */
button.account{cursor:pointer}
#menu-veil{position:fixed;inset:0;z-index:18;background:rgba(4,7,13,.4);
  opacity:0;pointer-events:none;transition:opacity .22s}
#menu-veil.on{opacity:1;pointer-events:auto}
#menu{
  position:fixed;right:18px;top:calc(var(--hd-h) + var(--safe-t) + 10px);z-index:19;
  min-width:236px;padding:10px;border-radius:14px;
  border:1px solid var(--c20);background:rgba(6,12,18,.97);backdrop-filter:blur(14px);
  display:flex;flex-direction:column;
  opacity:0;transform:translateY(-8px);pointer-events:none;
  transition:opacity .22s,transform .22s;
  /* Sur un ecran bas (telephone en paysage), la liste peut depasser le bas
     du viewport — rien ne la contraignait, elle debordait alors sans
     recours au defilement. */
  max-height:calc(100vh - var(--hd-h) - var(--safe-t) - 20px);
  overflow-y:auto;
}
#menu.on{opacity:1;transform:translateY(0);pointer-events:auto}
.mi{display:block;padding:11px 13px;border-radius:9px;text-decoration:none;
  font-size:12.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--cream);opacity:.85;transition:background .18s,opacity .18s}
.mi:hover{background:rgba(227,227,196,.1);opacity:1}
.mi.off{opacity:.3;pointer-events:none}
/* #mi-logout est un <button>, pas un <a> : memes reglages, sans les
   valeurs par defaut du navigateur pour les boutons. */
button.mi{width:100%;text-align:left;border:none;background:none;
  font-family:inherit;cursor:pointer}
.mi-lbl{padding:5px 13px 7px;font-size:10px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--cream);opacity:.38}
.mi-sep{height:1px;margin:7px 13px;background:var(--c20)}
/* Bloc de progression dans le menu : icone du niveau, compte, barre vers
   le suivant. Remplace l'ancien placeholder "Ma progression" desactive —
   plus besoin d'attendre les comptes pour la voir, elle est juste
   partagee par tout le monde en attendant. */
.mi-progress{padding:9px 13px 4px;display:block;text-decoration:none;border-radius:9px;transition:background .18s}
.mi-progress:hover{background:rgba(227,227,196,.1)}
.mp-head{display:flex;align-items:center;gap:10px}
.mp-ico{width:30px;height:30px;flex:none;display:block;opacity:.9}
.mp-ico img{width:100%;height:100%;display:block;object-fit:contain}
/* Lottie injecte un <svg> : meme traitement que l'image de repli. */
.mp-ico svg{width:100%;height:100%;display:block}
.mp-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.mp-level{font-size:12.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mp-count{font-size:10.5px;color:var(--cream-50)}
.mp-bar{margin-top:9px;height:3px;border-radius:2px;background:var(--c20);overflow:hidden}
.mp-bar span{display:block;height:100%;background:var(--cream);border-radius:2px;transition:width .3s ease}
.mp-next{margin-top:7px;font-size:10.5px;line-height:1.4;color:var(--cream-50)}

@media (max-width:820px){ #menu{right:12px;left:12px;min-width:0} }

/* ================= RAPPEL DE VISIBILITÉ =================
   Choix du calendrier, en dialogue centré plutôt qu'en menu déroulant
   (comme #menu) : c'est une décision ponctuelle, pas une navigation. */
#remind-veil{position:fixed;inset:0;z-index:28;background:rgba(4,7,13,.6);
  opacity:0;pointer-events:none;transition:opacity .22s}
#remind-veil.on{opacity:1;pointer-events:auto}
#remind-modal{
  position:fixed;left:50%;top:50%;z-index:29;width:min(400px,calc(100vw - 32px));
  transform:translate(-50%,-46%);opacity:0;pointer-events:none;
  transition:opacity .22s,transform .22s;
}
#remind-modal.on{opacity:1;transform:translate(-50%,-50%);pointer-events:auto}
#remind-modal .box{
  position:relative;padding:26px 24px 22px;border-radius:16px;
  border:1px solid var(--c20);background:rgba(8,15,22,.98);backdrop-filter:blur(16px);
  box-shadow:0 24px 60px rgba(0,0,0,.55);
}
#remind-close{
  position:absolute;right:14px;top:14px;width:28px;height:28px;border-radius:50%;
  border:none;background:transparent;color:var(--cream-50);font-size:20px;line-height:1;
  cursor:pointer;transition:color .18s,background .18s;
}
#remind-close:hover{color:var(--cream);background:rgba(227,227,196,.1)}
#remind-modal h2{
  font-size:17px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  color:var(--cream);padding-right:24px;
}
#remind-modal #remind-sub{
  margin-top:6px;font-size:13px;line-height:1.4;color:var(--cream-50);
}
#remind-opts{display:flex;flex-direction:column;gap:8px;margin-top:18px}
#remind-opts button{
  display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;
  border-radius:10px;border:1px solid var(--c20);background:rgba(227,227,196,.03);
  color:var(--cream);font-family:inherit;font-size:13.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.03em;text-align:left;cursor:pointer;
  transition:background .18s,border-color .18s;
}
#remind-opts button:hover{background:rgba(227,227,196,.1);border-color:var(--cream-50)}
#remind-opts button svg{width:18px;height:18px;flex:none;display:block}
#remind-opts .ro-note{
  display:block;margin-top:2px;font-size:11px;font-weight:400;text-transform:none;letter-spacing:0;
  color:var(--cream-50);
}

/* ================= ACTIONS AU SURVOL / AU TOUCHER =================
   Deux boutons révélés au survol de la carte, dans la vue du ciel comme
   dans la liste. La rangée est présente mais repliée : on anime sa
   hauteur, ce qui évite de déplacer la mise en page au chargement.

   Sur les appareils sans survol, elles restaient ouvertes en
   permanence — un bouton inaccessible au doigt n'aurait aucun intérêt,
   c'était le raisonnement d'origine. Mais ça grignotait en continu un
   bon tiers de la hauteur de la carte, sur l'écran où l'espace manque
   le plus. La classe `.open` (posée par JS au toucher de la carte,
   plus bas dans le fichier) prend le relais : repliées par défaut,
   révélées d'un tap, comme au survol. */
.c-acts{
  display:flex;gap:12px;align-items:stretch;width:100%;
  max-height:0;opacity:0;overflow:hidden;
  transition:max-height .28s ease,opacity .22s ease,margin-top .28s ease;
  margin-top:0;
}
.card.open .c-acts{max-height:46px;opacity:1;margin-top:12px}
/* :hover/:focus-within ne pilotent la revelation qu'aux vrais pointeurs
   a survol (souris) : sur un ecran tactile, iOS notamment applique un
   :hover "collant" apres un tap qui ne se relache qu'au tap suivant
   ailleurs — la carte se refermait alors correctement en JS (classe
   .open retiree, fleches qui redescendent) tout en restant visuellement
   ouverte, ce :hover fantome maintenant .c-acts deploye tout seul. Sans
   pointeur fin, .open (entierement pilotee par le JS de tap) reste la
   seule source de verite. */
@media (hover:hover) and (pointer:fine){
  .card:hover .c-acts,.card:focus-within .c-acts{max-height:46px;opacity:1;margin-top:12px}
}

.act{
  display:flex;align-items:center;justify-content:center;gap:10px;
  padding:8px 24px;border-radius:20000px;border:1px solid transparent;
  font-weight:700;font-size:14px;line-height:normal;text-transform:uppercase;
  text-align:center;white-space:nowrap;text-decoration:none;cursor:pointer;
  transition:background .2s,opacity .2s,border-color .2s;
}
/* Collecter : pleine largeur restante, avec l'ornement en filet */
.act.collect{flex:1 1 0;min-width:0;background:var(--cream);color:var(--ink);border-color:var(--cream)}
.act.collect:hover{background:#EFEFD6}
.act.collect .orn{display:flex;flex:1 1 auto;min-width:14px;align-items:center;gap:3px}
.act.collect .orn .ln{flex:1 1 auto;height:1px;background:rgba(6,10,16,.55)}
.act.collect .orn .r7{width:7px;height:7px;border-radius:50%;border:1px solid var(--ink);flex:none}
.act.collect .orn .d5{width:5px;height:5px;border-radius:50%;background:var(--ink);flex:none}
/* En savoir plus : contour clair, largeur au contenu */
.act.more{flex:none;padding:8px 32px;border-color:rgba(255,255,255,.5);color:#fff}
.act.more:hover{background:rgba(255,255,255,.1);border-color:#fff}
.act.more.off{opacity:.3;pointer-events:none}
/* Programmer un rappel / Rappel programmé : même gabarit que Collecter
   (largeur flexible + ornement en filet), mais en contour clair — comme
   « En savoir plus » — puisque ni l'un ni l'autre n'est l'action pleine
   du moment (on ne peut pas encore écouter). */
.act.remind,.act.reminder-done{flex:1 1 0;min-width:0;border-color:rgba(255,255,255,.5);color:#fff}
.act.remind:hover{background:rgba(255,255,255,.1);border-color:#fff}
.act.remind .ico,.act.reminder-done .ico{display:flex;flex:none;width:12px;height:12px}
.act.remind .ico svg,.act.reminder-done .ico svg{width:100%;height:100%;display:block}
.act.remind .orn,.act.reminder-done .orn{display:flex;flex:1 1 auto;min-width:14px;align-items:center;gap:3px}
.act.remind .orn .ln,.act.reminder-done .orn .ln{flex:1 1 auto;height:1px;background:rgba(255,255,255,.35)}
.act.remind .orn .r7,.act.reminder-done .orn .r7{width:7px;height:7px;border-radius:50%;border:1px solid #fff;flex:none}
.act.remind .orn .d5,.act.reminder-done .orn .d5{width:5px;height:5px;border-radius:50%;background:#fff;flex:none}
/* Rappel deja pose : meme habillage, juste plus sourd — l'action est faite */
.act.reminder-done{opacity:.6}
.act.reminder-done:hover{background:transparent;border-color:rgba(255,255,255,.5)}
/* "Programmer un rappel"/"Rappel programmé" sont nettement plus longs que
   "Collecter l'ekko" : partager la largeur avec "En savoir plus" comme au
   cote a cote habituel les faisait deborder (texte plus large que son
   propre bouton). On les empile plutot, chacun sur toute la largeur —
   la meme reponse que le mode mobile applique deja a toutes les paires,
   juste pas reservee a lui ici. */
.c-acts.stack{flex-direction:column;gap:8px}
.c-acts.stack .act{width:100%}
.card.open .c-acts.stack{max-height:92px}
@media (hover:hover) and (pointer:fine){
  .card:hover .c-acts.stack,.card:focus-within .c-acts.stack{max-height:92px}
}

@media (max-width:560px){
  .c-acts{gap:8px}
  .card.open .c-acts{max-height:92px}
  .c-acts{flex-direction:column}
  .act{padding:9px 18px;font-size:13px}
  .act.more{padding:9px 18px}
  .act.collect .orn,.act.remind .orn,.act.reminder-done .orn{display:none}
}
@media (max-width:560px) and (hover:hover) and (pointer:fine){
  .card:hover .c-acts,.card:focus-within .c-acts{max-height:92px}
}

/* ================= COLLECTION =================
   Second mode de navigation : la liste des 53 figures, filtrable par
   categorie. Le ciel reste derriere, assombri par un voile pour que les
   cartes se lisent. */
/* Fond de la collection : le meme ciel etoile que le splash, pas la carte
   interactive. Il est opaque, il masque donc entierement le moteur — qui
   continue de tourner derriere, invisible. */
#coll-bg{
  position:fixed;inset:0;z-index:7;pointer-events:none;
  background:linear-gradient(180deg,#000 0%,#0A1931 100%);
  opacity:0;transition:opacity .35s ease;
}
#coll-bg img{
  width:100%;height:100%;display:block;
  object-fit:cover;object-position:center bottom;
}
body.collection #coll-bg{opacity:1}

#collection{
  position:fixed;left:0;right:0;bottom:0;
  /* bord inferieur du selecteur, plus les 24 px d'ecart demandes */
  top:calc(var(--tg-top) + var(--safe-t) + var(--tg-h) + 24px);
  z-index:8;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:0 0 calc(50px + var(--safe-b));
  opacity:0;pointer-events:none;transition:opacity .35s ease;
}
body.collection #collection{opacity:1;pointer-events:auto}

/* Les filtres restent en tete du defilement : leur hauteur varie selon la
   largeur d'ecran, une position collante evite de la coder en dur. */
/* Les filtres defilent avec la liste. Ils etaient en position collante,
   ce qui obligeait a poser un fond opaque derriere pour masquer les cartes
   passant dessous — d'ou la bande noire. Sans epinglage, plus besoin de
   fond : le ciel etoile reste visible de bout en bout. */
.coll-filters{
  display:flex;flex-wrap:wrap;justify-content:center;gap:14px;
  padding:0 20px 22px;
}
.filt{
  padding:12px 26px;border-radius:20000px;cursor:pointer;
  border:1px solid var(--c50);
  background:linear-gradient(180deg,rgba(227,227,196,.02) 0%,rgba(227,227,196,.1) 100%);
  font-weight:700;font-size:16px;line-height:normal;text-transform:uppercase;
  color:var(--cream);white-space:nowrap;transition:background .2s,color .2s,border-color .2s;
}
.filt:hover{background:linear-gradient(180deg,rgba(227,227,196,.08) 0%,rgba(227,227,196,.2) 100%)}
.filt.on{background:var(--cream);color:var(--ink);border-color:var(--cream)}

.coll-grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px;
  width:min(1135px,calc(100% - 40px));margin:0 auto;
}
/* La carte du bas est reutilisee telle quelle, seule sa largeur change. */
.coll-grid .card{width:100%;cursor:default;transition:border-color .2s,box-shadow .2s,transform .2s}
.coll-grid .card:hover{
  border-color:var(--cream);
  box-shadow:0 20px 54px rgba(0,0,0,.5), 0 0 0 1px rgba(227,227,196,.35);
  transform:translateY(-2px);
}
.coll-empty{
  grid-column:1 / -1;text-align:center;padding:50px 20px;
  font-size:15px;color:var(--cream);opacity:.55;
}
.coll-count{
  width:min(1135px,calc(100% - 40px));margin:0 auto 14px;
  font-size:12px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:var(--cream);opacity:.5;
}

/* Les commandes propres au ciel s'effacent en mode collection. */
body.collection .card-row,
/* Les enfants aussi : .card-row > * les remet a « auto » (voir plus
   haut), il faut donc les neutraliser explicitement ici, sinon la carte
   et les fleches resteraient cliquables en mode Collection alors
   qu'elles y sont invisibles. */
body.collection .card-row > *,
body.collection .c-pos,
body.collection .zoom,
body.collection #reticle{opacity:0;pointer-events:none}
.card-row,.c-pos,.zoom{transition:opacity .3s ease,bottom .28s ease}

@media (max-width:900px){
  .coll-grid{grid-template-columns:1fr}
  .coll-filters{gap:10px;padding:0 14px 18px}
  .filt{padding:10px 18px;font-size:14px}
}
@media (max-width:520px){
  .filt{padding:9px 14px;font-size:13px}
  .coll-grid,.coll-count{width:calc(100% - 24px)}
}

/* ================= RETICULE ================= */
#reticle{
  position:fixed;left:50%;top:50%;transform:translate(-50%,-50%) scale(.84);
  width:min(44vmin,400px);height:min(44vmin,400px);z-index:5;pointer-events:none;
  opacity:0;transition:opacity .5s ease,transform .9s cubic-bezier(.2,.9,.3,1)}
#reticle.on{opacity:1;transform:translate(-50%,-50%) scale(1)}
#reticle svg{width:100%;height:100%;overflow:visible}
#reticle .spin{transform-origin:50% 50%;animation:ret-spin 34s linear infinite}
@keyframes ret-spin{to{transform:rotate(360deg)}}

/* ================= STATUT ================= */
#status{
  position:fixed;left:50%;transform:translateX(-50%);top:calc(232px + var(--safe-t));z-index:12;
  font-size:13px;letter-spacing:.12em;text-transform:uppercase;color:var(--cream-50);
  background:rgba(6,10,16,.6);border:1px solid var(--cream-25);border-radius:2000px;
  padding:8px 18px;backdrop-filter:blur(8px);transition:opacity .8s;text-align:center;max-width:88vw}
#status.off{opacity:0;pointer-events:none}

/* ================= RESPONSIVE ================= */
@media (max-width:1180px){
  header{padding-left:32px;padding-right:32px}
}
/* Cette regle etait indexee uniquement sur la largeur. Un telephone en
   paysage (souvent 800 a 930px de large) ne la declenchait donc jamais et
   gardait la mise en page "large" — carte flottante, boutons de zoom et
   toggle a taille et decalages penses pour un ecran haut — alors que la
   hauteur reelle n'y suffit pas : carte, zoom et toggle se retrouvaient
   superposes. Le second terme couvre ce cas sans dupliquer les regles. */
@media (max-width:820px), (max-height:500px){
  .c-pos{bottom:calc(118px + var(--safe-b));font-size:10px}
  :root{--hd-h:72px;--notch-w:210px;--notch-d:7px}
  header{padding:calc(18px + var(--safe-t)) 18px 18px}
  .logo{width:220px;height:30.5px}
  .account{gap:0}
  a.account{text-decoration:none}
.account .lbl{display:none}
  .account .ico{width:26px;height:26px}
  .hd-drop{width:54px;height:42px}
  :root{--tg-top:112px;--tg-h:42px}
  .toggle-wrap{top:calc(var(--tg-top) + var(--safe-t))}
  .tg{padding:11px 26px;font-size:14px}
  .tg + .tg{padding-left:20px}
  .tg.on{padding-left:26px;padding-right:26px}
  .orn .ln{width:12px}
  #status{top:calc(172px + var(--safe-t));font-size:11px;padding:7px 14px}
  .zoom{right:14px;bottom:calc(196px + var(--safe-b) + var(--aside-extra))}
  .zbtn{width:44px;height:44px}
  .zbtn svg{width:20px;height:20px}
  .card-row{
    padding:0 12px;bottom:calc(16px + var(--safe-b));
  }
  /* Les fleches flottaient par-dessus le contenu de la carte (position
     absolue, pour ne pas lui prendre de largeur) et son propre contenu —
     pastille « non collectee », bouton « en savoir plus » — passait
     dessous sur un ecran etroit. Le glisse tactile (voir plus bas dans le
     fichier) reste le moyen principal de naviguer, mais sans aucun repere
     visuel le swipe n'est pas evident a decouvrir : les fleches reviennent
     donc, a la meme taille que les boutons de zoom, du cote oppose et
     cote a cote plutot que l'une sur l'autre — hors du champ de la carte.
     Meme formule de decalage que .zoom (196px + --aside-extra), pour que
     les deux groupes restent toujours exactement a la meme hauteur. */
  .nav-side{
    position:fixed;bottom:calc(196px + var(--safe-b) + var(--aside-extra));z-index:11;
    height:auto;gap:0;transition:bottom .28s ease;
  }
  .nav-side .ln,.nav-side .d5,.nav-side .r7{display:none}
  .nav-side.prev{left:14px}
  .nav-side.next{left:calc(14px + 44px + 8px)}
  .nav-btn{
    width:44px;height:44px;border-radius:50%;
    border:1.064px solid var(--cream);background:
      linear-gradient(180deg,rgba(227,227,196,.04) 0%,rgba(227,227,196,.2) 100%);
    backdrop-filter:none;-webkit-backdrop-filter:none;
  }
  .nav-btn svg{width:18px;height:18px}
  .card{width:100%;padding:16px 14px;gap:14px}
  .medallion{width:66px;height:66px}
  .c-title{font-size:18px}
  .c-desc{font-size:13px}
  .c-state{width:100%}
}
@media (max-width:400px){
  .medallion{width:56px;height:56px}
  .chips{flex-wrap:wrap;gap:6px}
}

/* ================= BLOCAGE PAYSAGE MOBILE =================
   Le mode paysage sur telephone n'offre pas une experience satisfaisante
   (compas, carte flottante, statut : trop d'elements pour trop peu de
   hauteur). Plutot que de multiplier les compromis, l'ecran est bloque
   le temps que l'appareil repasse en portrait. `max-height` en paysage
   correspond a la largeur reelle de l'appareil : les telephones ne
   depassent quasiment jamais 560px sur leur petit cote, les tablettes si
   — c'est ce qui distingue les deux ici, sans jamais bloquer une tablette. */
#landscape-lock{
  position:fixed;inset:0;z-index:9999;
  display:none;align-items:center;justify-content:center;
  background:linear-gradient(180deg,#000 0%,#0A1931 100%);
  padding:40px;text-align:center;
}
.ll-box{max-width:360px}
.ll-icon{width:60px;height:60px;color:var(--cream);margin:0 auto 22px;display:block;
  animation:ll-rotate 2.6s ease-in-out infinite}
@keyframes ll-rotate{0%,15%{transform:rotate(0deg)}50%,65%{transform:rotate(-90deg)}100%{transform:rotate(-90deg)}}
.ll-title{font-weight:700;font-size:19px;text-transform:uppercase;letter-spacing:.05em;color:var(--cream)}
.ll-sub{margin-top:10px;font-size:14.5px;line-height:1.55;color:var(--cream);opacity:.6}
@media (orientation:landscape) and (max-height:560px){
  #landscape-lock{display:flex}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
