@charset "UTF-8";
/*
 * Caveat, l'écriture manuscrite des prédictions, embarquée avec l'app.
 *
 * Le fichier est servi par l'app elle-même (`public/fonts/`, donc `dist/fonts/`) : il part dans le
 * cache hors-ligne avec le reste, la Content-Security-Policy l'autorise (`font-src 'self'`), et
 * l'écriture est identique sur tous les appareils — sans elle, Android n'a aucune police
 * manuscrite à proposer et retombe sur une cursive quelconque.
 *
 * C'est une police variable : une seule graisse déclarée de 400 à 700 couvre tout ce dont l'app a
 * besoin. Le sous-ensemble latin suffit (lettres accentuées et apostrophe typographique comprises).
 *
 * Caveat, par The Caveat Project Authors, sous licence SIL Open Font License 1.1 — le texte de la
 * licence accompagne le fichier, dans `public/fonts/OFL.txt`.
 */
@font-face {
  font-family: "Caveat";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("fonts/caveat-latin.woff2") format("woff2");
}
:root {
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
}

#app {
  --app-w: 100vw;
  --app-h: 100vh;
  position: fixed;
  inset: 0;
  overflow: hidden;
}
#app[data-rotation="-90"], #app[data-rotation="90"] {
  inset: auto;
  top: 50%;
  left: 50%;
  width: var(--app-w);
  height: var(--app-h);
}
#app[data-rotation="-90"] {
  --safe-t: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-right, 0px);
  --safe-l: env(safe-area-inset-bottom, 0px);
  transform: translate(-50%, -50%) rotate(-90deg);
}
#app[data-rotation="90"] {
  --safe-t: env(safe-area-inset-right, 0px);
  --safe-r: env(safe-area-inset-bottom, 0px);
  --safe-b: env(safe-area-inset-left, 0px);
  --safe-l: env(safe-area-inset-top, 0px);
  transform: translate(-50%, -50%) rotate(90deg);
}

@supports (height: 1svh) {
  #app {
    --app-h: 100svh;
  }
}
/*
 * Écriture à la main des prédictions : Caveat, embarquée avec l'app (public/fonts/), et non
 * téléchargée depuis un serveur de polices — l'app est hors-ligne, et sa Content-Security-Policy
 * n'autorise que ses propres fichiers. Elle est donc la même sur tous les appareils.
 *
 * Les polices système suivent, au cas où le fichier manquerait : Bradley Hand et Noteworthy sur
 * iPhone et iPad, Segoe Script et Ink Free sur Windows, la cursive du système en dernier recours.
 */
*,
*::before,
*::after {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

html,
body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  background: #071a0f;
  color: #f1ede4;
}

body {
  position: fixed;
  inset: 0;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
}

[hidden] {
  display: none !important;
}

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

/*
 * Le tapis : un feutre vert de table de jeu, éclairé au centre et qui s'assombrit vers les bords,
 * avec un grain fin pour la texture du drap. Décor seulement — rien ne bouge pendant la routine,
 * et tout reste assez sombre pour que les cartes claires s'en détachent.
 */
#app {
  background: repeating-linear-gradient(58deg, rgba(255, 255, 255, 0.022) 0 1px, transparent 1px 3px), repeating-linear-gradient(-58deg, rgba(0, 0, 0, 0.05) 0 1px, transparent 1px 3px), radial-gradient(90% 62% at 50% 34%, rgba(255, 246, 214, 0.13), transparent 70%), radial-gradient(130% 95% at 50% 42%, #1a5130, #10361f 45%, #071a0f 100%);
}

#stage {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: calc(var(--safe-t) + 16px) calc(var(--safe-r) + 16px) calc(var(--safe-b) + 16px) calc(var(--safe-l) + 16px);
  touch-action: none;
  isolation: isolate;
}

/*
 * Les six cartes, étalées de haut en bas au centre de la scène.
 *
 * Trois transformations se superposent, chacune sur son élément pour ne pas se gêner :
 *   .carte        place la carte dans la pile (--profondeur), puis la fait sortir du cadre ;
 *   .carte-pivot  la retourne (rotateY) ;
 *   .carte-face   le dos et l'avant, dos à dos (backface-visibility).
 */
#paquet {
  /*
   * La taille de la carte, puis l'étalement du paquet, se calculent dans cet ordre à partir de
   * la place réellement disponible — l'étalement dépend de la carte, jamais l'inverse.
   *
   *   1. la carte prend la plus grande taille qui tienne en largeur, sans dépasser 58 % de la
   *      hauteur libre (le rapport 2,5 × 3,5 pouces commande sa largeur) ;
   *   2. tout ce qui reste en dessous se partage entre les cinq cartes du fond, sans qu'une
   *      carte découvre plus que le huitième de sa voisine.
   *
   * Les deux plafonds se répondent : 58 % pour la carte et 12 % de la carte pour chacun des cinq
   * crans font au plus 93 % de la hauteur libre. Le paquet remplit donc l'écran sans jamais en
   * sortir ni le toucher, qu'il soit haut, court, ou pivoté avec le téléphone.
   */
  --ratio: .714;
  --dispo-h: calc(var(--app-h) - var(--safe-t) - var(--safe-b) - 32px);
  --carte-h: min(
  	calc(var(--app-w) * .76 / var(--ratio)),
  	calc(var(--dispo-h) * .58),
  	500px
  );
  --carte-w: calc(var(--carte-h) * var(--ratio));
  --etalement: max(12px, min(calc((var(--dispo-h) - var(--carte-h)) / 5), calc(var(--carte-h) * .12)));
  --pile: calc(var(--etalement) * 5);
  --rayon: clamp(12px, calc(var(--carte-w) * .055), 26px);
  --marge: clamp(7px, calc(var(--carte-w) * .038), 16px);
  position: relative;
  width: var(--carte-w);
  height: var(--carte-h);
  margin-bottom: var(--pile);
  /*
   * Volontairement plat (transform-style par défaut) : chaque carte porte sa propre perspective.
   * Dans un espace 3D partagé, la carte qui tourne couperait le plan des cartes posées à plat,
   * et le navigateur découperait les polygones sur la ligne d'intersection — une couture bien
   * visible au milieu de la carte, sur l'axe même du retournement.
   */
}

/*
 * Les quatre couleurs de dos, pour les cartes de la scène comme pour les vignettes du menu
 * (styles/_menu.scss). Elles sont posées sur chaque carte et non sur le paquet : le réglage
 * « mix » en donne une différente à chaque carte (stage/paquet.ts, logic/settings.ts).
 *   --dos-clair / --dos-fonce  le fond, du haut vers le bas ;
 *   --trait                    le dessin du dos (stage/dos.ts), doré sur fond sombre, encre sur blanc.
 */
.carte,
.vignette {
  --dos-clair: #23242b;
  --dos-fonce: #0e0f13;
  --trait: #c8a15a;
}
.carte[data-couleur=rouge],
.vignette[data-couleur=rouge] {
  --dos-clair: #93222a;
  --dos-fonce: #430e13;
  --trait: #e8ca88;
}
.carte[data-couleur=bleu],
.vignette[data-couleur=bleu] {
  --dos-clair: #23508f;
  --dos-fonce: #0b1c38;
  --trait: #ddc88c;
}
.carte[data-couleur=blanc],
.vignette[data-couleur=blanc] {
  --dos-clair: #f4eee2;
  --dos-fonce: #d9d0bc;
  --trait: #2f3442;
}

.carte {
  /*
   * Où la carte est posée, et à quel rang du paquet. Les quatre valeurs sont écrites une fois
   * pour toutes par stage/paquet.ts, d'après l'étalement tiré au sort (logic/etalement.ts) :
   *   --dy    descente, en nombre de crans (0 pour la première carte) ;
   *   --dx    décalage latéral, en pixels ;
   *   --rot   inclinaison, en degrés ;
   *   --rang  place dans le paquet, pour l'ordre d'empilement.
   *
   * Elles ne dépendent pas du nombre de cartes déjà sorties : une carte posée là y reste, et
   * quand celle du dessus s'envole, les autres ne remontent pas.
   */
  --dy: 0;
  --dx: 0;
  --rot: 0;
  --rang: 0;
  --fit: 1;
  position: absolute;
  inset: 0;
  z-index: calc(100 - var(--rang));
  perspective: 1200px;
  transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * var(--etalement))) rotate(calc(var(--rot) * 1deg)) scale(calc(1 - var(--dy) * 0.012));
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.4s ease;
}

/*
 * Sortie du cadre : la carte part vers le haut, en tournant, et disparaît. Elle passe par-dessus
 * tout le paquet le temps de son vol.
 *
 * Le vol part de la place où la carte était posée, et la remonte d'une hauteur d'écran plus une
 * hauteur de carte : d'où qu'elle parte, même du bas de l'étalement, elle finit hors du cadre.
 */
.carte.sortie {
  z-index: 200;
  opacity: 0;
  transform: translate(calc(var(--dx) * 1px - 26%), calc(var(--dy) * var(--etalement) - var(--app-h) - var(--carte-h) - 20px)) rotate(calc(var(--rot) * 1deg - 17deg)) scale(calc(1 - var(--dy) * 0.012));
  transition: transform 0.65s cubic-bezier(0.45, 0, 0.75, 0.5), opacity 0.35s ease 0.34s;
}

.carte-pivot {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform 0.62s cubic-bezier(0.4, 0.02, 0.2, 1);
}

.carte.retournee .carte-pivot {
  transform: rotateY(180deg);
}

.carte-face {
  position: absolute;
  inset: 0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  border-radius: var(--rayon);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 18px 36px rgba(0, 0, 0, 0.45);
}

/* ---------- Le dos ---------- */
.dos {
  background: linear-gradient(155deg, var(--dos-clair), var(--dos-fonce));
  box-shadow: inset 0 0 0 var(--marge) #f3ecdd, inset 0 0 0 calc(var(--marge) + 1px) rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.5), 0 18px 36px rgba(0, 0, 0, 0.45);
  color: var(--trait);
}

/**
 * Le motif du dos, dessiné à l'intérieur de la marge de papier. Il occupe exactement la place
 * qu'il lui reste, quelle que soit la taille de la carte (le SVG s'étire avec elle).
 */
.dos-motif {
  position: absolute;
  inset: calc(var(--marge, 3px) + 1px);
  display: block;
  width: auto;
  height: auto;
}

/* ---------- L'avant : la prédiction ---------- */
.avant {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  padding: clamp(14px, 7%, 34px) clamp(10px, 4.5%, 22px);
  transform: rotateY(180deg);
  background: radial-gradient(120% 90% at 50% 30%, #fbf6ea, #f3ecdd 58%, #ded3bd 140%);
  box-shadow: inset 0 0 0 1px rgba(28, 39, 67, 0.16), 0 1px 2px rgba(0, 0, 0, 0.5), 0 18px 36px rgba(0, 0, 0, 0.45);
  color: #1c2743;
  text-align: center;
}

.carte-corps {
  width: 100%;
  position: relative;
  z-index: 1;
}

/*
 * Le bloc écrit : la prédiction et son soulignement. Il se serre sur le texte (largeur du contenu)
 * pour être mesuré tel quel, et pivote d'un bloc — les mots les plus longs sont écrits le long de
 * la diagonale de la carte (stage/paquet.ts : fit).
 */
.ecriture {
  display: inline-block;
  font-size: calc(var(--fit) * 38px);
  transform: rotate(var(--angle, 0deg));
}

.soulignement {
  display: block;
  width: 100%;
  height: 0.26em;
  margin-top: -0.03em;
  color: inherit;
  overflow: visible;
  /*
   * Le trait a la grosseur des lettres. Deux précautions pour cela : l'épaisseur est donnée en
   * `em`, donc relative à la taille du texte, et « non-scaling-stroke » l'empêche de suivre
   * l'étirement du repère du dessin — sans quoi le trait s'amincirait sur les mots longs et
   * s'épaissirait sur les courts.
   */
}
.soulignement path {
  stroke-width: 0.075em;
  vector-effect: non-scaling-stroke;
}

.entete {
  margin: 0 0 calc(var(--fit) * 18px);
  font: 600 calc(var(--fit) * 12px)/1.2 -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(28, 39, 67, 0.5);
}

.prediction {
  margin: 0;
  /*
   * Une écriture penchée déborde de la case que le navigateur mesure : l'encre d'un « ! » ou
   * d'une majuscule inclinée sort de sa largeur d'avance, et le mot venait frôler le bord de la
   * carte. Cette marge entre dans la mesure de l'ajustement (stage/paquet.ts), et comme elle est
   * donnée en `em`, elle grandit avec le texte.
   */
  padding: 0.06em 0.14em;
  font-family: "Caveat", "Bradley Hand", "Noteworthy", "Segoe Script", "Ink Free", cursive;
  font-weight: 600;
  line-height: 1.22;
  color: #1c2743;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  /*
   * Jamais de coupure automatique : une ligne reste d'un seul tenant, et c'est le retour à la
   * ligne écrit dans content/cartes.ts qui décide où ça casse. L'ajustement (stage/paquet.ts)
   * réduit alors la taille jusqu'à ce que la plus large des lignes tienne dans la carte.
   */
  white-space: nowrap;
  hyphens: none;
}

#paquet.no-anim .carte,
#paquet.no-anim .carte-pivot {
  transition: none;
}

#hold-ring {
  position: fixed;
  pointer-events: none;
  z-index: 30;
  width: 96px;
  height: 96px;
  margin: -48px 0 0 -48px;
  opacity: 0;
}
#hold-ring svg {
  display: block;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}
#hold-ring circle {
  fill: none;
  stroke-width: 6;
}
#hold-ring .track {
  stroke: rgba(241, 237, 228, 0.18);
}
#hold-ring .fill {
  stroke: #c8a15a;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}
#hold-ring.run {
  animation: ring-show 0.2s ease var(--ring-delay) forwards;
}
#hold-ring.run .fill {
  animation: ring-fill var(--ring-duration) linear var(--ring-delay) forwards;
}

@keyframes ring-show {
  to {
    opacity: 1;
  }
}
@keyframes ring-fill {
  to {
    stroke-dashoffset: 0;
  }
}
#menu {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  justify-content: center;
  background: #071a0f;
  color: #f1ede4;
}

.sheet {
  width: 100%;
  max-width: 560px;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  touch-action: manipulation;
  padding: calc(var(--safe-t) + 22px) calc(var(--safe-r) + 16px) calc(var(--safe-b) + 32px) calc(var(--safe-l) + 16px);
}
.sheet button {
  min-height: 46px;
  border-radius: 12px;
  font-family: inherit;
  font-size: 15px;
  color: #f1ede4;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(241, 237, 228, 0.14);
  cursor: pointer;
}
.sheet button.primary {
  border-color: transparent;
  background: #c8a15a;
  color: #1b1408;
  font-weight: 600;
}
.sheet button.link {
  width: 100%;
  margin-top: 6px;
  border: none;
  background: none;
  color: rgba(241, 237, 228, 0.6);
  font-size: 13px;
  text-decoration: underline;
}

.menu-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 16px;
}
.menu-head h1 {
  margin: 0;
  font: 400 30px/1.1 "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", "Noto Serif", Georgia, serif;
}
.menu-head span {
  color: rgba(241, 237, 228, 0.6);
  font-variant-numeric: tabular-nums;
}

.menu-version {
  -webkit-user-select: text;
  user-select: text;
  margin: 4px 0 0;
  font-size: 13px;
  color: rgba(241, 237, 228, 0.6);
  font-variant-numeric: tabular-nums;
}

.card {
  margin-bottom: 12px;
  padding: 14px 16px;
  border-radius: 16px;
  background: #151518;
  border: 1px solid rgba(241, 237, 228, 0.08);
}

.row-label {
  margin-bottom: 10px;
  font-size: 15px;
  color: rgba(241, 237, 228, 0.6);
}

.hint {
  margin: 0 0 8px;
  font-size: 13px;
  color: rgba(241, 237, 228, 0.6);
}

.carte-list {
  display: grid;
  gap: 6px;
  max-height: calc(var(--app-h) * 0.42);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.sheet .carte-list button {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  text-align: left;
  line-height: 1.3;
}
.sheet .carte-list button.current {
  border-color: #c8a15a;
  background: rgba(200, 161, 90, 0.14);
}
.carte-list .num {
  flex: none;
  min-width: 2ch;
  color: #c8a15a;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 6px;
  padding: 4px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.35);
}
.sheet .seg button {
  min-height: 40px;
  border-color: transparent;
  background: transparent;
}
.sheet .seg button[aria-checked=true] {
  background: rgba(200, 161, 90, 0.18);
  color: #c8a15a;
  box-shadow: inset 0 0 0 1px #c8a15a;
}

.options {
  display: grid;
}

.toggle-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 4px 0;
  font-size: 15px;
  cursor: pointer;
}
.toggle-row + .toggle-row {
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid rgba(241, 237, 228, 0.08);
}
.toggle-row input {
  flex: none;
  width: 22px;
  height: 22px;
  margin: 0;
  accent-color: #c8a15a;
}

.status {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
}
.status small {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: rgba(241, 237, 228, 0.6);
}

.dot {
  flex: none;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #5d5a55;
}
.dot.lock {
  background: #7fe0a0;
  box-shadow: 0 0 10px rgba(127, 224, 160, 0.7);
}
.dot.video {
  background: #f0c36a;
  box-shadow: 0 0 10px rgba(240, 195, 106, 0.6);
}

.about {
  display: grid;
  gap: 8px;
}

.about-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 14px;
  color: rgba(241, 237, 228, 0.6);
}
.about-row span {
  -webkit-user-select: text;
  user-select: text;
  color: #f1ede4;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  overflow-wrap: anywhere;
}

.actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 4px 0 12px;
}

.help {
  font-size: 14px;
  color: rgba(241, 237, 228, 0.6);
}
.help summary {
  cursor: pointer;
}
.help ul {
  margin: 10px 0 0;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.6;
}

/*
 * Choix du dos et de la couleur : on regarde les cartes, on ne lit pas leurs noms. Chaque bouton
 * porte une petite carte face cachée, dessinée exactement comme celles de la scène (stage/dos.ts).
 * Le nom du style reste en aria-label, pour les lecteurs d'écran.
 */
.vignettes {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.sheet .vignettes button {
  min-height: 0;
  padding: 6px;
  border-radius: 10px;
  border-color: transparent;
  background: rgba(0, 0, 0, 0.3);
}
.sheet .vignettes button[aria-checked=true] {
  border-color: #c8a15a;
  background: rgba(200, 161, 90, 0.16);
}
.vignettes.couleurs {
  grid-template-columns: repeat(5, 1fr);
}

.vignette {
  --marge: 3px;
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 5/7;
  border-radius: 5px;
  overflow: hidden;
  background: linear-gradient(155deg, var(--dos-clair), var(--dos-fonce));
  box-shadow: inset 0 0 0 var(--marge) #f3ecdd, inset 0 0 0 calc(var(--marge) + 1px) rgba(0, 0, 0, 0.3);
  color: var(--trait);
}

.vignette-mix {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 5/7;
}
.vignette-mix .vignette {
  --marge: 2px;
  position: absolute;
  top: 4%;
  left: 0;
  width: 68%;
  border-radius: 4px;
}
.vignette-mix .vignette:nth-child(2) {
  transform: translate(23%, 8%);
}
.vignette-mix .vignette:nth-child(3) {
  transform: translate(46%, 16%);
}

.mes-tours {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  margin: 4px 0 12px;
  border-radius: 12px;
  font-size: 15px;
  color: #f1ede4;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(241, 237, 228, 0.14);
  text-decoration: none;
}
