/* ============================================================
   Skydex — design-system.css : variables, palettes de tiers,
   composant carte + dos de carte (template validé).
   ============================================================ */

:root {
  /* fonds navy sombres */
  --bg-0: #070c14;
  --bg-1: #0a111d;
  --bg-2: #0d1626;
  --bg-3: #101828;
  --bg-4: #14273f;
  /* accents */
  --blue: #3d8bfd;
  --blue-btn: #2f7bf0;
  --blue-soft: #6fa8ff;
  --green: #37d67a;
  --green-check: #4ade80;
  /* texte */
  --txt: #fff;
  --txt-2: #9db0c6;
  --txt-3: #8fa1b8;
  --txt-hint: #6b7a90;
}

/* ---- palettes de tiers (variables par carte) ---- */
.tier-commune {
  --frame: linear-gradient(165deg, #efece3, #d9d4c5 55%, #efece3);
  --dark: #16324f; --dark-on-light: #16324f;
  --body-bg: #16324f; --badge-bg: #f4f2ea;
  --accent: #9db7d4; --star: #16324f;
  --panel-bg: #f4f2ec; --light: #edeae1;
  --glow: #7da7d9;
}
.tier-rare {
  --frame: linear-gradient(160deg, #b8f0d6, #57c79a 15%, #12674a 50%, #a7e8cd 85%, #2e8f68);
  --dark: #06231b; --dark-on-light: #0f5c42;
  --body-bg: #06231b; --badge-bg: #dff3e8;
  --accent: #5fd0a4; --star: #e3b23c;
  --panel-bg: #e7f5ec; --light: #dfefe5;
  --glow: #57c79a;
}
.tier-epique {
  --frame: linear-gradient(160deg, #f5b8c4, #e0485e 18%, #a03a8c 55%, #6d3f97 82%, #e8c8f0);
  --dark: #380f33; --dark-on-light: #8c2f6e;
  --body-bg: #380f33; --badge-bg: #fae4f0;
  --accent: #f096c8; --star: #e3b23c;
  --panel-bg: #f7ecf3; --light: #f1e4ec;
  --glow: #e0559c;
}
.tier-legendaire {
  --frame: linear-gradient(160deg, #f9e9ae, #f3d878 12%, #a8791f 45%, #f6e6a0 78%, #c99b33);
  --dark: #1a1509; --dark-on-light: #6b5416;
  --body-bg: #1a1509; --badge-bg: #f7ecc4;
  --accent: #d9b64a; --star: #e3b23c;
  --panel-bg: #f7eecd; --light: #f3ead1;
  --glow: #f3d878;
}

/* ============ LA CARTE (template validé) ============ */
/* ⚠️⚠️ RÈGLE PRODUIT (7 août 2026) : LA HAUTEUR D'UNE CARTE NE VARIE JAMAIS
   d'une carte à l'autre. Un jeu de cartes à collectionner a un format, point.
   Moins d'informations ne raccourcit pas la carte ; plus d'informations doit
   rentrer dans le même format. C'est la PHOTO qui absorbe la différence
   (flex: 1 sur .hero) — elle respire quand il y a peu de texte, elle se
   resserre quand il y en a beaucoup, mais le cadre est immuable.
   La valeur suit la hauteur d'écran pour rester sans scroll sur tout
   téléphone ; sur un appareil donné, toutes les cartes sont identiques. */
.card { position: relative; width: min(400px, 92vw); height: min(700px, 84vh); border-radius: 22px; padding: 7px; background: var(--frame); box-shadow: 0 12px 40px rgba(0,0,0,.5); color: #fff; }

/* Reflet holographique — piloté par holo.js (--px/--py/--sheen).
   Vaut pour TOUTES les cartes : révélation et Hangar. */
.card.holo::after {
  content: ''; position: absolute; inset: 0; border-radius: 24px; pointer-events: none;
  background: radial-gradient(circle at var(--px, 50%) var(--py, 40%), rgba(255,255,255,.22), transparent 42%);
  opacity: var(--sheen, 0);
}
.card-inner { border-radius: 16px; overflow: hidden; background: var(--body-bg);
  height: 100%; display: flex; flex-direction: column; }
/* tous les blocs gardent leur hauteur naturelle... */
.card-inner > * { flex: 0 0 auto; }
/* ...sauf la photo, qui absorbe le jeu pour que le format reste constant */
.card .hero { flex: 1 1 auto; min-height: 0; }
.card .head { display: flex; background: var(--dark); }
.card .head-left { flex: 1; padding: 10px 16px 7px; min-width: 0; }
.card .head-left h2 { font-family: 'Barlow Condensed'; font-style: italic; font-weight: 800; font-size: 2.05rem; line-height: .95; text-transform: uppercase; letter-spacing: .01em; white-space: nowrap; }
.card .head-left .cat { font-family: 'Barlow Condensed'; font-style: italic; font-weight: 700; font-size: .95rem; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); margin-top: 3px; }
/* ---- pastille CARGO EN SURIMPRESSION SUR LA PHOTO (13 août 2026) ----
   ⚠️⚠️ ELLE A ÉTÉ DÉPLACÉE DEPUIS `.head-left`, ET C'EST STRUCTUREL. Sous la
   catégorie, elle la faisait passer à TROIS lignes sur 11 des 12 cargos (55 px
   contre 18), et ces 37 px se prenaient sur la photo — qui a un plancher de
   150 px, dans une carte plafonnée à `min(700px, 84vh)`, avec `overflow: hidden`
   sur `.card-inner`. Sur écran court le bas de carte était donc ROGNÉ et les
   crédits disparaissaient. En surimpression elle coûte ZÉRO hauteur de flux.
   **Ne pas la remettre dans le flux.**

   ⚠️ ELLE GARDE `--accent`, LA COULEUR DU TIER, mais sur un FOND SOMBRE OPAQUE,
   ce que la version dans le flux n'avait pas à gérer : elle se posait sur le
   navy maîtrisé de l'en-tête, alors qu'ici elle est sur une PHOTO quelconque —
   ciel blanc, contre-jour, fuselage clair. Même règle que le viseur, écrite dans
   `app.css` : sur une image, la lisibilité vient du fond et de l'ombre, jamais
   de l'opacité du trait.
   ⚠️ En haut à GAUCHE : l'angle haut droit de la carte porte déjà le badge
   #0XX + tier + étoiles, et le bas de la photo touche la colonne d'identité.
   Le haut gauche prolonge la lecture titre → catégorie → cargo.
   ⚠️ `pointer-events: none` : la carte est pivotable (holo.js) et la photo peut
   être cliquable ; la pastille ne doit pas intercepter le geste. */
.card .hero .cargo-tag { position: absolute; top: 9px; left: 9px; z-index: 2;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px 4px; border-radius: 999px;
  font-family: 'Barlow', sans-serif;
  font-size: .6rem; font-style: normal; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  background: rgba(7, 12, 20, .82);
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  box-shadow: 0 1px 6px rgba(0,0,0,.45);
  pointer-events: none; }
.card .hero .cargo-tag svg { width: 11px; height: 11px; stroke: currentColor; fill: none;
  stroke-width: 1.9; stroke-linejoin: round; flex: 0 0 auto; }
/* ⚠️⚠️ COLONNE DROITE À LARGEUR FIXE — DÉCISION DE L'AUTEUR DU 13 AOÛT 2026 :
   « le numéro doit toujours être au même endroit, les étoiles au même endroit, et
   le cadre qui les contient toujours de la même taille. C'est le nom de l'avion
   et le type qui doivent s'adapter. »

   CE QUE ÇA CORRIGE, ET C'ÉTAIT UN VRAI BUG. Avant, `flex: 0 0 auto` + `max-width:
   52%` faisait dimensionner cette colonne par son CONTENU — donc par la longueur
   du libellé de tier, le nombre d'étoiles et la variante d'instance. Mesuré :
   la colonne variait de **99 à 149 px**, et la place restante pour le titre de
   **159 à 228 px**. Conséquence signalée par l'auteur : « Boeing 737 MAX 8 » et
   « Boeing 737 MAX 9 » portent le MÊME nom de 16 caractères mais recevaient 226 px
   contre 203 px, uniquement parce que l'un est COMMUN (1 étoile) et l'autre
   ÉPIQUE (3 étoiles). Le « 8 » passait donc à la ligne sur une carte et pas sur
   l'autre. **La rareté d'un avion ne doit pas décider de la mise en page de son
   nom.**

   ⚠️ LA LARGEUR DE 120 px N'EST PAS ARBITRAIRE : c'est le pire cas mesuré du
   badge COMPACTÉ (118 px — numéro à 3 chiffres, toujours `padStart(3)`, plus
   4 étoiles), avec 2 px de marge. Sans le compactage ci-dessous il aurait fallu
   152 px, ce qui aurait fait passer **120 titres sur 2 lignes contre 69
   aujourd'hui**. Avec le compactage : **66**, donc MIEUX qu'avant tout en rendant
   le cadre déterministe. Les deux changements ne se séparent pas.

   ⚠️ CONTREPARTIE ASSUMÉE, mesurée : sur une instance très longue (le cas
   Challenger 350 documenté le 5 août), la puce s'ellipse 10 caractères plus tôt
   (120 px de large au lieu de 172). En échange le titre gagne 52 px sur cette
   même carte. La puce s'ellipse DÉJÀ par conception et la variante complète reste
   dans la donnée de capture — c'est donc un arbitrage cohérent avec la décision
   du 5 août, pas une régression. Le bug d'origine (colonne qui s'élargit sans
   borne et écrase le titre) est de toute façon impossible avec une largeur fixe. */
.card .head-right { flex: 0 0 120px; display: flex; flex-direction: column;
  min-width: 0; }
/* ---- BADGE EN GRILLE (13 août 2026) ----
   ⚠️ CE N'EST PAS UN CHOIX ESTHÉTIQUE, C'EST UN GAIN DE LARGEUR POUR LA COLONNE
   DE GAUCHE. Avant, `.badge` était une rangée flex : [ #229 au-dessus de
   LEGENDARY ] puis [ ★★★★ ]. Sa largeur valait donc « le plus long des deux
   textes empilés » + gap + étoiles, et « LEGENDARY » poussait tout le bloc.
   Or `.head-right` est plafonné à 52 % : plus le badge est large, moins la
   CATÉGORIE a de place à gauche. Mesuré avant ce changement : la largeur
   disponible pour `.cat` variait de 130 à 186 px selon le libellé de tier, si
   bien que les cartes LÉGENDAIRES — les plus rares, donc les plus regardées —
   étaient celles qui avaient le MOINS de place pour leur catégorie.
   Désormais le numéro et les étoiles partagent la première ligne et le libellé
   passe SOUS les étoiles : le badge ne fait plus que la largeur du plus large
   des deux au lieu de leur somme.
   ⚠️ `align-items: baseline` sur la première ligne : les étoiles doivent
   s'aligner sur le PIED du numéro, pas sur son centre, sinon elles flottent au
   milieu d'un chiffre de 1,5 rem et le resserrement ne se voit pas.
   ⚠️ `justify-items: end` + `text-align: right` : le badge est collé au bord
   droit de la carte, donc tout doit s'aligner à droite, sinon le libellé de tier
   flotterait à gauche sous les étoiles. */
/* ⚠️⚠️ BADGE COMPACTÉ LE 13 AOÛT 2026, ET C'EST INDISSOCIABLE DE LA LARGEUR FIXE
   DE `.head-right` CI-DESSUS. Sans ce compactage, le pire cas du badge mesure
   152 px, et figer la colonne à cette valeur ferait passer **120 titres sur
   2 lignes au lieu de 69**. Compacté, le pire cas tombe à 118 px, la colonne
   peut être figée à 120, et on retombe à **66 titres sur 2 lignes — donc mieux
   qu'avant**. Ne pas « rendre au badge sa respiration » sans refaire ce calcul.
   Trois leviers, tous mesurés : padding latéral 14 → 10 px, écart numéro/étoiles
   7 → 5 px, étoiles 1 → 0,8 rem sans interlettrage, numéro 1,5 → 1,35 rem.
   ⚠️ `width: 100%` : le badge remplit la colonne fixe, donc son fond crème et son
   angle arrondi tombent TOUJOURS au même endroit d'une carte à l'autre — c'est
   précisément ce que demandait l'auteur. */
.card .badge { background: var(--badge-bg); color: var(--dark); padding: 7px 10px 6px;
  width: 100%; box-sizing: border-box;
  border-bottom-left-radius: 14px;
  display: grid; grid-template-columns: auto auto; column-gap: 5px; row-gap: 1px;
  align-items: baseline; justify-items: end; }
.card .badge .num { font-family: 'Barlow Condensed'; font-style: italic; font-weight: 800; font-size: 1.35rem; line-height: 1; }
/* le libellé s'étend sur les DEUX colonnes : c'est lui qui passe sous les étoiles */
.card .badge .tier-label { grid-column: 1 / -1; font-weight: 700; font-size: .62rem;
  letter-spacing: .1em; text-transform: uppercase; text-align: right; }
.card .badge .stars { color: var(--star); font-size: .8rem; letter-spacing: 0; line-height: 1; }
/* Ellipse et non repli : une variante interminable se coupe (« BOMBARDIER
   BD-100 Challen… ») au lieu de gonfler le bandeau sur plusieurs lignes. La
   variante complète n'est pas perdue, elle reste dans la donnée de capture. */
.card .instance-chip { background: var(--dark); color: #cfd6e0; font-size: .66rem; padding: 4px 14px 5px; text-align: right; letter-spacing: .03em; border-top: 1px solid rgba(255,255,255,.12);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card .instance-chip b { color: #fff; font-weight: 600; }
.card .hero { position: relative; height: auto; min-height: 150px; background: #22303c; }
.card .hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* (`.card.tight` a été retiré le 7 août : la hauteur fixe + la photo élastique
   rendent le cas « titre sur deux lignes » automatique.) */
/* placeholder photo, en attendant le module Commons */
.card .hero-ph { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  background: linear-gradient(180deg, #2c4360 0%, #1c2c42 70%, #16233a 100%); }
.card .hero-ph svg { width: 64px; height: 64px; fill: rgba(255,255,255,.25); }
.card .hero-ph span { font-size: .62rem; letter-spacing: .18em; text-transform: uppercase; color: rgba(255,255,255,.4); }
.card .body { display: flex; background: var(--dark); padding: 8px 12px; gap: 10px; }
.card .idcol { flex: 1 1 46%; display: flex; flex-direction: column; justify-content: space-between; min-width: 0; }
.card .idrow { display: flex; align-items: center; gap: 9px; padding: 4.5px 2px; }
.card .idrow + .idrow { border-top: 1px dotted rgba(255,255,255,.25); }
.card .idrow .ic { flex: 0 0 24px; height: 24px; border: 1.6px solid rgba(255,255,255,.85); border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.card .idrow .ic svg { width: 15px; height: 15px; stroke: #fff; fill: none; stroke-width: 1.8; }
.card .idrow .lbl { font-size: .6rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); }
.card .idrow .val { font-size: .8rem; color: #fff; line-height: 1.15; overflow-wrap: anywhere; }
/* width serait ignoré ici : flex-basis (54%) prime sur width pour un élément flex */
.card .statcol { flex: 1 1 54%; background: var(--panel-bg); border-radius: 14px; padding: 6px 10px; color: #111; align-self: flex-start; }
.card .stat2 { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.card .stat2 + .stat2 { border-top: 1px solid rgba(0,0,0,.1); }
.card .stat2 .ic { flex: 0 0 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.card .stat2 .ic svg { width: 15px; height: 15px; stroke: #fff; fill: none; stroke-width: 1.9; }
.card .stat2 .lblwrap { flex: 1; min-width: 0; }
.card .stat2 .lbl { font-family: 'Barlow Condensed'; font-style: italic; font-weight: 700; font-size: .78rem; text-transform: uppercase; line-height: 1; }
.card .stat2 .unit { font-size: .62rem; color: #555; }
.card .stat2 .val { font-family: 'Barlow Condensed'; font-style: italic; font-weight: 800; font-size: 1.6rem; line-height: 1; white-space: nowrap; }
.card .desc { display: flex; gap: 9px; padding: 6px 14px; background: var(--light); color: #222; align-items: flex-start; }
.card .desc svg { flex: 0 0 19px; width: 19px; height: 19px; fill: var(--dark-on-light); margin-top: 2px; }
/* ⚠️ La description tient sur TROIS lignes, jamais quatre (règle de l'auteur,
   7 août) : une 4e ligne pour un seul mot déséquilibre la carte. Le clamp est
   un filet — la vraie contrainte est à la RÉDACTION : ~130 caractères max. */
.card .desc p { font-size: .76rem; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* Bandeau de vol : une ligne, façon souche de billet. Masqué s'il n'y a
   ni indicatif ni route (le rendu ne génère alors pas l'élément). */
.card .flight-band { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  background: var(--dark); color: #cfd6e0; padding: 7px 14px 8px;
  border-top: 1px solid rgba(255,255,255,.1); font-size: .68rem; }
.card .flight-band .cs { font-family: 'Barlow Condensed'; font-style: italic; font-weight: 800;
  font-size: .95rem; letter-spacing: .03em; color: #fff; }
.card .flight-band .rt { color: #cfd6e0; }
.card .flight-band .rt b { color: #fff; font-weight: 700; letter-spacing: .04em; }
/* cran 2 de la cascade : opérateur + pays, quand il n'y a pas de route.
   Volontairement plus discret que la route (pas de blanc pur, pas de gras) :
   c'est un lot de consolation, il ne doit pas se lire comme un itinéraire. */
.card .flight-band .rt.op { color: #b9c4d2; font-style: italic; }
.card .flight-band .arrow { color: var(--accent); padding: 0 3px; font-weight: 700; }

.card .capture-strip { display: flex; background: var(--light); border-top: 1px dashed rgba(0,0,0,.25); padding: 5px 8px; color: #1a1a1a; }
.card .cap-item { flex: 1; display: flex; gap: 8px; padding: 0 8px; min-width: 0; }
.card .cap-item + .cap-item { border-left: 1px solid rgba(0,0,0,.15); }
.card .cap-item .ic { flex: 0 0 22px; height: 22px; border-radius: 50%; background: var(--dark-on-light); display: flex; align-items: center; justify-content: center; }
.card .cap-item .ic svg { width: 13px; height: 13px; stroke: #fff; fill: none; stroke-width: 1.9; }
/* ⚠️ Les valeurs de la colonne identité sont PLAFONNÉES à 3 lignes (constaté
   le 6 août 2026 sur le 767-400ER capturé en test : sa capacité fait 146
   caractères — « Environ 245 passagers en configuration 2 classes (243 selon
   flugzeuginfo), jusqu'à… » — et la carte doublait de hauteur). 79 types sur
   219 ont une capacité verbeuse : les fiches du pipeline de recherche ont
   gardé leur traçabilité dans le champ d'affichage. Le plafond CSS protège la
   carte QUEL QUE SOIT le contenu ; le nettoyage des données elles-mêmes est à
   faire avec la vague 2 (raccourcir à l'essentiel, la traçabilité reste dans
   la colonne notes de l'Excel). */
.card .idrow .val { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; }
.card .cap-item .lbl { font-size: .56rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--dark-on-light); }
.card .cap-item .val { font-size: .74rem; font-weight: 600; line-height: 1.15; overflow-wrap: anywhere; }
.card .cap-item .sub { font-size: .58rem; color: #555; }
/* Les crédits tenaient sur 2 lignes (« airplanes.live · OpenSky Network ·
   adsbdb » débordait) : le label « Data: » passe en ligne avec les noms et
   la colonne de gauche prend la place qu'il faut. Une ligne gagnée. */
.card .credits { display: flex; justify-content: space-between; gap: 10px; background: var(--light); padding: 5px 12px 6px; border-top: 1px solid rgba(0,0,0,.12); }
.card .credits div { font-size: .55rem; color: #444; line-height: 1.25; }
.card .credits div:first-child { flex: 1 1 62%; }
.card .credits div:first-child br { display: none; }
.card .credits div:first-child b { margin-left: .25em; }
.card .credits div:last-child { flex: 0 1 38%; }

/* ============ DOS DE CARTE ============ */
.cardback { width: 100%; height: 100%; border-radius: 24px; padding: 9px; background: var(--frame); }
.cardback-inner {
  height: 100%; border-radius: 16px; background: var(--dark); position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background-image:
    radial-gradient(rgba(255,255,255,.05) 1.2px, transparent 1.3px),
    radial-gradient(rgba(255,255,255,.035) 1.2px, transparent 1.3px);
  background-size: 26px 26px, 26px 26px;
  background-position: 0 0, 13px 13px;
}
.cardback-inner::before {
  content: ''; position: absolute; inset: 10px; border-radius: 11px;
  border: 1.5px solid rgba(255,255,255,.28); pointer-events: none;
}
.cardback-inner::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .1;
  background:
    radial-gradient(circle at 50% 46%, transparent 118px, rgba(255,255,255,.55) 119px, transparent 121px),
    linear-gradient(rgba(255,255,255,.4), rgba(255,255,255,.4)) 50% 46% / 1.5px 300px no-repeat,
    linear-gradient(rgba(255,255,255,.4), rgba(255,255,255,.4)) 50% 46% / 300px 1.5px no-repeat;
}
.cardback-inner .mark {
  width: 96px; height: 128px; border-radius: 16px; border: 3px solid #efe9da;
  display: flex; align-items: center; justify-content: center; position: relative;
}
.cardback-inner .mark svg { width: 52px; height: 52px; fill: #efe9da; }
.cardback-inner .mark .spark { position: absolute; top: 12px; right: 14px; color: #efe9da; font-size: .85rem; line-height: 1; }
.cardback-inner .mark .trail {
  position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%);
  width: 34px; height: 26px;
  background: linear-gradient(180deg, #7da7d9, transparent);
  clip-path: polygon(38% 0, 62% 0, 100% 100%, 0 100%);
  opacity: .85;
}
.cardback-inner .logo {
  font-family: 'Barlow Condensed'; font-style: italic; font-weight: 800; font-size: 2rem;
  letter-spacing: .1em; text-transform: uppercase; color: #efe9da;
}
.cardback-inner .logo b {
  background: linear-gradient(120deg, #9dc4f0, #4a7fc9);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.cardback-inner .baseline { font-size: .6rem; color: #8fa5c4; letter-spacing: .28em; text-transform: uppercase; margin-top: -6px; }
.cardback-inner .tap { font-size: .72rem; color: var(--accent); letter-spacing: .18em; text-transform: uppercase; animation: blink 1.8s infinite; }
@keyframes blink { 50% { opacity: .35; } }
/* ⚠️ CARTE LEGENDAIRE VERROUILLEE (gratuit) — 2 septembre 2026.
   La ligne « touche pour reveler » cede la place a un etat + un appel discret.
   `animation: none` est DELIBERE : le clignotement invite a toucher, or ici le
   toucher ne retourne rien — le garder mentirait sur l'affordance. */
.cardback-inner .tap.lock { color: #8fa5c4; animation: none; }
.cardback-inner .lock-cta {
  margin-top: 2px; border: 0; border-radius: 999px; padding: 9px 16px;
  background: var(--blue-btn); color: #fff; cursor: pointer;
  font-family: inherit; font-size: .74rem; font-weight: 600; letter-spacing: .02em;
}
.cardback-inner .lock-cta:active { transform: scale(.97); }
