/* =====================================================================
   L'Appel des Portes — design system
   Repris de maquette-design-medieval.html : palette, typographies et
   composants sont ceux de la maquette, portés en responsive et étendus
   aux écrans de la phase 1 (formulaires, alertes, charte d'identifiants).
   ===================================================================== */

:root {
  --parchment:      #f2e4c5;
  --parchment-dark: #e2cf9e;
  --parchment-light:#fff8e6;
  --ink:            #3b2a1a;
  --ink-soft:       #6b5637;
  --gold:           #b8860b;
  --gold-light:     #e8c25a;
  /* Doré pour du TEXTE posé sur une surface claire.
     `--gold` et `--gold-light` sont pensés pour les fonds sombres de la
     maquette — bourgogne, forêt, marine — et pour les bordures. Sur du
     parchemin ils tombent respectivement à 3,07 et 1,4 pour 1, là où un
     texte courant en demande 4,5. Celui-ci tient 4,8 même sur le
     parchemin le plus foncé. */
  --gold-text:      #6d5210;
  --burgundy:       #7a1f2b;
  --burgundy-dark:  #5c1620;
  --forest:         #2f4a2f;
  --navy:           #1e2f4a;
  --shadow-deep:    #241505;
  --danger:         #8c2b20;

  --radius:  10px;
  --shell-max: 430px;
}

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

/* L'attribut `hidden` doit l'emporter. Les encarts de notification sont
   rendus masqués et révélés par le script : une règle de mise en page qui
   poserait `display` les ferait apparaître avant que le script n'ait
   décidé s'ils ont lieu d'être. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  min-height: 100vh;
  background: linear-gradient(160deg, #1a120a, #2b1c0f);
  background-attachment: fixed;
  font-family: 'Merriweather', Georgia, 'Times New Roman', serif;
  color: var(--ink);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  line-height: 1.55;
}

/* --- Coquille de l'application -------------------------------------- */

.app-shell {
  width: 100%;
  max-width: var(--shell-max);
  min-height: 100vh;
  background: var(--parchment);
  background-image:
    radial-gradient(circle at 20% 18%, rgba(139, 101, 42, 0.08) 0%, transparent 42%),
    radial-gradient(circle at 80% 82%, rgba(139, 101, 42, 0.10) 0%, transparent 42%);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Au-delà du mobile, la coquille redevient un « objet » posé sur le fond
   sombre, comme dans la maquette. */
@media (min-width: 520px) {
  body { padding: 24px 16px; align-items: center; }
  .app-shell {
    min-height: auto;
    border: 6px solid var(--gold);
    border-radius: 16px;
    box-shadow: 0 0 0 3px var(--shadow-deep), 0 20px 50px rgba(0, 0, 0, 0.6);
  }
}

/* --- Barre supérieure ------------------------------------------------ */

.topbar {
  background: linear-gradient(180deg, var(--burgundy), var(--burgundy-dark));
  padding: 14px 16px;
  padding-top: max(14px, env(safe-area-inset-top));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 3px solid var(--gold);
}

.hero-badge { display: flex; align-items: center; gap: 10px; min-width: 0; }

.hero-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  flex-shrink: 0;
  background: radial-gradient(circle at 35% 30%, #f4d78a, var(--gold) 70%, #7a5a12);
  border: 2px solid var(--gold-light);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Cinzel', Georgia, serif;
  font-weight: 700;
  color: var(--shadow-deep);
  font-size: 15px;
}

.hero-text { min-width: 0; }
.hero-name {
  font-family: 'Cinzel', Georgia, serif;
  color: var(--parchment);
  font-size: 14px;
  font-weight: 700;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hero-role {
  color: var(--gold-light);
  font-size: 11px;
  margin: 2px 0 0;
  letter-spacing: 0.5px;
}

.streak {
  display: flex;
  align-items: center;
  gap: 6px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--gold);
  border-radius: 20px;
  padding: 5px 12px;
  color: var(--gold-light);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}

/* --- Indicateur d'état réseau ----------------------------------------
   Bandeau fin sous la barre supérieure. Discret en ligne, franc hors
   ligne : le joueur doit comprendre pourquoi le questionnaire refuse de
   s'ouvrir, sans avoir à le deviner. */

.net-status {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 10.5px;
  letter-spacing: 0.4px;
  border-bottom: 1px solid rgba(184, 134, 11, 0.35);
}

.net-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.net-status.is-online   { background: rgba(47, 74, 47, 0.10); color: var(--forest); }
.net-status.is-online .net-dot { background: var(--forest); }

/* Hors ligne mais du contenu disponible : c'est un état de marche, pas
   une panne — d'où l'ambre plutôt que le rouge. */
.net-status.is-degraded { background: rgba(184, 134, 11, 0.16); color: var(--gold-text); }
.net-status.is-degraded .net-dot { background: var(--gold); }

.net-status.is-offline  { background: rgba(140, 43, 32, 0.12); color: var(--danger); }
.net-status.is-offline .net-dot { background: var(--danger); }

.network-note {
  margin: 10px 0 0;
  padding: 11px 13px;
  border: 2px solid var(--gold);
  border-left-width: 6px;
  border-left-color: var(--danger);
  border-radius: 8px;
  background: var(--parchment-light);
  font-size: 13px;
  color: #5e1c14;
}

/* Action mise en file : ce n'est pas un échec, c'est un report. Le vert
   de la forêt plutôt que le rouge, pour que le joueur n'ait pas
   l'impression d'avoir perdu sa lecture. */
.network-note.is-queued {
  border-left-color: var(--forest);
  color: #24391f;
}

/* --- Contenu --------------------------------------------------------- */

.content {
  padding: 20px 18px 28px;
  padding-bottom: max(28px, env(safe-area-inset-bottom));
  flex: 1;
}

.title-banner { text-align: center; margin-bottom: 18px; }
.title-banner h1 {
  font-family: 'MedievalSharp', 'Cinzel', Georgia, serif;
  font-size: 26px;
  line-height: 1.2;
  color: var(--burgundy);
  margin: 0 0 6px;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
}
.title-banner p {
  font-size: 12.5px;
  color: var(--ink-soft);
  margin: 0;
  font-style: italic;
}

.section-title {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 12px;
  color: var(--burgundy);
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  margin: 0 0 8px;
}

/* --- Cadre orné ------------------------------------------------------ */

.ornate-frame {
  border: 2px solid var(--gold);
  border-radius: var(--radius);
  background: var(--parchment-dark);
  padding: 16px;
  margin-bottom: 16px;
  position: relative;
}

/* Équerres dorées aux quatre coins — signature visuelle de la maquette. */
.ornate-frame::before,
.ornate-frame::after,
.ornate-frame > .corner-bl,
.ornate-frame > .corner-br {
  content: '';
  position: absolute;
  width: 14px;
  height: 14px;
  border: 2px solid var(--gold);
  pointer-events: none;
}
.ornate-frame::before { top: -3px; left: -3px;  border-right: none; border-bottom: none; }
.ornate-frame::after  { top: -3px; right: -3px; border-left: none;  border-bottom: none; }
.ornate-frame > .corner-bl { bottom: -3px; left: -3px;  border-right: none; border-top: none; }
.ornate-frame > .corner-br { bottom: -3px; right: -3px; border-left: none;  border-top: none; }

.ornate-frame.is-light { background: var(--parchment-light); }

/* --- Bulle de message du héros --------------------------------------- */

.message-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin-bottom: 18px;
}

.message-avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f4d78a, var(--gold) 70%, #7a5a12);
  border: 2px solid var(--gold-light);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Cinzel', Georgia, serif;
  font-weight: 700;
  color: var(--shadow-deep);
  font-size: 13px;
}

.message-scroll {
  background: var(--parchment-light);
  border: 1px solid var(--gold);
  border-radius: 8px;
  border-bottom-left-radius: 2px;
  padding: 12px 14px;
  font-size: 13.5px;
  font-style: italic;
  color: #4a3826;
  flex: 1;
  min-width: 0;
}

/* --- Boutons --------------------------------------------------------- */

.btn {
  display: block;
  width: 100%;
  background: linear-gradient(180deg, var(--burgundy), var(--burgundy-dark));
  color: var(--parchment);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 1px;
  text-align: center;
  text-decoration: none;
  padding: 14px;
  border: 2px solid var(--gold-light);
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.15s ease;
}
.btn:hover  { filter: brightness(1.1); }
.btn:active { transform: translateY(1px); }

.btn-secondary {
  background: transparent;
  color: var(--burgundy);
  border-color: var(--gold);
}
.btn-secondary:hover { background: rgba(184, 134, 11, 0.12); filter: none; }

.btn-ghost {
  background: none;
  border: none;
  color: var(--ink-soft);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 12px;
  letter-spacing: 0.5px;
  text-decoration: underline;
  cursor: pointer;
  padding: 8px;
  width: auto;
}

.btn + .btn, .btn + .btn-secondary { margin-top: 10px; }

/* Accessibilité : un contour visible au clavier, sur toutes les cibles. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.choice:focus-within {
  outline: 3px solid var(--burgundy);
  outline-offset: 2px;
}

/* --- Formulaires ----------------------------------------------------- */

.field { margin-bottom: 16px; }

.field label {
  display: block;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  color: var(--burgundy);
  margin-bottom: 6px;
}

.field .hint {
  display: block;
  font-size: 11.5px;
  font-style: italic;
  color: var(--ink-soft);
  margin: 4px 0 0;
}

.field input[type="text"],
.field input[type="password"],
.field textarea {
  width: 100%;
  padding: 12px 13px;
  font-family: 'Merriweather', Georgia, serif;
  font-size: 15px; /* >= 16px évite le zoom iOS ; 15 + max() ci-dessous */
  color: var(--ink);
  background: var(--parchment-light);
  border: 2px solid var(--gold);
  border-radius: 8px;
}
@media (max-width: 519px) {
  /* Sous iOS, un champ à moins de 16px déclenche un zoom automatique à
     la mise au point, qui casse la mise en page. */
  .field input, .field textarea { font-size: 16px; }
}

.field input::placeholder { color: #a89673; }

/* Choix du héros — deux cartes plutôt qu'une liste déroulante : c'est un
   moment d'identification, pas un champ administratif. */
.choice-group { display: flex; gap: 10px; }

.choice {
  flex: 1;
  position: relative;
  border: 2px solid var(--gold);
  border-radius: var(--radius);
  background: var(--parchment-light);
  padding: 14px 10px;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice .choice-name {
  display: block;
  font-family: 'Cinzel', Georgia, serif;
  font-weight: 700;
  font-size: 15px;
  color: var(--burgundy);
}
.choice .choice-sub {
  display: block;
  font-size: 11px;
  color: var(--ink-soft);
  font-style: italic;
  margin-top: 2px;
}
.choice:has(input:checked) {
  background: var(--forest);
  border-color: var(--gold-light);
  box-shadow: 0 0 0 3px rgba(184, 134, 11, 0.25);
}
.choice:has(input:checked) .choice-name { color: var(--parchment); }
.choice:has(input:checked) .choice-sub  { color: var(--gold-light); }

/* --- Alertes --------------------------------------------------------- */

.alert {
  border: 2px solid var(--gold);
  border-left-width: 6px;
  border-radius: 8px;
  padding: 11px 13px;
  margin-bottom: 14px;
  font-size: 13.5px;
  background: var(--parchment-light);
}
.alert-error   { border-left-color: var(--danger);   color: #5e1c14; }
.alert-success { border-left-color: var(--forest);   color: #24391f; }
.alert-info    { border-left-color: var(--navy);     color: #1e2f4a; }

/* --- Charte d'identifiants ------------------------------------------- */

.credentials {
  background: var(--parchment-light);
  border: 3px double var(--gold);
  border-radius: var(--radius);
  padding: 18px 16px;
  text-align: center;
  margin-bottom: 16px;
}

.credential-line + .credential-line {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed rgba(184, 134, 11, 0.5);
}

.credential-label {
  display: block;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 6px;
}

.credential-value {
  display: block;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--burgundy);
  word-break: break-word;
  user-select: all; /* un appui long sélectionne la valeur entière */
}

.copy-btn {
  margin-top: 8px;
  background: none;
  border: 1px solid var(--gold);
  border-radius: 6px;
  color: var(--ink-soft);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 11px;
  letter-spacing: 0.5px;
  padding: 5px 12px;
  cursor: pointer;
  width: auto;
}
.copy-btn:hover { background: rgba(184, 134, 11, 0.12); }
.copy-btn.is-done { border-color: var(--forest); color: var(--forest); }

.warning-scroll {
  background: rgba(122, 31, 43, 0.08);
  border: 1px solid var(--burgundy);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 13px;
  color: #5e1c14;
  margin-bottom: 16px;
}
.warning-scroll strong { font-family: 'Cinzel', Georgia, serif; }

/* --- Bandeau de récompenses ------------------------------------------ */

/* Marge basse explicite : le bandeau de récompenses est visuellement
   lourd (aplats sombres), et ce qui le suit doit respirer autant que le
   reste de la page. */
.reward-row { display: flex; gap: 8px; margin-top: 16px; margin-bottom: 16px; }

.reward-chip {
  flex: 1;
  background: var(--navy);
  border: 1px solid var(--gold);
  border-radius: 8px;
  padding: 9px 6px;
  text-align: center;
  color: var(--gold-light);
  font-size: 10px;
  line-height: 1.35;
  font-family: 'Cinzel', Georgia, serif;
}
.reward-chip strong { display: block; font-size: 15px; color: var(--parchment); }

/* --- Illustration de ville -------------------------------------------- */

.city-illustration-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2.4 / 1;
  object-fit: cover;
  border: 3px solid var(--gold);
  border-radius: var(--radius);
  margin-bottom: 14px;
}

/* Cadre décoratif tant que l'image n'a pas été déposée : mieux vaut un
   emplacement assumé qu'une image cassée. */
.city-illustration {
  width: 100%;
  aspect-ratio: 2.4 / 1;
  border: 3px solid var(--gold);
  border-radius: var(--radius);
  margin-bottom: 14px;
  background: linear-gradient(150deg, #6b4a2b, #3d2a17 60%, var(--shadow-deep));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--gold-light);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 11.5px;
  letter-spacing: 0.5px;
  text-align: center;
  padding: 12px;
  position: relative;
}
.city-illustration::after {
  content: '';
  position: absolute;
  inset: 6px;
  border: 1px solid rgba(232, 194, 90, 0.4);
  border-radius: 6px;
  pointer-events: none;
}
.city-illustration .muted { color: rgba(232, 194, 90, 0.65); font-size: 10.5px; }

/* --- Texte biblique ---------------------------------------------------- */

.scripture {
  background: var(--parchment-light);
  border: 2px solid var(--gold);
  border-radius: var(--radius);
  padding: 18px 16px;
  margin-bottom: 12px;
}

.verse {
  margin: 0 0 10px;
  font-size: 15px;
  line-height: 1.75;   /* lecture longue : on aère */
  text-align: left;
}
.verse:last-child { margin-bottom: 0; }

.verse-number {
  display: inline-block;
  min-width: 1.6em;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 11px;
  font-weight: 700;
  /* Sur le parchemin clair de `.scripture`, le doré ordinaire ne donnait
     que 3,07 pour 1 — insuffisant à 11 px, et c'est l'écran le plus lu de
     toute l'application. */
  color: var(--gold-text);
  vertical-align: baseline;
}

/* --- Questionnaire ----------------------------------------------------- */

.quiz-progress {
  display: flex;
  gap: 6px;
  justify-content: center;
  margin-bottom: 16px;
}
.quiz-pip {
  width: 26px;
  height: 5px;
  border-radius: 3px;
  background: rgba(184, 134, 11, 0.28);
}
.quiz-pip.is-past    { background: var(--forest); }
.quiz-pip.is-current { background: var(--gold); box-shadow: 0 0 0 2px rgba(184, 134, 11, 0.25); }

.quiz-statement {
  display: block;
  width: 100%;
  padding: 0 0 14px;
  font-family: 'Merriweather', Georgia, serif;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.5;
  color: var(--ink);
}

/* Réponses : cibles larges, pensées pour le pouce sur un téléphone. */
.quiz-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: var(--parchment-light);
  border: 2px solid var(--gold);
  border-radius: var(--radius);
  padding: 13px 14px;
  margin-bottom: 10px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.quiz-option:hover { background: #fffdf5; }

/* Le bouton radio natif est remplacé par une pastille dessinée, mais reste
   présent et focusable : la navigation au clavier continue de fonctionner. */
.quiz-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.quiz-option-text {
  position: relative;
  padding-left: 30px;
  font-size: 14.5px;
  line-height: 1.5;
}
.quiz-option-text::before {
  content: '';
  position: absolute;
  left: 0;
  top: 2px;
  width: 19px;
  height: 19px;
  border: 2px solid var(--gold);
  border-radius: 50%;
  background: var(--parchment);
}
.quiz-option:has(input:checked) {
  background: var(--forest);
  border-color: var(--gold-light);
  color: var(--parchment);
}
.quiz-option:has(input:checked) .quiz-option-text::before {
  background: var(--gold-light);
  box-shadow: inset 0 0 0 3px var(--forest);
}
.quiz-option:has(input:focus-visible) {
  outline: 3px solid var(--burgundy);
  outline-offset: 2px;
}

.quiz-form .btn { margin-top: 4px; }

/* --- Correction --------------------------------------------------------- */

.verdict {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border: 2px solid var(--gold);
  border-left-width: 6px;
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 16px;
  background: var(--parchment-light);
}
.verdict.is-correct { border-left-color: var(--forest); }
.verdict.is-wrong   { border-left-color: var(--danger); }

.verdict-mark {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  font-weight: 700;
  color: var(--parchment);
}
.verdict.is-correct .verdict-mark { background: var(--forest); }
.verdict.is-wrong   .verdict-mark { background: var(--danger); }

.verdict-text { margin: 0; font-size: 14px; line-height: 1.55; }

/* Le verset gagné : mis en avant, c'est la récompense de la bonne réponse. */
.scripture-highlight {
  border-width: 3px;
  border-style: double;
  box-shadow: 0 0 0 3px rgba(184, 134, 11, 0.12);
}
.verse-reference {
  margin: 12px 0 0;
  text-align: right;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 11.5px;
  letter-spacing: 0.5px;
  color: var(--burgundy);
}

/* --- Route des villes -------------------------------------------------- */

.route { display: flex; align-items: center; gap: 4px; }

/* Les pastilles accessibles sont des liens : on neutralise le style de
   lien pour qu'elles restent des pastilles. */
a.city-node { text-decoration: none; }
a.city-node:hover { filter: brightness(1.12); }

.city-names {
  display: flex;
  justify-content: space-between;
  gap: 6px;
  font-size: 9.5px;
  color: var(--ink-soft);
  margin-top: 6px;
}
.city-names span { flex: 1; text-align: center; }
.city-names span:first-child { text-align: left; }
.city-names span:last-child  { text-align: right; }
.city-names span:only-child  { text-align: center; }
.city-node {
  width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Cinzel', Georgia, serif; font-size: 12px; font-weight: 700;
  flex-shrink: 0;
}
.city-node.done    { background: var(--forest); color: var(--parchment); border: 2px solid var(--gold-light); }
.city-node.current { background: var(--gold); color: var(--shadow-deep); border: 2px solid var(--burgundy);
                     box-shadow: 0 0 0 4px rgba(184, 134, 11, 0.25); }
/* Une ville verrouillée reste éteinte, mais son NUMÉRO doit se lire : le
   participant s'en sert pour se situer sur la route. L'ancien gris sur
   gris ne donnait que 2,06 pour 1. */
.city-node.locked  { background: #b7ab8c; color: #413a2c; border: 2px solid #9c9070; }
.connector { flex: 1; height: 3px;
             background: repeating-linear-gradient(90deg, var(--gold) 0 6px, transparent 6px 10px); }

/* --- Pied de page ---------------------------------------------------- */

.shell-footer {
  text-align: center;
  padding: 14px 18px 20px;
  padding-bottom: max(20px, env(safe-area-inset-bottom));
  border-top: 1px solid rgba(184, 134, 11, 0.35);
}

.muted { color: var(--ink-soft); font-size: 12px; }

.stack > * + * { margin-top: 12px; }
.text-center { text-align: center; }

/* --- Classes utilitaires ---------------------------------------------
   AUCUN attribut style="" dans les gabarits : la politique de sécurité
   de contenu déclare `style-src 'self'` sans 'unsafe-inline', ce qui
   fait purement et simplement ignorer les styles en ligne par le
   navigateur. Un espacement posé en ligne disparaît donc en production
   alors qu'il s'affiche dans un aperçu sans en-tête CSP — panne
   silencieuse et difficile à relier à sa cause.
   Tout ce qui suit remplace ces styles en ligne.                        */

.frame-text { margin: 0; font-size: 13.5px; }
.frame-text + .frame-text { margin-top: 8px; }
.frame-note { margin: 10px 0 0; }
.frame-quote { margin: 0; font-style: italic; }

.link-row  { margin-top: 18px; }
.link-note { margin-top: 10px; font-style: italic; }

.footer-username { margin: 4px 0 0; }

/* Un fieldset apporte bordure et marges propres au navigateur : on les
   neutralise pour qu'il se comporte comme les autres champs. */
.fieldset-reset { border: 0; padding: 0; margin-inline: 0; }

.field-legend {
  padding: 0;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  color: var(--burgundy);
  margin-bottom: 6px;
}

/* --- Prologue --------------------------------------------------------- */

/* Première phrase du récit : posée comme une inscription gravée, pour
   marquer l'entrée dans la fiction avant le premier paragraphe courant. */
.prologue-opening {
  margin: 0 0 12px;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.45;
  color: var(--burgundy);
  text-align: center;
}

.prologue-closing {
  margin: 18px 0;
  font-family: 'MedievalSharp', 'Cinzel', Georgia, serif;
  font-size: 19px;
  color: var(--burgundy);
  text-align: center;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
}

/* Filets dorés de part et d'autre de la phrase de clôture. */
.prologue-closing::before,
.prologue-closing::after {
  content: '';
  display: block;
  width: 90px;
  height: 1px;
  margin: 10px auto;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}

/* Lien de relecture, discret sous le tableau de bord. */
.story-link {
  display: block;
  margin-top: 16px;
  text-align: center;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 12px;
  letter-spacing: 0.5px;
  color: var(--ink-soft);
}

/* --- Écran d'accueil non connecté ------------------------------------ */

/* Emblème d'accueil : l'icône de l'application elle-même, plutôt qu'un
   caractère emoji dont le dessin varie d'un système à l'autre — et dont
   les glyphes de porte disponibles évoquent tous d'autres cultures. */
.landing-emblem {
  display: block;
  width: 96px;
  height: 96px;
  margin: 6px auto 16px;
  border-radius: 22px;
  box-shadow: 0 6px 18px rgba(36, 21, 5, 0.35);
}

.landing-crest {
  width: 96px;
  height: 96px;
  margin: 6px auto 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f4d78a, var(--gold) 68%, #7a5a12);
  border: 3px solid var(--gold-light);
  box-shadow: 0 6px 18px rgba(36, 21, 5, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'MedievalSharp', 'Cinzel', Georgia, serif;
  font-size: 44px;
  color: var(--shadow-deep);
}

/* --- Cinzel, hébergé dans le projet ------------------------------------
   Les titres — et le splash, qui s'affiche à chaque ouverture y compris
   sans réseau — ne doivent pas dépendre d'un serveur tiers. Les deux
   graisses réellement utilisées, et elles seules.

   `swap` : le texte s'affiche immédiatement dans la police de repli puis
   bascule. Sur le splash, mieux vaut un titre en Georgia pendant 80 ms
   qu'un titre absent.

   Si les fichiers ne sont pas déposés, le navigateur retombe sur Georgia,
   exactement comme aujourd'hui hors ligne — et le gabarit continue alors
   de demander Cinzel à Google. */

@font-face {
  font-family: 'Cinzel';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/cinzel-500.woff2') format('woff2');
}

@font-face {
  font-family: 'Cinzel';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/cinzel-700.woff2') format('woff2');
}

@font-face {
  font-family: 'MedievalSharp';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/medievalsharp-400.woff2') format('woff2');
}

/* Le corps de texte. C'est la famille la plus lourde du projet, et de
   loin — voir le LISEZ-MOI du dossier : les fichiers déposés couvrent
   tous les alphabets, là où le seul latin suffirait. */
@font-face {
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/merriweather-400.woff2') format('woff2');
}

@font-face {
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/merriweather-700.woff2') format('woff2');
}

/* --- Écran de démarrage ------------------------------------------------
   Masqué par défaut. `splash.js` pose `splash-actif` sur <html> avant
   l'analyse du corps, au seul démarrage à froid : le splash est donc
   correctement stylé dès sa première peinture, et ne clignote jamais sur
   une navigation interne. */

.splash { display: none; }

html.splash-actif .splash {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--shadow-deep);
  opacity: 1;
}

/* Le corps ne défile pas derrière le splash : un doigt posé pendant
   l'attente ferait sinon défiler une page qu'on ne voit pas encore. */
html.splash-actif body { overflow: hidden; }

html.splash-actif .splash.est-sortant {
  opacity: 0;
  transition: opacity 420ms ease-out;
  pointer-events: none;
}

.splash-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Le voile garantit la lisibilité du titre quel que soit ce que montre
   l'image à cet endroit — un ciel clair comme une zone chargée. */
.splash-voile {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 42%;
  background: linear-gradient(
    to top,
    var(--shadow-deep) 0%,
    rgba(36, 21, 5, 0.86) 32%,
    rgba(36, 21, 5, 0.45) 66%,
    rgba(36, 21, 5, 0) 100%
  );
}

/* Titre et sous-titre forment un bloc : le second se pose sous le premier
   sans que la position du groupe ne dépende du fait qu'il soit là ou non —
   une campagne sans sous-titre garde exactement le cadrage d'avant. */
.splash-texte {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 13%;
  text-align: center;
}

.splash-titre {
  margin: 0;
  font-family: 'Cinzel', Georgia, serif;
  font-weight: 700;
  font-size: clamp(26px, 7.5vw, 40px);
  letter-spacing: 2px;
  line-height: 1.25;
  color: var(--gold-light);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.75);
}

/* --- Sous-titre du splash : une ligne, toujours ------------------------
   Le texte vient de la campagne (`campaigns.splash_subtitle`) : il change
   à chaque édition, et sa longueur avec lui. Trois règles se combinent
   pour qu'il ne se replie jamais, quelle que soit cette longueur et quelle
   que soit la largeur de l'écran :

     1. `white-space: nowrap` interdit le repli. Seul, il ferait déborder
        un texte trop long au lieu de le replier — d'où les deux suivantes.
     2. La taille suit la longueur, par paliers posés en PHP (`est-court`,
        `est-moyen`, `est-long` — voir partials/splash.php). Les valeurs en
        `vw` sont calculées pour que le palier le plus défavorable tienne
        encore dans 320 px de large, la plus petite largeur réelle.
     3. `text-overflow: ellipsis` est le filet : si un texte échappait
        malgré tout aux paliers, il serait tronqué sur une ligne plutôt que
        de casser la mise en page. Il ne devrait jamais se déclencher, la
        saisie étant plafonnée à 48 caractères côté admin.

   Merriweather et non Cinzel : la famille du corps de texte est nettement
   plus étroite à taille égale — le sous-titre y gagne trois à quatre
   pixels de corps sur un téléphone — et l'écart de dessin avec le titre
   dit d'un coup d'œil lequel des deux est le titre. */
.splash-sous-titre {
  margin: 10px 0 0;
  font-family: 'Merriweather', Georgia, serif;
  font-weight: 400;
  letter-spacing: 0.5px;
  line-height: 1.3;
  color: var(--parchment-dark);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.8);

  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Jusqu'à 22 caractères — « Camp Lomé 2026 ». */
.splash-sous-titre.est-court { font-size: clamp(12px, 6.2vw, 18px); }

/* 23 à 34 — « Camp Lomé 2026 - JAD Antenne-Ville ». */
.splash-sous-titre.est-moyen { font-size: clamp(10px, 4.1vw, 16px); }

/* 35 à 48, la limite de saisie. Mesuré sur des libellés réels de 48
   caractères : 259 px occupés pour 280 disponibles en 320 px de large. La
   marge restante absorbe l'écart entre Merriweather et la Georgia de
   repli, pas une chaîne de 48 majuscules — celle-là, le filet
   `text-overflow` s'en charge. */
.splash-sous-titre.est-long  { font-size: clamp(9px, 3vw, 14px); }

/* --- Route des villes, hors ligne --------------------------------------
   Le tableau de bord reconstruit par la coquille. Volontairement plus
   sobre que sa version en ligne : il annonce un état daté, il ne doit pas
   avoir l'air d'un écran vivant. */

.offline-route { list-style: none; margin: 16px 0 0; padding: 0; }

.offline-ville {
  border: 1px solid rgba(184, 134, 11, 0.35);
  border-radius: 8px;
  background: var(--parchment-light);
  margin-bottom: 6px;
}

/* Le contenu de la carte : un lien pour la ville en cours, un simple
   conteneur pour les autres. Même mise en forme dans les deux cas, pour
   que la liste garde un rythme régulier. */
.offline-lien {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  text-decoration: none;
  color: inherit;
}

/* Seule la ville en cours réagit : curseur, survol, et une chevrure qui
   annonce qu'il y a quelque chose derrière. Les autres cartes n'ont ni
   curseur ni cible — le clic n'ouvrirait rien, leur chapitre n'étant pas
   en cache. */
.offline-ville.est-cliquable { cursor: pointer; }
.offline-ville.est-cliquable:hover { background: var(--parchment-dark); }
.offline-ville.est-cliquable:focus-within {
  outline: 3px solid var(--burgundy);
  outline-offset: 2px;
}

.offline-fleche {
  flex: 0 0 auto;
  font-size: 20px;
  line-height: 1;
  color: var(--burgundy);
}

.offline-rang {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 11px;
  font-weight: 700;
  background: var(--parchment-dark);
  color: var(--ink);
}

.offline-corps { flex: 1; min-width: 0; }
.offline-nom {
  display: block;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 13.5px;
  color: var(--burgundy);
}
.offline-etat { display: block; font-size: 11.5px; color: var(--ink-soft); }

.offline-ville.est-franchie .offline-rang { background: var(--forest); color: var(--parchment); }
.offline-ville.est-courante { border-color: var(--burgundy); border-width: 2px; }
.offline-ville.est-courante .offline-rang { background: var(--gold); color: var(--shadow-deep); }
.offline-ville.est-en-attente .offline-rang { background: var(--navy); color: var(--parchment); }
.offline-ville.est-a-venir { opacity: 0.7; }

/* --- Programme du camp -------------------------------------------------
   Horaires réels, identiques pour tous. La journée en cours se distingue
   par son cadre, les activités passées par leur pâleur : on doit repérer
   « où en est-on » sans lire les heures une à une. */

.programme-jour { margin-bottom: 20px; }

.programme-date {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 14px;
  color: var(--burgundy);
  margin: 0 0 8px;
  padding-bottom: 5px;
  border-bottom: 1px solid rgba(184, 134, 11, 0.35);
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.programme-marque {
  font-family: 'Merriweather', Georgia, serif;
  font-size: 10.5px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  background: var(--burgundy);
  color: var(--parchment);
  border-radius: 10px;
  padding: 2px 9px;
}

.programme-jour.est-aujourdhui {
  border: 2px solid var(--gold);
  border-radius: var(--radius);
  background: var(--parchment-light);
  padding: 12px;
}

.programme-liste { list-style: none; margin: 0; padding: 0; }

.programme-activite {
  display: flex;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid rgba(184, 134, 11, 0.2);
}
.programme-activite:last-child { border-bottom: none; }
/* Une activité passée reste lisible : on la consulte encore pour se
   repérer, elle ne doit pas disparaître. */
.programme-activite.est-passee { opacity: 0.55; }

.programme-heure {
  flex: 0 0 auto;
  min-width: 52px;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 14px;
  color: var(--burgundy);
  text-align: right;
}
.programme-fin { font-size: 10.5px; color: var(--ink-soft); }

.programme-corps { flex: 1; min-width: 0; }
.programme-titre { display: block; font-size: 14px; color: var(--ink); }
.programme-lieu { display: block; font-size: 12px; color: var(--ink-soft); }
.programme-detail { display: block; font-size: 12px; color: var(--ink-soft); font-style: italic; }

/* --- Fil de discussion -------------------------------------------------
   Sur le parchemin clair de la coquille, comme les cartes de compagnons :
   fond clair, cadre doré, texte sombre. */

.fil { list-style: none; margin: 16px 0; padding: 0; }

.fil-message {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--parchment-light);
  border: 1px solid rgba(184, 134, 11, 0.35);
  border-radius: 10px;
}

/* Ses propres messages se repèrent d'un coup d'œil dans un fil long. */
.fil-message.est-mien {
  border-color: var(--gold);
  border-left-width: 4px;
  background: var(--parchment-dark);
}

.fil-medaillon {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 35% 30%, #f4d78a, var(--gold) 70%, #7a5a12);
  color: var(--shadow-deep);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 15px;
}

.fil-corps { flex: 1; min-width: 0; }

.fil-entete {
  margin: 0 0 4px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.fil-auteur {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 13px;
  color: var(--burgundy);
}
.fil-date { font-size: 11px; color: var(--ink-soft); }

/* `word-break` : un mot de deux cents caractères collé sans espace ne doit
   pas élargir la coquille et faire défiler la page en travers. */
.fil-texte {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
  overflow-wrap: anywhere;
}

/* Le signalement est discret à dessein : c'est un recours, pas une action
   courante. Trop visible, il invite au clic ; caché, il ne sert à rien. */
.fil-signalement { margin: 6px 0 0; }
.fil-signaler {
  background: none;
  border: none;
  padding: 0;
  font-family: 'Merriweather', Georgia, serif;
  font-size: 11.5px;
  color: var(--ink-soft);
  text-decoration: underline;
  cursor: pointer;
}
.fil-signaler:hover { color: var(--danger); }
.fil-signale-note { margin: 6px 0 0; font-size: 11.5px; color: var(--ink-soft); font-style: italic; }

/* La pagination encadre le fil : « plus anciens » au-dessus, « plus
   récents » en dessous, le repère au milieu. On arrive sur la dernière
   page, donc le second bouton manque le plus souvent. */
.fil-pages { margin: 14px 0; }
.fil-pages > * + * { margin-top: 8px; }

.fil-saisie {
  width: 100%;
  font-family: 'Merriweather', Georgia, serif;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--parchment-light);
  border: 2px solid var(--gold);
  border-radius: 8px;
  padding: 10px;
  resize: vertical;
}

/* --- Compagnons de route ---------------------------------------------- */

.compagnons { list-style: none; margin: 16px 0 0; padding: 0; }

.compagnon { margin-bottom: 8px; }

/* La coquille est en PARCHEMIN CLAIR : le dégradé sombre du fond de page
   ne s'étend pas sous elle, il n'est visible qu'en marge sur grand écran.
   Cette carte avait été écrite pour une surface sombre qui n'existe pas
   ici — d'où un nom à 1,11 pour 1, illisible. Elle suit maintenant le même
   parti que `.scripture` et `.ornate-frame.is-light` : fond clair, cadre
   doré, texte sombre. */
.compagnon-lien {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  text-decoration: none;
  color: var(--ink);
  background: var(--parchment-light);
  border: 2px solid var(--gold);
  border-radius: 10px;
}
.compagnon-lien:hover { background: var(--parchment-dark); }

.compagnon-medaillon {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 35% 30%, #f4d78a, var(--gold) 70%, #7a5a12);
  color: var(--shadow-deep);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 17px;
}

.compagnon-corps { flex: 1; min-width: 0; }

/* Même bourgogne que `.section-title` : c'est la couleur des titres sur
   fond clair dans toute la maquette. */
.compagnon-nom {
  display: block;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 14px;
  color: var(--burgundy);
}
/* Une profession longue ne doit pas pousser le compteur hors du cadre. */
.compagnon-metier {
  display: block;
  font-size: 12px;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compagnon-villes {
  flex: 0 0 auto;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 18px;
  color: var(--burgundy);
}

.recompenses { list-style: none; margin: 8px 0 0; padding: 0; }
.recompenses li { padding: 3px 0; font-size: 13.5px; }

/* --- Préférences système --------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  /* Le splash disparaît alors d'un coup. `splash.js` retire la classe sur
     un délai et non sur `transitionend`, qui ne se déclencherait pas. */
}

@media print {
  body { background: #fff; }
  .app-shell { border: none; box-shadow: none; }
  .btn, .copy-btn, .topbar { display: none; }
}
