:root {
  --ivory: oklch(0.98 0.012 90);
  --ivory-2: oklch(0.955 0.018 88);
  --line: oklch(0.88 0.025 85);
  --ink: oklch(0.27 0.02 60);
  --ink-2: oklch(0.45 0.02 60);
  --gold: oklch(0.74 0.12 78);
  --gold-deep: oklch(0.55 0.1 68);
  --gold-glow: oklch(0.85 0.13 85 / 0.7);
  --sage: oklch(0.93 0.045 140);
  --card: oklch(0.985 0.01 90 / 0.94);
  --glass: oklch(0.98 0.01 90 / 0.86);
  --serif: "Cormorant Garamond", Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --r: 10px;
  --shadow: 0 1px 2px oklch(0.3 0.03 60 / 0.12), 0 8px 24px oklch(0.3 0.03 60 / 0.16);
  --top: calc(env(safe-area-inset-top) + 58px);
  --rail: 0px;
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--ivory); color: var(--ink); font-family: var(--sans); -webkit-tap-highlight-color: transparent; }
a { color: var(--gold-deep); } a:hover { color: var(--ink); }
[hidden] { display: none !important; }
.serif { font-family: var(--serif); font-weight: 500; }
.muted { color: var(--ink-2); font-size: 13px; line-height: 1.5; margin: 0; }
.spacer { flex: 1; }
code { font: 11px ui-monospace, Menlo, monospace; color: var(--ink-2); word-break: break-all; }
:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; }
/* ---- MODE D'AFFICHAGE : <html data-mode="mobile|pc"> (src/mode.js) au lieu des media queries de largeur ---- */
[data-mode="mobile"] .desktop-only { display: none !important; }
[data-mode="pc"] .mobile-only { display: none !important; } :root[data-mode="pc"] { --top: 62px; --rail: 80px; }
body:not(.admin-mode) .admin-only { display: none !important; }

/* Contrôles */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 42px; padding: 0 14px; border-radius: var(--r); border: 1px solid var(--line); background: var(--ivory); color: var(--ink); font: 500 15px var(--sans); cursor: pointer; }
.btn:hover { background: var(--ivory-2); }
.btn:active { background: var(--line); }
.btn-primary { border-color: var(--gold); color: var(--gold-deep); }
.btn-primary:hover { background: oklch(0.95 0.04 85); }
.btn:disabled { opacity: .45; cursor: default; }
.btn-icon { width: 40px; height: 40px; display: inline-grid; place-items: center; border: 0; border-radius: var(--r); background: none; color: var(--ink); font-size: 18px; cursor: pointer; }
.btn-icon:hover { background: var(--ivory-2); }
.input { width: 100%; min-height: 40px; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--line); background: oklch(0.995 0.005 90); color: var(--ink); font: 14px var(--sans); }
.input:focus { outline: 2px solid var(--gold); outline-offset: 0; border-color: transparent; }
textarea.input { min-height: 64px; resize: vertical; }
.field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--ink-2); }
.tag { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font: 13px var(--sans); background: var(--ivory); border: 1px solid var(--line); color: var(--ink); cursor: pointer; }
.tag:hover { background: var(--ivory-2); }
.tag[aria-pressed="true"] { border-color: var(--gold); background: oklch(0.95 0.05 85); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--gold-deep); }
.row-actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
.app-icon { width: 40px; height: 40px; border-radius: 10px; background: linear-gradient(160deg, var(--gold), var(--gold-deep)); object-fit: cover; }

/* Décor + arbre */
/* ---- IMAGE DE FOND : « L'ARBRE DE VIE » (gardée de l'ancienne appli, octet pour octet) ----
   Ses mots : « ne modifie pas l'image » ; « arriere plan ne veut pas dire flou donc l'image doit etre a son
   aspect réelle ». Même cadrage que FondArbreDeVie.tsx (object-fit: cover ; object-position: 50% 42%) :
   aucun voile, aucun filtre, aucune transparence. Le dégradé n'est visible que si l'image manque.
   inset: -5% = marge du léger effet de parallaxe du paquet (onView). */
#bg { position: fixed; inset: -5%; background: url(img/arbre-de-vie.webp) 50% 42% / cover no-repeat, linear-gradient(180deg, oklch(0.72 0.08 240), oklch(0.6 0.08 140)); will-change: transform; }
/* ---- FIN IMAGE DE FOND ---- */
#viewport { position: fixed; inset: 0; overflow: hidden; touch-action: none; cursor: grab; z-index: 1; }
#viewport.grabbing { cursor: grabbing; }
#layer { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; }
#links { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
/* ---- LIENS SUR L'IMAGE DE FOND (fond-arbre-de-vie.css de l'ancienne appli) ----
   Sur l'Arbre de Vie, les liens passent en clair : crème pour les liens ordinaires, or clair (--sepia)
   pour les cordons de la famille proche. */
#links { --lien: #FFF6E0; --sepia: #FFD98A; }
#links path { fill: none; stroke: var(--lien); stroke-width: 2; filter: drop-shadow(0 0 3px var(--gold-glow)); }
/* ---- FIN LIENS SUR L'IMAGE DE FOND ---- */

/* ---- LIEN LUMINEUX (lien-lumineux.css de l'ancienne appli) ----
   La famille proche de la personne choisie (3 générations au-dessus, 2 au-dessous, conjoints compris) :
   un halo sépia flou sous un trait plein, et une lueur qui CIRCULE le long du cordon — vers le haut sur
   les cordons d'ascendance (--monte), vers le bas sur ceux de descendance. */
#links .lien-lumineux__halo { stroke: var(--sepia); stroke-width: 9px; opacity: 0.28; filter: blur(3px); animation: lien-lumineux-respire 2.4s ease-in-out infinite; }
#links .lien-lumineux__coeur { stroke: var(--sepia); stroke-width: 2.6px; filter: drop-shadow(0 0 3px var(--sepia)); }
/* La lueur : un segment clair (80 sur 1000) qui parcourt le cordon. */
#links .lien-lumineux__lueur { stroke: #ffe7bd; stroke-width: 3px; stroke-linecap: round; stroke-dasharray: 80 920; filter: drop-shadow(0 0 4px #ffd89a) drop-shadow(0 0 9px var(--sepia)); animation: lien-lumineux-descend 2.2s linear infinite; }
#links .lien-lumineux--monte .lien-lumineux__lueur { animation-name: lien-lumineux-monte; }
@keyframes lien-lumineux-descend { from { stroke-dashoffset: 1000; } to { stroke-dashoffset: 0; } }
@keyframes lien-lumineux-monte { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 1000; } }
@keyframes lien-lumineux-respire { 0%, 100% { opacity: 0.2; } 50% { opacity: 0.4; } }
/* Sur l'image de fond (fond-arbre-de-vie.css) : le halo, plus présent, ne respire plus. */
#links .lien-lumineux .lien-lumineux__halo { opacity: 0.55; animation: none; }
/* ---- FIN LIEN LUMINEUX ---- */

/* ---- LUMIÈRE DES PARENTS (lumiere-parents.css de l'ancienne appli) ----
   1. Le cordon qui mène à un enfant brille sur toute sa longueur. */
#links .lien-lumineux--cordon .lien-lumineux__coeur { stroke: #fff3d6; stroke-width: 4px; filter: drop-shadow(0 0 4px #ffc861) drop-shadow(0 0 10px #e9a94f); }
#links .lien-lumineux--cordon .lien-lumineux__halo { stroke: #83501f; stroke-width: 10px; opacity: 0.6; filter: blur(1.5px); animation: none; }
/* Les cordons du couple de parents vers TOUS leurs enfants (frères et sœurs compris) brillent de même. */
#links path.cordon-fratrie { stroke: #fff3d6; stroke-width: 4px; opacity: 1; filter: drop-shadow(0 0 1.5px #83501f) drop-shadow(0 0 4px #ffc861) drop-shadow(0 0 10px #e9a94f); }
/* 2. Le contour de la carte du père et de la mère : lumineux, il clignote. */
.node.is-parent-lit { --trait-carte: #E6DFCF; animation: parent-contour-clignote 1.1s ease-in-out infinite; }
@keyframes parent-contour-clignote {
  0%, 100% { border-color: #e9a94f; box-shadow: 0 0 0 3px #e9a94f, 0 0 0 6px rgba(255, 236, 190, 0.9), 0 0 28px 12px rgba(255, 186, 80, 0.95); }
  50% { border-color: var(--trait-carte); box-shadow: 0 0 0 1px rgba(168, 103, 43, 0.25), 0 0 0 0 rgba(255, 200, 110, 0); }
}
@media (prefers-reduced-motion: reduce) {
  #links .lien-lumineux__lueur, #links .lien-lumineux__halo { animation: none !important; } /* passe aussi devant la lueur qui monte */
}
/* ---- FIN LUMIÈRE DES PARENTS ---- */
.node { position: absolute; width: 168px; height: 58px; display: flex; align-items: center; gap: 8px; padding: 6px 10px 6px 6px; border-radius: 8px; border: 1px solid var(--gold); background: var(--card); box-shadow: var(--shadow); color: var(--ink); font: inherit; text-align: left; cursor: pointer; transition: opacity .2s; }
.node:hover { box-shadow: 0 0 0 2px var(--gold-glow), var(--shadow); }
.node.is-sel { border-width: 2px; box-shadow: 0 0 0 4px var(--gold-glow), 0 0 30px var(--gold-glow), var(--shadow); }
.node.is-dim { opacity: .35; }
.node.is-dirty::after { content: ""; position: absolute; top: -4px; right: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 2px var(--ivory); }
.av { flex: none; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ivory-2); border: 1px solid var(--line); font: 600 14px var(--serif); color: var(--gold-deep); }
.av img { width: 100%; height: 100%; object-fit: cover; }
.node-text { display: flex; flex-direction: column; min-width: 0; }
.node-name { font: 600 15px/1.1 var(--serif); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.node-name b, .name b { font-weight: inherit; text-transform: uppercase; letter-spacing: .02em; }
.node-years { font-size: 11px; color: var(--ink-2); }

/* Barre haute */
#topbar { position: fixed; top: 0; left: 0; right: 0; z-index: 3; height: var(--top); display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: env(safe-area-inset-top) 16px 0; background: var(--ivory); border-bottom: 1px solid var(--line); }
.tb-left, .tb-right { display: flex; align-items: center; gap: 10px; }
.brand { font-size: 30px; line-height: 1; }
.tb-id { display: flex; flex-direction: column; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); line-height: 1.4; }
#status { font-size: 12px; color: var(--ink-2); }
.user-chip { display: inline-flex; align-items: center; gap: 6px; border: 0; background: none; color: var(--ink); font: 500 14px var(--sans); letter-spacing: .02em; cursor: pointer; min-height: 44px; padding: 0 6px; border-radius: var(--r); }
.user-chip:hover { background: var(--ivory-2); }
.user-chip .ph-user-circle { font-size: 24px; color: var(--gold-deep); }

/* Rail (PC) */
#rail { position: fixed; z-index: 3; top: var(--top); left: 0; bottom: 0; width: var(--rail); display: flex; flex-direction: column; gap: 6px; padding: 14px 6px; background: var(--ivory); border-right: 1px solid var(--line); }
#rail button { min-height: 64px; border: 0; border-radius: 12px; background: none; color: var(--ink); font: 13px var(--sans); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; cursor: pointer; }
#rail button i { font-size: 22px; }
#rail button:hover { background: var(--ivory-2); }
#rail button[aria-current="page"] { background: var(--sage); }

/* Recherche (PC) */
#searchbar { position: fixed; z-index: 3; top: calc(var(--top) + 14px); left: var(--rail); right: 0; display: flex; flex-direction: column; align-items: center; gap: 10px; pointer-events: none; }
#searchbar > * { pointer-events: auto; }
.search { display: flex; align-items: center; gap: 10px; width: min(430px, 90%); height: 44px; padding: 0 14px; border-radius: 10px; background: var(--ivory); border: 1px solid var(--gold); box-shadow: var(--shadow); }
.search i { color: var(--gold-deep); font-size: 18px; }
.search input { flex: 1; border: 0; background: none; outline: 0; font: 18px var(--serif); color: var(--ink); }
.results { width: min(430px, 90%); max-height: 300px; overflow: auto; padding: 4px; border-radius: 10px; background: var(--ivory); box-shadow: var(--shadow); }
.chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.result { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px; border: 0; border-radius: 8px; background: none; color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
.result:hover, .result.is-sel { background: var(--ivory-2); }
.result small { display: block; font-size: 12px; color: var(--ink-2); }
.result .name { font: 600 16px var(--serif); }

/* Zoom */
#zoom { position: fixed; z-index: 3; right: 12px; top: calc(var(--top) + 14px); display: flex; flex-direction: column; align-items: center; padding: 4px; border-radius: 12px; background: var(--glass); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); box-shadow: 0 4px 16px oklch(0.3 0.03 60 / .18); }
#zoom button { width: 44px; height: 44px; border: 0; background: none; color: var(--ink); font-size: 20px; cursor: pointer; border-radius: 8px; }
#zoom button:hover { background: var(--ivory-2); }
.js-zoom-pct { font-size: 11px; color: var(--ink-2); padding: 2px 0; font-variant-numeric: tabular-nums; }

/* Fiche détaillée */
#panel { position: fixed; z-index: 4; left: 12px; right: 12px; bottom: calc(env(safe-area-inset-bottom) + 80px); max-height: 62vh; display: flex; flex-direction: column; border-radius: 14px; background: var(--glass); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); box-shadow: 0 8px 24px oklch(0.3 0.03 60 / .2); border: 1px solid oklch(1 0 0 / .6); }
#panel.has-portrait { margin-top: 48px; }
.panel-body { overflow: auto; padding: 18px; display: flex; flex-direction: column; gap: 12px; }
#panel.has-portrait .panel-body { padding-top: 56px; }
.portrait { position: absolute; top: -46px; left: 18px; width: 92px; height: 92px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ivory-2); border: 3px solid var(--ivory); box-shadow: var(--shadow); font: 600 28px var(--serif); color: var(--gold-deep); }
.portrait img { width: 100%; height: 100%; object-fit: cover; }
.panel-close { position: absolute; top: 8px; right: 8px; }
.p-title { margin: 0; font: 500 30px/1.05 var(--serif); }
.p-title b { display: block; font-weight: 500; text-transform: uppercase; letter-spacing: .02em; }
.facts { display: flex; flex-direction: column; gap: 8px; font-size: 15px; color: var(--ink); }
.facts div { display: flex; align-items: center; gap: 10px; }
.facts .ph-fill { font-size: 9px; color: var(--ink-2); }
.facts .ph-globe-hemisphere-west { font-size: 16px; color: var(--gold-deep); }
.links-list { display: flex; flex-wrap: wrap; gap: 6px; }
.ed-label { font-size: 12px; color: var(--ink-2); }
.admin-box { display: flex; flex-direction: column; gap: 6px; padding-top: 6px; font-size: 14px; }
.admin-box-title { font-weight: 600; }
.add-kinds { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }

/* Éditeur (PC admin) */
.ed-head { display: flex; gap: 12px; align-items: center; }
.ed-head h2 { margin: 0; font: 500 24px/1.1 var(--serif); }
.ed-photo { position: relative; flex: none; width: 76px; height: 76px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ivory-2); border: 1px solid var(--gold); cursor: pointer; font: 600 22px var(--serif); color: var(--gold-deep); }
.ed-photo img { width: 100%; height: 100%; object-fit: cover; }
.ed-photo .hint { position: absolute; inset: auto 0 0; padding: 2px 0 4px; text-align: center; font-size: 14px; background: oklch(0.98 0.01 90 / .85); color: var(--ink); }
.ed-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ed-grid .full { grid-column: 1 / -1; }
.ed-section { display: flex; flex-direction: column; gap: 8px; }
.ed-rel { display: grid; grid-template-columns: 1fr 1.4fr auto; gap: 6px; }

/* Barre basse (mobile) */
#tabbar { position: fixed; z-index: 3; left: 0; right: 0; bottom: 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; padding: 6px 6px calc(env(safe-area-inset-bottom) + 6px); background: var(--ivory); border-top: 1px solid var(--line); }
#tabbar button { min-height: 52px; border: 0; border-radius: 12px; background: none; color: var(--ink-2); font: 500 11px var(--sans); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; cursor: pointer; }
#tabbar button i { font-size: 22px; }
#tabbar button[aria-current="page"] { background: var(--sage); color: var(--ink); }

/* Feuilles : recherche mobile, profil, installation, modération */
#sheet { position: fixed; z-index: 5; left: 12px; right: 12px; bottom: calc(env(safe-area-inset-bottom) + 80px); max-height: 70vh; overflow: auto; padding: 18px; border-radius: 14px; background: var(--glass); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: var(--shadow); border: 1px solid oklch(1 0 0 / .6); display: flex; flex-direction: column; gap: 12px; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sheet-head h2 { margin: 0; font: 500 26px/1.1 var(--serif); }
.mod-row { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 10px; background: var(--ivory); border: 1px solid var(--line); }
.mod-row strong { font: 600 18px var(--serif); }
.mod-row dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 0; font-size: 12px; }
.mod-row dt { color: var(--ink-2); } .mod-row dd { margin: 0; }

#toast { position: fixed; z-index: 6; left: 50%; transform: translateX(-50%); bottom: calc(env(safe-area-inset-bottom) + 84px); width: max-content; max-width: min(92vw, 560px); padding: 10px 14px; border-radius: 10px; background: var(--ink); color: var(--ivory); font-size: 13px; line-height: 1.4; box-shadow: var(--shadow); }

/* Auth */
#auth { position: fixed; inset: 0; z-index: 7; display: grid; place-items: center; padding: 20px; }
.auth-card { width: min(400px, 100%); display: flex; flex-direction: column; gap: 12px; padding: 24px; border-radius: 16px; background: var(--glass); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: var(--shadow); }
.auth-card h1 { margin: 0; font-size: 42px; }
.auth-msg { margin: 0; min-height: 1em; font-size: 13px; color: var(--gold-deep); }

/* Mise en page PC (mode « pc ») */
[data-mode="pc"] #topbar { display: grid; grid-template-columns: 1fr auto 1fr; padding: 0 18px; }
[data-mode="pc"] #topbar .tb-right { justify-content: flex-end; }
[data-mode="pc"] .brand { font-size: 36px; }
[data-mode="pc"] #zoom { right: auto; top: auto; left: calc(var(--rail) + 20px); bottom: 18px; }
[data-mode="pc"] #panel { left: auto; right: 20px; bottom: auto; top: calc(var(--top) + 120px); width: 260px; max-height: calc(100vh - var(--top) - 188px); }
[data-mode="pc"] #panel.is-editing { width: 380px; top: calc(var(--top) + 20px); max-height: calc(100vh - var(--top) - 40px); }
[data-mode="pc"] .portrait { left: 50%; transform: translateX(-50%); }
[data-mode="pc"] #panel:not(.is-editing) .p-title { font-size: 27px; }
[data-mode="pc"] #panel:not(.is-editing) .p-title b { display: inline; }
[data-mode="pc"] .p-title, [data-mode="pc"] .p-user { text-align: center; }
[data-mode="pc"] #sheet { left: auto; right: 20px; bottom: auto; top: calc(var(--top) + 20px); width: 380px; max-height: calc(100vh - var(--top) - 40px); }
[data-mode="pc"] #sheet.wide { width: 520px; }
[data-mode="pc"] #toast { bottom: 24px; }

/* Mode Mobile forcé sur un grand écran : colonne de téléphone centrée (430 px, cadre discret). Le transform
   fait de #app le bloc conteneur de ses éléments « fixed » : barres, zoom et fiche restent dans la colonne. */
@media (min-width: 600px) {
  [data-mode="mobile"][data-mode-forced] body { background: oklch(0.9 0.012 85); }
  [data-mode="mobile"][data-mode-forced] #bg { inset: 0 auto 0 calc(50% - 215px); width: 430px; }
  [data-mode="mobile"][data-mode-forced] #bg { transform: none !important; }
  [data-mode="mobile"][data-mode-forced] #pano { display: none !important; } /* un PC ne pivote pas */
  [data-mode="mobile"][data-mode-forced] #app { position: fixed; top: 0; bottom: 0; left: calc(50% - 215px); width: 430px; transform: translateZ(0); overflow: hidden; box-shadow: 0 0 0 1px var(--line), 0 10px 40px oklch(0.3 0.03 60 / .25); }
}
/* Sélecteur dans Paramètres / Profil */
.mode-switch { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 4px; border-radius: 12px; background: var(--ivory-2); border: 1px solid var(--line); }
.mode-switch button { min-height: 44px; padding: 0 6px; border: 0; border-radius: 9px; background: none; color: var(--ink); font: 500 13px var(--sans); cursor: pointer; }
.mode-switch button[aria-pressed="true"] { background: var(--ivory); box-shadow: 0 0 0 1px var(--gold); color: var(--gold-deep); }
/* ---- FIN MODE D'AFFICHAGE ---- */

/* ---- VISITEUR SANS COMPTE (sa règle « Google ») ----
   L'interface se voit, sans aucune donnée ; le formulaire d'inscription du paquet s'ouvre dans la feuille. */
#sheet .auth-card { width: 100%; padding: 0; background: none; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
#sheet .auth-card h1 { font-size: 30px; }
.auth-card .names { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.check { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--ink); cursor: pointer; }
.check input { width: 18px; height: 18px; accent-color: var(--gold-deep); }
/* ---- FIN VISITEUR SANS COMPTE ---- */

/* ---- CARTE « INSTALLER ANCESTRIA » (idée de la maquette sombre, couleurs de la claire) ---- */
.install-head { display: flex; gap: 12px; align-items: center; }
.install-head .app-icon { width: 56px; height: 56px; border-radius: 14px; flex: none; }
.install-title { font: 600 24px/1.1 var(--serif); }
.install-sub { font-size: 13px; color: var(--ink-2); margin-top: 2px; }
.install-ios { font-size: 13px; color: var(--ink-2); line-height: 1.5; margin: 0; }
.btn-ghost { border-color: transparent; background: none; color: var(--gold-deep); }
#sheet.install { gap: 14px; }
a.btn { text-decoration: none; } /* « Ouvrir dans Chrome » est un lien qui a l'air d'un bouton */
/* ---- FIN CARTE « INSTALLER ANCESTRIA » ---- */

/* ---- MODE PAYSAGE ET VUE PANORAMIQUE (téléphone) ----
   Sa demande : « OPTIMISATION MODE HORIZONTAL (PAYSAGE) SUR MOBILE : • Gère nativement la rotation d'écran
   (Portrait/Paysage). • En mode horizontal, masque automatiquement les barres d'outils secondaires pour offrir
   une vue panoramique plein écran de l'Arbre de Lumière. • Ajoute un bouton tactile d'orientation
   ("Vue Panoramique 🔄") pour forcer le basculement horizontal même si la rotation automatique du smartphone
   est désactivée. »
   body.paysage = téléphone tenu à l'horizontale (app.js, media query) OU vue pivotée par CSS (body.pano-css,
   repli quand le verrou d'orientation est refusé, ex. Safari iPhone). L'image de fond n'est jamais modifiée. */
body.paysage #topbar, body.paysage #tabbar, body.paysage #searchbar, body.paysage .chips { display: none !important; }
body.paysage { --top: 0px; }
body.paysage #zoom { top: 8px; right: 8px; padding: 2px; }
body.paysage #zoom button { width: 38px; height: 38px; font-size: 18px; }
body.paysage #pano { bottom: 8px; right: auto; left: 8px; min-height: 38px; font-size: 13px; }
/* La fiche : panneau latéral étroit au lieu de la feuille du bas. */
body.paysage #panel { left: auto; right: 60px; top: 8px; bottom: 8px; width: min(280px, 40%); max-height: none; }
body.paysage #panel.has-portrait { margin-top: 0; top: 52px; }
body.paysage #sheet { left: auto; right: 60px; top: 8px; bottom: 8px; width: min(380px, 60%); max-height: none; }
/* Repli : la vue entière pivote de 90° (le pan/zoom convertit les coordonnées du doigt, tree-view.js). */
body.pano-css #bg, body.pano-css #app { position: fixed; inset: auto; top: 0; left: 100vw; width: 100vh; width: 100dvh; height: 100vw; transform-origin: 0 0; transform: rotate(90deg) !important; }
body.pano-css #app { overflow: hidden; }
/* ---- FIN MODE PAYSAGE ET VUE PANORAMIQUE ---- */


/* ---- ARBRE DE LUMIÈRE (ses modèles du 13/10, téléphone et PC) ----
   En-tête avec M'ASTEL.974 ; petites cartes blanches compactes ; grande carte dorée de l'ancêtre ; pastille sous
   chaque couple ; liens en courbes dorées qui brillent ; la personne choisie et son couple brillent ;
   une seule colonne de zoom ; « Vue Panoramique 🔄 » en bas à droite du téléphone ; drapeau d'origine. */
[data-mode="mobile"] .p-user { display: none; }
.p-user { font-size: 12px; letter-spacing: .06em; color: var(--ink-2); }
.facts .flag { width: 18px; height: 13px; border-radius: 2px; flex: none; box-shadow: 0 0 0 1px oklch(0.88 0.025 85); }
.marque { font-size: 13px; font-weight: 500; letter-spacing: .03em; }
[data-mode="mobile"] .brand { font-size: 33px; }
[data-mode="mobile"] #tabbar button { font-size: 12.5px; }
[data-mode="mobile"] #tabbar button i { font-size: 24px; }
[data-mode="mobile"] .user-chip .ph-user-circle { font-size: 22px; }
#links > path:not(.cordon-fratrie) { stroke: #F3C76E; stroke-width: 3px; filter: drop-shadow(0 0 2px #ffd98a) drop-shadow(0 0 5px rgba(233, 169, 79, .8)); }
.node { gap: 5px; padding: 4px 6px 4px 4px; border-radius: 6px; border: 1px solid oklch(0.9 0.02 85); background: oklch(0.995 0.004 90 / .97); box-shadow: 0 1px 3px oklch(0.3 0.03 60 / .25); }
.node .av { width: 32px; height: 32px; font-size: 12px; }
.node-name { font-size: 14px; line-height: 1.05; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.node-years { font-size: 10px; }
.node.is-sel, .node.is-famille { border-color: #e9a94f; box-shadow: 0 0 0 2px rgba(255, 220, 150, .95), 0 0 18px 6px rgba(255, 186, 80, .85); }
.node.node--souche { flex-direction: column; justify-content: center; align-items: center; gap: 1px; padding: 8px 12px; text-align: center; border-radius: 8px; border: 1.5px solid #e9b955; background: oklch(0.99 0.008 90 / .97);
  box-shadow: 0 0 0 1px rgba(255, 220, 150, .9), 0 0 24px 6px rgba(255, 190, 90, .7), 0 4px 14px oklch(0.3 0.03 60 / .25); }
.node--souche .av { position: absolute; top: 12px; left: 12px; width: 60px; height: 60px; font-size: 20px; opacity: .7; }
.souche-first, .souche-last { font: 500 42px/1.05 var(--serif); color: var(--ink); max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.souche-last { text-transform: uppercase; letter-spacing: .02em; }
.souche-sub { font: 24px/1.35 var(--sans); color: var(--ink); }
[data-mode="pc"] .souche-first, [data-mode="pc"] .souche-last { font-size: 30px; }
[data-mode="pc"] .souche-sub { font-size: 15px; }
[data-mode="pc"] .node--souche .av { width: 36px; height: 36px; font-size: 13px; top: 8px; left: 8px; }
.union { position: absolute; height: 14px; border-radius: 3px; background: oklch(0.995 0.004 90 / .94); border: 1px solid oklch(0.9 0.02 85); font: 600 9px/12px var(--sans); letter-spacing: .05em; color: var(--ink-2); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 4px; pointer-events: none; }
#pano { position: fixed; z-index: 3; right: 12px; bottom: calc(env(safe-area-inset-bottom) + 84px); min-height: 44px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--gold); background: var(--glass); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); box-shadow: 0 4px 16px oklch(0.3 0.03 60 / .18); color: var(--gold-deep); font: 500 14px var(--sans); cursor: pointer; white-space: nowrap; }
/* ---- FIN ARBRE DU TÉLÉPHONE ---- */

/* ---- ÉCRAN TACTILE : PAS DE BARRE DE ZOOM (13/10, ses mots : « la barre de zoom est inutile sur un tactile ») ----
   Sur un écran qu'on touche, on agrandit et on déplace l'arbre avec les doigts (pincer, glisser : PanZoom de
   tree-view.js). La barre « + / % / − / ⛶ » reste seulement pour la souris. */
@media (pointer: coarse) {
  #zoom { display: none !important; }
}
/* ---- FIN ÉCRAN TACTILE ---- */

/* ---- FORMULAIRE SANS DOUBLON (14/10/2026) ----
   Ses mots : « il faut de la fluidité donc pas de doublon ». Dans la feuille, un seul titre (celui de la feuille) :
   l'icône, le 2e « Ancestria » et sa phrase sont retirés de l'affichage. Un seul chemin visible (src/auth-mode.js). */
#sheet .auth-card > .app-icon,
#sheet .auth-card > h1,
#sheet .auth-card > p.muted { display: none; }
#auth-form [hidden] { display: none !important; }
#auth-form[data-auth-mode="signin"] .names,
#auth-form[data-auth-mode="signin"] .check { display: none; }
#auth-form .row-actions .btn:not([hidden]) { flex: 1; }
.auth-switch { margin: 0; text-align: center; font-size: 14px; color: var(--ink); }
.auth-switch .lien { background: none; border: 0; padding: 4px 2px; font: inherit; font-weight: 600; color: var(--gold-deep); text-decoration: underline; cursor: pointer; }
/* ---- FIN FORMULAIRE SANS DOUBLON ---- */

/* ---- APRÈS « CRÉER MON COMPTE » (14/10/2026) : seule l'étape « Vérifiez votre boîte mail » reste (src/inscription-envoyee.js) ---- */
.auth-envoye { display: none; }
#auth-form[data-auth-mode="envoye"] > :not(.auth-envoye) { display: none !important; }
#auth-form[data-auth-mode="envoye"] .auth-envoye { display: flex; flex-direction: column; gap: 10px; text-align: center; font-size: 15px; color: var(--ink); }
.auth-envoye p { margin: 0; }
.auth-envoye-icone { font-size: 40px; line-height: 1; }
/* ---- FIN APRÈS « CRÉER MON COMPTE » ---- */

/* ---- UNE SEULE PAGE : PAS DE BOUTON « ARBRE » (14/10/2026) ----
   Ses mots : « sur ton image je vois deux pages donc tu ne m'écoutes pas », « y a accueil puis arbre ». L'appli n'a
   qu'une page : l'arbre de la personne tapée s'ouvre sur l'Accueil même. « Arbre » faisait doublon avec « Accueil ». */
[data-nav="tree"] { display: none !important; }
/* ---- FIN UNE SEULE PAGE ---- */

/* ---- AUCUN DOUBLON (14/10/2026) ----
   Ses mots : « sur la page d'accueil deux barres de recherche doublons », « sur le PC idem, tu ne fais aucune analyse ».
   Relevé de toute la page (PC et téléphone, chaque feuille ouverte) : une fonction = un seul bouton.
   · PC : « Recherche » de la barre de gauche refaisait la barre de recherche du haut → retiré ;
   · « Modération » était dans Paramètres ET dans Mon Compte → gardée dans Mon Compte seulement ;
   · téléphone : « Admin » ouvrait, pour un non-administrateur, la même feuille que le bouton du haut → montré à
     l'administrateur seulement (classe est-admin posée par render()). */
#rail [data-nav="search"] { display: none !important; }
#sheet[data-kind="settings"] [data-nav="moderation"] { display: none !important; }
body:not(.est-admin) [data-nav="admin"] { display: none !important; }
/* ---- FIN AUCUN DOUBLON ---- */

/* ---- TÉLÉPHONE : LA RECHERCHE SUR LA PAGE MÊME (15/10/2026) ----
   Ses mots : « je t'ai demandé en plusieurs fois de supprimer la deuxième page et je vois que c'est actif ».
   Sur le téléphone, « Recherche » ouvrait une feuille plein écran = une deuxième page. La barre de recherche du PC
   (#searchbar : champ, pastilles d'origine, résultats) est maintenant aussi sur la page du téléphone, et le bouton
   « Recherche » n'existe plus nulle part. Une seule page, une seule recherche. */
[data-nav="search"] { display: none !important; }
[data-mode="mobile"] #searchbar.desktop-only { display: flex !important; left: 12px; right: 68px; top: calc(var(--top) + 10px); gap: 8px; }
[data-mode="mobile"] #searchbar .search, [data-mode="mobile"] #searchbar .results { width: 100%; }
[data-mode="mobile"] #searchbar .chips { gap: 6px; }
[data-mode="mobile"] #searchbar .chips button { font-size: 12px; }
@media (pointer: coarse) { [data-mode="mobile"] #searchbar.desktop-only { right: 12px; } } /* pas de barre de zoom au tactile */
/* ---- FIN TÉLÉPHONE : LA RECHERCHE SUR LA PAGE ---- */

/* ---- L'IMAGE DE FOND FIGÉE (15/10/2026) ----
   Ses mots : « l'image doit être figée dans la page, alors que je scrolle la souris l'image se déplace ».
   onView() (app.js) décalait le fond de 3 % du déplacement de l'arbre (effet de profondeur) : annulé ici. Seul
   l'arbre bouge et zoome ; l'image reste immobile. */
#bg { transform: none !important; }
/* ---- FIN L'IMAGE DE FOND FIGÉE ---- */

/* ---- INSTALLER, FLUIDE (15/10/2026) : la carte de src/installer-fluide.js ---- */
.install-gestes { margin: 4px 0 12px; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; font-size: 15px; line-height: 1.45; color: var(--ink); }
.install-gestes li::marker { font-weight: 700; color: var(--gold-deep); }
.install-ok { margin: 4px 0 8px; font-size: 15px; line-height: 1.45; color: var(--ink); }
/* ---- FIN INSTALLER, FLUIDE ---- */

/* ---- APPLI INSTALLÉE : PLUS DE BOUTON « INSTALLER » (15/10/2026) ----
   Ses mots : « une fois l'installation terminée on ne devrait plus voir le bouton d'installation ».
   Ouverte depuis son icône (fenêtre d'appli, sans barre d'adresse) → display-mode standalone ; iPhone → classe
   posée par src/installer-fluide.js ; installation acceptée dans le navigateur → même classe. */
@media (display-mode: standalone), (display-mode: fullscreen), (display-mode: minimal-ui) {
  [data-nav="install"] { display: none !important; }
}
body.appli-installee [data-nav="install"] { display: none !important; }
/* ---- FIN APPLI INSTALLÉE ---- */

/* ---- LA FICHE NE CACHE JAMAIS L'ARBRE (15/10/2026, src/fiche-mobile.js) ----
   La fiche ne s'ouvre que pour inscrire des noms (carte touchée sur le PC) ; fermée = cachée, l'arbre reste. */
#panel.fiche-cachee { display: none !important; }
/* ---- FIN LA FICHE NE CACHE JAMAIS L'ARBRE ---- */

/* ---- LE FOND NE BOUGE JAMAIS (15/10/2026) ----
   Ses mots : « quand je zoome sur l'arborescence l'image de fond bouge en même temps ». Seul l'arbre se zoome :
   pas de zoom de la page entière, pas de rebond ni de « tirer pour actualiser » qui déplaçait l'écran. */
html, body { overscroll-behavior: none; touch-action: none; }
#bg { touch-action: none; pointer-events: none; }
#searchbar, #panel, #sheet, #tabbar, #topbar, #rail { touch-action: manipulation; }
#sheet, .results, .panel-body { touch-action: pan-y; }
/* ---- FIN LE FOND NE BOUGE JAMAIS ---- */

/* ---- FICHE = INSCRIPTION SEULEMENT (15/10/2026) ----
   Ses mots : « la fiche de la personne doit s'ouvrir que pour l'inscription des noms ». Sa capture : fiche en grand,
   longue liste d'enfants, le rond du portrait par-dessus les noms quand on fait défiler.
   La fiche (carte touchée, PC) ne montre plus que : le nom, « Modifier », « Ajouter un membre » (Enfant, Conjoint·e,
   Parent). Les listes Parents / Conjoint / Enfants et les faits restent dans l'arbre lui-même. Le portrait ne passe
   plus jamais par-dessus : la partie qui défile commence sous lui. */
#panel:not(.is-editing) .facts, #panel:not(.is-editing) .ed-label, #panel:not(.is-editing) .links-list,
#panel:not(.is-editing) .admin-box, #panel:not(.is-editing) .p-user { display: none !important; }
#panel.has-portrait .panel-body { margin-top: 48px; padding-top: 10px; }
/* ---- FIN FICHE = INSCRIPTION SEULEMENT ---- */

/* ---- ENVOI SUR LE TÉLÉPHONE (15/10/2026) ----
   L'administrateur inscrit aussi depuis son téléphone (« + Enfant » sur l'épouse) : la barre du haut garde
   « Ancestria » et M'ASTEL.974 ; le texte « n modification(s) en brouillon » se cache (le nombre reste sur « Envoi (n) »). */
[data-mode="mobile"] #status { display: none !important; }
[data-mode="mobile"] #publish { min-height: 34px; padding: 0 10px; font-size: 13px; }
[data-mode="mobile"] #publish i { display: none; }
/* ---- FIN ENVOI SUR LE TÉLÉPHONE ---- */

/* ---- IMAGE ENTIÈRE EN VERTICAL (15/10/2026) ----
   Ses mots : « l'image en mode vertical, on ne voit plus le mode responsive pour que l'on puisse voir la totalité de
   l'image ». Téléphone tenu droit : le banian (1456 × 734, l'image n'est PAS modifiée) est montré EN ENTIER (contain,
   sans déformation) au lieu d'être coupé sur les côtés (cover n'en montrait qu'un quart de la largeur) ; au-dessus,
   la couleur du ciel du bord haut de l'image (#2a5da0, mesurée) ; au-dessous, celle de la terre du bord bas (#594232).
   Retirer ce bloc = le fond d'avant. */
@media (orientation: portrait) {
  [data-mode="mobile"] #bg {
    background: url(img/arbre-de-vie.webp) 50% 55% / contain no-repeat,
                linear-gradient(180deg, #2a5da0 0 55%, #594232 55% 100%);
  }
}
/* ---- FIN IMAGE ENTIÈRE EN VERTICAL ---- */

/* ---- SANS « VUE PANORAMIQUE » SUR LE TÉLÉPHONE (15/10/2026) ----
   Ses mots, sur sa page d'images : « le A mais sans cette bulle » (sa capture : le bouton « Vue Panoramique 🔄 »).
   Le bouton n'est plus montré sur le téléphone ; le PC n'est pas touché (« le PC on fera plus tard »).
   Retirer ce bloc = le bouton d'avant. */
[data-mode="mobile"] #pano { display: none !important; }
/* ---- FIN SANS « VUE PANORAMIQUE » SUR LE TÉLÉPHONE ---- */

/* ---- PAS DE PASTILLES D'ORIGINE SUR LA PAGE DU TÉLÉPHONE (15/10/2026) ----
   Ses mots (sa capture des pastilles Europe · Inde · Afrique · Madagascar · Chine · Nom d'affranchi) : « on avait déjà
   discuté de ces blocs qui ne devraient plus être visibles sur la page mais dans la page d'ajout de nom, de leur
   origine » (déjà retirées de l'Accueil de l'ancienne appli le 13/10). L'origine se choisit dans la petite page
   d'inscription (champ « Origine », mêmes six choix). Téléphone seulement (« le PC on fera plus tard »).
   Retirer ce bloc = les pastilles d'avant. */
[data-mode="mobile"] #chips { display: none !important; }
/* ---- FIN PAS DE PASTILLES D'ORIGINE ---- */

/* ---- PAS DE BARRE DE ZOOM EN MODE TÉLÉPHONE (15/10/2026) ----
   Ses mots (sa capture « + / 96 % / − / ⛶ » dans l'essai téléphone du PC) : « pour un tactile on n'a pas besoin de ça ».
   Déjà cachée au toucher (13/10) ; maintenant aussi dans tout le mode téléphone (essai à la souris compris) : on agrandit
   avec les doigts. Retirer ce bloc = comme avant. */
[data-mode="mobile"] #zoom { display: none !important; }
/* ---- FIN PAS DE BARRE DE ZOOM EN MODE TÉLÉPHONE ---- */
