/* =========================================================================
   SOCAR SHIPPING — VUE « TABLEAU » (écran de référence)

   Le socle commun (jetons, en-tête, rail, suivi) est dans base.css. Ce
   fichier ne contient que ce qui est propre à la grille tarifaire en lignes :
   une destination = une ligne, quatre colonnes de prix, navire et date.

   C'est la vue de production. Les deux autres (cartes.html, navires.html)
   explorent d'autres découpages de la MÊME donnée.
   ========================================================================= */

/* =========================== CORPS ======================================= */

/* Le rail garde sa largeur de conception sur une dalle 16:9, et n'en gagne
   qu'au delà : `21vw` ne dépasse `27.5rem` que si la fenêtre est plus large
   que 16:9, puisque 1rem est alors calé sur la hauteur. Le surplus d'une
   dalle ultra-large est ainsi partagé entre le rail (dont les cartes portent
   une photo et un nom de ville, donc gagnent à être larges) et le tableau, au
   lieu d'être versé en totalité aux colonnes de prix. Plafonné à 34rem : au
   delà, la carte destination devient une bannière et son nom se perd dans la
   largeur. */
.grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(27.5rem, 21vw, 34rem);
  gap: 0.9rem;
  min-height: 0;
}

/* --- Layout adaptatif ----------------------------------------------------
   Dès qu'une destination porte une remarque, le rail cède sa place à une
   colonne REMARQUES de largeur IDENTIQUE (27.5rem + 0.9rem de gouttière).
   Les colonnes tarifaires ne se déplacent donc pas d'un seul pixel entre les
   deux états : le client garde ses repères, et l'écran ne clignote pas d'une
   mise en page à l'autre. */
body.has-remarks .grid { grid-template-columns: 1fr; }
/* Le rail emporte avec lui le bloc de suivi, donc le lockup de marque. Le
   symbole remonte alors dans l'en-tête, à côté du QR qui fait le même trajet
   pour la même raison : ni la marque ni l'action utile ne quittent l'écran. */
body.has-remarks .header-mark { display: block; }
/* MÊME largeur que le rail, gouttière comprise, et surtout : la même
   EXPRESSION. Une constante (28.4rem) tenait tant que le rail était fixe ;
   depuis qu'il s'élargit sur une dalle ultra-large (`clamp` ci-dessus), une
   constante ferait glisser les colonnes tarifaires de 6rem entre les deux
   modes — exactement ce que §3 promet qu'il n'arrivera jamais. */
body.has-remarks .thead,
body.has-remarks .row { --col-remark: calc(clamp(27.5rem, 21vw, 34rem) + 0.9rem); }

/* --------------------------- TABLEAU ------------------------------------ */

/* Dégradé horizontal bleu roi → marine, relevé au pixel sur l'écran SOCAR de
   production (#26448C à gauche, #182B56 à droite). Il n'est pas décoratif :
   il assombrit progressivement vers la droite, donc vers les colonnes NAVIRE
   et DÉPART, ce qui laisse la moitié gauche — ville et prix — au plus haut
   contraste de la planche. */
.rates {
  position: relative;         /* ancre du bloc QR en mode remarques */
  display: grid;
  grid-template-rows: auto 1fr;
  min-height: 0;
  background: linear-gradient(90deg, var(--grid-1), var(--grid-2));
  border: 0.0625rem solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

/* Une seule définition de gabarit de colonnes, partagée par l'en-tête et les
   lignes : impossible de les désaligner.

   `--col-dest` doit loger « DAKAR TRANSIT MALI » suivi d'une pastille de 9
   caractères, sans troncature. Mesuré : 252 px pour le nom, 74 px pour la
   pastille — 23rem n'en offraient que 196 et l'écran affichait
   « DAKAR TRA… NOUVEAU » juste sous une ligne « DAKAR ». 25.5rem, pris sur
   les colonnes de prix, qui compensent par une police légèrement réduite.
   Un nom de port coupé est exactement ce qui fait douter un client du reste
   de la ligne.

   Ces largeurs sont les MÊMES dans les deux modes, et la colonne remarques
   occupe exactement la place du rail (27.5 + 0.9 de gouttière) : les colonnes
   tarifaires font donc 9.69rem avec ou sans remarque, et ne bougent jamais
   d'un pixel. */
/* Toutes les colonnes sont en `minmax(plancher, Nfr)`, et les deux nombres
   comptent :

     - le PLANCHER est la largeur mesurée en dessous de laquelle un contenu
       réel est tronqué. Il ne se négocie pas ;
     - le POIDS `fr` ne sert QUE sur une dalle plus large que 16:9. À 120rem,
       chaque colonne retombe exactement sur son plancher et les colonnes de
       prix sur 8.07rem — c'est-à-dire au pixel près la mise en page d'avant,
       vérifiée en rendu. Sur une dalle 21:9, le surplus se répartit selon ces
       poids au lieu d'aller en totalité aux prix, qui se retrouveraient à
       16rem de large pour 7rem de texte : un montant flottant au milieu de
       son vide se lit moins bien, pas mieux.

   Les poids sont ordonnés par capacité réelle à absorber de la largeur : la
   ville (nom long, aligné à gauche) plus que le navire, le navire plus que
   les prix, les dates presque pas — « 26/09/2026 » a une largeur finie et
   l'étirer ne produit que du blanc.

   Ces poids ont été RELEVÉS le jour où la planche a cessé d'être bridée à
   138rem (voir `--content-max` dans base.css) : le surplus d'une dalle
   ultra-large, jusqu'ici repeint en marge, arrive maintenant dans le tableau
   et il fallait dire où il va. DESTINATION et BATEAU en prennent la plus
   grosse part, les prix le minimum — à 2560x1080 une colonne tarifaire passe
   de 8.07 à 10rem, ce qui reste une colonne et pas un couloir. */
.thead, .row {
  display: grid;
  grid-template-columns:
    /* DESTINATION. 25.5rem doit loger « DAKAR TRANSIT MALI » suivi d'une
       pastille de 9 caractères, sans troncature. Mesuré : 252 px pour le nom,
       74 px pour la pastille — 23rem n'en offraient que 196 et l'écran
       affichait « DAKAR TRA… NOUVEAU » juste sous une ligne « DAKAR ». */
    minmax(var(--col-dest, 25.5rem), 5fr)
    repeat(var(--price-cols, 4), minmax(7.6rem, 0.8fr))
    /* 16.5rem, pas 13.5 : « Grande Sierra Leone » réclame 226 px à 1.22rem et
       n'en avait que 210, donc s'affichait « Grande Sierra … ». Un nom de
       navire coupé oblige le client à demander au comptoir exactement ce que
       l'écran est censé lui éviter. Mesuré, pas estimé. */
    minmax(16.5rem, 2.4fr)
    minmax(8.5rem, 0.7fr)
    /* SUIVANT. 6.5rem et pas 8.5 : la cellule ne porte que « 06/10 », l'année
       étant déjà donnée par la colonne DÉPART qui la précède (voir
       `nextDateMarkup`). Les 2rem économisés reviennent aux colonnes de prix,
       qui passent de 9.69 à 8.07rem au lieu de 7.56 — « 2 570 € » y tient
       encore à 1.7rem, ce qui est la limite qu'on refuse de franchir. */
    minmax(6.5rem, 0.55fr)
    var(--col-remark, 0rem);
  align-items: center;
}

/* Deux filets, pas un. L'écran SOCAR de production ferme sa bande d'en-tête
   par un liseré clair EN HAUT autant qu'en bas ; sans le premier, la bande
   flotte sur le fond et le tableau n'a pas de bord supérieur. Le liseré haut
   est plus discret que le bas : il ferme, il ne souligne pas. */
.thead {
  background: linear-gradient(180deg, #2b4f9c, #1c3568);
  border-top: 0.125rem solid rgb(142 214 247 / 0.45);
  border-bottom: 0.125rem solid var(--brand);
  padding: 0.55rem 0 0.6rem;
  /* Les cellules occupent toute la hauteur de l'en-tête : c'est ce qui permet
     au groupe des gabarits de porter un fond et des filets pleine hauteur. */
  align-items: stretch;
}

.th {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.05rem;
  padding: 0 0.5rem;
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: #dceaf4;
  text-align: center;
}
.th:first-child { justify-items: start; padding-left: 1.1rem; }

/* --- Colonnes de gabarit -------------------------------------------------
   Les quatre colonnes tarifaires forment un GROUPE : même axe de lecture,
   même unité, comparables entre elles. DESTINATION, BATEAU et DÉPART ne le
   sont pas. Un fond légèrement plus clair réunit le groupe, un filet vertical
   sépare ses membres — sans cela l'en-tête est une file de sept étiquettes
   entre lesquelles l'œil ne trouve aucune articulation, ce qui est exactement
   ce qui rendait les colonnes BIG VAN indistinctes.

   Le filet est dessiné en ombre interne : il ne consomme aucune largeur de
   mise en page, donc les colonnes de prix restent alignées au pixel sur les
   lignes du tableau. */
/* Trois rangées, TOUJOURS, même quand la colonne n'a pas de port : sans cette
   réserve, VOITURE (deux rangées) et BIG VAN (trois) centrent leur bloc à des
   hauteurs différentes, et les quatre silhouettes ne partagent plus de ligne
   de sol. Or c'est justement leur alignement qui rend la progression de taille
   lisible — l'encodage tombe pour trois pixels d'écart. */
.th-cat {
  gap: 0;
  grid-template-rows: auto auto 1.34rem;
  background: linear-gradient(180deg, rgb(127 208 245 / 0.07), rgb(127 208 245 / 0.02));
  box-shadow: inset 0.0625rem 0 0 rgb(127 208 245 / 0.14);
}
/* Pas de filet à gauche du premier gabarit : il ferme le groupe au lieu d'en
   séparer deux membres. `:first-of-type` ne conviendrait pas — toutes les
   cellules sont des `div`, et DESTINATION est la première. */
.th:not(.th-cat) + .th-cat { box-shadow: none; }

/* En-tête de la colonne remarques : alignée à gauche comme son contenu. */
.th-remark { justify-items: start; padding-left: 1rem; }

/* SUIVANT est subordonné à DÉPART, pas son égal : même graisse pour rester
   lisible à 3 m, mais un cran plus petit et en gris de libellé. Sans cette
   hiérarchie, l'en-tête propose DEUX dates au même rang et le client doit
   lire les deux avant de savoir laquelle le concerne. */
.th-next { font-size: 0.95rem; color: var(--ink-3); padding: 0 0.25rem; }

/* Le corps distribue la hauteur disponible entre les lignes : 20 ou 24
   destinations tiennent sans pagination et sans réglage manuel. */
.tbody {
  display: grid;
  grid-auto-rows: 1fr;
  min-height: 0;
}

.row {
  border-bottom: 0.0625rem solid rgb(142 214 247 / 0.14);
  min-height: 0;
}
/* Zébrage assombrissant et non éclaircissant : sur le dégradé bleu roi, un
   voile blanc délave la ligne et rapproche les deux alternances au point
   qu'on ne les distingue plus à 3 m. Un voile noir creuse au contraire
   l'écart sans toucher au contraste du texte, qui est blanc dans les deux
   cas. C'est ce que fait l'écran SOCAR de production. */
.row:nth-child(even) { background: rgb(0 0 0 / 0.17); }
.row:last-child { border-bottom: 0; }

/* --- Filets verticaux du groupe tarifaire --------------------------------
   Prolongés de l'en-tête jusque dans le corps. Uniquement entre les QUATRE
   colonnes de prix, et c'est le même argument que dans l'en-tête : ces
   colonnes forment un groupe comparable, et le filet sépare deux membres du
   groupe. Il sépare surtout les deux BIG VAN, qui portent le même libellé et
   diffèrent de 200 €.

   Ce qu'on ne fait PAS : quadriller toute la ligne. DESTINATION, BATEAU et
   DÉPART ne sont pas comparables entre eux ; les enfermer dans des cases
   ajoute sept traits par ligne, soit 140 traits à l'écran, et referme la
   ligne que l'œil est justement en train de suivre de la ville jusqu'au prix.

   Dessiné en ombre interne, comme dans l'en-tête : il ne consomme aucune
   largeur de mise en page, donc les colonnes restent alignées au pixel entre
   l'en-tête et le corps.

   La cellule doit donc occuper toute la hauteur de la ligne pour porter le
   filet, sans que le montant cesse d'être centré. D'où la grille en une seule
   rangée : `align-content: center` centre la rangée dans la hauteur, et
   `align-items: baseline` garde le « € » posé sur la ligne de base du
   chiffre, exactement comme quand les deux étaient en flux inline. */
.row .price {
  height: 100%;
  display: grid;
  grid-auto-flow: column;
  align-content: center;
  align-items: baseline;
  justify-content: center;
  box-shadow: inset 0.0625rem 0 0 rgb(142 214 247 / 0.12);
}
/* Pas de filet à gauche de la première colonne de prix : il fermerait le
   groupe au lieu de séparer deux de ses membres. */
.row .cell-dest + .price { box-shadow: none; }

.cell-dest {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding-left: 1.1rem;
  min-width: 0;
}

.city {
  font-size: 1.78rem;
  font-weight: 700;
  letter-spacing: 0.015em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* La pastille de service (« TRANSIT ») ne doit pas être avalée par l'ellipse
   du nom de ville : c'est elle qui distingue deux lignes voisines. */
.city .via { flex: none; }

/* Cellule navire : point + nom dans la couleur du navire. C'est le lien
   pré-attentif avec le rail de droite. */
.cell-vessel {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  justify-content: center;
  padding: 0 0.4rem;
  min-width: 0;
}
.vessel-name {
  font-size: 1.16rem;
  font-weight: 600;
  color: var(--vc);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 1.7rem au lieu du 1.82rem du socle : les colonnes tarifaires ont rendu
   0.625rem chacune à la colonne destination (voir plus haut). Le prix reste
   le texte le plus large de sa cellule, donc le plus lisible de la ligne. */
.row .price { font-size: 1.7rem; }
.row .price .cur { font-size: 1.26rem; }

.cell-date {
  text-align: center;
  font-size: 1.35rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
/* Une date déjà passée n'est jamais affichée telle quelle : l'écran de
   production actuel montre « 13/06/2023 », ce qui détruit la crédibilité. */
.cell-date.past { color: var(--v-amber); font-size: 1rem; font-weight: 700; letter-spacing: 0.05em; }

/* Départ SUIVANT. Volontairement en retrait : c'est une information de repli
   (« j'ai raté celui-là »), pas la date que 90 % des clients cherchent. Si
   elle avait le même poids que la colonne DÉPART, chaque ligne obligerait à
   arbitrer entre deux dates au lieu d'en lire une. */
.cell-next {
  text-align: center;
  font-size: 1.12rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.cell-next.empty { color: var(--ink-4); font-weight: 500; }

/* --- Cellule remarque ----------------------------------------------------
   La remarque appartient à UNE destination : en colonne, elle est physiquement
   sur la ligne de sa ville. C'est ce qu'un bandeau pleine largeur ne peut pas
   faire — il laisserait croire qu'elle s'applique à toutes les lignes.

   Budget réel : ~28 rem de large sur une ligne de tableau, soit une ligne de
   ~40 caractères à la taille lisible à 3 m. L'agent REFUSE tout texte plus
   long au lieu de le tronquer (agent/display.js) : sur un kiosque il n'y a
   pas de « voir plus », et une phrase coupée sur un tarif fait douter le
   client de la remise elle-même. */
.cell-remark {
  display: flex;
  align-items: center;
  min-width: 0;
  height: 100%;
  padding: 0 0.9rem 0 1rem;
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1.2;
  color: #d6e6f1;
  white-space: nowrap;
  overflow: hidden;
  border-left: 0.0625rem solid var(--line-soft);
}

/* Liseré de gravité : reprend la couleur de la pastille posée à côté de la
   ville, pour que l'œil relie les deux extrémités de la ligne. */
.cell-remark[data-type] {
  box-shadow: inset 0.25rem 0 0 var(--tag-info);
  animation: fade 0.5s ease;
}
.cell-remark[data-type="promo"]   { box-shadow: inset 0.25rem 0 0 var(--tag-promo); }
.cell-remark[data-type="warning"] { box-shadow: inset 0.25rem 0 0 var(--tag-warning); }
.cell-remark[data-type="new"]     { box-shadow: inset 0.25rem 0 0 var(--tag-new); }
@keyframes fade { from { opacity: 0; transform: translateY(0.35rem); } }

/* --- QR de suivi en mode remarques ---------------------------------------
   Le rail emporte le seul QR de l'écran quand la colonne REMARQUES prend sa
   place. Ce bloc le remplace, posé sur le bas de cette colonne : elle est
   vide 16 lignes sur 20, la surface est déjà payée.

   Trois règles, chacune contre une fausse bonne idée :
     - OPAQUE. Un QR en filigrane ne se lit pas : le capteur a besoin de noir
       franc sur blanc franc, pas d'une trame par-dessus une image ;
     - FIXE. Un QR qui apparaît toutes les X secondes rate sa cible — le
       client met une dizaine de secondes à sortir et déverrouiller son
       téléphone, le QR a déjà disparu ;
     - 7.2 rem, soit ~7 cm, soit ~70 cm de portée (voir DESIGN-DECISIONS §22).
       Même taille que celui du rail : la même action ne change pas de format
       d'un mode à l'autre. */
.remark-qr {
  position: absolute;
  right: 0.9rem;
  bottom: 0.9rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.7rem 1.2rem 0.7rem 0.75rem;
  background: linear-gradient(135deg, #12557d, #0a2a3f);
  border: 0.0625rem solid #2a7ba8;
  border-radius: var(--radius);
  box-shadow: 0 0.7rem 2.2rem rgb(2 10 18 / 0.65);
}
.remark-qr[hidden] { display: none; }

.rq-code {
  width: 7.2rem;
  height: 7.2rem;
  flex: none;
  background: #fff;
  border-radius: 0.35rem;
  padding: 0.18rem;
}
.rq-code svg { width: 100%; height: 100%; display: block; }

.rq-text { display: grid; gap: 0.25rem; }
.rq-text b {
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1.1;
}
.rq-text span {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--brand-soft);
}
