/* ==========================================================================
   toobigtoshare — feuille de style unique
   Design system « Nocturne », palette inversée (claire).
   Polices système. Aucune requête réseau externe.

   1. Tokens
   2. Base
   3. Design system (btn, input, field, card, tag, hr)
   4. Coque et mise en page
   5. Blocs partagés
   6. Écrans
   7. Sommaire de revue
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens — repris tels quels de la maquette (Nocturne inversé)
   -------------------------------------------------------------------------- */

:root {
  --color-bg: #f3f5fe;
  --color-surface: #e4e7f5;
  --color-text: #292b31;
  --color-divider: color-mix(in srgb, #292b31 16%, transparent);
  --color-accent: #5d5294;
  --color-accent-300: #423a6a;
  --color-neutral-100: #292b31;
  --color-neutral-200: #3f424d;
  --color-neutral-300: #3f424d;
  --color-neutral-400: #595d6c;
  --color-neutral-500: #595d6c;
  --color-neutral-600: #b2b6ca;
  --color-neutral-700: #cfd3e5;
  --color-neutral-800: #e4e7f5;
  --color-neutral-900: color-mix(in srgb, #e4e7f5 60%, #f3f5fe);

  --shadow-sm: 0 0 0 1px #cfd3e5;
  --shadow-md: 0 0 0 1px #cfd3e5, 0 6px 18px rgba(41, 43, 49, 0.10);
  --shadow-lg: 0 0 0 1px #b2b6ca, 0 16px 40px rgba(41, 43, 49, 0.14);

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Titre des ecrans de lecture. Ecrit ici parce que la pastille de
     `.read__head`, qui est sa soeur et non son enfant, se positionne avec sa
     hauteur de ligne. */
  --fs-read-title: clamp(27px, 4.6cqi, 32px);
  --lh-read-title: 1.15;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;

  /* La maquette importait deux familles Google. Pile système, même échelle. */
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-heading: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Cible tactile minimale. */
  --tap: 44px;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 500;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }

a { color: var(--color-accent); }
a:hover { color: var(--color-accent-300); }

img, video { max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@keyframes tbts-pulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   3. Design system
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--tap);
  padding: 10px var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 15px;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.btn-primary {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-bg);
}
.btn-primary:hover { background: var(--color-accent-300); border-color: var(--color-accent-300); color: var(--color-bg); }

.btn-secondary {
  background: var(--color-surface);
  border-color: var(--color-neutral-600);
  color: var(--color-text);
}
.btn-secondary:hover { background: var(--color-neutral-700); color: var(--color-text); }

.btn-ghost {
  padding: 10px 0;
  border-color: transparent;
  background: transparent;
  color: var(--color-accent);
  font-size: 14px;
}
.btn-ghost:hover { color: var(--color-accent-300); }

.btn-block { display: flex; width: 100%; }

.btn:disabled,
.btn[aria-disabled="true"] {
  cursor: not-allowed;
  background: var(--color-neutral-600);
  border-color: var(--color-neutral-600);
  color: var(--color-bg);
}
.btn-secondary:disabled,
.btn-ghost:disabled {
  background: transparent;
  border-color: var(--color-neutral-600);
  color: var(--color-neutral-500);
}

/* Bouton d'action principal, taille « accueil » et « écran final ». */
.btn-lg { min-height: 48px; padding: 12px 22px; font-size: 16px; }
.btn-xl { min-height: 52px; padding: 14px 26px; font-size: 17px; }

.field { display: block; }
.field--sm { max-width: 360px; }
.field > label {
  display: block;
  /* Le libelle appartient a son champ : colle-le dessus, sinon il flotte entre
     le champ precedent et le sien et l'oeil hesite sur ce qu'il annonce. */
  margin-bottom: var(--space-1);
  font-size: 14px;
  line-height: 1.35;
  color: var(--color-neutral-300);
}

.input {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 1px solid var(--color-neutral-600);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text);
  font: inherit;
  font-size: 16px; /* < 16px déclenche un zoom au focus sur iOS */
}
.input::placeholder { color: var(--color-neutral-600); }
.input:focus-visible { border-color: var(--color-accent); }

/* Champ de message : mêmes bords que `.input`, la hauteur en plus. On ne
   redimensionne qu'en vertical — l'horizontal déborderait de la colonne. */
.textarea {
  min-height: 160px;
  padding: 10px var(--space-3);
  line-height: 1.5;
  resize: vertical;
}

.card {
  padding: clamp(16px, 3cqi, 22px);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.tag {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-neutral-900);
  color: var(--color-neutral-400);
  font-size: 12px;
}

.hr {
  height: 1px;
  margin: var(--space-6) 0;
  border: 0;
  background: var(--color-divider);
}

/* --------------------------------------------------------------------------
   4. Coque et mise en page
   -------------------------------------------------------------------------- */

.shell {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--color-bg);
  transition: background 0.15s;
}

/* Survol de glisser-déposer : toute la page se teinte. */
/* Sans cible dessinee, c'est la page entiere qui s'allume : rien d'autre ne
   dirait qu'on peut lacher le fichier. Un ecran qui porte une `.drop-zone`
   a deja sa cible — la teinter en plus ferait clignoter tout l'ecran. */
.shell.is-dragging:not(:has(.drop-zone)) {
  background: color-mix(in srgb, var(--color-accent) 22%, var(--color-bg));
}

.brand {
  padding: clamp(20px, 4cqi, 28px) clamp(20px, 4cqi, 32px) 0;
  font-family: var(--font-heading);
  letter-spacing: -0.02em;
}
.brand-link {
  color: inherit;
  text-decoration: none;
  display: inline-block;
  border-radius: var(--radius-sm);
}
.brand-link:hover .brand-a,
.brand-link:hover .brand-b { opacity: .75; }
.brand-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }

.brand-a { font-weight: 800; font-size: 22px; }
.brand-b { font-weight: 200; font-size: 22px; color: var(--color-accent); }

.col {
  flex: 1;
  width: min(620px, 100%);
  margin: 0 auto;
  padding: clamp(20px, 3cqi, 32px) clamp(20px, 5cqi, 40px) clamp(60px, 9cqi, 100px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  justify-content: safe center;
}

/* Écrans de consultation : pensés mobile d'abord, ancrés en haut. */
.col--read { justify-content: flex-start; }

/* Lecture longue : les pages légales sont une suite de chapitres, pas un écran.
   `h2` et `p` sont à zéro marge partout ailleurs, ce qui convient à des blocs
   courts et posés à la main ; ici tout se touchait, et le titre d'un chapitre
   collait au dernier paragraphe du précédent. On écarte donc le titre de ce qui
   le précède, en le laissant près de son propre texte. */
.col--read h2 {
  margin: clamp(32px, 6cqi, 52px) 0 var(--space-3);
}
.col--read h2:first-of-type { margin-top: clamp(24px, 4cqi, 36px); }
.col--read p + p,
.col--read ul,
.col--read dl { margin-top: var(--space-3); }
.col--read li + li { margin-top: var(--space-2); }

/* Colonne élargie : sommaire de revue. */
.col--wide { width: min(920px, 100%); }

/* Colonne du blog. Les écrans du parcours tiennent en 620px parce qu'ils ne
   portent que quelques lignes ; un article, lui, a des tableaux de trois
   colonnes et se lit d'un bout à l'autre. 780px laisse environ 90 signes par
   ligne — au-delà, l'œil perd le début de la ligne suivante. */
.col--article { width: min(780px, 100%); }

.center { text-align: center; }

/* --------------------------------------------------------------------------
   5. Blocs partagés
   -------------------------------------------------------------------------- */

.title {
  font-size: clamp(26px, 5cqi, 34px);
  margin: 0 0 28px;
}
.title--flush { margin-bottom: 0; }
.title--wide { margin-bottom: clamp(24px, 4cqi, 32px); }

.title-md {
  font-size: clamp(24px, 4.6cqi, 32px);
  margin: 0 0 16px;
}
.title-sm {
  font-size: clamp(22px, 4.2cqi, 28px);
  margin: 0 0 clamp(28px, 5cqi, 40px);
}
.title-sm--tight { margin-bottom: 20px; }
.title-file { word-break: break-word; text-wrap: pretty; }
/* Le titre du dépôt porte un prénom saisi ailleurs : il se replie en lignes
   d'égale longueur, comme la maquette, et ne déborde pas sur un nom long. */
.title-drop { text-wrap: balance; overflow-wrap: break-word; }

.lede--resume {
  max-width: 44ch;
  margin-bottom: clamp(24px, 4cqi, 32px);
  color: var(--color-neutral-300);
}

.lede {
  max-width: 46ch;
  margin: 0 0 clamp(28px, 5cqi, 40px);
  font-size: 15px;
  color: var(--color-neutral-400);
  text-wrap: pretty;
}

/* Chapeau resserre : sur un ecran de formulaire, le chapeau n'introduit pas une
   page mais deux champs. L'ecart de lecture d'un article eloignerait trop le
   premier libelle de ce qui l'explique. */
.lede--tight { margin-bottom: clamp(16px, 3cqi, 24px); }

.eyebrow--tight { margin-bottom: 6px; }
.eyebrow--flush { margin-bottom: 0; }

.eyebrow {
  margin-bottom: 10px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.hint {
  max-width: 46ch;
  font-size: 13px;
  color: var(--color-neutral-500);
  text-wrap: pretty;
}

.meta {
  font-size: 14px;
  color: var(--color-neutral-300);
}

/* Ligne titre + pictogramme. */
.icon-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.icon-row > svg { flex: none; display: block; }

/* Tableau de caractéristiques : libellé / valeur. */
.specs {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: var(--space-2) var(--space-5);
  margin: 0;
  font-size: 15px;
}
.specs dt { color: var(--color-neutral-500); }
.specs dd { margin: 0; word-break: break-word; text-wrap: pretty; }

.specs--wide { grid-template-columns: 168px 1fr; }

@media (max-width: 560px) {
  .specs, .specs--wide { grid-template-columns: 1fr; gap: 0; }
  .specs dt { font-size: 13px; }
  .specs dd { margin-bottom: var(--space-3); }
  .specs dd:last-child { margin-bottom: 0; }
}

/* Barre de progression. */
.bar {
  height: 3px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--color-text) 12%, transparent);
  overflow: hidden;
}
.bar__fill {
  display: block;
  height: 100%;
  background: var(--color-accent);
  transition: width 0.2s linear;
}
.bar__fill--muted { background: var(--color-neutral-500); }

.bar-legend {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: 6px;
  font-size: 13px;
  color: var(--color-neutral-400);
}

/* Encart d'information. */
.notice {
  display: flex;
  gap: 10px;
  padding: var(--space-3) 14px;
  border-radius: var(--radius-md);
  background: var(--color-neutral-900);
}
.notice__icon {
  flex: none;
  line-height: 1.5;
  color: var(--color-accent);
}
.notice__text {
  font-size: 13px;
  color: var(--color-neutral-300);
  text-wrap: pretty;
}

.dot {
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--color-accent);
  animation: tbts-pulse 1.2s ease-in-out infinite;
}

/* Encart d'avertissement encadré (fichier trop gros, reprise incohérente). */
.callout {
  padding: 14px var(--space-4);
  border: 1px solid var(--color-neutral-600);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-size: 14px;
  text-wrap: pretty;
}
.callout--lg { padding: clamp(20px, 4cqi, 28px); font-size: clamp(15px, 2.8cqi, 17px); }

/* Lien à copier. */
.linkbox {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  padding: 10px 10px 10px 14px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.linkbox__value {
  flex: 1;
  min-width: 150px;
  font-size: clamp(13px, 2.4cqi, 15px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.linkbox .btn { padding: 0 var(--space-4); }

/* Bouton de copie sans mot : l'icone dit ce qu'elle fait, et la boite reste
   assez etroite pour tenir sous le bouton principal. La coche prend la place
   des deux feuillets au clic — c'est le meme bouton, pas un second. */
.linkbox__copy {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-neutral-400);
  cursor: pointer;
  transition: color .15s ease, background-color .15s ease;
}
.linkbox__copy:hover {
  background: var(--color-neutral-900);
  color: var(--color-text);
}
.linkbox__copy svg { display: block; }
.linkbox__copy [data-copy-ok] { color: var(--color-accent); }

/* La confirmation, sous la boite. Elle parait au clic et s'efface avec le
   libelle du bouton : rien ne reste allume une fois le geste oublie. */
.linkbox__status {
  margin: 0;
  font-size: 13px;
  color: var(--color-accent);
}
/* Vide, elle ne tient aucune place : un ecran au repos n'a pas a montrer le
   creux ou une phrase viendra. */
.linkbox__status:empty { display: none; }
/* Le presse-papier a refuse : la meme ligne, sans la couleur de la reussite. */
.linkbox__status.is-ko { color: var(--color-neutral-400); }

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.actions--lg { gap: 10px; }

/* Emplacement tenu par un tiers (Stripe) ou par une image générée (QR). */
.slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 186px;
  padding: var(--space-3);
  border: 1px dashed var(--color-neutral-700);
  border-radius: var(--radius-sm);
  color: var(--color-neutral-500);
  font-size: 12px;
  text-align: center;
}
.slot--card { min-height: 170px; }

/* Choix du moyen de paiement : portefeuilles en haut, carte en dessous.
   Les deux blocs prennent toute la largeur de l'emplacement, que .slot
   centrerait sinon. */
.wallets,
.pay-card { width: 100%; }
.wallets { margin-bottom: var(--space-2); }

/* Les portefeuilles sous condition. Tant que les CGV ne sont pas cochees, un
   voile transparent recouvre les boutons : Apple Pay ne s'ouvre donc jamais
   pour rien, et le clic sert a dire ce qui manque. Le voile n'existe que
   verrouille - sinon il resterait dans l'ordre de tabulation. */
.wallets-zone { position: relative; }
.wallets-zone.is-verrou .wallets { opacity: .45; }
.wallets__voile {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: var(--radius-md);
  cursor: not-allowed;
}
.wallets-zone:not(.is-verrou) .wallets__voile { display: none; }

/* Separateur annonce : « ou payer par carte », trait de part et d'autre. */
.wallets__sep {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  margin: var(--space-4) 0;
  color: var(--color-neutral-500);
  font-size: 12px;
}
.wallets__sep::before,
.wallets__sep::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--color-divider);
}

.qr-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.qr {
  display: grid;
  place-items: center;
  width: 132px;
  height: 132px;
  border: 1px dashed var(--color-neutral-700);
  border-radius: var(--radius-sm);
  font-size: 11px;
  color: var(--color-neutral-500);
}
.qr-note {
  max-width: 22ch;
  font-size: 12px;
  color: var(--color-neutral-500);
  text-wrap: pretty;
}

/* Barre de revue : sortie, rang, ecran precedent et suivant. Presente sans
   jamais entrer dans le cadre — elle s'efface tant qu'on ne la vise pas. */
.echap {
  position: fixed;
  right: clamp(12px, 3cqi, 20px);
  bottom: clamp(12px, 3cqi, 20px);
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: var(--color-neutral-900);
  box-shadow: var(--shadow-sm);
  font-size: 12px;
  opacity: .55;
  transition: opacity .15s ease;
}
.echap:hover,
.echap:focus-within { opacity: 1; }

.echap a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  border-radius: 999px;
  color: var(--color-neutral-500);
  text-decoration: none;
  transition: color .15s ease, background .15s ease;
}
.echap a:hover,
.echap a:focus-visible { background: var(--color-neutral-800); color: var(--color-accent); }

.echap__sortie { padding: 0 10px; }
.echap__fleche {
  gap: 4px;
  max-width: 15ch;
  padding: 0 10px;
  overflow: hidden;
  white-space: nowrap;
}
.echap__fleche span:not(.echap__chevron) {
  overflow: hidden;
  text-overflow: ellipsis;
}
.echap__chevron {
  flex: none;
  font-size: 15px;
  line-height: 1;
}
.echap__rang {
  padding: 0 4px;
  color: var(--color-neutral-500);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

[hidden] { display: none !important; }

/* Case à cocher qui débloque un bouton. */
.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: var(--tap);
  padding: var(--space-3) 0;
  font-size: 14px;
  color: var(--color-neutral-200);
  cursor: pointer;
}
.check input {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--color-accent);
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   6. Écrans
   -------------------------------------------------------------------------- */

/* Accueil ------------------------------------------------------------------ */
.home-title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(28px, 5.2cqi, 46px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-align: center;
  text-wrap: balance;
  margin: 0 0 clamp(28px, 5cqi, 52px);
  max-width: 20ch;
  margin-inline: auto;
}

.home-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}
.home-price {
  margin-top: var(--space-3);
  font-size: 14px;
  color: var(--color-neutral-400);
}

@media (max-width: 420px) {
  .home-actions .btn { width: 100%; }
}

/* Page introuvable ---------------------------------------------------------- */

/* Le nombre s'ecrit comme la marque : deux chiffres gras, celui du milieu fin
   et accentue, comme « toobig / toshare ». Rien d'autre ne le decore — a cette
   taille, la graisse suffit. Il est masque aux lecteurs d'ecran : le titre dit
   deja ce qui s'est passe, « quatre cent quatre » n'y ajoute rien. */
.nf__code {
  font-family: var(--font-heading);
  font-size: clamp(72px, 20cqi, 132px);
  line-height: 1;
  letter-spacing: -0.04em;
  margin: 0 0 clamp(16px, 3cqi, 24px);
  animation: tbts-nf .5s ease-out both;
}
.nf__code b { font-weight: 800; }
.nf__code i { font-weight: 200; font-style: normal; color: var(--color-accent); }

@keyframes tbts-nf {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Le chapeau garde sa largeur de lecture, mais se centre sous le titre. */
.nf .lede { margin-inline: auto; }

/* Annonce de survol de l'accueil : la page entière s'éteint au profit d'une
   seule ligne. Les écrans qui dessinent une boîte, eux, s'allument sur place
   — voir `.drop-zone`. */
.drop__over {
  font-size: clamp(19px, 3.6cqi, 24px);
  color: var(--color-accent-300);
}

/* Zone de dépôt dessinée — écran de dépôt ---------------------------------- */
/* Le déposant arrive par un lien reçu : il n'a pas choisi ce site et rien
   d'autre sur la page ne lui dit où lâcher son fichier. La boîte le montre.
   La cible réelle reste la page entière, tenue par `[data-drop]`. */
.drop-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: clamp(28px, 6cqi, 44px) clamp(20px, 4cqi, 32px);
  border: 1px dashed var(--color-neutral-600);
  border-radius: var(--radius-lg);
  text-align: center;
  transition: border-color .15s ease, background-color .15s ease;
}
.drop-zone__icon {
  margin-bottom: var(--space-2);
  color: var(--color-accent);
}
.drop-zone__rest {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}
.drop-zone__main {
  font-size: clamp(16px, 3cqi, 19px);
  color: var(--color-text);
}
.drop-zone__or,
.drop-zone__max {
  font-size: 13px;
  color: var(--color-neutral-500);
}
.drop-zone__max { margin-top: var(--space-2); }
.drop-zone__here {
  font-size: clamp(17px, 3.2cqi, 20px);
  color: var(--color-accent);
}

/* Un fichier survole la page : la boîte s'allume, elle seule. Le liseré
   pointillé se pose en dehors du cadre — le contenu ne bouge pas d'un pixel
   entre les deux états, seule la couleur change. */
.is-dragging .drop-zone {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  outline: 2px dotted color-mix(in srgb, var(--color-accent) 45%, transparent);
  outline-offset: 6px;
}

/* Les lignes posées sous la boîte se centrent avec elle. */
.drop-zone + .hint { margin: var(--space-5) auto 0; }
.drop-zone + .hint + .hint { margin-top: var(--space-3); }

/* Décompte d'envoi automatique --------------------------------------------- */
.countdown {
  padding: clamp(16px, 3cqi, 20px);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}
.countdown__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.countdown__clock {
  font-family: var(--font-heading);
  font-size: clamp(24px, 4.4cqi, 30px);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  color: var(--color-accent-300);
}
.countdown__note {
  margin-top: var(--space-3);
  font-size: 13px;
  color: var(--color-neutral-400);
  text-wrap: pretty;
}

/* Consultation d'un fichier ------------------------------------------------ */
/* Une ligne « nom · poids ». */
.file-line {
  font-size: 15px;
  word-break: break-word;
  text-wrap: pretty;
}
.file-meta {
  font-size: 14px;
  color: var(--color-neutral-400);
  word-break: break-word;
}

/* Attente de confirmation du paiement. */
.polling {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 60px 0;
  font-size: clamp(16px, 3cqi, 19px);
  color: var(--color-neutral-300);
}
.polling .dot { margin-top: 0; }

/* Réservé aux petits écrans. */
.only-mobile { display: none; }
@media (max-width: 620px) {
  .only-mobile { display: block; }
  .btn.only-mobile { display: inline-flex; }
}

/* --------------------------------------------------------------------------
   Ecran de telechargement (handoff « Cadrage du livrable design », 2a)
   Une colonne centree, alignee sur un seul bord ; le signalement isole en bas.
   -------------------------------------------------------------------------- */
.read {
  align-items: center;
  justify-content: space-between;
  text-align: center;
}
.read__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(32px, 6cqi, 56px) 0;
}
/* Le titre du createur est une phrase, adresse comprise : il lui faut plus que
   les 20ch d'un titre de trois mots, et une adresse doit pouvoir se couper. */
.read__title--sent { max-width: 26ch; overflow-wrap: break-word; }

/* Avec un lecteur, le contenu est trop haut pour etre centre : on l'ancre. */
.read--player { justify-content: flex-start; }

.read__title {
  font-size: var(--fs-read-title);
  font-weight: 500;
  line-height: var(--lh-read-title);
  letter-spacing: -0.025em;
  max-width: 20ch;
  margin: 0 0 18px;
}

/* Le nom peut passer a la ligne ; le poids et l'expiration restent solidaires,
   pour qu'aucune ligne ne commence par un separateur orphelin. */
.read__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  column-gap: 7px;
  max-width: 44ch;
  margin: 0 0 34px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--color-neutral-400);
}
.read__name { word-break: break-word; }
.read__facts { white-space: nowrap; }

.btn-dl {
  min-height: 48px;
  padding: 0 34px;
  font-size: 16px;
}

/* Bouton principal, lien du QR, puis le QR. La colonne prend la largeur de
   son plus large enfant intrinseque — le bouton : le QR, en pourcentage, s'y
   aligne sans qu'aucune valeur ne soit ecrite deux fois. */
.read__actions {
  --largeur-action: 260px;   /* la largeur du bouton, tenue par .download .btn */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
  width: min(var(--largeur-action), 100%);
  margin-inline: auto;
}
.read__actions .btn-dl { width: 100%; min-width: 0; }
.read__actions .download { margin: 0; }
.read__qr-lien {
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-accent);
  font-size: 14px;
}
.read__qr-lien:hover { color: var(--color-accent-300, var(--color-accent)); }

/* Le carre et sa legende ne font qu'un : la legende n'a rien a dire quand le
   carre est replie, elle se cache donc avec lui. */
.read__qr-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.read__qr-block .read__qr { margin-top: 0; }

/* Carre du QR : fond blanc, contour fin, a la largeur du bouton. */
.read__qr {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 1;
  margin-top: 6px;
  padding: 8px;
  border-radius: var(--radius-md);
  background: #fff;
  box-shadow: var(--shadow-sm);
  box-sizing: border-box;
}
.read__qr svg { display: block; width: 100%; height: 100%; }

/* Ecran du createur : la pastille de confirmation precede le titre. Le titre
   est une phrase entiere, adresse comprise, qui se plie sur trois lignes :
   centre, ses lignes s'ecartaient de la pastille censee les designer. Tout
   l'ecran se range donc sur un seul bord, a gauche. */
.read--sent { text-align: left; }
.read--sent .read__body { align-items: stretch; }
.read--sent .read__head { justify-content: flex-start; }
.read--sent .read__meta { justify-content: flex-start; }
/* La colonne s'elargit : la boite du lien y montre assez de l'adresse pour
   qu'on la reconnaisse avant les points de suspension. Le bouton et le QR
   suivent, ils prennent leur largeur de la meme variable. */
.read--sent .read__actions { --largeur-action: 340px; margin-inline: 0; }
/* Le bouton principal prend toute la colonne, comme la boite du lien : deux
   largeurs differentes l'une sous l'autre feraient deux blocs au lieu d'un.
   Ailleurs, un bouton de telechargement se contente de sa largeur propre. */
.read--sent .read__actions .btn-dl { width: 100%; }

/* Le titre peut tenir sur deux lignes : la pastille se cale au milieu de la
   premiere, pas au milieu du bloc. Sans quoi elle descend a chaque ligne
   ajoutee et ne designe plus rien. */
.read__head {
  --pastille: 30px;
  align-items: flex-start;
  justify-content: center;
  margin-bottom: 18px;
}
.read__head > svg {
  margin-top: calc((var(--fs-read-title) * var(--lh-read-title) - var(--pastille)) / 2);
}
.read__head .read__title { margin-bottom: 0; }

/* Une phrase, sans couple insecable : elle se replie ou elle veut. */
.read__meta--flow { display: block; }

/* Le lien en clair. Sur l'ecran de partage il est toujours la — c'est
   l'adresse qu'on donne ; sur celui du createur d'un lien de depot, il ne
   parait que si le presse-papier a refuse. */
.read__lien {
  margin: 0;
  font-size: 14px;
  word-break: break-all;
}

/* Legende du QR : ce qu'il fait, pas ce qu'il est. */
.read__qr-note {
  margin: 0;
  font-size: 14px;
  color: var(--color-neutral-500);
}
@media (max-width: 480px) {
  .btn-dl { width: 100%; }
}

.file-title {
  font-size: clamp(24px, 4.6cqi, 32px);
  margin: 0 0 var(--space-2);
}
.file-size {
  margin-bottom: clamp(20px, 4cqi, 28px);
  font-size: clamp(17px, 3cqi, 20px);
  color: var(--color-neutral-400);
}

.player {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin-bottom: clamp(20px, 4cqi, 28px);
  border-radius: var(--radius-md);
  background: var(--color-neutral-800);
  box-shadow: var(--shadow-sm);
  color: var(--color-neutral-500);
  font-size: 13px;
  overflow: hidden;
}
.player__play {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
  color: var(--color-accent);
}

.download .btn { width: 100%; }
@media (min-width: 620px) {
  .download .btn { width: auto; min-width: 260px; }
}

.report {
  /* Le lien porte deja une cible tactile de 44px : son texte flotte a 13px
     du bord du bloc. La marge est donc comptee pour l'ecart visible, pas
     pour l'ecart entre boites. */
  margin-top: clamp(10px, 2cqi, 16px);
  font-size: 13px;
}
/* Liens de texte isolés : cible tactile portée à 44px. */
.report a,
.foot a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
}
.report a { color: var(--color-neutral-500); }
.report a:hover { color: var(--color-accent); }

/* Une seule ligne : les liens au milieu, le sélecteur de langue à leur suite.
   Ils partagent la taille et la couleur — le sélecteur ne doit pas se lire
   comme un bouton posé sous le pied de page, mais comme le dernier élément
   de la même rangée. */
.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 var(--space-4);
  padding: var(--space-5) clamp(20px, 5cqi, 40px);
  font-size: 12px;
  color: var(--color-neutral-500);
}
/* Centre sur l'axe de la page. La colonne de 620px suffisait a centrer le bloc,
   pas les liens : sans `justify-content`, ils se rangeaient contre son bord
   gauche, decales par rapport au contenu centre au-dessus. */
.foot ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 var(--space-4);
  max-width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}
.foot a { color: var(--color-neutral-500); }
.foot a:hover { color: var(--color-accent); }

/* Sélecteur de langue ------------------------------------------------------
   Tout en bas, sous le pied de page quand il y en a un, et seul en bas de
   page quand il n'y en a pas. Seule la langue lue s'affiche ; les trois
   autres sortent d'un `<details>` replié — quatre lignes de drapeaux, c'est
   le bloc le plus voyant d'un pied de page qu'on ne regarde qu'une fois.

   Le drapeau porte l'identification à distance, le nom porte la certitude :
   un drapeau seul confond l'anglais avec le Royaume-Uni, et l'espagnol avec
   l'Espagne. Les deux ensemble ne trompent personne, et le nom reste écrit
   dans sa propre langue. */
.langs {
  display: flex;
  justify-content: flex-end;
  font-size: 12px;
}
/* Hors pied de page — l'écran d'envoi, les maquettes — il tient la ligne seul,
   toujours à droite, et reprend la marge que le pied de page lui donnait. */
.shell > .langs { padding: 0 clamp(20px, 5cqi, 40px) var(--space-5); }
.langs__menu { position: relative; }
.langs__item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: var(--tap);
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-neutral-500);
  text-decoration: none;
  white-space: nowrap;
}
.langs__item:hover { color: var(--color-accent); }

/* La langue lue : c'est le bouton. Le marqueur natif du `<summary>` ferait un
   second chevron, à gauche et dans l'autre sens. */
.langs__current {
  color: var(--color-neutral-500);
  cursor: pointer;
  list-style: none;
}
.langs__current::-webkit-details-marker { display: none; }
.langs__current:hover { background: var(--color-surface); }
.langs__chev { width: 10px; height: 6px; margin-left: var(--space-1); }
.langs__menu[open] .langs__chev { transform: rotate(180deg); }

/* La liste s'ouvre vers le haut : sous le sélecteur, il n'y a plus de page.
   Elle se pose au-dessus du contenu plutôt que de le pousser, sinon ouvrir le
   menu déplacerait le bouton qu'on vient de viser. */
.langs__menu ul {
  position: absolute;
  bottom: calc(100% + var(--space-1));
  right: 0;
  z-index: 20;
  min-width: 100%;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: var(--shadow-md);
}
.langs__menu ul .langs__item { display: flex; }
.langs__menu ul .langs__item:hover { background: var(--color-surface); }

/* Le filet évite qu'un drapeau clair — l'espagnol, l'allemand — se fonde dans
   le fond de la page. */
.langs__flag {
  flex: none;
  width: 20px;
  height: 14px;
  border-radius: 2px;
  object-fit: cover;
  box-shadow: 0 0 0 1px var(--color-divider);
}

/* Espacements verticaux réutilisés ----------------------------------------- */
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: clamp(24px, 4cqi, 32px); }
.mt-7 { margin-top: clamp(28px, 5cqi, 40px); }
.mt-8 { margin-top: clamp(32px, 6cqi, 48px); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: 14px; }

/* --------------------------------------------------------------------------
   7. Sommaire de revue (index.html)
   -------------------------------------------------------------------------- */

.toc { width: min(880px, 100%); }
.toc h2 {
  margin: clamp(28px, 5cqi, 40px) 0 var(--space-3);
  font-size: 18px;
}
.toc h2:first-of-type { margin-top: var(--space-5); }
.toc ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Numerotation continue d'une section a l'autre : c'est le numero qu'on cite
   en recette, pas le nom de fichier. */
.toc { counter-reset: ecran; }
.toc li { counter-increment: ecran; }
.toc li a::before {
  content: counter(ecran) " · ";
  color: var(--color-neutral-500);
}
.toc li a {
  display: block;
  min-height: var(--tap);
  padding: 11px 14px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 14px;
  text-decoration: none;
}
.toc li a:hover { border-color: var(--color-accent); color: var(--color-accent); }
.toc li a small {
  display: block;
  color: var(--color-neutral-500);
  font-size: 12px;
}

/* Valeur legale restant a renseigner. Volontairement criarde : aucune de ces
   marques ne doit survivre a l'ouverture au public.
   Controle : grep -rn "À COMPLÉTER" web/  (voir TODO.md, section A). */
.todo {
  padding: 0 5px;
  border-radius: 3px;
  background: #ffd84d;
  color: #1a1a1a;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   8. Blog (blog.html, blog-<slug>.html)
   -------------------------------------------------------------------------- */

/* Une liste de liens, pas des cartes : le titre porte tout, le reste
   l'accompagne. Le filet separe deux articles sans les encadrer. */
.posts {
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Annule le `li + li` de .col--read : ici l'ecart vient du remplissage du
   lien, pour que toute la ligne — et pas seulement le titre — soit cliquable. */
.col--read .posts li + li {
  margin-top: 0;
  border-top: 1px solid var(--color-divider);
}
/* Classe portee, et non `.posts a` : l'etat vide contient un lien de phrase,
   qui doit rester un lien de phrase. */
.post {
  display: block;
  padding: var(--space-4) 0;
  color: var(--color-text);
  text-decoration: none;
}
.post:hover .post__title { color: var(--color-accent); }
.post__title {
  display: block;
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.post__lede {
  display: block;
  margin-top: 6px;
  font-size: 15px;
  color: var(--color-neutral-400);
  text-wrap: pretty;
}
.post__date {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  color: var(--color-neutral-500);
}
.posts__empty {
  padding: var(--space-4) 0;
  color: var(--color-neutral-400);
  font-size: 15px;
}

/* Article ------------------------------------------------------------------
   Meme colonne que les pages legales : une suite de chapitres, pas un ecran.
   Ne s'y ajoute que ce qu'un article a en propre — un encadre de reponse, des
   tableaux de valeurs, des citations de messages d'erreur. */
.col--read h3 {
  margin: clamp(22px, 4cqi, 30px) 0 var(--space-2);
  font-size: 17px;
}
.col--read ol { margin-top: var(--space-3); padding-left: 1.3em; }
.col--read ol li + li { margin-top: var(--space-2); }

.article__meta {
  margin-bottom: clamp(16px, 3cqi, 22px);
  font-size: 13px;
  color: var(--color-neutral-500);
}
.article__meta a { color: var(--color-neutral-500); }
.article__meta a:hover { color: var(--color-accent); }

/* La reponse en tete : ce que le lecteur est venu chercher, avant tout le
   reste. Le filet a gauche la distingue sans l'encadrer une seconde fois. */
.answer {
  margin-bottom: clamp(24px, 4cqi, 32px);
  border-left: 3px solid var(--color-accent);
}

/* Les tableaux de valeurs debordent sur telephone : ils defilent dans leur
   propre boite, jamais la page. */
.table-wrap {
  margin-top: var(--space-4);
  overflow-x: auto;
}
.table-wrap table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.table-wrap th,
.table-wrap td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--color-divider);
  text-align: left;
  vertical-align: top;
}
.table-wrap th {
  color: var(--color-neutral-400);
  font-weight: 600;
}
.table-wrap tbody tr:last-child td { border-bottom: 0; }

/* Un chemin de registre, une commande ou une adresse n'a pas d'espace ou se
   couper : sans ca, un seul mot long fait deborder toute la page sur
   telephone. `break-word` ne coupe que le mot qui ne tient pas. */
.col--read p,
.col--read li,
.col--read td { overflow-wrap: break-word; }

.col--read code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  overflow-wrap: anywhere;
}

/* Message d'erreur cite mot pour mot : c'est ce que le lecteur a sous les yeux
   et ce qu'il a colle dans un moteur de recherche. */
.quote-err {
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--color-neutral-600);
  color: var(--color-neutral-300);
  font-style: italic;
}

.cta { margin-top: clamp(32px, 6cqi, 48px); }

.article-nav { margin-top: clamp(32px, 6cqi, 48px); }
.article-nav h2 { font-size: 16px; }
.col--read .article-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  padding: 0;
  list-style: none;
  font-size: 14px;
}
.col--read .article-nav li + li { margin-top: 0; }

/* Le defi anti-robot, quand Cloudflare en demande un. Il vit dans <body> pour
   survivre au changement d'ecran, donc il se place lui-meme : au-dessus du
   pied de page, centre, et de taille nulle tant qu'aucun defi n'est pose. */
.turnstile {
  position: fixed;
  left: 50%;
  bottom: var(--space-5);
  z-index: 40;
  transform: translateX(-50%);
}

/* Sauf quand l'ecran lui reserve une place : il se pose alors dedans, aligne
   a gauche sur le bouton, et non centre en bas de la fenetre. */
.turnstile--ancre {
  position: absolute;
  bottom: auto;
  transform: none;
}

/* Centre dans la place qui lui est faite, et non cale a son bord gauche. */
.turnstile--ancre.turnstile--centre { transform: translateX(-50%); }

/* L'emplacement lui-meme n'occupe rien : sans defi, l'ecran est celui d'avant.
   Sa marge tient l'ecart avec le bouton. */
.turnstile-slot { margin-top: var(--space-4); }
