/* ==========================================================================
   MyTransition — design system
   --------------------------------------------------------------------------
   Deux familles de variables cohabitent, volontairement :

   - la palette brute (--navy, --ink, --ink-dim, --line, --gold, --danger,
     --ok, --bg-a/b/c, --text-on-gold), référencée directement par des styles
     en ligne dans de nombreuses vues. La renommer casserait silencieusement
     des pages qu'on n'aurait pas rouvertes ;
   - les tokens sémantiques --color-*, simples alias des précédents. C'est eux
     que le nouveau code utilise : un seul endroit à modifier pour faire
     évoluer la palette.

   Le thème sombre est la racine ; [data-theme="light"] et le bloc
   prefers-color-scheme de [data-theme="system"] fournissent la variante
   claire. L'attribut data-theme est posé sur <html> par le layout.
   ========================================================================== */
:root{
  /* ---- palette brute (sombre, par défaut) ---- */
  --navy:#121e34;         /* surface carte */
  --navy-2:#172641;       /* surface élevée */
  --navy-3:#0b1424;       /* surface la plus profonde */
  --gold: var(--theme-color, #D7AD45);
  --gold-soft: color-mix(in srgb, var(--gold) 15%, transparent);
  --gold-dim: color-mix(in srgb, var(--gold) 55%, var(--ink-dim));
  --ink:#F5F2EB;
  --ink-dim:#8E9AB0;
  --ink-faint:#5F6B85;
  --line: rgba(255,255,255,.08);
  --line-strong: rgba(255,255,255,.16);
  --danger:#d98a78; --ok:#7fceab; --warn:#d9b96a; --info:#8aa9e0;
  --bg-a:#152341; --bg-b:#0d172b; --bg-c:#080f1e;
  --text-on-gold:#221a0d;
  color-scheme: dark;

  /* ---- tokens sémantiques (design system MyTransition) ---- */
  --color-bg: var(--bg-b);
  --color-surface: var(--navy);
  --color-surface-elevated: var(--navy-2);
  --color-surface-hover: color-mix(in srgb, var(--navy) 82%, white 6%);
  --color-border: var(--line);
  --color-border-strong: var(--line-strong);
  --color-text-primary: var(--ink);
  --color-text-secondary: var(--ink-dim);
  --color-text-muted: var(--ink-faint);
  --color-accent: var(--gold);
  --color-accent-soft: var(--gold-soft);
  --color-accent-contrast: var(--text-on-gold);
  --color-success: var(--ok);
  --color-warning: var(--warn);
  --color-error: var(--danger);
  --color-info: var(--info);

  --radius-sm:10px; --radius-md:14px; --radius-lg:20px; --radius-xl:24px; --radius-pill:999px;
  --shadow-card: none;
  --shadow-elevated: 0 30px 80px rgba(0,0,0,.45);
  --ease: cubic-bezier(.22,.61,.36,1);
  --dur-fast:120ms; --dur-med:220ms; --dur-slow:420ms;
  --sidenav-w: 214px; --sidenav-w-collapsed: 68px;

  /* ZONES SÛRES
     La balise viewport porte « viewport-fit=cover » : la page s'étend sous
     l'encoche, sous les coins arrondis et sous l'indicateur d'accueil. C'est ce
     qu'il faut pour qu'un fond aille jusqu'au bord de l'écran — mais tout ce qui
     touche un bord doit désormais s'écarter lui-même de ces quatre zones.

     Sans « cover », env() vaut zéro et ces variables ne coûtent rien : c'est
     précisément ce qui s'est passé ici pendant des mois. La barre du bas croyait
     flotter au-dessus de l'indicateur d'accueil de l'iPhone, et ne le faisait pas,
     faute de ce seul mot dans la balise.

     La valeur de repli 0px est indispensable : sur un navigateur qui ne connaît
     pas env(), une déclaration sans repli est invalide et emporte toute la règle. */
  --sr-haut: env(safe-area-inset-top, 0px);
  --sr-droite: env(safe-area-inset-right, 0px);
  --sr-bas: env(safe-area-inset-bottom, 0px);
  --sr-gauche: env(safe-area-inset-left, 0px);
}

[data-theme="light"]{
  --navy:#FFFFFF; --navy-2:#FBF7EC; --navy-3:#F5EFDe;
  --ink:#1b2338; --ink-dim:#5c6785; --ink-faint:#8b93ab; --line: rgba(28,36,56,.12); --line-strong: rgba(28,36,56,.22);
  --bg-a:#FBF8F1; --bg-b:#F4EFE3; --bg-c:#ECE4CE;
  color-scheme: light;
}
@media (prefers-color-scheme: light){
  [data-theme="system"]{
    --navy:#FFFFFF; --navy-2:#FBF7EC; --navy-3:#F5EFDe;
    --ink:#1b2338; --ink-dim:#5c6785; --ink-faint:#8b93ab; --line: rgba(28,36,56,.12); --line-strong: rgba(28,36,56,.22);
    --bg-a:#FBF8F1; --bg-b:#F4EFE3; --bg-c:#ECE4CE;
    color-scheme: light;
  }
}
@media (prefers-color-scheme: dark){ [data-theme="system"]{ color-scheme: dark; } }

/* ---- reset / base ---- */
*{box-sizing:border-box;}
html{width:100%;}
body{
  margin:0; min-height:100vh; width:100%; font-family:'Inter',sans-serif; color:var(--color-text-primary);
  background:radial-gradient(circle at 18% -12%, var(--bg-a) 0%, var(--bg-b) 55%, var(--bg-c) 100%);
  background-attachment:fixed;
  overflow-wrap:break-word;
  -webkit-font-smoothing:antialiased;
}
img, svg{max-width:100%;}
/* POURQUOI « break-word » ET NON « anywhere »
   Les deux coupent un mot trop long plutôt que de le laisser déborder. Ils ne se
   comportent pas de la même façon pour autant : « anywhere » fait entrer les coupures
   dans le calcul de la largeur minimale de l'élément, « break-word » non.

   Autrement dit, avec « anywhere », un navigateur considère qu'une cellule de tableau ou
   un élément de liste peut légitimement mesurer un caractère de large. Il se le permet dès
   que la place manque — et le texte descend alors une lettre par ligne. C'est ce qu'on
   voyait sur téléphone, sur le compte rendu de prise de sang comme ailleurs.

   « break-word » garde le mot le plus long comme largeur plancher : la colonne reste
   lisible, quitte à ce que le tableau défile. Là où une chaîne vraiment insécable doit
   pouvoir être coupée n'importe où — une adresse électronique, une adresse web — la règle
   est posée sur place, et seulement là. */
.card, .desc, p, li, td, th, h1, h2, h3, h4{overflow-wrap:break-word;}
h1,h2,h3{font-family:'Cormorant Garamond',serif; font-weight:600; letter-spacing:.01em; color:var(--color-text-primary);}
a{color:inherit;}
.wrap{max-width:1100px; margin:0 auto;
  padding:0 calc(24px + var(--sr-droite)) 0 calc(24px + var(--sr-gauche));}

/* ==========================================================================
   Barre supérieure
   ========================================================================== */
header.topbar{
  display:flex; align-items:center; justify-content:flex-start;
  /* Le fond monte jusqu'au bord haut de l'écran, le contenu s'arrête sous
     l'encoche : c'est le rembourrage qui porte la différence, pas une marge. */
  padding:calc(16px + var(--sr-haut)) calc(26px + var(--sr-droite))
          16px calc(26px + var(--sr-gauche));
  border-bottom:1px solid var(--color-border); flex-wrap:wrap; gap:12px;
  position:sticky; top:0; z-index:20; backdrop-filter:blur(14px);
  background:color-mix(in srgb, var(--bg-b) 78%, transparent);
}
header.topbar .brand{display:flex; align-items:center; gap:10px; font-size:1.28rem; font-weight:600; letter-spacing:.01em;}
header.topbar .brand img{height:30px;}
header.topbar .brand span{color:var(--color-accent); font-style:italic;}
.topbar-actions{display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-left:auto;}

/* ==========================================================================
   Navigation latérale (desktop) — compacte, réductible
   ========================================================================== */
.layout{
  display:flex; gap:26px; max-width:1240px; margin:0 auto; align-items:flex-start;
  padding:24px calc(26px + var(--sr-droite)) 96px calc(26px + var(--sr-gauche));
}
.layout main{flex:1; min-width:0;}

nav.sidenav{
  display:flex; flex-direction:column; gap:1px; min-width:var(--sidenav-w); width:var(--sidenav-w);
  position:sticky; top:88px; transition:width var(--dur-med) var(--ease), min-width var(--dur-med) var(--ease);
}
nav.sidenav a{
  display:flex; align-items:center; gap:11px; position:relative;
  padding:7px 10px 7px 13px; border-radius:var(--radius-sm); color:var(--color-text-secondary); text-decoration:none; font-size:.83rem;
  transition:background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  white-space:nowrap; overflow:hidden;
}
nav.sidenav a span{overflow:hidden; text-overflow:ellipsis;}
nav.sidenav a .icon{width:16px; height:16px; opacity:.85;}
/* État actif discret : liseré d'accent + couleur, jamais un gros aplat plein — la navigation
   ne doit pas rivaliser visuellement avec le contenu (voir la note de conception). */
nav.sidenav a.active{color:var(--color-accent); font-weight:600; background:transparent;}
nav.sidenav a.active .icon{opacity:1;}
nav.sidenav a.active::before{content:''; position:absolute; left:0; top:16%; bottom:16%; width:2px; border-radius:2px; background:var(--color-accent);}
nav.sidenav a:hover, nav.sidenav a:focus-visible{background:var(--color-surface-hover); color:var(--color-text-primary);}
nav.sidenav a.active:hover{color:var(--color-accent);}
.icon{width:17px; height:17px; flex-shrink:0; color:inherit;}
.btn .icon{width:15px; height:15px;}
a:focus-visible, button:focus-visible, .btn:focus-visible, input:focus-visible, select:focus-visible{outline:2px solid var(--color-accent); outline-offset:2px;}
.sidenav-section{
  font-size:.63rem; text-transform:uppercase; letter-spacing:.1em; color:var(--color-text-muted);
  padding:18px 13px 5px; font-weight:600; white-space:nowrap; overflow:hidden; opacity:.75;
}
.sidenav-section:first-child{padding-top:2px;}

.sidenav-collapse{
  display:flex; align-items:center; gap:10px; margin-top:10px; padding:9px 12px; border-radius:var(--radius-sm);
  border:1px solid var(--color-border); background:transparent; color:var(--color-text-muted); cursor:pointer;
  font-size:.78rem; width:100%;
}
.sidenav-collapse:hover{color:var(--color-text-primary); border-color:var(--color-border-strong);}
.sidenav-collapse .icon{transition:transform var(--dur-med) var(--ease);}

/* Mode réduit desktop : icônes seules + tooltip natif (title=""), état actif toujours visible */
.layout.is-collapsed nav.sidenav{width:var(--sidenav-w-collapsed); min-width:var(--sidenav-w-collapsed);}
.layout.is-collapsed nav.sidenav a{justify-content:center; padding:10px;}
.layout.is-collapsed nav.sidenav a span, .layout.is-collapsed .sidenav-section{
  position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;
}
.layout.is-collapsed .sidenav-collapse{justify-content:center;}
.layout.is-collapsed .sidenav-collapse span{display:none;}
.layout.is-collapsed .sidenav-collapse .icon{transform:rotate(180deg);}

@media (max-width:1080px){
  .layout:not(.is-collapsed) nav.sidenav{width:210px; min-width:210px;}
}

/* ==========================================================================
   Cartes
   ========================================================================== */
.card{
  background:var(--color-surface);
  border:1px solid var(--color-border); border-radius:var(--radius-lg); padding:26px; margin-bottom:18px;
  box-shadow:var(--shadow-card);
  animation: fadeInUp var(--dur-slow) var(--ease) both;
}
.card h2{margin:0 0 4px; font-family:'Cormorant Garamond',serif; font-size:1.42rem; color:var(--color-text-primary); font-weight:600; letter-spacing:.01em;}
.card .desc{color:var(--color-text-secondary); font-size:.85rem; margin-bottom:14px; line-height:1.5;}
.card--accent{border-color:color-mix(in srgb, var(--color-accent) 40%, var(--color-border));}
.card--quiet{box-shadow:none;}
.card-head{display:flex; justify-content:space-between; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:2px;}
.card-head .btn{padding:6px 12px; font-size:.75rem;}

/* ==========================================================================
   En-tête personnel de page ("Bonjour Elsa")
   ========================================================================== */
.page-hero{margin-bottom:34px; display:flex; justify-content:space-between; align-items:flex-end; gap:16px; flex-wrap:wrap;}
.page-hero h1{margin:0; font-size:clamp(1.9rem, 1.3rem + 2.4vw, 2.85rem); font-weight:600; line-height:1.08;}
.page-hero p{margin:7px 0 0; color:var(--color-text-secondary); font-size:1.02rem;}
.page-hero .hero-date{color:var(--color-text-muted); font-size:.82rem; white-space:nowrap;}

/* ==========================================================================
   Statistique héros — la donnée principale de la page
   --------------------------------------------------------------------------
   Directement sur le fond, jamais dans une carte : c'est la valeur elle-même
   qui doit dominer visuellement, pas son conteneur. Utilisée pour "jours depuis le début" en tête de dashboard.
   ========================================================================== */
.hero-stat{margin:18px 0 30px;}
.hero-stat .hs-value{
  font-family:'Cormorant Garamond',serif; font-weight:600; color:var(--color-text-primary);
  font-size:clamp(3.4rem, 2.6rem + 4vw, 5.4rem); line-height:.95; letter-spacing:-.01em;
}
.hero-stat .hs-label{font-size:.78rem; text-transform:uppercase; letter-spacing:.08em; color:var(--color-text-muted); margin-top:6px;}
.hero-stat .hs-meta{font-size:.85rem; color:var(--color-text-secondary); margin-top:2px;}

/* Rangée de statistiques secondaires — légère, jamais des cartes identiques
   (voir la note de conception). Simples groupes typographiques séparés par
   un filet vertical à peine visible. */
.stat-row{display:flex; flex-wrap:wrap; gap:26px; row-gap:16px; margin:0 0 30px;}
.stat-row .sr-item{display:flex; flex-direction:column; gap:2px; padding-left:18px; border-left:1px solid var(--color-border);}
.stat-row .sr-item:first-child{padding-left:0; border-left:none;}
.stat-row .sr-value{font-family:'Cormorant Garamond',serif; font-size:1.5rem; font-weight:600; color:var(--color-text-primary); line-height:1;}
.stat-row .sr-label{font-size:.68rem; text-transform:uppercase; letter-spacing:.06em; color:var(--color-text-muted);}
.stat-row .sr-meta{font-size:.72rem; color:var(--color-text-muted);}

/* Section "libre" : regroupe du contenu par l'espace et un léger séparateur,
   sans jamais dessiner une carte — réservé aux blocs qui n'ont pas besoin
   d'un conteneur pour se distinguer (voir la note de conception). */
.section{margin:0 0 34px;}
.section-head{display:flex; justify-content:space-between; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:12px;}
.section-head h2{margin:0; font-size:1.02rem; font-weight:600; color:var(--color-text-primary); font-family:'Inter',sans-serif; text-transform:uppercase; letter-spacing:.06em;}
.section-head h2.editorial{font-family:'Cormorant Garamond',serif; text-transform:none; letter-spacing:.01em; font-size:1.3rem;}

/* Lien discret ("Tout voir") : texte simple, jamais un bouton répété partout
   (voir la note de conception). */
.link-more{font-size:.78rem; color:var(--color-text-muted); text-decoration:none; display:inline-flex; align-items:center; gap:3px; transition:color var(--dur-fast) var(--ease);}
.link-more:hover{color:var(--color-accent);}
.link-more::after{content:'→'; font-size:.85em; transition:transform var(--dur-fast) var(--ease);}
.link-more:hover::after{transform:translateX(2px);}

/* ==========================================================================
   Statistiques façon "applications de santé"
   ========================================================================== */
.stat-grid{display:grid; grid-template-columns:repeat(auto-fit, minmax(128px,1fr)); gap:12px; margin-bottom:20px;}
.stat-card{
  background:var(--color-surface); border:1px solid var(--color-border); border-radius:var(--radius-md);
  padding:16px 16px 14px; display:flex; flex-direction:column; gap:4px; min-width:0;
  transition:background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.stat-card:hover{background:var(--color-surface-hover); border-color:var(--color-border-strong);}
.stat-card .stat-icon{color:var(--color-text-muted); margin-bottom:6px;}
.stat-card .stat-value{font-family:'Cormorant Garamond',serif; font-size:2rem; font-weight:600; color:var(--color-text-primary); line-height:1; white-space:nowrap;}
.stat-card .stat-value small{font-size:.95rem; color:var(--color-text-secondary); font-weight:500; margin-left:2px; font-family:'Inter',sans-serif;}
.stat-card .stat-label{font-size:.68rem; text-transform:uppercase; letter-spacing:.06em; color:var(--color-text-muted); margin-top:2px;}
.stat-card .stat-meta{font-size:.72rem; color:var(--color-text-muted); margin-top:2px;}
.stat-card .stat-trend{font-size:.74rem; display:inline-flex; align-items:center; gap:3px; margin-top:2px; font-weight:600;}
.stat-trend.up{color:var(--color-error);}
.stat-trend.down{color:var(--color-success);}
.stat-trend.flat{color:var(--color-text-muted);}
.stat-box{display:inline-block; margin:0 22px 10px 0;}
.stat-box .num{font-family:'Cormorant Garamond'; font-size:1.9rem; color:var(--color-accent); font-weight:600;}
.stat-box .lbl{font-size:.7rem; text-transform:uppercase; color:var(--color-text-muted);}

/* ==========================================================================
   Mise en avant (prochain rendez-vous, événement clé)
   ========================================================================== */
.spotlight{display:flex; gap:18px; align-items:center;}
.spotlight-date{
  display:flex; flex-direction:column; align-items:center; justify-content:center; flex-shrink:0;
  min-width:72px; padding:10px 8px; border-radius:var(--radius-md);
  background:var(--color-surface-elevated); border:1px solid var(--color-border);
}
.spotlight-date .day{font-family:'Cormorant Garamond',serif; font-size:2.1rem; color:var(--color-accent); font-weight:600; line-height:1;}
.spotlight-date .month{font-size:.62rem; text-transform:uppercase; letter-spacing:.08em; color:var(--color-text-muted); margin-top:3px;}
.spotlight-body{min-width:0;}
.spotlight-body h3{margin:0 0 2px; font-size:1.08rem; font-weight:600; overflow-wrap:anywhere;}
.spotlight-body .place{color:var(--color-text-secondary); font-size:.85rem;}
.spotlight-countdown{display:inline-block; margin-top:9px; padding:4px 11px; border-radius:var(--radius-pill); background:var(--color-accent-soft); color:var(--color-accent); font-size:.72rem; font-weight:600;}
.spotlight-empty{color:var(--color-text-secondary); font-size:.88rem;}

/* Listes compactes (rendez-vous suivants, événements récents…) */
.list-compact{list-style:none; margin:0; padding:0; display:flex; flex-direction:column;}
.list-compact li{display:flex; justify-content:space-between; align-items:center; gap:12px; padding:11px 0; border-bottom:1px solid var(--color-border);}
.list-compact li:last-child{border-bottom:none;}
.list-compact a.li-link{display:flex; justify-content:space-between; align-items:center; gap:12px; width:100%; text-decoration:none; color:inherit;}
.list-compact .li-date{font-size:.76rem; color:var(--color-text-muted); white-space:nowrap; min-width:78px;}
.list-compact .li-main{min-width:0; flex:1;}
.list-compact .li-title{color:var(--color-text-primary); font-size:.9rem;}
.list-compact .li-meta{color:var(--color-text-secondary); font-size:.78rem; margin-top:1px;}
.list-compact .li-sub{display:block; color:var(--color-text-secondary); font-size:.78rem; margin-top:1px;}
/* Groupe de boutons en fin de ligne. Écrit douze fois en style direct dans les vues, il
   n'avait nulle part les deux propriétés qui comptent : ne pas rétrécir, et savoir passer
   à la ligne quand la place manque vraiment. */
.li-actions{display:flex; gap:6px; align-items:center; flex-shrink:0; flex-wrap:wrap;}
.li-actions form{margin:0;}

/* ==========================================================================
   Traitement / posologie
   ========================================================================== */
.tx-card{display:flex; flex-direction:column; gap:14px;}
.tx-head{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;}
.tx-head h3{margin:0; font-size:1.25rem; font-weight:600;}
.tx-meta{color:var(--color-text-secondary); font-size:.85rem;}
.tx-since{color:var(--color-text-muted); font-size:.8rem;}
.dose-grid{display:flex; gap:26px; flex-wrap:wrap;}
.dose-col .dose-label{font-size:.65rem; text-transform:uppercase; letter-spacing:.08em; color:var(--color-text-muted);}
.dose-dots{display:flex; gap:5px; margin-top:6px;}
.dose-dots span{width:9px; height:9px; border-radius:50%; background:var(--color-accent); display:inline-block;}

/* ==========================================================================
   Timeline — repères "jour en cercle"
   --------------------------------------------------------------------------
   Regroupée par mois ; chaque événement est une seule ligne compacte (jour +
   libellé), reliée par une ligne verticale à peine visible. Ce n'est plus
   une carte contenant une longue liste : la timeline vit directement sur le
   fond de page.
   ========================================================================== */
.tl-month{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.1em; color:var(--color-text-muted);
  margin:26px 0 6px; font-weight:600;
}
.tl-month:first-child{margin-top:0;}
.tl{position:relative; list-style:none; margin:0; padding:0;}
.tl::before{content:'';position:absolute; left:17px; top:2px; bottom:2px; width:1px; background:var(--color-border); z-index:0;}
.tl-item{position:relative; display:flex; align-items:center; gap:14px; padding:6px 0;}
.tl-day{
  position:relative; z-index:1; flex-shrink:0; width:34px; height:34px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-family:'Cormorant Garamond',serif; font-size:.95rem; font-weight:600; color:var(--color-text-secondary);
  background:var(--color-bg); border:1px solid var(--color-border);
  transition:background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.tl-item.is-today .tl-day{background:var(--color-accent); color:var(--color-accent-contrast); border-color:var(--color-accent);}
.tl-body{min-width:0; flex:1;}
.tl-row{display:flex; gap:8px; flex-wrap:wrap; align-items:center;}
.tl-item .tl-date{font-size:.72rem; color:var(--color-text-muted); text-transform:uppercase; letter-spacing:.03em; white-space:nowrap;}
.tl-item .tl-title{font-size:.88rem; color:var(--color-text-primary);}
.tl-item a.tl-title-link{color:inherit; text-decoration:none; display:block;}
.tl-item a.tl-title-link:hover .tl-title{color:var(--color-accent);}
.tl-item .tl-sub{font-size:.78rem; color:var(--color-text-secondary); margin-top:1px;}
.tl-item .tl-actions{margin-top:4px; display:flex; gap:6px;}

/* ==========================================================================
   Formulaires
   ========================================================================== */
label{display:block; font-size:.7rem; text-transform:uppercase; letter-spacing:.06em; color:var(--color-text-muted); margin:12px 0 5px; font-weight:600;}
.info-btn{
  display:inline-flex; align-items:center; justify-content:center; width:15px; height:15px;
  border-radius:50%; border:1px solid var(--color-text-muted); background:transparent; color:var(--color-text-muted);
  font-size:.65rem; line-height:1; cursor:pointer; padding:0; vertical-align:middle; text-transform:none;
}
.info-btn:hover{ border-color:var(--color-accent); color:var(--color-accent); }
.info-box{
  display:none; margin-top:4px; padding:8px 10px; border-radius:var(--radius-sm); background:var(--color-surface-elevated);
  border:1px solid var(--color-border); color:var(--color-text-primary); font-size:.78rem; text-transform:none;
  letter-spacing:normal; line-height:1.4;
}
input,select,textarea{
  width:100%; background:var(--color-bg); border:1px solid var(--color-border); color:var(--color-text-primary);
  padding:10px 12px; border-radius:var(--radius-sm); font-family:inherit; font-size:.9rem;
  transition:border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
input:focus, select:focus, textarea:focus{outline:none; border-color:var(--color-accent); box-shadow:0 0 0 3px var(--color-accent-soft);}
select:hover{border-color:var(--color-border-strong);}
select option{background:var(--color-surface); color:var(--color-text-primary);}
select:disabled, input:disabled, textarea:disabled{opacity:.55; cursor:not-allowed;}
.form-row{display:flex; gap:12px; flex-wrap:wrap;}
.form-row > div{flex:1; min-width:160px;}

/* ==========================================================================
   Boutons
   ========================================================================== */
button, .btn{
  cursor:pointer; border:none; border-radius:var(--radius-sm); padding:10px 18px; font-size:.85rem; font-weight:600;
  background:var(--color-accent); color:var(--color-accent-contrast); text-decoration:none; display:inline-flex;
  align-items:center; gap:8px; transition:filter var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
/* Un libellé de bouton ne se coupe pas. Sans cette ligne, un bouton pris dans une rangée
   trop étroite se laisse comprimer jusqu'à la largeur d'une lettre, et « Supprimer »
   s'écrit verticalement. Un bouton qui ne tient pas doit passer à la ligne suivante en
   entier, pas se replier sur lui-même. */
button, .btn{white-space:nowrap;}
button:hover, .btn:hover{filter:brightness(1.08);}
button:active, .btn:active{transform:translateY(1px);}
.btn.ghost{background:transparent; border:1px solid var(--color-border); color:var(--color-text-secondary); font-weight:500;}
.btn.ghost:hover{border-color:var(--color-accent); color:var(--color-accent); filter:none;}
.btn.subtle{background:var(--color-surface-elevated); color:var(--color-text-primary); font-weight:500;}
.btn.subtle:hover{background:var(--color-surface-hover); filter:none;}
.btn.danger{background:var(--color-error); color:#241511;}
.btn.icon-only{padding:9px; }
.btn.sm{padding:6px 12px; font-size:.76rem;}

/* ==========================================================================
   Tableaux / badges / alertes
   ========================================================================== */
table{width:100%; border-collapse:collapse; margin-top:10px; font-size:.85rem;}
th,td{padding:10px 12px; border-bottom:1px solid var(--color-border); text-align:left;}
th{color:var(--color-text-muted); font-size:.68rem; text-transform:uppercase; letter-spacing:.05em; font-weight:600;}
tbody tr{transition:background var(--dur-fast) var(--ease);}
tbody tr:hover{background:var(--color-surface-hover);}
.badge{display:inline-block; padding:3px 10px; border-radius:var(--radius-pill); font-size:.7rem; background:var(--color-accent-soft); color:var(--color-accent); font-weight:600;}
.badge.neutral{background:transparent; border:1px solid var(--color-border); color:var(--color-text-secondary); font-weight:500;}
.badge.success{background:color-mix(in srgb, var(--color-success) 18%, transparent); color:var(--color-success);}
.badge.warning{background:color-mix(in srgb, var(--color-warning) 18%, transparent); color:var(--color-warning);}
.badge.error{background:color-mix(in srgb, var(--color-error) 18%, transparent); color:var(--color-error);}
.badge.info{background:color-mix(in srgb, var(--color-info) 18%, transparent); color:var(--color-info);}
.alert{padding:13px 16px; border-radius:var(--radius-md); margin-bottom:16px; font-size:.88rem; border:1px solid transparent;}
.alert.success{background:color-mix(in srgb, var(--color-success) 14%, transparent); color:var(--color-success); border-color:color-mix(in srgb, var(--color-success) 45%, transparent);}
.alert.error{background:color-mix(in srgb, var(--color-error) 14%, transparent); color:var(--color-error); border-color:color-mix(in srgb, var(--color-error) 45%, transparent);}
.alert.info{background:var(--color-accent-soft); color:var(--color-accent); border-color:color-mix(in srgb, var(--color-accent) 45%, transparent);}
.grid-2{display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:18px;}

/* États vides */
.empty-state{padding:18px 4px; color:var(--color-text-secondary); font-size:.88rem; display:flex; flex-direction:column; gap:4px;}
.empty-state .empty-title{color:var(--color-text-primary); font-weight:600; font-size:.92rem;}

/* Chargement */
.spinner{width:18px; height:18px; border-radius:50%; border:2px solid var(--color-border); border-top-color:var(--color-accent); animation:spin .7s linear infinite; display:inline-block;}
@keyframes spin{to{transform:rotate(360deg);}}

/* Onglets */
.tabs{display:flex; gap:6px; flex-wrap:wrap; border-bottom:1px solid var(--color-border); margin-bottom:18px; padding-bottom:0;}
.tabs a, .tabs button{
  background:transparent; border:none; color:var(--color-text-secondary); padding:9px 4px; margin-right:18px; font-size:.85rem;
  font-weight:500; border-bottom:2px solid transparent; border-radius:0; cursor:pointer;
}
.tabs a.active, .tabs button.active{color:var(--color-accent); border-bottom-color:var(--color-accent); font-weight:600;}

/* ==========================================================================
   Authentification / pages autonomes
   ========================================================================== */
.auth-wrap{
  min-height:100vh; display:flex; align-items:center; justify-content:center;
  padding:calc(20px + var(--sr-haut)) calc(20px + var(--sr-droite))
          calc(20px + var(--sr-bas)) calc(20px + var(--sr-gauche));
}
.auth-card{width:100%; max-width:420px;}
.auth-card .card{animation:fadeInUp var(--dur-slow) var(--ease) both;}
.lang-switch{display:flex; border:1px solid var(--color-border); border-radius:var(--radius-sm); overflow:hidden;}
.lang-switch a{padding:7px 10px; font-size:.72rem; font-weight:600; text-decoration:none; color:var(--color-text-secondary);}
.lang-switch a.active{background:var(--color-accent); color:var(--color-accent-contrast);}

/* ==========================================================================
   Profil public — en-tête
   ========================================================================== */
.public-hero{display:flex; align-items:center; gap:20px; flex-wrap:wrap;}
.public-hero .avatar{width:84px; height:84px; border-radius:50%; object-fit:cover; border:1px solid var(--color-border); flex-shrink:0;}
.public-hero h1{margin:0; font-size:1.7rem;}
.public-hero .bio{color:var(--color-text-secondary); margin-top:8px; max-width:56ch;}
.public-hero .badges{display:flex; gap:6px; flex-wrap:wrap; margin-top:10px;}

/* ==========================================================================
   Photos
   ========================================================================== */
.thumb{width:100%; aspect-ratio:3/4; object-fit:cover; border-radius:var(--radius-md); border:1px solid var(--color-border);}
.photo-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(140px,1fr)); gap:14px;}

/* ==========================================================================
   Pied de page
   ========================================================================== */
footer.appfooter{
  text-align:center; color:var(--color-text-muted); font-size:.75rem; line-height:1.7;
  padding:34px calc(20px + var(--sr-droite)) 26px calc(20px + var(--sr-gauche));
}
footer.appfooter a{color:var(--color-text-secondary); text-decoration:none;}
footer.appfooter a:hover{color:var(--color-accent);}
footer.appfooter .footer-sep{margin:0 6px; opacity:.5;}

/* ==========================================================================
   Graphiques (chart.js maison)
   ========================================================================== */
.chart-wrap{position:relative;}
.chart-tooltip{
  display:none; position:absolute; transform:translate(-50%, -100%);
  margin-top:-10px; background:var(--color-surface-elevated); color:var(--color-text-primary); border:1px solid var(--color-border);
  border-radius:var(--radius-sm); padding:6px 11px; font-size:.78rem; white-space:nowrap;
  box-shadow:var(--shadow-elevated); pointer-events:none; z-index:5; max-width:220px;
}
.chart-tooltip--right{transform:translate(-90%, -100%);}
.chart-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:thin; scrollbar-color:var(--color-border) transparent;}
.chart-scroll:focus-visible{outline:2px solid var(--color-accent); outline-offset:-2px;}
.chart-scroll::-webkit-scrollbar{height:8px;}
.chart-scroll::-webkit-scrollbar-track{background:transparent;}
.chart-scroll::-webkit-scrollbar-thumb{background:var(--color-border); border-radius:4px;}
.chart-scroll::-webkit-scrollbar-thumb:hover{background:var(--color-accent);}
.table-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch; margin-top:10px; scrollbar-width:thin; scrollbar-color:var(--color-border) transparent;}
.table-scroll table{margin-top:0;}
.table-scroll:focus-visible{outline:2px solid var(--color-accent); outline-offset:-2px;}
.table-scroll::-webkit-scrollbar{height:8px;}
.table-scroll::-webkit-scrollbar-track{background:transparent;}
.table-scroll::-webkit-scrollbar-thumb{background:var(--color-border); border-radius:4px;}
.table-scroll::-webkit-scrollbar-thumb:hover{background:var(--color-accent);}
.period-select{width:auto; padding:6px 30px 6px 12px; font-size:.78rem;}
.chip-row{display:flex; gap:8px; flex-wrap:wrap;}
.chip{padding:6px 14px; border:1px solid var(--color-border); border-radius:var(--radius-pill); font-size:.78rem; cursor:pointer; color:var(--color-text-secondary); background:transparent; transition:all var(--dur-fast) var(--ease);}
.chip:hover{border-color:var(--color-accent);}
.chip.active{background:var(--color-accent); color:var(--color-accent-contrast); border-color:var(--color-accent); font-weight:600;}

/* ==========================================================================
   Interrupteur (booléens)
   ========================================================================== */
input.switch{
  appearance:none; -webkit-appearance:none; -moz-appearance:none;
  width:42px; height:24px; min-width:42px; flex-shrink:0; padding:0; margin:0;
  border-radius:999px; background:var(--color-bg); border:1px solid var(--color-border);
  position:relative; cursor:pointer; transition:background .15s, border-color .15s;
}
input.switch::before{
  content:''; position:absolute; top:2px; left:2px; width:18px; height:18px; border-radius:50%;
  background:var(--color-text-muted); transition:transform .15s, background .15s;
}
input.switch:checked{ background:var(--color-accent); border-color:var(--color-accent); }
input.switch:checked::before{ transform:translateX(18px); background:var(--color-accent-contrast); }
input.switch:focus-visible{ outline:2px solid var(--color-accent); outline-offset:2px; }
input.switch:disabled{ opacity:.5; cursor:not-allowed; }

/* ==========================================================================
   Bouton menu (mobile)
   ========================================================================== */
.burger-btn{
  display:none; flex-direction:column; justify-content:center; align-items:center; gap:4px;
  width:38px; height:38px; border:1px solid var(--color-border); border-radius:var(--radius-sm); background:transparent;
  cursor:pointer; padding:0; flex-shrink:0;
}
.burger-btn span{display:block; width:18px; height:2px; background:var(--color-text-primary); transition:transform .15s, opacity .15s;}
.burger-btn.open span:nth-child(1){transform:translateY(6px) rotate(45deg);}
.burger-btn.open span:nth-child(2){opacity:0;}
.burger-btn.open span:nth-child(3){transform:translateY(-6px) rotate(-45deg);}

/* ==========================================================================
   Action rapide "+"
   ========================================================================== */
.quick-add{position:relative;}
.quick-add-btn{
  width:38px; height:38px; padding:0; justify-content:center; border-radius:var(--radius-pill);
  background:var(--color-accent); color:var(--color-accent-contrast); font-size:1.2rem; line-height:1;
}
.quick-add-menu{
  display:none; position:absolute; right:0; top:calc(100% + 8px); min-width:220px; z-index:30;
  background:var(--color-surface-elevated); border:1px solid var(--color-border); border-radius:var(--radius-md);
  box-shadow:var(--shadow-elevated); padding:6px; flex-direction:column; gap:1px;
}
.quick-add.open .quick-add-menu{display:flex;}
.quick-add-menu a{
  display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:var(--radius-sm); text-decoration:none;
  color:var(--color-text-secondary); font-size:.85rem;
}
.quick-add-menu a:hover{background:var(--color-surface-hover); color:var(--color-text-primary);}
.quick-add-backdrop{display:none;}
.quick-add.open .quick-add-backdrop{display:block; position:fixed; inset:0; z-index:25;}

/* ==========================================================================
   Navigation basse (mobile)
   ========================================================================== */
.bottom-nav{display:none;}

/* ==========================================================================
   Animations discrètes
   ========================================================================== */
@keyframes fadeInUp{ from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:translateY(0);} }
.card:nth-of-type(1){animation-delay:0ms;}
.card:nth-of-type(2){animation-delay:40ms;}
.card:nth-of-type(3){animation-delay:80ms;}
.card:nth-of-type(4){animation-delay:120ms;}

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

@media (max-width:860px){
  .chart-tooltip{white-space:normal; font-size:.74rem;}
}

/* ==========================================================================
   Responsive — tablette
   ========================================================================== */
@media (max-width:1080px) and (min-width:861px){
  .layout{gap:18px; padding:20px;}
  .stat-grid{grid-template-columns:repeat(3, 1fr);}
}

/* ==========================================================================
   Responsive — mobile
   ========================================================================== */
@media (max-width:860px){
  .wrap{padding:0 16px;}
  header.topbar{
    padding:calc(14px + var(--sr-haut)) calc(16px + var(--sr-droite))
            14px calc(16px + var(--sr-gauche));
  }
  .burger-btn{display:flex;}
  .layout{flex-direction:column; padding:12px 12px 88px;}
  nav.sidenav{
    display:none; flex-direction:column; width:100%; min-width:0; max-width:100%; position:static;
    background:var(--color-surface-elevated); border:1px solid var(--color-border); border-radius:var(--radius-lg);
    padding:8px; margin-bottom:14px; box-sizing:border-box;
  }
  nav.sidenav.open{display:flex;}
  nav.sidenav a{padding:12px 14px; font-size:.95rem;} /* cible tactile confortable */
  .sidenav-collapse{display:none;}
  .layout main{width:100%; min-width:0;}
  .form-row > div{min-width:0; flex-basis:100%;}
  table{display:block; overflow-x:auto; -webkit-overflow-scrolling:touch;}
  .stat-grid{grid-template-columns:repeat(2, 1fr);}
  .page-hero{align-items:flex-start;}
  .spotlight{flex-wrap:wrap;}

  .bottom-nav{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:20; justify-content:space-around; align-items:center;
    padding:8px calc(6px + var(--sr-droite)) calc(8px + var(--sr-bas))
            calc(6px + var(--sr-gauche));
    background:color-mix(in srgb, var(--bg-b) 92%, transparent);
    backdrop-filter:blur(14px); border-top:1px solid var(--color-border);
  }
  .bottom-nav a, .bottom-nav button{
    display:flex; flex-direction:column; align-items:center; gap:3px; color:var(--color-text-muted); text-decoration:none;
    font-size:.62rem; padding:4px 10px; border-radius:var(--radius-sm); background:none; border:none; cursor:pointer; font-family:inherit;
  }
  .bottom-nav a .icon, .bottom-nav button .icon{width:20px; height:20px;}
  .bottom-nav a.active{color:var(--color-accent);}
  .bottom-nav button.bn-add{color:var(--color-accent-contrast);}
  .bottom-nav button.bn-add .bn-add-circle{
    width:44px; height:44px; border-radius:50%; background:var(--color-accent); display:flex; align-items:center; justify-content:center;
    margin-top:-22px; box-shadow:var(--shadow-elevated); font-size:1.4rem; line-height:1;
  }
  .topbar .quick-add{display:none;}
  .bottom-nav .quick-add-menu{
    position:fixed; top:auto; width:auto; min-width:0;
    right:calc(14px + var(--sr-droite)); left:calc(14px + var(--sr-gauche));
    bottom:calc(78px + var(--sr-bas));
  }
}

/* ==========================================================================
   ==========================================================================
   CONSULTATION D'ABORD, AJOUT ENSUITE
   --------------------------------------------------------------------------
   Tout ce qui suit sert une seule idée : une page s'ouvre sur DES DONNÉES,
   jamais sur un formulaire. L'ajout est une action discrète (.add-action),
   la saisie vit dans une modale (.modal-overlay / .modal), et la lecture
   s'appuie sur de grandes valeurs (.data-hero, .kv-grid) plutôt que sur des
   tableaux administratifs.
   ==========================================================================
   ========================================================================== */

/* --------------------------------------------------------------------------
   En-tête de rubrique — le titre, la donnée principale, puis l'action.
   -------------------------------------------------------------------------- */
.page-head{margin:0 0 30px;}
.page-head .ph-eyebrow{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.14em; color:var(--color-text-muted);
  font-weight:600; margin-bottom:10px;
}
.page-head h1{
  margin:0; font-family:'Cormorant Garamond',serif; font-weight:600;
  font-size:clamp(1.9rem, 1.3rem + 2.4vw, 2.85rem); line-height:1.08; letter-spacing:.01em;
}
.page-head .ph-sub{margin:7px 0 0; color:var(--color-text-secondary); font-size:1.02rem;}
.page-head .ph-row{display:flex; justify-content:space-between; align-items:flex-end; gap:18px; flex-wrap:wrap;}

/* --------------------------------------------------------------------------
   Donnée principale d'une rubrique — posée sur le fond, jamais dans une carte.
   Ex. Mesurations : « 86,9 kg » puis « Dernière mesure · 27 juillet 2026 ».
   -------------------------------------------------------------------------- */
.data-hero{margin:0 0 34px;}
.data-hero .dh-value{
  font-family:'Cormorant Garamond',serif; font-weight:600; color:var(--color-text-primary);
  font-size:clamp(3rem, 2.2rem + 3.6vw, 4.6rem); line-height:.95; letter-spacing:-.012em;
}
.data-hero .dh-value .dh-unit{
  font-family:'Inter',sans-serif; font-size:.28em; font-weight:500;
  color:var(--color-text-secondary); margin-left:.22em; letter-spacing:0;
}
.data-hero .dh-label{
  font-size:.72rem; text-transform:uppercase; letter-spacing:.1em; color:var(--color-text-muted);
  margin-top:12px; font-weight:600;
}
.data-hero .dh-meta{font-size:.88rem; color:var(--color-text-secondary); margin-top:4px;}
.data-hero .dh-trend{font-size:.84rem; margin-top:6px; font-weight:600;}
.data-hero .dh-trend.up{color:var(--color-error);}
.data-hero .dh-trend.down{color:var(--color-success);}
.data-hero .dh-trend.flat{color:var(--color-text-muted);}

/* --------------------------------------------------------------------------
   Grille de valeurs — un libellé discret, une valeur lisible. Remplace les
   tableaux dès qu'il s'agit de LIRE un enregistrement (dernier bilan, dernière
   mesure, détail d'un rendez-vous).
   -------------------------------------------------------------------------- */
.kv-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); gap:22px 26px;}
.kv{min-width:0;}
.kv .kv-label{
  font-size:.65rem; text-transform:uppercase; letter-spacing:.09em; color:var(--color-text-muted);
  font-weight:600; margin-bottom:5px;
}
.kv .kv-value{
  font-family:'Cormorant Garamond',serif; font-size:1.65rem; font-weight:600; line-height:1.05;
  color:var(--color-text-primary); overflow-wrap:anywhere;
}
.kv .kv-value.is-empty{color:var(--color-text-muted); font-size:1.2rem;}
.kv .kv-value small{font-family:'Inter',sans-serif; font-size:.55em; font-weight:500; color:var(--color-text-secondary); margin-left:3px;}
.kv .kv-value.kv-text{font-family:'Inter',sans-serif; font-size:.95rem; font-weight:400; line-height:1.5;}

/* --------------------------------------------------------------------------
   Action d'ajout — un lien doré discret, jamais un gros bouton plein qui
   dominerait les données qu'il accompagne.
   -------------------------------------------------------------------------- */
.add-action{
  border:0; background:transparent; color:var(--color-accent); font-size:.92rem; font-weight:500;
  cursor:pointer; padding:6px 0; display:inline-flex; align-items:center; gap:7px; font-family:inherit;
  text-decoration:none; border-radius:var(--radius-sm);
}
.add-action:hover{filter:none; text-decoration:underline; text-underline-offset:3px;}
.add-action:active{transform:none;}
.add-action .icon{width:15px; height:15px;}
.add-action--block{margin-top:22px;}

/* Rangée d'actions secondaires d'un enregistrement : texte discret, jamais des
   boutons pleins alignés (pas de croix, pas de boutons partout). */
.row-actions{display:flex; gap:14px; align-items:center; flex-wrap:wrap;}
.row-actions form{margin:0;}
.link-action{
  background:none; border:0; padding:0; font-family:inherit; font-size:.78rem; font-weight:500;
  color:var(--color-text-muted); cursor:pointer; text-decoration:none; display:inline-flex; align-items:center; gap:5px;
}
.link-action:hover{color:var(--color-accent); filter:none; text-decoration:underline; text-underline-offset:3px;}
.link-action:active{transform:none;}
.link-action.is-danger:hover{color:var(--color-error);}

/* --------------------------------------------------------------------------
   Liste d'enregistrements — l'historique d'une rubrique. Une ligne = une date
   discrète + un contenu lisible. Aucune bordure de tableau, aucun en-tête de
   colonne : ce n'est pas un back-office.
   -------------------------------------------------------------------------- */
.record-list{list-style:none; margin:0; padding:0;}
.record-list > li{
  display:flex; gap:20px; align-items:flex-start; padding:16px 0;
  border-bottom:1px solid var(--color-border);
}
.record-list > li:last-child{border-bottom:none;}
.rec-date{
  flex-shrink:0; width:74px; font-size:.76rem; color:var(--color-text-muted); padding-top:3px;
  font-variant-numeric:tabular-nums;
}
.rec-body{flex:1; min-width:0;}
.rec-title{font-size:.98rem; color:var(--color-text-primary); font-weight:500;}
.rec-meta{font-size:.82rem; color:var(--color-text-secondary); margin-top:3px; line-height:1.5;}
.rec-values{display:flex; flex-wrap:wrap; gap:6px 18px; margin-top:7px;}
.rec-values span{font-size:.8rem; color:var(--color-text-secondary);}
.rec-values span b{color:var(--color-text-primary); font-weight:600; font-variant-numeric:tabular-nums;}
.rec-side{flex-shrink:0; display:flex; flex-direction:column; align-items:flex-end; gap:8px;}

/* --------------------------------------------------------------------------
   Repère de date en pastille (prochain rendez-vous, en-tête d'un événement).
   -------------------------------------------------------------------------- */
.date-chip{
  display:flex; flex-direction:column; align-items:center; justify-content:center; flex-shrink:0;
  width:70px; height:76px; border-radius:var(--radius-md);
  background:var(--color-surface-elevated); border:1px solid var(--color-border);
}
.date-chip .dc-day{font-family:'Cormorant Garamond',serif; font-size:1.85rem; font-weight:600; color:var(--color-accent); line-height:1;}
.date-chip .dc-month{font-size:.6rem; text-transform:uppercase; letter-spacing:.09em; color:var(--color-text-muted); margin-top:4px;}

/* ==========================================================================
   MODALES DE SAISIE
   --------------------------------------------------------------------------
   Principe : la page reste visible derrière, simplement assombrie. La modale
   est compacte, lisible, et parle le même langage visuel que le tableau de
   bord. Sur mobile elle devient un panneau qui monte depuis le bas et occupe
   presque tout l'écran — jamais un formulaire desktop rétréci.

   Fermeture : bouton « Annuler » explicite, petite
   icône de fermeture correctement placée DANS l'en-tête, touche Échap, ou clic
   sur le fond. Aucune croix ailleurs, et jamais une croix à la place d'un
   bouton d'action. Comportement : public/assets/js/modal.js.
   ========================================================================== */
.modal-overlay{
  position:fixed; inset:0; z-index:60; display:none;
  align-items:center; justify-content:center; padding:24px;
  background:rgba(4,8,17,.62); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
}
.modal-overlay.open{display:flex; animation:modalFade var(--dur-med) var(--ease) both;}
.modal{
  width:min(560px, 100%); max-height:calc(100vh - 48px); overflow-y:auto;
  background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:var(--radius-xl); padding:30px; box-shadow:var(--shadow-elevated);
  animation:modalRise var(--dur-med) var(--ease) both;
}
.modal--wide{width:min(760px, 100%);}
.modal-head{display:flex; justify-content:space-between; align-items:flex-start; gap:16px; margin-bottom:24px;}
.modal-title{
  margin:0; font-family:'Cormorant Garamond',serif; font-size:1.75rem; font-weight:600;
  color:var(--color-text-primary); line-height:1.15;
}
.modal-sub{margin:6px 0 0; color:var(--color-text-secondary); font-size:.86rem; line-height:1.5;}
/* Discrète, alignée dans l'en-tête, jamais confondue avec une action principale. */
.modal-close{
  flex-shrink:0; width:32px; height:32px; padding:0; border:0; border-radius:50%;
  background:transparent; color:var(--color-text-muted); cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center; font-size:1.25rem; line-height:1;
}
.modal-close:hover{background:var(--color-surface-elevated); color:var(--color-text-primary); filter:none;}
.modal-close:active{transform:none;}

.modal-body{display:grid; grid-template-columns:1fr 1fr; gap:16px 18px;}
.modal-body .field{min-width:0;}
.modal-body .field.full{grid-column:1 / -1;}
.modal-body label{margin-top:0;}
.modal-body .field-help{font-size:.76rem; color:var(--color-text-muted); margin-top:5px; line-height:1.45; text-transform:none; letter-spacing:normal;}
.modal-body .check-row{
  display:flex; align-items:center; gap:10px; text-transform:none; letter-spacing:normal;
  font-size:.88rem; color:var(--color-text-primary); font-weight:400; margin:0;
}
.modal-body .check-row input{width:auto;}

.modal-actions{display:flex; justify-content:flex-end; align-items:center; gap:12px; margin-top:26px; flex-wrap:wrap;}
.modal-actions .spacer{margin-right:auto;}
.modal-actions .btn.ghost, .modal-actions button.secondary{font-weight:500;}

@keyframes modalFade{from{opacity:0;} to{opacity:1;}}
@keyframes modalRise{from{opacity:0; transform:translateY(14px) scale(.985);} to{opacity:1; transform:none;}}

/* Empêche le défilement de l'arrière-plan pendant qu'une modale est ouverte. */
body.modal-open{overflow:hidden;}

/* ==========================================================================
   Menu « + » contextuel
   --------------------------------------------------------------------------
   La première entrée est TOUJOURS celle de la rubrique consultée quand elle
   existe : elle est visuellement prioritaire (doré, description sous le
   libellé), les autres suivent, discrètes. L'ordre est calculé côté serveur
   dans views/layout.php à partir du chemin courant.
   ========================================================================== */
.quick-add-menu{min-width:266px; padding:8px;}
.quick-add-menu .qa-heading{
  font-size:.62rem; text-transform:uppercase; letter-spacing:.12em; color:var(--color-text-muted);
  font-weight:600; padding:6px 10px 8px;
}
.quick-add-menu .qa-sep{height:1px; background:var(--color-border); margin:6px 8px;}
.quick-add-menu a.qa-primary{
  color:var(--color-accent); background:var(--color-accent-soft); align-items:flex-start; padding:11px 10px;
}
.quick-add-menu a.qa-primary:hover{background:color-mix(in srgb, var(--color-accent) 22%, transparent); color:var(--color-accent);}
.quick-add-menu a.qa-primary .icon{margin-top:2px;}
.quick-add-menu a.qa-primary .qa-text{display:flex; flex-direction:column; gap:2px;}
.quick-add-menu a.qa-primary .qa-label{font-weight:600;}
.quick-add-menu a.qa-primary .qa-desc{font-size:.75rem; color:var(--color-text-secondary); font-weight:400;}

/* ==========================================================================
   Graphique compact intégré à une page de consultation
   ========================================================================== */
.mini-chart{margin:6px 0 30px;}
.mini-chart svg{width:100%; height:180px; display:block;}

/* ==========================================================================
   Séparateur de section respirant (remplace un titre de carte quand il n'y a
   pas besoin de conteneur).
   ========================================================================== */
.section--airy{margin:0 0 44px;}
.section-rule{border:0; border-top:1px solid var(--color-border); margin:0 0 26px;}

/* ==========================================================================
   PROFIL PUBLIC & PARTAGE TEMPORAIRE
   --------------------------------------------------------------------------
   Deux expériences de CONSULTATION autonomes : aucune administration, aucun
   formulaire, aucun bouton réservé au propriétaire. Elles partagent le langage
   visuel de l'application sans en reprendre la mise en page de travail.
   ========================================================================== */
.pub-shell{max-width:820px; margin:0 auto;
  padding:0 calc(22px + var(--sr-droite)) 70px calc(22px + var(--sr-gauche));}
.pub-shell--wide{max-width:980px;}

.pub-masthead{padding:56px 0 40px; text-align:center;}
.pub-masthead .pm-avatar{
  width:96px; height:96px; border-radius:50%; object-fit:cover; margin:0 auto 22px; display:block;
  border:1px solid var(--color-border);
}
.pub-masthead .pm-name{
  margin:0; font-family:'Cormorant Garamond',serif; font-weight:600; line-height:1.05;
  font-size:clamp(2.2rem, 1.5rem + 3vw, 3.4rem); letter-spacing:.01em;
}
.pub-masthead .pm-kicker{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.16em; color:var(--color-text-muted);
  font-weight:600; margin-bottom:14px;
}
.pub-masthead .pm-tagline{margin:10px auto 0; color:var(--color-text-secondary); font-size:1.02rem; max-width:52ch; line-height:1.6;}
.pub-masthead .pm-badges{display:flex; gap:8px; flex-wrap:wrap; justify-content:center; margin-top:18px;}

/* Compteur d'ouverture : « Depuis le 25 juin 2026 — 39 jours ». */
.pub-since{
  display:flex; align-items:baseline; justify-content:center; gap:14px; flex-wrap:wrap;
  margin:30px 0 0; padding-top:26px; border-top:1px solid var(--color-border);
}
.pub-since .ps-value{font-family:'Cormorant Garamond',serif; font-size:3.2rem; font-weight:600; line-height:1;}
.pub-since .ps-label{font-size:.72rem; text-transform:uppercase; letter-spacing:.1em; color:var(--color-text-muted); font-weight:600;}
.pub-since .ps-date{font-size:.86rem; color:var(--color-text-secondary);}

.pub-section-title{
  font-family:'Cormorant Garamond',serif; font-size:1.55rem; font-weight:600; margin:0 0 18px;
  color:var(--color-text-primary);
}
.pub-block{margin:0 0 48px;}

/* En-tête d'un partage temporaire : on annonce clairement ce que c'est. */
.share-masthead{padding:52px 0 34px; border-bottom:1px solid var(--color-border); margin-bottom:44px;}
.share-masthead .sm-brand{font-size:1.32rem; font-weight:600; letter-spacing:.01em;}
.share-masthead .sm-brand span{color:var(--color-accent); font-style:italic;}
.share-masthead .sm-title{
  margin:20px 0 0; font-family:'Cormorant Garamond',serif; font-weight:600; line-height:1.1;
  font-size:clamp(1.7rem, 1.2rem + 2vw, 2.5rem);
}
.share-masthead .sm-meta{margin-top:12px; display:flex; gap:10px; flex-wrap:wrap; align-items:center;}

/* Bandeau propriétaire (aperçu, profil suivi) : nettement séparé du contenu
   consulté, pour qu'on ne le confonde jamais avec la page publique elle-même. */
.owner-banner{
  display:flex; justify-content:space-between; align-items:center; gap:14px; flex-wrap:wrap;
  padding:12px 18px; border-radius:var(--radius-md); margin-bottom:26px;
  background:var(--color-accent-soft); color:var(--color-accent); font-size:.85rem;
  border:1px solid color-mix(in srgb, var(--color-accent) 35%, transparent);
}

/* Sélecteur de thème de la page publique : discret, en haut à droite. */
.pub-theme{display:flex; justify-content:flex-end; gap:2px; padding-top:18px;}
.pub-theme button{
  background:none; border:0; padding:7px 9px; border-radius:var(--radius-sm); cursor:pointer;
  color:var(--color-text-muted); font-size:.9rem; line-height:1;
}
.pub-theme button:hover{background:var(--color-surface); color:var(--color-text-primary); filter:none;}
.pub-theme button:active{transform:none;}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width:860px){
  /* Une modale devient un panneau qui monte depuis le bas : on ne rétrécit
     jamais simplement la version desktop (et non une version desktop rétrécie). */
  .modal-overlay{padding:0; align-items:flex-end;}
  .modal{
    width:100%; max-width:100%; max-height:92vh;
    padding:22px calc(20px + var(--sr-droite)) calc(22px + var(--sr-bas))
            calc(20px + var(--sr-gauche));
    border-radius:var(--radius-xl) var(--radius-xl) 0 0; border-bottom:0;
    animation:modalSheet var(--dur-med) var(--ease) both;
  }
  .modal-body{grid-template-columns:1fr;}
  .modal-body .field.full{grid-column:auto;}
  .modal-title{font-size:1.45rem;}
  .modal-actions{margin-top:22px;}
  .modal-actions .btn, .modal-actions button{flex:1; justify-content:center; min-height:44px;}
  .modal-actions .spacer{flex:0 0 100%; margin:0 0 6px;}

  .record-list > li{flex-direction:column; gap:6px;}
  .rec-date{width:auto; padding-top:0;}
  .rec-side{flex-direction:row; align-items:center; align-self:flex-start;}
  .kv-grid{grid-template-columns:repeat(auto-fill, minmax(118px, 1fr)); gap:18px;}
  .page-head{margin-bottom:24px;}
  .pub-shell{padding:0 18px 60px;}
  .pub-masthead{padding:36px 0 28px;}
  .add-action{min-height:44px;}
  .quick-add-menu{min-width:0;}
}

/* ==========================================================================
   Téléphone — ce qui ne peut pas rester une rangée
   --------------------------------------------------------------------------
   Une rangée horizontale n'est pas une mise en page : c'est un pari sur la
   largeur disponible. Sur un écran de 360 points, ce pari est perdu, et le
   navigateur le règle en comprimant ce qu'il peut — c'est-à-dire le texte.

   On préfère décider nous-mêmes de ce qui passe à la ligne : la date d'abord,
   le contenu ensuite, les commandes en dernier. Rien n'est masqué, rien n'est
   déplacé dans un menu : la page contient exactement les mêmes éléments,
   empilés au lieu d'être alignés.
   ========================================================================== */
@media (max-width:640px){

  .list-compact li, .list-compact a.li-link{
    flex-wrap:wrap; align-items:flex-start; gap:6px 10px; padding:14px 0;
  }
  /* La date monte en tête de bloc : c'est elle qui distingue deux lignes
     voisines, elle doit se lire avant le reste. */
  .list-compact .li-date{flex:0 0 100%; min-width:0;}
  .list-compact .li-main{flex:1 1 100%;}
  /* Les commandes rejoignent la rangée précédente si elles y tiennent, et
     descendent d'un rang sinon — au lieu d'écraser ce qui les précède. */
  .list-compact .li-actions{flex:1 1 auto; justify-content:flex-end;}

  /* Cible tactile : 38 points de haut, sans changer la largeur des libellés. */
  .li-actions .btn, .li-actions button,
  .row-actions .btn, .row-actions button{min-height:38px;}

  /* Rendez-vous et traitements : mêmes rangées, même remède. Les commandes
     descendent sous le contenu plutôt que de lui disputer la largeur. */
  .appointment{flex-wrap:wrap; gap:12px 14px;}
  .appointment .row-actions{flex:1 1 100%; justify-content:flex-end; flex-wrap:wrap;}
  .tx-top{flex-wrap:wrap; gap:10px;}
  .tx-top .row-actions{flex:1 1 100%; justify-content:flex-end;}

  /* Les tableaux de bord et d'administration défilent latéralement plutôt que
     de se comprimer : cinq colonnes de statuts ne se replient pas honnêtement. */
  .card > table{display:block; overflow-x:auto; -webkit-overflow-scrolling:touch;}

  /* --- Compte rendu de prise de sang -------------------------------------
     Quatre colonnes dont trois insécables : il n'y a pas de largeur à laquelle
     ce tableau tienne sur un téléphone. Chaque ligne devient donc un bloc —
     le marqueur en intitulé, la valeur en dessous, l'écart et la fourchette
     préfixés par le nom de leur colonne, qui n'est plus visible en haut. */
  .report-table--stack thead{
    /* Masqué à l'œil, conservé pour les lecteurs d'écran : les intitulés
       reviennent en préfixe de chaque cellule, mais la structure du tableau,
       elle, ne change pas. */
    position:absolute; width:1px; height:1px; margin:-1px; padding:0;
    overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
  }
  .report-table--stack,
  .report-table--stack tbody,
  .report-table--stack tr,
  .report-table--stack th,
  .report-table--stack td{display:block; width:auto;}

  .report-table--stack tbody tr{padding:13px 0; border-bottom:1px solid var(--color-border);}
  .report-table--stack tbody tr:last-child{border-bottom:none;}
  .report-table--stack tbody th,
  .report-table--stack tbody td{padding:0; border-bottom:none;}

  .report-table--stack tbody th[scope="row"]{
    font-size:.72rem; text-transform:uppercase; letter-spacing:.08em; font-weight:600;
    color:var(--color-text-muted); margin-bottom:3px;
  }
  .report-table--stack .num{text-align:left; white-space:normal;}
  .report-table--stack td[data-label]{font-size:.78rem; color:var(--color-text-muted); margin-top:3px;}
  .report-table--stack td[data-label]::before{content:attr(data-label) " : ";}
  /* Un écart absent n'a pas de préfixe à afficher : la cellule disparaît. */
  .report-table--stack td.report-change:not([data-label]){display:none;}
}
@keyframes modalSheet{from{opacity:0; transform:translateY(24px);} to{opacity:1; transform:none;}}

@media (prefers-reduced-motion: reduce){
  .modal, .modal-overlay{animation:none !important;}
}

/* ==========================================================================
   Navigation de rubriques du profil public autonome
   --------------------------------------------------------------------------
   Une barre horizontale discrète sous l'en-tête, pas un menu latéral
   d'application : la page publique doit se lire comme une page personnelle,
   pas comme un espace de travail.
   ========================================================================== */
.pub-nav{border-bottom:1px solid var(--color-border);}
.pub-nav-inner{
  max-width:980px; margin:0 auto; padding:0 22px; display:flex; gap:4px;
  overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none;
}
.pub-nav-inner::-webkit-scrollbar{display:none;}
.pub-nav a.pub-nav-link{
  display:inline-flex; align-items:center; gap:8px; white-space:nowrap; text-decoration:none;
  padding:14px 12px; font-size:.83rem; color:var(--color-text-muted);
  border-bottom:2px solid transparent; transition:color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.pub-nav a.pub-nav-link .icon{width:15px; height:15px;}
.pub-nav a.pub-nav-link:hover{color:var(--color-text-primary);}
.pub-nav a.pub-nav-link.active{color:var(--color-accent); border-bottom-color:var(--color-accent); font-weight:600;}

/* ==========================================================================
   ==========================================================================
   COMPOSITION DU TABLEAU DE BORD, POSOLOGIE, PROFIL PUBLIC
   --------------------------------------------------------------------------
   Le haut du tableau de bord repose sur de véritables blocs statistiques
   (.stat-band / .stat-block) plutôt que sur un empilement de lignes qui se
   lirait comme un pâté de texte. La posologie a une représentation graphique
   (.tx / .dots), et le profil public est bâti sur exactement les mêmes
   composants que l'espace personnel.

   RÈGLE DE FIDÉLITÉ : toute évolution visuelle passe par ce fichier, jamais
   par du style en ligne ajouté dans une vue. C'est ce qui garantit qu'une
   maquette et l'interface réelle ne peuvent pas diverger.
   ==========================================================================
   ========================================================================== */

/* --------------------------------------------------------------------------
   Bande de statistiques — le haut du tableau de bord.
   --------------------------------------------------------------------------
   Une valeur dominante occupant deux colonnes sur deux rangées, entourée de
   quatre blocs secondaires. Les cadres sont volontairement à peine visibles :
   ils séparent, ils ne décorent pas. Chaque bloc secondaire est un lien vers
   sa rubrique — la statistique devient une porte d'entrée, pas une ligne de
   tableau.
   -------------------------------------------------------------------------- */
.stat-band{
  display:grid; grid-template-columns:repeat(4, 1fr); grid-auto-rows:minmax(112px, auto);
  gap:14px; margin:0 0 38px;
}
.stat-block{
  position:relative; display:flex; flex-direction:column; min-width:0;
  padding:20px 22px; border-radius:var(--radius-lg);
  background:var(--color-surface); border:1px solid var(--color-border);
  text-decoration:none; color:inherit; overflow:hidden;
  transition:border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
a.stat-block:hover{border-color:var(--color-border-strong); background:var(--color-surface-hover);}
a.stat-block:hover .sb-value{color:var(--color-accent);}
a.stat-block:active{transform:translateY(1px);}

.sb-head{display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:auto;}
.sb-icon{
  width:30px; height:30px; border-radius:9px; flex-shrink:0;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--color-surface-elevated); color:var(--color-text-muted);
}
.sb-icon .icon{width:15px; height:15px;}
.sb-value{
  font-family:'Cormorant Garamond',serif; font-weight:600; color:var(--color-text-primary);
  font-size:2.3rem; line-height:1; letter-spacing:-.008em; margin-top:14px;
  transition:color var(--dur-fast) var(--ease); white-space:nowrap;
}
.sb-value .sb-unit{
  font-family:'Inter',sans-serif; font-size:.34em; font-weight:500; letter-spacing:0;
  color:var(--color-text-secondary); margin-left:.3em;
}
.sb-label{
  font-size:.7rem; text-transform:uppercase; letter-spacing:.09em; font-weight:600;
  color:var(--color-text-secondary); margin-top:9px; line-height:1.35;
}
.sb-foot{font-size:.74rem; color:var(--color-text-muted); margin-top:5px;}

/* Bloc dominant : deux colonnes, deux rangées, une courbe de fond discrète. */
.stat-block--hero{grid-column:span 2; grid-row:span 2; padding:28px 30px; justify-content:flex-end;}
.stat-block--hero .sb-head{margin-bottom:0;}
.stat-block--hero .sb-value{
  font-size:clamp(3.6rem, 2.6rem + 4vw, 5.2rem); line-height:.9; margin-top:0;
}
.stat-block--hero .sb-label{font-size:.75rem; letter-spacing:.11em; margin-top:14px; color:var(--color-text-secondary);}
.stat-block--hero .sb-foot{font-size:.8rem; margin-top:6px;}
/* Courbe de fond : purement illustrative, jamais porteuse d'une donnée chiffrée
   qu'on ne pourrait pas lire autrement. Masquée aux lecteurs d'écran. */
.sb-spark{position:absolute; left:0; right:0; bottom:0; height:78px; opacity:.5; pointer-events:none;}
.sb-spark svg{width:100%; height:100%; display:block;}

@media (max-width:1080px){
  .stat-band{grid-template-columns:repeat(2, 1fr);}
  .stat-block--hero{grid-column:span 2; grid-row:span 1;}
}
@media (max-width:520px){
  .stat-band{gap:10px;}
  .stat-block{padding:16px 16px;}
  .stat-block--hero{padding:22px 20px;}
  .sb-value{font-size:1.85rem;}
  .sb-label{font-size:.64rem;}
}

/* --------------------------------------------------------------------------
   Panneau — la surface de section du tableau de bord.
   --------------------------------------------------------------------------
   Remplace l'usage générique de .card sur le tableau de bord : en-tête avec
   titre + action discrète, corps respirant. Une section qui n'a pas besoin de
   surface reste posée sur le fond (.section--airy).
   -------------------------------------------------------------------------- */
.panel{
  background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:var(--radius-lg); padding:24px 26px; min-width:0;
}
.panel + .panel{margin-top:16px;}
.panel-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  flex-wrap:wrap; margin-bottom:20px;
}
.panel-head h2{
  margin:0; font-family:'Cormorant Garamond',serif; font-size:1.34rem; font-weight:600;
  color:var(--color-text-primary); letter-spacing:.01em;
}
.panel-foot{margin-top:20px; padding-top:16px; border-top:1px solid var(--color-border);}
.panel--quiet{background:transparent; border-color:transparent; padding:0;}

/* Grille principale du tableau de bord : deux panneaux côte à côte, empilés
   sous 900px. Distincte de .grid-2 (générique, minmax 300px) pour garder un
   rythme identique à celui du prototype. */
.dash-duo{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:38px; align-items:start;}
@media (max-width:900px){ .dash-duo{grid-template-columns:1fr;} }

/* ==========================================================================
   POSOLOGIE — représentation graphique d'un traitement
   --------------------------------------------------------------------------
   Chaque prise est représentée par des points. Les points ne sont JAMAIS
   décoratifs : ils sont toujours accompagnés du moment et de la quantité
   écrite en toutes lettres, et portent aria-hidden puisque l'information
   chiffrée est déjà lisible à côté (voir App\Support\Posology).
   ========================================================================== */
.tx-list{display:flex; flex-direction:column; gap:20px;}
.tx-list > .tx + .tx{padding-top:20px; border-top:1px solid var(--color-border);}

.tx{min-width:0;}
.tx-top{display:flex; align-items:flex-start; justify-content:space-between; gap:12px; margin-bottom:16px;}
.tx-name{
  margin:0; font-family:'Cormorant Garamond',serif; font-size:1.3rem; font-weight:600;
  color:var(--color-text-primary); line-height:1.2;
}
.tx-sub{font-size:.82rem; color:var(--color-text-secondary); margin-top:3px;}

/* Répartition des prises sur la journée (ou sur la période). */
.tx-schedule{display:flex; flex-wrap:wrap; gap:12px 28px;}
.tx-slot{min-width:0;}
.tx-slot-label{
  font-size:.62rem; text-transform:uppercase; letter-spacing:.1em; font-weight:600;
  color:var(--color-text-muted);
}
.tx-slot-qty{font-size:.76rem; color:var(--color-text-secondary); margin-top:5px;}

.dots{display:flex; align-items:center; gap:5px; margin-top:8px; min-height:11px;}
.dots i{
  width:9px; height:9px; border-radius:50%; background:var(--color-accent);
  display:inline-block; flex-shrink:0;
}
/* Quantité fractionnaire (ex. 0,5 comprimé) : demi-point, jamais un point entier. */
.dots i.is-half{background:linear-gradient(90deg, var(--color-accent) 50%, transparent 50%); border:1px solid var(--color-accent);}
/* Au-delà du seuil de lisibilité, on cesse d'aligner des points et on écrit le
   nombre : « ● × 20 » plutôt que vingt pastilles qui débordent. */
.dots .dots-x{
  font-size:.78rem; font-weight:600; color:var(--color-accent); margin-left:2px;
  font-variant-numeric:tabular-nums;
}

.tx-foot{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px; flex-wrap:wrap;
  margin-top:16px;
}
.tx-total{
  font-size:.86rem; font-weight:600; color:var(--color-text-primary);
}
.tx-total .tx-total-unit{color:var(--color-text-secondary); font-weight:400;}
.tx-since{font-size:.76rem; color:var(--color-text-muted);}

/* Traitement non quotidien : une seule prise, présentée comme une ligne. */
.tx--single .tx-schedule{gap:10px 20px; align-items:center;}
.tx--single .tx-slot-label{letter-spacing:.08em;}

/* Traitement arrêté : présent, lisible, mais visuellement en retrait. */
.tx--past .tx-name, .tx--past .tx-total{color:var(--color-text-secondary);}
.tx--past .dots i{background:var(--color-text-muted); opacity:.55;}

/* ==========================================================================
   Profil public — mêmes composants que le tableau de bord
   --------------------------------------------------------------------------
   Le profil public n'a pas son propre système visuel : il réutilise
   .stat-band, .stat-block, .panel, .tx, .tl. Seules l'en-tête (.pub-masthead)
   et l'absence totale d'action le distinguent.
   ========================================================================== */
/* Conteneur d'une rubrique publique. En mode « linéaire » il n'a volontairement aucun style :
   les rubriques se suivent. En mode « rubriques », views/public/show.php ajoute une règle
   locale `.pub-section{display:none} .pub-section.active{display:block}` et le script de
   bascule cible cette même classe. Elle est déclarée ici pour qu'elle ne soit pas une classe
   fantôme introuvable dans la feuille de style. */
.pub-section{min-width:0;}
/* Point d'accroche JavaScript de la rangée horizontale de rubriques, utilisée uniquement
   lorsqu'un profil suivi est consulté DANS l'application (FollowController::view). Elle
   n'apporte aucun style propre — l'apparence vient de .btn / .btn.ghost — mais elle est
   déclarée ici pour rester repérable depuis la feuille de style. */
.pub-nav-btn{}

.pub-band{margin-bottom:44px;}
.pub-band .stat-block{cursor:default;}
.pub-lead{
  text-align:center; font-size:.68rem; text-transform:uppercase; letter-spacing:.16em;
  font-weight:600; color:var(--color-text-muted); margin:0 0 18px;
}
.pub-block > .panel{margin-bottom:0;}

/* ==========================================================================
   Champs groupés d'une modale
   --------------------------------------------------------------------------
   La modale de traitement est longue : on la découpe en sections nommées
   plutôt qu'en une seule grille de quinze champs.
   ========================================================================== */
.form-section{grid-column:1 / -1; margin-top:4px;}
.form-section:first-child{margin-top:0;}
.form-section-title{
  font-size:.63rem; text-transform:uppercase; letter-spacing:.12em; font-weight:600;
  color:var(--color-text-muted); padding-bottom:8px; border-bottom:1px solid var(--color-border);
  margin-bottom:14px;
}
/* Grille des moments de prise, dans la modale : libellé + quantité + unité. */
.slot-rows{display:flex; flex-direction:column; gap:10px;}
.slot-row{display:grid; grid-template-columns:1fr 92px auto; gap:10px; align-items:center;}
.slot-row .slot-name{font-size:.88rem; color:var(--color-text-primary);}
.slot-row input[type="number"]{text-align:right;}
.slot-row .slot-unit{font-size:.78rem; color:var(--color-text-muted); white-space:nowrap;}
@media (max-width:560px){
  .slot-row{grid-template-columns:1fr 80px auto;}
}

/* ==========================================================================
   Pages autonomes — barre de préférences et conteneur étroit
   --------------------------------------------------------------------------
   Les écrans d'installation, d'authentification et de documents légaux n'ont
   ni barre supérieure ni navigation latérale. Le choix de langue et de thème
   y vit donc en pied de page : accessible partout, sans jamais disputer
   l'attention au formulaire qui est le sujet de la page.

   La barre est en position fixe pour rester atteignable sur un formulaire
   long ; .auth-wrap réserve la hauteur correspondante pour que le bas d'une
   carte ne passe jamais dessous.
   ========================================================================== */
.prefs-bar{
  position:fixed; left:0; right:0; bottom:0; z-index:30;
  display:flex; justify-content:center; align-items:center; gap:10px; flex-wrap:wrap;
  pointer-events:none;
  /* Un élément en position fixe se place par rapport à la fenêtre, jamais par
     rapport au rembourrage d'un parent : il porte donc ses zones sûres lui-même. */
  padding:12px calc(16px + var(--sr-droite)) calc(12px + var(--sr-bas))
          calc(16px + var(--sr-gauche));
}
.prefs-bar .lang-switch{
  pointer-events:auto; background:var(--color-surface);
  box-shadow:0 6px 24px rgba(0,0,0,.18);
}
.prefs-bar .lang-switch a{white-space:nowrap;}
.prefs-bar .lang-switch a:hover{color:var(--color-text-primary);}
.prefs-bar .lang-switch a.active:hover{color:var(--color-accent-contrast);}

.auth-wrap{padding-bottom:calc(84px + var(--sr-bas));}

/* Page de lecture : documents légaux, assistant d'installation. Mesure de ligne
   volontairement courte — ces pages se lisent, elles ne se survolent pas. */
.page-narrow{max-width:820px; margin:0 auto;
  padding:calc(40px + var(--sr-haut)) calc(20px + var(--sr-droite))
          calc(104px + var(--sr-bas)) calc(20px + var(--sr-gauche));}
.page-narrow h2{margin-top:26px;}
.page-narrow h3{margin:18px 0 6px; font-size:1rem;}
.page-narrow p{line-height:1.65;}

/* Liste de contrôle des prérequis d'installation. */
.checklist{list-style:none; padding:0; margin:0; font-size:.88rem;}
.checklist li{display:flex; gap:10px; align-items:baseline; padding:7px 0; border-bottom:1px solid var(--color-border);}
.checklist li:last-child{border-bottom:0;}
.checklist .yes{color:var(--color-success); font-weight:600;}
.checklist .no{color:var(--color-error); font-weight:600;}

/* Case à cocher d'acceptation : libellé lisible en casse normale, à l'inverse
   des libellés de champ qui sont en petites capitales. */
.consent{display:flex; align-items:flex-start; gap:9px; text-transform:none; letter-spacing:normal;
  font-size:.85rem; color:var(--color-text-secondary); margin-top:16px; font-weight:400;}
.consent input[type="checkbox"]{width:auto; margin-top:3px; flex-shrink:0;}
.consent a{color:var(--color-accent);}

.brandmark{margin:0 0 4px; text-align:center;}
.brandmark em{color:var(--color-accent); font-style:italic;}

/* ==========================================================================
   Assistant de configuration
   --------------------------------------------------------------------------
   Une étape par page. L'avancement est donc la seule chose qui relie les
   écrans entre eux : il doit dire où l'on en est, combien il reste, et à
   quelle phase on appartient — sans quoi une suite de pages indépendantes
   ressemble à une errance.

   Les segments franchis sont pleins, le segment courant est cerclé, les
   suivants restent en creux. Aucun n'est cliquable : on ne saute pas une
   étape qu'on n'a pas encore vue.
   ========================================================================== */
.wizard{max-width:640px; margin:0 auto;
  padding:calc(40px + var(--sr-haut)) calc(20px + var(--sr-droite))
          calc(104px + var(--sr-bas)) calc(20px + var(--sr-gauche));}
.wizard-head{margin-bottom:26px;}
.wizard-phase{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.08em; font-weight:600;
  color:var(--color-accent); margin-bottom:6px;
}
.wizard-count{font-size:.78rem; color:var(--color-text-secondary); margin-top:10px;}
.wizard-bar{display:flex; gap:6px; margin-top:12px;}
.wizard-bar span{
  flex:1; height:4px; border-radius:2px; background:var(--color-border);
  transition:background var(--dur-med) var(--ease);
}
.wizard-bar span.done{background:var(--color-accent);}
.wizard-bar span.current{background:color-mix(in srgb, var(--color-accent) 55%, transparent);}
.wizard-actions{display:flex; gap:10px; align-items:center; margin-top:22px; flex-wrap:wrap;}
.wizard-actions button[type="submit"]{flex:1; justify-content:center; min-width:180px;}
.wizard-skip{font-size:.82rem; color:var(--color-text-secondary); text-decoration:underline;}
.wizard-skip:hover{color:var(--color-text-primary);}

/* Interrupteur commenté : le libellé porte la question, la ligne dessous porte la
   conséquence. Sans cette seconde ligne, un interrupteur est une devinette. */
.toggle-row{
  display:flex; gap:14px; align-items:flex-start; padding:16px 0;
  border-bottom:1px solid var(--color-border);
}
.toggle-row:last-of-type{border-bottom:0;}
.toggle-row input[type="checkbox"]{width:auto; margin-top:3px; flex-shrink:0;}
.toggle-row .toggle-text{flex:1; min-width:0;}
.toggle-row .toggle-label{
  display:block; font-weight:600; font-size:.95rem; color:var(--color-text-primary);
  text-transform:none; letter-spacing:normal; margin:0;
}
.toggle-row .toggle-help{margin:4px 0 0; font-size:.84rem; color:var(--color-text-secondary); line-height:1.5;}
/* Une option dépendante est décalée et estompée quand son parent est fermé : la
   hiérarchie se voit, plutôt que de se deviner à l'usage. */
.toggle-row.is-child{margin-left:26px; border-left:2px solid var(--color-border); padding-left:16px;}
.toggle-row.is-muted{opacity:.5;}

/* Récapitulatif de fin : ce qui a été décidé, en une lecture. */
.recap{list-style:none; padding:0; margin:0; font-size:.9rem;}
.recap li{display:flex; justify-content:space-between; gap:14px; padding:9px 0; border-bottom:1px solid var(--color-border);}
.recap li:last-child{border-bottom:0;}
.recap .recap-value{color:var(--color-text-secondary); text-align:right;}
.recap .recap-value.on{color:var(--color-success); font-weight:600;}
.recap .recap-value.off{color:var(--color-text-muted);}

/* ==========================================================================
   Barre d'outils d'un graphique
   --------------------------------------------------------------------------
   Les pastilles de marqueur et le choix de période partagent une ligne, et
   passent l'une sous l'autre quand la place manque. Le sélecteur ne prend que
   la largeur nécessaire : c'est un réglage, pas un champ de saisie.
   ========================================================================== */
.chart-toolbar{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:14px;}
.chart-toolbar .chip-row{flex:1; min-width:0;}
.chart-toolbar .chart-period{width:auto; min-width:150px; padding:7px 10px; font-size:.82rem;}
.chart-toolbar .sr-inline{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
/* Les pastilles de marqueur sont des boutons : mêmes repères visuels que .chip,
   mais atteignables au clavier, ce qu'un <div> cliquable n'est jamais. */
.chip-row button.chip{border:1px solid var(--color-border); font:inherit;}

/* Grille de saisie de la posologie : autant de colonnes que la largeur le permet,
   sans jamais descendre sous une largeur où le nombre saisi devient illisible. */
.posology-grid{display:grid; grid-template-columns:repeat(auto-fit, minmax(96px, 1fr)); gap:10px 12px;}
.posology-grid label.posology-moment{margin:0 0 4px; font-size:.62rem;}

/* ==========================================================================
   Bilan sanguin
   --------------------------------------------------------------------------
   Le dernier bilan se lit comme un compte rendu de laboratoire : une valeur
   dominante par marqueur, son unité en retrait, sa fourchette de référence
   dessous. La fourchette est une indication de situation, jamais un verdict :
   aucune couleur d'alerte n'est appliquée à la valeur.
   ========================================================================== */
.kv-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(160px, 1fr)); gap:20px 22px;}
.kv-label{
  font-size:.68rem; text-transform:uppercase; letter-spacing:.08em; font-weight:600;
  color:var(--color-text-muted); line-height:1.35;
}
.kv-unit{text-transform:none; letter-spacing:normal; font-weight:400; color:var(--color-text-muted);}
.kv-ref{font-size:.72rem; color:var(--color-text-muted); margin-top:4px;}

/* Titre de groupe à l'intérieur d'une modale longue : le bilan complet compte une
   vingtaine de champs, les découper évite le mur de saisie. */
.modal-group{
  margin:22px 0 12px; font-family:'Inter',sans-serif; font-size:.7rem; font-weight:600;
  text-transform:uppercase; letter-spacing:.09em; color:var(--color-accent);
}
.modal-group:first-of-type{margin-top:6px;}

/* Unité rappelée sous chaque quantité de posologie : le nombre seul ne dit pas
   s'il s'agit de pressions, de comprimés ou de milligrammes. Tenue à jour par
   public/assets/js/posology.js d'après l'unité choisie. */
.posology-unit{display:block; margin-top:4px; font-size:.7rem; color:var(--color-text-muted);}
.posology-unit:empty{display:none;}

/* ==========================================================================
   Photos d'évolution
   --------------------------------------------------------------------------
   Une grille de vignettes datées. Les images sont servies par un contrôleur
   qui vérifie l'appartenance à chaque lecture : elles ne sont pas dans
   public/, et n'ont donc pas d'adresse devinable.
   ========================================================================== */
.photo-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:18px;}
.photo-card{
  margin:0; background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:var(--radius-lg); overflow:hidden; display:flex; flex-direction:column;
}
.photo-card img{width:100%; aspect-ratio:3/4; object-fit:cover; display:block; background:var(--color-surface-elevated);}
.photo-card figcaption{padding:14px 16px; display:flex; flex-direction:column; gap:5px;}
.photo-card .photo-date{font-size:.78rem; font-weight:600; color:var(--color-text-primary);}
.photo-card .photo-note{font-size:.8rem; color:var(--color-text-secondary); line-height:1.45;}
.photo-card .row-actions{display:flex; gap:6px; margin-top:6px;}

/* --------------------------------------------------------------------------
   Tuile d'ajout
   --------------------------------------------------------------------------
   Elle occupe une case de la galerie, aux mêmes proportions qu'une photo :
   le geste d'ajouter se tient là où se tiendra le résultat. Le trait est
   pointillé et la surface vide — elle se lit comme un emplacement libre,
   pas comme une image qu'on aurait ratée.
   -------------------------------------------------------------------------- */
.photo-add{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px;
  width:100%; aspect-ratio:3/4; padding:16px;
  background:transparent; color:var(--color-text-secondary);
  border:1px dashed var(--color-border-strong); border-radius:var(--radius-lg);
  font-size:.82rem; font-weight:500; text-align:center; white-space:normal;
  transition:border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
             background var(--dur-fast) var(--ease);
}
.photo-add:hover{
  border-color:var(--color-accent); color:var(--color-accent);
  background:var(--color-accent-soft); filter:none;
}
.photo-add:focus-visible{outline:2px solid var(--color-accent); outline-offset:2px;}
/* Hors galerie — l'écran d'accueil quand aucune photo n'existe encore — la tuile n'a pas
   de voisines dont copier la largeur. Sans cette borne elle occuperait toute la carte. */
.card > .photo-add{max-width:190px; margin-top:14px;}
/* L'icône porte tout le sens : elle est grande, et le libellé la commente. */
.photo-add .icon{width:52px; height:52px; stroke-width:1.25;}

/* --------------------------------------------------------------------------
   Provenance d'une image : appareil photo ou bibliothèque
   -------------------------------------------------------------------------- */
.pick-source{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:10px;}
.pick-source .btn{flex:1 1 150px; justify-content:center; min-height:46px;}
.pick-chosen{
  margin:6px 0 0; font-size:.82rem; color:var(--color-text-primary);
  overflow-wrap:anywhere;
}
/* Le champ reste dans le document et reste focusable : un champ requis rendu
   invisible par display:none empêche le navigateur d'afficher son message de
   validation, et le formulaire refuse alors de partir sans rien expliquer. */
.pick-file--managed{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; opacity:0;
}

/* Filtre de chronologie : une case à cocher habillée en pastille, pour rester
   utilisable sans JavaScript comme au clavier. */
.chip-row label.chip{display:inline-flex; align-items:center; cursor:pointer;}
.chip-row label.chip input{margin:0;}

/* ==========================================================================
   Texte replié
   --------------------------------------------------------------------------
   Deux lignes visibles, le reste au clic. Le repli est posé par
   public/assets/js/collapse.js : sans script, le texte reste entier plutôt
   que tronqué et inaccessible.
   ========================================================================== */
.collapsible.is-collapsed{
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; cursor:pointer;
}
.collapse-toggle{
  background:none; border:0; padding:0; margin-top:8px;
  font-size:.8rem; font-weight:500; color:var(--color-accent);
  text-decoration:underline; cursor:pointer;
}
.collapse-toggle:hover{filter:none; color:var(--color-text-primary);}
.collapse-toggle:active{transform:none;}

/* Icône d'un signet. Un carré neutre tient la place quand elle manque, pour que
   les intitulés restent alignés d'une ligne à l'autre. */
.bookmark-icon{width:16px; height:16px; flex-shrink:0; border-radius:3px; object-fit:contain;}
.bookmark-icon--empty{background:var(--color-surface-elevated); border:1px solid var(--color-border);}

/* Photo de profil et son champ de remplacement, sur une même ligne. */
.avatar-row{display:flex; gap:16px; align-items:flex-start; margin-bottom:8px;}
.avatar-preview{width:72px; height:72px; border-radius:50%; object-fit:cover; flex-shrink:0;
  border:1px solid var(--color-border); background:var(--color-surface-elevated);}
.avatar-preview--empty{display:block;}

/* ==========================================================================
   Compte rendu d'un bilan
   --------------------------------------------------------------------------
   Lecture en tableau, comme un compte rendu de laboratoire : le marqueur à
   gauche, la valeur alignée à droite, l'écart avec le relevé précédent, puis
   la fourchette de référence.

   AUCUNE couleur de verdict. La fourchette situe une valeur, elle ne la juge
   pas — un laboratoire, une unité ou un protocole différents suffisent à
   déplacer une borne, et c'est l'équipe médicale qui sait laquelle
   s'applique. Colorer une ligne en rouge reviendrait à poser un diagnostic.
   ========================================================================== */
.report{
  background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:var(--radius-lg); padding:26px 28px;
}
.report-group + .report-group{margin-top:30px; padding-top:24px; border-top:1px solid var(--color-border);}
.report-group h2{
  margin:0 0 12px; font-family:'Inter',sans-serif; font-size:.7rem; font-weight:600;
  text-transform:uppercase; letter-spacing:.09em; color:var(--color-accent);
}
.report-table{width:100%; border-collapse:collapse; font-size:.88rem;}
.report-table th, .report-table td{padding:9px 10px; border-bottom:1px solid var(--color-border); text-align:left;}
.report-table thead th{
  font-size:.62rem; text-transform:uppercase; letter-spacing:.07em;
  color:var(--color-text-muted); font-weight:600; border-bottom-width:1px;
}
.report-table tbody th{font-weight:500; color:var(--color-text-primary);}
.report-table .num{text-align:right; white-space:nowrap;}
.report-value{font-family:'Cormorant Garamond',serif; font-size:1.25rem; font-weight:600;}
.report-unit{font-size:.72rem; color:var(--color-text-muted); margin-left:4px;}
.report-change{color:var(--color-text-secondary); font-size:.8rem;}
.report-range{color:var(--color-text-muted); font-size:.78rem; white-space:nowrap;}
.report-own{
  display:inline-block; margin-left:6px; padding:1px 7px; border-radius:var(--radius-pill);
  font-size:.62rem; border:1px solid var(--color-border);
}
.report-foot{
  margin-top:26px; padding-top:14px; border-top:1px solid var(--color-border);
  font-size:.78rem; color:var(--color-text-muted); display:flex;
  justify-content:space-between; gap:14px; flex-wrap:wrap;
}
.report-nav{display:flex; justify-content:space-between; align-items:center; gap:12px; margin-top:18px; flex-wrap:wrap;}

@media print {
  .topbar, .sidenav, .appfooter, .report-nav, .ph-row .btn, .prefs-bar{display:none !important;}
  .layout{display:block; padding:0;}
  .report{border:0; padding:0;}
  .report-table{font-size:.8rem;}
}

/* Écarts d'un bilan au précédent, dans la liste. Aucune couleur de sens : une
   hausse n'est ni bonne ni mauvaise, c'est un fait. Le signe et le nombre
   suffisent, et laisser la couleur en dehors évite de suggérer un verdict. */
.delta-row{display:flex; gap:12px; flex-wrap:wrap; align-items:baseline; margin-top:3px;}
.delta{font-size:.74rem; color:var(--color-text-muted); white-space:nowrap;}
.delta-value{color:var(--color-text-secondary); font-weight:600; margin-left:3px;}
.delta--muted{font-style:italic;}

/* ==========================================================================
   Listes d'étapes
   --------------------------------------------------------------------------
   Une case, un libellé, une suppression. Les étapes proposées au départ sont
   indicatives : rien n'oblige à les suivre, ni dans cet ordre, ni du tout.
   La barre d'avancement dit où l'on en est, elle n'encourage rien.
   ========================================================================== */
.checklist-bar{height:4px; border-radius:2px; background:var(--color-border); overflow:hidden; margin-bottom:18px;}
.checklist-bar span{display:block; height:100%; background:var(--color-accent); transition:width var(--dur-med) var(--ease);}
.checklist-items{list-style:none; margin:0; padding:0;}
.checklist-items li{
  display:flex; align-items:center; gap:12px; padding:10px 0;
  border-bottom:1px solid var(--color-border);
}
.checklist-items li:last-child{border-bottom:0;}
.checklist-items li form{display:flex; margin:0;}
.checklist-check{
  width:22px; height:22px; min-width:22px; padding:0; border-radius:6px;
  background:transparent; border:1px solid var(--color-border-strong); color:var(--color-accent);
  display:inline-flex; align-items:center; justify-content:center; font-size:.8rem; font-weight:700;
}
.checklist-check:hover{border-color:var(--color-accent); filter:none;}
.checklist-items li.is-done .checklist-check{background:var(--color-accent); color:var(--color-accent-contrast); border-color:var(--color-accent);}
.checklist-items li.is-done .checklist-label{color:var(--color-text-muted); text-decoration:line-through;}
.checklist-label{flex:1; min-width:0; font-size:.9rem;}
.checklist-add{display:flex; gap:8px; margin-top:16px; align-items:center;}
.checklist-add input{flex:1;}
.sr-only{position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;}

/* Rendez-vous : la date en pastille, le contenu à côté, les actions dessous.
   Un reflet de chirurgie se distingue par un liseré : il ne se modifie pas ici. */
.appointment{display:flex; gap:16px; align-items:flex-start; padding:16px 0; border-bottom:1px solid var(--color-border);}
.appointment:last-of-type{border-bottom:0;}
.appointment--mirror{opacity:.85; border-left:2px solid var(--color-accent); padding-left:14px;}
.appointment-body{flex:1; min-width:0;}
.appointment-body h3{margin:0 0 3px; font-family:'Cormorant Garamond',serif; font-size:1.2rem; font-weight:600;}
.appointment-block{margin-top:10px;}
.appointment-block-title{font-size:.62rem; text-transform:uppercase; letter-spacing:.1em; font-weight:600; color:var(--color-text-muted);}
.appointment-block p{margin:3px 0 0; font-size:.86rem; white-space:pre-wrap; line-height:1.55;}
.appointment .row-actions{display:flex; gap:6px; flex-shrink:0;}

/* ==========================================================================
   Barre d'onglets du bas — téléphone et tablette verticale
   --------------------------------------------------------------------------
   La barre est écrite dans chaque page mais masquée par défaut : c'est la
   feuille de style, et elle seule, qui décide de la montrer. Tourner
   l'appareil doit suffire à changer de navigation, sans nouvelle requête et
   sans que le serveur ait à deviner la forme de l'écran.

   Deux conditions, pas une : moins de 860 px ET orientation portrait. Un
   téléphone tenu à l'horizontale a de la largeur et pas de hauteur ; lui
   prendre 76 px en bas serait lui prendre ce qui lui manque.

   Le fond est translucide et flouté là où le navigateur sait le faire, opaque
   partout ailleurs. La lisibilité ne dépend jamais du flou : c'est la couche
   de couleur dessous qui garantit le contraste, le flou n'ajoute que la
   profondeur.
   ========================================================================== */
.tabbar{display:none;}
.sheet-overlay{display:none;}

@media (max-width:860px) and (orientation: portrait){

  .tabbar{
    display:block; position:fixed; left:0; right:0; z-index:60;
    /* safe-area : la barre flotte au-dessus de l'indicateur d'accueil, jamais dessous. */
    bottom:calc(10px + var(--sr-bas));
    padding:0 calc(14px + var(--sr-droite)) 0 calc(14px + var(--sr-gauche));
    pointer-events:none;
  }

  .tabbar-inner{
    pointer-events:auto;
    display:flex; align-items:center; justify-content:space-around; gap:4px;
    max-width:520px; margin:0 auto; padding:8px 10px;
    border-radius:26px;
    background:color-mix(in srgb, var(--color-surface-elevated) 88%, transparent);
    border:1px solid var(--color-border-strong);
    box-shadow:0 10px 30px rgba(0,0,0,.32), 0 1px 0 rgba(255,255,255,.05) inset;
  }

  @supports (backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px)){
    .tabbar-inner{
      background:color-mix(in srgb, var(--color-surface-elevated) 68%, transparent);
      -webkit-backdrop-filter:blur(22px) saturate(160%);
      backdrop-filter:blur(22px) saturate(160%);
    }
  }

  .tab{
    flex:1; min-width:0; display:flex; flex-direction:column; align-items:center; gap:3px;
    padding:6px 2px; border:0; background:none; cursor:pointer;
    color:var(--color-text-secondary); text-decoration:none;
    font-size:.62rem; font-weight:500; letter-spacing:.01em;
    border-radius:16px; transition:color .18s ease, background .18s ease;
    -webkit-tap-highlight-color:transparent;
  }
  .tab span{
    max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .tab svg{width:22px; height:22px; flex-shrink:0;}
  .tab:hover{color:var(--color-text-primary);}
  .tab.active{color:var(--color-accent); background:var(--color-accent-soft);}
  .tab:focus-visible{outline:2px solid var(--color-accent); outline-offset:2px;}

  /* Le « + » n'est pas un onglet et ne doit pas en avoir l'air : il n'ouvre pas
     une page mais une feuille de choix. Plus haut, plus rond, plein. */
  .tab-add{
    flex:0 0 auto; width:52px; height:52px; margin:-14px 4px 0;
    display:flex; align-items:center; justify-content:center;
    border:0; border-radius:50%; cursor:pointer;
    background:var(--color-accent); color:var(--color-accent-contrast);
    box-shadow:0 6px 18px color-mix(in srgb, var(--color-accent) 42%, transparent);
    transition:transform .18s ease, box-shadow .18s ease;
    -webkit-tap-highlight-color:transparent;
  }
  .tab-add svg{width:26px; height:26px;}
  .tab-add:active{transform:scale(.94);}
  .tab-add:focus-visible{outline:2px solid var(--color-accent); outline-offset:3px;}

  /* De la place sous le contenu, sinon la barre recouvrirait la dernière ligne
     de chaque page — et personne ne penserait à faire défiler plus bas. */
  .layout{padding-bottom:calc(96px + var(--sr-bas));}
  .appfooter{padding-bottom:calc(88px + var(--sr-bas));}

  /* Le menu complet devient une feuille posée sur la page, comme celle du « + ».
     Laissé dans le flux, il se serait ouvert en haut du document : quelqu'un
     qui appuie sur « Menu » en bas d'une longue page n'aurait rien vu bouger,
     et aurait conclu que le bouton ne marche pas. */
  nav.sidenav.open{
    position:fixed; left:0; right:0; z-index:65;
    bottom:calc(84px + var(--sr-bas));
    max-height:64vh; overflow-y:auto; -webkit-overflow-scrolling:touch;
    margin:0; border-radius:24px 24px 0 0;
    padding:14px calc(14px + var(--sr-droite)) 18px calc(14px + var(--sr-gauche));
    box-shadow:0 -14px 44px rgba(0,0,0,.44);
    animation:sheet-up .22s cubic-bezier(.32,.72,0,1);
  }
  /* Fond assombri : un simple pseudo-élément, donc un clic dessus atteint la
     navigation elle-même — c'est ce que le script attend pour refermer. */
  nav.sidenav.open::before{
    content:''; position:fixed; inset:0; z-index:-1; background:rgba(0,0,0,.5);
  }

  /* ---- Feuille de choix ------------------------------------------------ */
  .sheet-overlay{
    display:none; position:fixed; inset:0; z-index:70;
    background:rgba(0,0,0,.5); align-items:flex-end; justify-content:center;
    padding:0;
  }
  .sheet-overlay.open{display:flex;}
  @supports (backdrop-filter: blur(4px)){
    .sheet-overlay{-webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);}
  }

  .sheet{
    width:100%; max-width:560px; box-sizing:border-box;
    background:var(--color-surface-elevated);
    border:1px solid var(--color-border-strong); border-bottom:0;
    border-radius:24px 24px 0 0;
    padding:10px calc(18px + var(--sr-droite)) calc(20px + var(--sr-bas))
            calc(18px + var(--sr-gauche));
    box-shadow:0 -14px 44px rgba(0,0,0,.44);
    animation:sheet-up .22s cubic-bezier(.32,.72,0,1);
    max-height:82vh; overflow-y:auto; -webkit-overflow-scrolling:touch;
  }
  @keyframes sheet-up{from{transform:translateY(14%); opacity:.6;} to{transform:none; opacity:1;}}

  .sheet-grip{
    width:38px; height:4px; border-radius:2px; margin:2px auto 12px;
    background:var(--color-border-strong);
  }
  .sheet-head{margin-bottom:14px;}
  .sheet-title{margin:0; font-family:'Cormorant Garamond',serif; font-size:1.32rem; font-weight:600;}
  .sheet-sub{margin:4px 0 0; font-size:.8rem; color:var(--color-text-secondary); line-height:1.5;}

  .sheet-grid{
    display:grid; grid-template-columns:repeat(auto-fill, minmax(96px, 1fr)); gap:8px;
  }
  .sheet-item{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px;
    padding:16px 8px; text-decoration:none; text-align:center;
    border-radius:var(--radius-lg); border:1px solid var(--color-border);
    background:var(--color-surface); color:var(--color-text-primary);
    transition:border-color .18s ease, transform .18s ease;
    -webkit-tap-highlight-color:transparent;
  }
  .sheet-item:active{transform:scale(.96);}
  .sheet-item:hover{border-color:var(--color-accent);}
  .sheet-item:focus-visible{outline:2px solid var(--color-accent); outline-offset:2px;}
  .sheet-item-icon{
    display:flex; align-items:center; justify-content:center;
    width:38px; height:38px; border-radius:50%;
    background:var(--color-accent-soft); color:var(--color-accent);
  }
  .sheet-item-icon svg{width:20px; height:20px;}
  .sheet-item-label{font-size:.74rem; font-weight:500; line-height:1.3;}
  .sheet-cancel{width:100%; margin-top:14px;}

  body.sheet-open{overflow:hidden;}
}

@media print{
  .tabbar, .sheet-overlay{display:none !important;}
}

/* ==========================================================================
   Visite d'un profil public
   --------------------------------------------------------------------------
   Les deux points de passage des commandes d'écriture — la modale et le bloc
   d'actions de ligne — ne sont pas rendus par le serveur pendant une visite.
   Restent quelques formulaires écrits directement dans une vue : le bloc
   d'informations du parcours, le dépôt d'une photo, la fiche d'un dossier
   chirurgical. Ils sont masqués ici.

   Ceci n'est PAS la protection : elle tient aux routes d'écriture, toutes
   derrière `auth`, et un visiteur n'est connecté à rien. C'est ce qui évite
   d'afficher des commandes qui ne mèneraient nulle part.

   Les formulaires en GET restent visibles : ce sont des filtres et des tris,
   pas des écritures.
   ========================================================================== */
body.visite form[method="POST"],
body.visite form[method="post"],
body.visite [data-modal-open],
body.visite .checklist-add,
body.visite .checklist-check{display:none !important;}

body.visite .checklist-items li{padding-left:2px;}

/* ==========================================================================
   Lecteur audio / vidéo
   --------------------------------------------------------------------------
   Les contrôles sont ceux du navigateur : accessibles au clavier, traduits
   dans la langue du système, et déjà connus de la personne qui s'en sert. Un
   lecteur maison serait plus joli et moins utilisable.

   On ne règle donc ici que l'encombrement.
   ========================================================================== */
.media-player{
  display:block; width:100%; max-width:520px; min-width:0;
  border-radius:var(--radius-md, 10px); background:var(--color-surface-elevated);
}
audio.media-player{height:40px;}
video.media-player{max-height:340px; background:#000;}

@media (max-width:860px){
  .media-player{max-width:100%;}
}
