:root {
  /* Sans cette ligne, le navigateur dessine ses propres widgets — champs qu'il
     remplit tout seul, menus déroulants, ascenseurs — en clair quel que soit le
     thème, et son blanc se retrouve sous notre texte clair. */
  color-scheme: light;
  --bg: #f6f5f2;
  --panel: #ffffff;
  --panel-2: #faf9f7;
  --border: #e2ded6;
  --text: #22201d;
  --muted: #746d63;
  --accent: #8a5a2b;
  --accent-soft: #f0e6da;
  --danger: #a33a2c;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 8px 24px rgba(0, 0, 0, 0.04);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg: #17161a;
    --panel: #1f1e23;
    --panel-2: #26252b;
    --border: #35333b;
    --text: #eceaf0;
    --muted: #a09aa8;
    --accent: #d2a06a;
    --accent-soft: #33291f;
    --danger: #e0736a;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.25);
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Les noms viennent de l'utilisateur : un mot de cinquante lettres sans
     espace ne doit pas pouvoir élargir la page. « anywhere » plutôt que
     « break-word » parce que seul le premier entre dans le calcul de la
     largeur minimale du contenu — celle dont les grilles refusent de
     descendre, et qui poussait toute la page. */
  overflow-wrap: anywhere;
}

.hidden {
  display: none !important;
}

/* ---------------------------------------------------------- Connexion */

.login {
  display: grid;
  place-items: center;
  min-height: 100vh;
  /* 100vh compte la barre d'adresse du téléphone comme si elle n'existait
     pas : la page dépasse toujours d'autant. dvh mesure ce qu'on voit. */
  min-height: 100dvh;
  padding: 24px;
}

.login-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 32px;
  width: min(400px, 100%);
  display: grid;
  gap: 12px;
}

.login-card h1 {
  margin: 0;
  font-size: 22px;
}

.login-card p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}

/* ---------------------------------------------------------- Structure */

.app {
  display: grid;
  grid-template-columns: 264px 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

/* Un élément de grille refuse par défaut de descendre sous la largeur de son
   contenu. Un tableau un peu large poussait donc la colonne, qui poussait la
   page : elle partait en travers au lieu de laisser la carte défiler seule.
   Même piège pour les deux colonnes liste / fiche. */
.app > *,
.split > * {
  min-width: 0;
}

.sidebar {
  background: var(--panel);
  border-right: 1px solid var(--border);
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand-mark {
  font-size: 24px;
}

.brand strong {
  display: block;
  font-size: 15px;
}

.brand small {
  color: var(--muted);
  font-size: 12px;
}

.story-picker {
  display: grid;
  gap: 8px;
}

.story-picker label,
.field label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

nav {
  display: grid;
  gap: 2px;
}

/* Le menu déroulant ne sert qu'au téléphone : sur un grand écran, la liste
   verticale montre les seize écrans d'un seul coup d'œil. */
.nav-select {
  display: none;
}

nav button {
  all: unset;
  cursor: pointer;
  padding: 9px 12px;
  border-radius: 8px;
  font-size: 14px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}

nav button:hover {
  background: var(--panel-2);
}

nav button.active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

nav button .count {
  font-size: 12px;
  color: var(--muted);
}

.current-story {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 12px;
  padding: 8px 10px;
  border: 1px dashed var(--border);
  border-radius: 8px;
}

.meta.ok {
  color: var(--accent);
}

.meta.warn-text {
  color: var(--danger);
}

.sidebar-footer {
  margin-top: auto;
  display: grid;
  gap: 6px;
}

/* Sur grand écran, ces actions tiennent sans gêner : le panneau est la barre
   elle-même, et le bouton « ⋯ » n'a pas lieu d'être. */
.actions-menu-bouton {
  display: none;
}

.actions-menu-panel {
  display: grid;
  gap: 6px;
}

main {
  padding: 32px 40px 80px;
  max-width: 1600px;
  width: 100%;
  margin-inline: auto;
}

/* Un champ d'une seule ligne n'a pas besoin de mille pixels. Au-delà, l'œil
   perd le début de la ligne en arrivant au bout, et la carte paraît vide sur
   sa droite — c'est ce qui donnait l'impression que tout était entassé à
   gauche à l'intérieur même des cartes. Les grilles et les rangées ne sont
   pas concernées : elles se partagent déjà la largeur. */
.card > .field > input,
.card > .field > select,
.card > .field > .row > input,
.card > .field > .row > select {
  max-width: 640px;
}

/* Un texte se lit mal au-delà d'une certaine longueur de ligne : on garde une
   mesure confortable plutôt que d'étirer jusqu'au bord. */
.card > .field > textarea,
.card > .field > .markdown-preview {
  max-width: 76ch;
}

/* Sur un grand écran, les champs d'une carte se rangent en colonnes au lieu
   de s'empiler sur une seule. Tout ce qui n'est pas un champ — titre, texte
   d'explication, tableau, rangée de boutons — garde la largeur entière. */
@media (min-width: 1200px) {
  /* Seulement les cartes qui ont PLUSIEURS champs : sur une carte qui n'en a
     qu'un, la grille laisserait ce champ dans un quart de la largeur et trois
     quarts de vide à côté. « .field ~ .field » ne vaut qu'à partir du second. */
  .card:has(.field ~ .field) {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    column-gap: 28px;
    align-content: start;
  }

  .card:has(.field ~ .field) > *:not(.field) {
    grid-column: 1 / -1;
  }

  /* Sans cela, un champ dont le voisin porte une explication s'étire en
     hauteur pour s'aligner sur lui : deux champs identiques n'auraient pas
     la même taille selon ce qui se trouve à côté. */
  .card:has(.field ~ .field) > .field {
    align-content: start;
  }

  .card:has(.field ~ .field) > .field > input,
  .card:has(.field ~ .field) > .field > select,
  .card:has(.field ~ .field) > .field > textarea {
    max-width: none;
  }

  /* L'encadré du caractère est un bloc à part, pas un champ : ses propres
     champs s'étiraient donc sur toute la largeur. Même remède. */
  .profile-box {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    column-gap: 28px;
    align-content: start;
  }

  .profile-box > *:not(.field) {
    grid-column: 1 / -1;
  }

  .profile-box > .field {
    align-content: start;
  }
}

/* ---------------------------------------------------------- Éléments communs */

h1 {
  font-size: 26px;
  margin: 0 0 4px;
}

h2 {
  font-size: 18px;
  margin: 0 0 12px;
}

h3 {
  font-size: 15px;
  margin: 0;
}

.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}

.subtitle {
  color: var(--muted);
  font-size: 14px;
  margin: 0;
  max-width: 62ch;
}

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 16px;
}

.card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}

/* Un titre de fiche porte un nom saisi par l'utilisateur : c'est lui qui cède
   la place, jamais la largeur de la page. Les boutons, eux, portent des
   libellés écrits par l'application : ils gardent leur largeur. */
.card-head > * {
  min-width: 0;
}

.card-head > .row {
  flex: 0 0 auto;
}

/* La fiche d'un élément fait plusieurs écrans : ses boutons restent visibles. */
.card-head.sticky-head {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--panel);
  padding: 14px 0 12px;
  margin-top: -14px;
  border-bottom: 1px solid var(--border);
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
}

.field {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 5px;
  margin-bottom: 14px;
}

.field .hint {
  font-size: 12px;
  color: var(--muted);
}

input,
select,
textarea,
button {
  font: inherit;
  color: inherit;
}

/* Énumérer les types un par un avait laissé le champ « Adresse e-mail »
   dehors : il gardait le fond blanc du navigateur sous la couleur du thème,
   soit du gris clair sur du blanc en thème sombre. On désigne donc tous les
   champs de saisie, et l'on retire les deux qui doivent rester des cases. */
input:not([type="checkbox"]):not([type="radio"]),
select,
textarea {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 11px;
  width: 100%;
}

/* Le texte d'exemple doit rester lisible sans se faire prendre pour une
   valeur saisie. */
input::placeholder,
textarea::placeholder {
  color: var(--muted);
  opacity: 1;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

textarea {
  resize: vertical;
  min-height: 90px;
  line-height: 1.6;
}

button {
  /* Le corps autorise la coupure d'un mot très long, parce que les noms
     viennent de l'utilisateur. Un libellé de bouton, lui, est écrit par
     l'application : « Enregistrer » n'a pas à devenir « Enregistr / er ». */
  overflow-wrap: normal;
  background: var(--accent);
  color: #fff;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 9px 14px;
  cursor: pointer;
  font-weight: 500;
}

button:hover {
  filter: brightness(1.08);
}

button.ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}

button.ghost:hover {
  background: var(--panel-2);
  filter: none;
}

button.small {
  padding: 6px 10px;
  font-size: 13px;
}

button.danger {
  color: var(--danger);
  border-color: var(--border);
  background: transparent;
}

button.danger:hover {
  background: var(--panel-2);
}

button.danger-solid {
  background: var(--danger);
  color: #fff;
  border-color: transparent;
}

.row {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

/* ---------------------------------------------------------- Boîtes de dialogue */

.dialog-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(0, 0, 0, 0.45);
  display: grid;
  place-items: center;
  padding: 20px;
}

.dialog-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 22px;
  width: min(460px, 100%);
  max-height: 90vh;
  max-height: 90dvh;
  overflow-y: auto;
}

.dialog-card h2 {
  margin-bottom: 6px;
}

.dialog-card .subtitle {
  margin-bottom: 16px;
}

.dialog-card .field:last-of-type {
  margin-bottom: 0;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}

.toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.toolbar input[type="text"],
.toolbar select {
  width: auto;
  min-width: 160px;
  flex: 1 1 160px;
}

.result-count {
  color: var(--muted);
  font-size: 13px;
  white-space: nowrap;
  align-self: center;
}

.tag {
  display: inline-block;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 100px;
  padding: 2px 9px;
  font-size: 12px;
  font-weight: 500;
}

.pill {
  display: inline-block;
  border: 1px solid var(--border);
  border-radius: 100px;
  padding: 2px 9px;
  font-size: 12px;
  color: var(--muted);
}

.empty {
  color: var(--muted);
  font-size: 14px;
  padding: 24px;
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

.error {
  color: var(--danger);
  font-size: 13px;
  margin: 0;
}

/* ---------------------------------------------------------- Listes */

.split {
  display: grid;
  grid-template-columns: minmax(240px, 320px) 1fr;
  gap: 16px;
  align-items: start;
}

/* La piste d'une grille refuse par défaut de descendre sous la largeur
   minimale de son contenu. Le résumé d'une fiche étant en « nowrap », cette
   largeur minimale est celle du résumé entier : une fiche au nom ou au résumé
   un peu long faisait 561 px dans une colonne de 362, poussait la liste, la
   colonne, puis la page — qui partait alors en travers. « minmax(0, 1fr) »
   rend à la piste le droit de rétrécir, et l'ellipsis retrouve son rôle. */
.list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
  max-height: 70vh;
  overflow-y: auto;
}

.list-item {
  all: unset;
  cursor: pointer;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  display: grid;
  gap: 2px;
  /* Après « all: unset », il faut redire que cet élément a le droit de
     rétrécir : sans quoi il s'étale à la largeur de son résumé en « nowrap ». */
  min-width: 0;
}

.list-item:hover {
  border-color: var(--accent);
}

.list-item.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.list-item .name {
  font-weight: 600;
  font-size: 14px;
}

.list-item .meta {
  font-size: 12px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------------------------------------------------------- Attributs libres */

.attributes {
  display: grid;
  gap: 6px;
}

.attribute-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 2fr auto;
  gap: 6px;
  align-items: center;
}

/* ---------------------------------------------------------- Structure narrative */

.tree {
  display: grid;
  gap: 6px;
}

.tree-node {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  padding: 10px 12px;
}

.tree-children {
  margin-left: 22px;
  margin-top: 6px;
  display: grid;
  gap: 6px;
  border-left: 2px solid var(--border);
  padding-left: 12px;
}

.tree-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

/* ---------------------------------------------------------- Divers */

pre.code {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre;
  margin: 0 0 10px;
}

.markdown-preview {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 16px;
  max-height: 60vh;
  overflow-y: auto;
  white-space: pre-wrap;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.6;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

th,
td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.steps {
  padding-left: 20px;
  margin: 0;
  display: grid;
  gap: 10px;
}

.steps li {
  padding-left: 4px;
}

.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  padding: 10px 18px;
  border-radius: 100px;
  font-size: 14px;
  box-shadow: var(--shadow);
  z-index: 50;
}

.toast.error {
  background: var(--danger);
  color: #fff;
}

/* ---------------------------------------------------------- Rangs d'importance */

.rank {
  /* « body { overflow-wrap: anywhere } » coupe les mots partout ; dans une
     etiquette de dix caracteres ca donne « Secondair / e ». Elle reste donc
     entiere, quitte a passer a la ligne suivante. */
  white-space: nowrap;
  overflow-wrap: normal;
  display: inline-block;
  border-radius: 100px;
  padding: 1px 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  margin-left: 6px;
  border: 1px solid transparent;
  vertical-align: middle;
}

.rank-principal {
  background: var(--accent);
  color: #fff;
}

.rank-secondaire {
  background: var(--accent-soft);
  color: var(--accent);
}

.rank-mineur {
  background: transparent;
  color: var(--muted);
  border-color: var(--border);
}

.rank-mention {
  background: transparent;
  color: var(--muted);
  border-color: transparent;
  font-weight: 400;
  font-style: italic;
}

.list-item .name {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}

.list-item .name > span {
  min-width: 0;
}

/* Une ligne de liste est un bouton, mais son libellé est le nom saisi par
   l'utilisateur : lui, il a le droit de se couper. */
.list-item {
  overflow-wrap: anywhere;
}

.meta-block {
  font-size: 14px;
  color: var(--muted);
  margin-top: 6px;
  white-space: pre-wrap;
}

/* ---------------------------------------------------------- Caractère et scène */

.profile-box {
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 14px;
  background: var(--panel-2);
}

.profile-box h3 {
  margin-bottom: 4px;
  color: var(--accent);
}

.profile-box .hint {
  font-size: 12px;
  color: var(--muted);
  display: block;
  margin-bottom: 12px;
}

.group-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 10px;
  background: var(--panel-2);
}

.group-card .card-head input {
  font-weight: 600;
}

/* Nom, ce qu'il fait, son état, comment il assiste à la scène, depuis quand,
   puis déplacer et retirer. Les deux du milieu disent ce qu'il n'a pas pu
   percevoir : être présent n'est pas avoir tout vu. */
.member-row {
  display: grid;
  grid-template-columns: 1.2fr 1.2fr 0.9fr auto 0.9fr auto auto;
  gap: 6px;
  align-items: center;
  margin-bottom: 6px;
}

.member-row select,
.member-row input {
  min-width: 0;
}

/* Sept contrôles par personnage : ils se rangent deux par deux, le nom seul
   sur sa ligne. Un simple trait sépare les personnages — un cadre complet
   coûterait plus de hauteur qu'il n'en fait gagner. */
/* La jauge de la page « Ce que reçoit l'IA » : un nombre ne dit pas lequel
   ecrase les autres, une barre si. */
.jauge {
  margin-top: 6px;
  height: 6px;
  border-radius: 3px;
  background: var(--border);
  overflow: hidden;
}

.jauge-plein {
  height: 100%;
  background: var(--accent, #6b8afd);
  border-radius: 3px;
}

/* L'envoi groupe de photos. Pense pour un telephone d'abord : c'est de la
   pellicule que viennent les portraits, et la ligne doit rester lisible sur
   une largeur de pouce. */
.photo-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--border);
}

.photo-apercu {
  width: 56px;
  height: 56px;
  border-radius: 8px;
  object-fit: cover;
  flex: none;
  background: var(--border);
}

.photo-ligne input[type="text"] {
  width: 100%;
}

/* Touchee, la photo passe en grand : une vignette de pouce ne suffit pas a
   reconnaitre quelqu'un, et c'est justement ce qu'on demande ici. */
.photo-apercu-grand {
  width: 100%;
  height: auto;
  max-height: 60vh;
  object-fit: contain;
}

@media (max-width: 900px) {
  .member-row {
    grid-template-columns: 1fr 1fr;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
  }

  .member-row > *:first-child {
    grid-column: 1 / -1;
    font-weight: 600;
  }
}

.checkline {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  padding: 8px 0;
}

/* ---------------------------------------------------------- Organigrammes */

.chart-tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.chip {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 100px;
  padding: 6px 14px;
  font-size: 13px;
}

.chip:hover {
  background: var(--panel-2);
  filter: none;
}

.chip.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.link-picker {
  display: grid;
  gap: 4px;
  margin-bottom: 8px;
}

.link-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
}

.link-row:hover {
  background: var(--panel-2);
  border-color: var(--border);
}

.link-row input[type="checkbox"] {
  width: auto;
  margin: 0;
}

.link-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.small-select {
  width: auto;
  font-size: 12px;
  padding: 4px 8px;
}

/* Le schéma peut être plus large que la colonne : il défile seul,
 * la page ne part jamais en travers. */
.chart-canvas {
  overflow-x: auto;
  padding: 4px 0 10px;
}

.chart-svg {
  display: block;
  max-width: none;
}

.chart-box {
  fill: var(--panel-2);
  stroke: var(--border);
  stroke-width: 1.5;
}

.rank-node-principal .chart-box {
  fill: var(--accent-soft);
  stroke: var(--accent);
}

.chart-label {
  fill: var(--text);
  font-size: 13px;
  font-weight: 600;
  text-anchor: middle;
}

.chart-sub {
  fill: var(--muted);
  font-size: 11px;
  text-anchor: middle;
}

.chart-edge {
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.5;
}

.chart-edge.past {
  stroke-dasharray: 4 4;
  opacity: 0.6;
}

.chart-edge.side {
  stroke: var(--accent);
  stroke-width: 2;
}

.chart-node.clickable {
  cursor: pointer;
}

.chart-node.clickable:hover .chart-box {
  stroke: var(--accent);
  stroke-width: 2.5;
}

/* ---------------------------------------------------------- Connaissances */

.acq-form {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 8px;
  align-items: center;
  margin-bottom: 14px;
}

@media (max-width: 700px) {
  .acq-form {
    grid-template-columns: 1fr;
  }
}

.past-row td {
  opacity: 0.65;
}

/* ---------------------------------------------------------- Récits croisés */

.crossover {
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  padding: 12px 14px;
  background: var(--panel-2);
}

.crossover-story + .crossover-story {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.crossover-events {
  margin: 6px 0 0;
  padding-left: 18px;
  font-size: 14px;
  color: var(--muted);
}

.warn {
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid var(--danger);
  border-radius: 8px;
  color: var(--danger);
  font-size: 13px;
}

.checkline input[type="checkbox"] {
  width: auto;
  margin: 0;
}

/* ---------------------------------------------------------- Compte */

/* Qui est connecté, en bas de la barre latérale. Discret : c'est un repère,
   pas une commande qu'on cherche. */
.account-line {
  display: grid;
  gap: 4px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.account-line button {
  justify-content: flex-start;
  gap: 8px;
}

.account-line .count {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 6px;
}

/* Le texte gris qui accompagne une valeur sans lui voler la vedette.
   Existait déjà pour quelques usages précis ; ici pour tous. */
.meta {
  color: var(--muted);
  font-size: 13px;
}

/* Le jeton d'une clé MCP, montré une seule fois : il doit pouvoir se
   sélectionner et se copier sans risque de coupure. */
.dialog-card .code {
  max-height: 140px;
  overflow: auto;
  word-break: break-all;
}

/* Une case à cocher porte une phrase, pas un intitulé de champ : la mettre en
   capitales comme les autres étiquettes rendrait illisible une liste de titres
   d'histoires. */
.field label.checkline {
  text-transform: none;
  letter-spacing: 0;
  font-size: 14px;
  font-weight: 400;
  color: var(--text);
}

/* ---------------------------------------------------------- Plan des lieux */

/* Trois choix sur une ligne : « ce lieu — se trouve dans — cet autre ». La
   phrase se lit d'un trait, ce qui rend le sens de saisie évident. */
.place-form {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 8px;
  align-items: center;
  margin-bottom: 6px;
}

.place-form select {
  min-width: 0;
}

.place-summary {
  display: grid;
  gap: 8px;
  margin-bottom: 12px;
}

.place-line {
  display: grid;
  grid-template-columns: minmax(0, 110px) minmax(0, 1fr);
  gap: 10px;
  align-items: baseline;
}

.place-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.place-line > span:last-child {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.place-pill {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  color: var(--text);
  padding-right: 2px;
}

/* La croix d'effacement vit dans la pastille : elle ne doit ni l'agrandir ni
   se donner l'allure d'un bouton à part entière. */
.place-pill button {
  min-height: 0;
  padding: 0 4px;
  line-height: 1.2;
  color: var(--muted);
  border: 0;
  background: transparent;
}

.place-pill button:hover {
  color: var(--danger);
  background: transparent;
  filter: none;
}

/* ------------------------------------------------- Sections repliables

   La structure est la même à toute taille — sinon déplacer la fenêtre d'un
   écran à l'autre laisserait une mise en page figée. Sur grand écran, une
   section est toujours ouverte : son titre redevient un simple intitulé, qui
   ne réagit pas au clic. */

.card-pliable > summary,
.field-pliable > summary {
  list-style: none;
}

.card-pliable > summary::-webkit-details-marker,
.field-pliable > summary::-webkit-details-marker {
  display: none;
}

@media (min-width: 901px) {
  /* Le titre d'une carte reprend l'allure d'un h2, celui d'un bloc celle
     d'une étiquette de champ. Ni curseur ni repliage : il n'y a rien à
     ouvrir, tout est déjà là. */
  .card-pliable > summary {
    pointer-events: none;
    font-size: 18px;
    font-weight: 600;
    margin: 0 0 12px;
  }

  .field-pliable > summary {
    pointer-events: none;
    font-size: 12px;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 5px;
  }

  /* Le caractère garde son encadré : c'est ce qui le distingue du reste de
     la fiche, et ces champs-là sont ceux qui empêchent l'IA d'intervertir
     les personnalités. */
  .profil-pliable {
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    padding: 16px;
    background: var(--panel-2);
  }

  .profil-pliable > summary {
    font-size: 15px;
    color: var(--accent);
    text-transform: none;
    letter-spacing: 0;
  }

  /* Rien à replier ici : le chevron promettrait une action qui n'existe pas. */
  .card-pliable > summary::after,
  .field-pliable > summary::after {
    content: none;
  }
}

/* ------------------------------------------------- Repliage (téléphone)

   N'existent que sur téléphone : les fonctions « carte » et « bloc » de
   app.js rendent un simple div sur grand écran. */

.card-pliable > summary,
.field-pliable > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 44px;
}

/* Le triangle par défaut du navigateur est minuscule et mal placé : on met le
   nôtre, à droite, et qui pivote quand la section s'ouvre. */
.card-pliable > summary::-webkit-details-marker,
.field-pliable > summary::-webkit-details-marker {
  display: none;
}

.card-pliable > summary::after,
.field-pliable > summary::after {
  content: '⌄';
  font-size: 18px;
  line-height: 1;
  color: var(--muted);
  transition: transform 0.15s;
}

.card-pliable[open] > summary::after,
.field-pliable[open] > summary::after {
  transform: rotate(180deg);
}

.card-pliable > summary {
  font-size: 18px;
  font-weight: 600;
}

/* Un bloc replié tient sur sa ligne ; ouvert, il se détache du suivant. */
.field-pliable {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 12px;
  margin-bottom: 8px;
}

.field-pliable > summary {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.field-pliable[open] {
  padding-bottom: 12px;
}

.field-pliable[open] > summary {
  border-bottom: 1px solid var(--border);
  margin-bottom: 10px;
}

/* Une carte repliée ne garde pas la hauteur d'une carte ouverte. */
.card-pliable:not([open]) {
  padding-top: 12px;
  padding-bottom: 12px;
}

/* ------------------------------------------------ Activité de l'assistant */

.activite {
  font-size: 11px;
  line-height: 1.4;
  margin-top: 6px;
}

.activite:empty {
  display: none;
}

/* Ce bandeau se lit quand on se demande ce que fabrique l'assistant : il doit
   mener a la reponse, pas seulement l'annoncer. La cible est large — c'est un
   texte de 11 px, sur un telephone, avec un pouce. */
.activite-lien {
  cursor: pointer;
  padding: 4px 0;
}

.activite-fleche {
  text-decoration: underline;
  white-space: nowrap;
}

/* ---------------------------------------------------------- Carte d'identité */

.identite {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  padding: 16px 0 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}

.identite-media {
  display: grid;
  gap: 8px;
  justify-items: center;
  width: 150px;
}

.identite-photo {
  /* La photo est posee en absolu par-dessus : un « height: 100% » dans une
     grille centree ne se resout pas (la hauteur de la rangee depend alors du
     contenu, et le pourcentage n'a plus de reference). L'image sortait donc a
     ses proportions d'origine au lieu d'etre recadree. */
  position: relative;
  width: 150px;
  height: 150px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  overflow: hidden;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: border-color 0.15s, opacity 0.15s;
}

.identite-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.identite-photo.vide {
  border-style: dashed;
}

.identite-photo:hover,
.identite-photo.survolee {
  border-color: var(--accent);
}

/* Pendant l'envoi : l'image pâlit, pour qu'on voie qu'il se passe quelque chose
   sur une connexion lente au lieu de recliquer trois fois. */
.identite-photo.occupee {
  opacity: 0.45;
  pointer-events: none;
}

.identite-initiales {
  font-size: 34px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
}

.identite-media .hint {
  text-align: center;
  font-size: 11px;
}

.identite-actions {
  gap: 6px;
}

.identite-corps {
  display: grid;
  gap: 6px;
  align-content: start;
  min-width: 0;
}

.identite-titre {
  font-size: 17px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

.identite-ligne {
  font-size: 13px;
  display: flex;
  gap: 8px;
  min-width: 0;
}

.identite-label {
  color: var(--muted);
  flex: 0 0 82px;
}

.identite-resume {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
}

.badge {
  font-size: 11px;
  border-radius: 100px;
  padding: 1px 8px;
  border: 1px solid var(--border);
  color: var(--muted);
}

/* La vignette de la liste : deux lignes de texte à droite, l'image à gauche
   sur les deux. Sans photo, la fiche garde exactement sa mise en page. */
.list-item.avec-photo {
  grid-template-columns: 36px minmax(0, 1fr);
  column-gap: 10px;
  align-items: center;
}

.list-item .vignette {
  grid-row: 1 / 3;
  width: 36px;
  height: 36px;
  border-radius: 6px;
  object-fit: cover;
  display: block;
}

/* ------------------------------------------------------ Mode téléphone
 *
 * Mesuré sur un iPhone 13, soit 390 x 664 px utiles : repliée en bandeau, la
 * barre latérale occupait encore 420 px — les deux tiers de l'écran. Chaque
 * page commençait donc sous la ligne de flottaison, avant même son titre.
 *
 * Le bandeau est reconstruit pour tenir en deux fois moins : la marque perd
 * son texte (on sait quelle application on a ouverte), l'étiquette « Histoire »
 * disparaît puisque le menu déroulant porte déjà le nom, et les commandes
 * rares du bas tiennent sur une ligne qui défile au lieu d'une grille qui
 * s'empile. */
@media (max-width: 900px) {
  .app {
    grid-template-columns: 1fr;
  }

  .sidebar {
    position: relative;
    height: auto;
    overflow: visible;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }

  .brand div {
    display: none;
  }

  .brand-mark {
    font-size: 22px;
  }

  .story-picker {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 8px;
  }

  .story-picker > label {
    display: none;
  }

  .current-story {
    grid-column: 1 / -1;
    padding: 6px 9px;
  }

  nav {
    grid-column: 1 / -1;
  }

  /* Une bande d'onglets qu'il faut faire glisser latéralement ne se navigue pas
     au pouce : les onglets des deux bords sont coupés, et rien ne dit combien
     il en reste. Le menu déroulant, lui, s'ouvre en plein écran et montre les
     seize écrans d'un coup. */
  nav {
    display: block;
    overflow: visible;
    padding-bottom: 0;
  }

  nav button {
    display: none;
  }

  .nav-select {
    display: block;
    width: 100%;
    font-weight: 600;
  }

  /* Exporter, supprimer, se déconnecter : on s'en sert une fois par mois. Ces
     boutons n'ont pas à repousser le contenu hors de l'écran à chaque page. */
  /* Ces quatre boutons prenaient deux rangées en haut de chaque écran, et
     « Supprimer l'histoire » se trouvait sous le pouce de qui visait autre
     chose. Ils passent derrière un bouton « ⋯ », qui ne coûte plus une seule
     rangée : le panneau s'ouvre PAR-DESSUS le contenu. */
  .sidebar-footer {
    margin-top: 0;
    display: contents;
  }

  .actions-menu-bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    grid-column: 3;
    grid-row: 1;
    min-width: 44px;
    padding: 0;
    font-size: 20px;
    line-height: 1;
  }

  .actions-menu-panel {
    display: none;
    position: absolute;
    top: 58px;
    right: 12px;
    z-index: 30;
    min-width: 220px;
    padding: 8px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }

  .actions-menu-panel.is-open {
    display: grid;
    gap: 4px;
  }

  .actions-menu-panel button {
    justify-content: flex-start;
    text-align: left;
    white-space: nowrap;
  }

  .account-line {
    display: grid;
    gap: 4px;
    margin: 0 0 4px;
    padding: 0 0 8px;
    border-top: 0;
    border-bottom: 1px solid var(--border);
  }

  /* Le geste irréversible est mis à part, et sous les autres : on ne l'atteint
     pas en visant « Exporter ». */
  #delete-story {
    margin-top: 4px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
    border-radius: 0 0 8px 8px;
  }

  main {
    padding: 18px 14px 60px;
  }

  .card {
    padding: 16px 14px;
  }

  .page-head {
    margin-bottom: 18px;
    gap: 10px;
  }

  h1 {
    font-size: 22px;
  }

  .split {
    grid-template-columns: 1fr;
  }

  /* Une liste qui défile à l'intérieur d'une page qui défile : au doigt, l'une
     mange le geste destiné à l'autre. La liste s'allonge, la page s'en charge. */
  .list {
    max-height: none;
  }

  /* Safari agrandit toute la page dès qu'on touche un champ écrit en moins de
     16 px, et ne la réduit jamais ensuite. */
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  textarea {
    font-size: 16px;
  }

  /* Un doigt ne vise pas comme un pointeur : les cibles mesuraient 34 à 38 px. */
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  button:not(.small):not(.chip),
  nav button,
  .list-item {
    min-height: 44px;
  }

  button.small {
    min-height: 36px;
  }

  /* Quatre personnages font vingt-huit contrôles : à 44 px chacun, l'écran y
     passe. Le nom garde sa cible pleine, les champs qui l'accompagnent se
     contentent de 38. */
  .member-row > *:not(:first-child) {
    min-height: 38px;
  }

  input[type="checkbox"] {
    width: 20px;
    height: 20px;
  }

  /* Six colonnes dans 350 px, ce n'est pas un tableau, c'est une grille de
     mots coupés. Faire défiler la carte sur le côté n'était qu'un pis-aller :
     on ne navigue pas au pouce en balayant à l'horizontale. Chaque ligne
     devient donc une petite fiche, et chaque valeur reprend le nom de sa
     colonne — celui que « data-label » porte. */
  .card table,
  .card thead,
  .card tbody,
  .card tr,
  .card td {
    display: block;
    width: auto;
  }

  .card thead {
    display: none;
  }

  .card tbody tr {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 8px;
  }

  .card tbody td {
    border-bottom: 0;
    padding: 3px 0;
    display: grid;
    grid-template-columns: minmax(0, 96px) minmax(0, 1fr);
    gap: 10px;
    align-items: baseline;
  }

  /* La colonne des boutons n'a pas d'intitulé : elle prend toute la largeur
     plutôt que de laisser une gouttière vide devant elle. */
  .card tbody td[data-label='']::before {
    content: none;
  }

  .card tbody td[data-label=''] {
    display: block;
    padding-top: 8px;
  }

  .card tbody td::before {
    content: attr(data-label);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
  }

  /* Une cellule vide n'a pas à occuper une ligne pour ne rien dire. */
  .card tbody td:empty {
    display: none;
  }

  .attribute-row {
    grid-template-columns: 1fr auto;
  }

  .attribute-row > :first-child {
    grid-column: 1 / -1;
  }

  .tree-children {
    margin-left: 10px;
    padding-left: 8px;
  }

  .dialog-backdrop {
    padding: 12px;
  }

  .dialog-card {
    padding: 18px 16px;
  }

  .dialog-actions {
    flex-wrap: wrap;
  }

  .dialog-actions button {
    flex: 1 1 auto;
  }

  /* Le bloc de configuration se copie en entier : le faire passer à la ligne
     ne change rien à ce qu'on colle, et évite le dernier balayage latéral. */
  pre.code {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }

  /* La phrase « ce lieu — se trouve dans — cet autre » ne tient pas sur une
     ligne de 390 px : elle s'empile, chaque choix pleine largeur. */
  .place-form {
    grid-template-columns: 1fr;
  }

  .place-line {
    grid-template-columns: 1fr;
    gap: 4px;
  }

  /* Le nom complet est juste en dessous, dans la carte d'identité. Dans
     l'en-tête collant, une seule ligne suffit donc : « Amelia Hayes Volkov
     Andrews » y prenait quatre lignes et repoussait la photo hors de l'écran. */
  .sticky-head h2 {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Sur 390 px, la photo et le texte côte à côte laissent trois mots par ligne.
     La carte s'empile donc, et la photo passe pleine largeur — c'est elle qu'on
     vient regarder. */
  .identite {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .identite-media {
    width: 100%;
  }

  .identite-photo {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    /* Assez haut pour qu'un carre de 390 px de large tienne sans etre rogne,
       assez bas pour qu'il reste de la place au texte sur un ecran court. */
    max-height: 55vh;
  }

  .identite-label {
    flex-basis: 70px;
  }
}

/* Ce que l'IA a posé : se lit, ne se remplit pas. */
.poses-ia { margin: 0 0 12px; }
.poses-ia dt { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin-top: 10px; }
.poses-ia dd { margin: 2px 0 0; white-space: pre-wrap; }

/* Un élément masqué doit l'être même quand sa classe lui donne un affichage
 * (grid, flex) : sans cela, `hidden` ne fait rien et la case reste là. */
[hidden] { display: none !important; }

/* Une nouvelle version est en ligne : collé en haut, impossible à manquer. */
.bandeau-version {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  background: var(--accent, #8f5b2e);
  color: #fff;
  font-weight: 600;
}

/* Les tiroirs de la page Univers : un en-tête par type de fiche. */
.tiroir-tete {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 4px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border, #ddd);
  text-transform: capitalize;
}
.tiroir-tete:first-child { margin-top: 0; }
.tiroir-tete button { margin-left: auto; text-transform: none; }
