* { box-sizing: border-box; }
html, body { height: 100%; }
body {
    font-family: Roboto, -apple-system, "Segoe UI", Arial, sans-serif;
    margin: 0; padding: 8px 16px;
    background: #f7f7f8; color: #1a1a1a;
    display: flex; flex-direction: column;
    overflow: hidden;
}
/* align-items:flex-end : la colonne de gauche fait deux lignes (titre, puis bandeau d'exemple), celle de
   droite une seule - les aligner par le BAS met les controles de droite a hauteur du bandeau, comme
   demande, au lieu de les centrer entre les deux lignes. */
.app-header {
    flex-shrink: 0; display: flex; align-items: flex-end; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; padding-bottom: 8px; margin-bottom: 8px; border-bottom: 1px solid #e5e7eb;
}
/* En-tete sur deux lignes : titre + retour accueil, puis le bandeau d'exemple juste dessous
   (demande utilisateur), a hauteur du bouton "Mes documents" de la colonne de droite. */
.app-header-titles { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.app-header-ligne { display: flex; align-items: center; gap: 12px; }
.app-header h1 { font-size: 1.1rem; margin: 0; }
.app-sub { color: #666; font-size: 0.75rem; margin: 2px 0 0; }
/* nowrap + flex-shrink:0 : ces trois controles restent groupes sur une seule ligne a droite. C'est
   le bandeau d'exemple qui cede la largeur (cf. .demo-banner ci-dessous), pas eux. */
.app-header-actions { display: flex; align-items: center; gap: 16px; flex-shrink: 0; flex-wrap: nowrap; }
/* en-tête uniformisée avec les autres services Gnet (videos/mon-compte/protectis/geneatique-net/toponymes) :
   retour à l'accueil des services en bouton avant le titre + prénom du compte + déconnexion à droite. */
.back-link, .account-name { color: #64748b; text-decoration: none; font-size: .9em; }
.back-link:hover { color: #4fa066; }
.logout-link { color: #64748b; text-decoration: none; font-size: .9em; }
.logout-link:hover { color: #4fa066; }
.account-btn { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: 1px solid #cbd5e1;
                border-radius: 6px; color: #64748b; text-decoration: none; font-size: .8em; font-weight: 600; }
.account-btn:hover { background: #f1f5f9; color: #4fa066; border-color: #4fa066; }
/* La barre de compte affiche desormais deux etats exclusifs (data-gnet-auth="anonyme"/"connecte", cf.
   index.php et inc/login_modal.php), masques par l'attribut HTML `hidden`. Or la regle navigateur
   [hidden]{display:none} n'est qu'une regle d'origine "user agent" : le `display: inline-flex` de
   .account-btn ci-dessus la bat en specificite, et un bouton pose en hidden resterait VISIBLE (on
   verrait "Se connecter" ET "Mon compte" cote a cote). D'ou ce !important, indispensable ici. */
[hidden] { display: none !important; }
.gnet-footer { flex-shrink: 0; background: #fff; border-top: 1px solid #e5e7eb; padding: 6px 16px;
               margin: 8px -16px -8px; display: flex; justify-content: space-between; align-items: center; font-size: .75em; }
.gnet-footer .gnet-footer-brand { color: #4fa066; font-weight: 700; }
.gnet-footer .gnet-footer-version { color: #000; }
.panel-toggle-btn {
    border: 1px solid #ccc; border-radius: 6px; background: #fff; color: #333;
    font-size: 0.78rem; font-weight: 600; padding: 5px 10px; cursor: pointer; white-space: nowrap;
}
.panel-toggle-btn:hover { background: #f3f4f6; }
.panel-toggle-btn.is-collapsed { background: #eff6ff; border-color: #93c5fd; color: #1e3a8a; }

/* selecteur de langue d'interface (cf. #gnetLangueSelect, inc/i18n.php::gnet_rendreSelecteurLangue) - meme
   gabarit que .panel-toggle-btn pour rester coherent dans la meme ligne d'actions de l'entete. */
.gnet-lang-select {
    border: 1px solid #ccc; border-radius: 6px; background: #fff; color: #333;
    font-size: 0.78rem; font-weight: 600; padding: 4px 6px; cursor: pointer;
}
.gnet-lang-select:hover { border-color: #4fa066; }

/* panneaux lateraux : quand replies (manuellement via les boutons de l'entete, ou automatiquement
   pour "Mes documents" des qu'un bloc est actif), ils sont entierement retires du flux (display:none)
   pour ne laisser aucun espace mort - on les rouvre via les boutons, toujours visibles dans l'entete. */
.layout {
    flex: 1;
    min-height: 0;
    display: flex;
    gap: 20px;
    align-items: stretch;
}
/* Panneau de gauche resserre (320 -> 250px, demande utilisateur) : il ne porte qu'un depot de
   fichier et un historique de credits, alors que la colonne centrale doit loger l'image ET son
   texte cote a cote - chaque pixel repris ici profite directement a la lecture du document. */
.panel-form { width: 250px; flex-shrink: 0; }
.panel-history { width: 280px; flex-shrink: 0; }
.layout.form-collapsed .panel-form,
.layout.history-collapsed .panel-history { display: none; }
@media (max-width: 1000px) {
    body { overflow: auto; height: auto; }
    .layout { height: auto; flex-direction: column; }
    .panel-form, .panel-history { width: 100%; }
    .panel { height: auto !important; }
}

.panel {
    background: #fff; border: 1px solid #ddd; border-radius: 8px;
    padding: 14px; height: 100%; min-height: 0;
}
.panel h2 { font-size: 0.95rem; margin: 0 0 10px; }

.panel-form, .panel-history { overflow-y: auto; }

label { display: block; margin-top: 10px; font-weight: 600; font-size: 0.82rem; }
input[type=text], textarea, select {
    width: 100%; padding: 6px 8px; margin-top: 4px;
    border: 1px solid #ccc; border-radius: 4px; font-family: inherit; font-size: 0.85rem;
}
textarea { resize: vertical; }

.dropzone {
    margin-top: 0; margin-bottom: 16px; border: 2px dashed #93c5fd; border-radius: 8px;
    padding: 24px 12px; text-align: center; cursor: pointer;
    background: #eff6ff; color: #1e3a8a; transition: background 0.15s, border-color 0.15s;
}
.dropzone:hover, .dropzone.dragover { background: #e6f4ea; border-color: #4fa066; }
.dropzone-icon { font-size: 2rem; }
.dropzone p { margin: 6px 0 0; font-size: 0.85rem; }
.dropzone-hint { color: #6b7280; font-size: 0.72rem !important; }

.advanced { margin-top: 14px; font-size: 0.82rem; }
.advanced summary { cursor: pointer; font-weight: 600; color: #444; }

.progress-block { margin-top: 16px; }
.progress-label { font-size: 0.8rem; color: #333; margin: 0 0 4px; font-weight: 600; }
.progress-bar { height: 8px; border-radius: 4px; background: #e5e7eb; overflow: hidden; position: relative; }
.progress-fill { height: 100%; background: #4fa066; width: 0%; transition: width 0.2s; }
.progress-bar.indeterminate .progress-fill {
    width: 40% !important; position: absolute;
    animation: indeterminate 1.1s infinite linear;
}
@keyframes indeterminate {
    0% { left: -40%; }
    100% { left: 100%; }
}

.error-msg { color: #b91c1c; font-size: 0.82rem; font-weight: 600; margin-top: 12px; }

.history-list { display: flex; flex-direction: column; gap: 8px; }
.history-empty { color: #888; font-size: 0.82rem; }
.history-item {
    display: flex; align-items: center; gap: 2px;
    border: 1px solid #eee; border-radius: 6px;
    background: #fff; width: 100%;
}
.history-item:hover { border-color: #93c5fd; }
.history-item-open {
    display: flex; gap: 8px; align-items: center; padding: 6px;
    border: none; border-radius: 6px 0 0 6px; cursor: pointer; text-align: left;
    background: none; font: inherit; color: inherit; flex: 1; min-width: 0;
}
.history-item-open:hover { background: #f0f4ff; }
.history-item-delete {
    flex-shrink: 0; width: 26px; height: 26px; margin-right: 6px;
    border: none; border-radius: 4px; background: none; color: #999;
    cursor: pointer; font-size: 0.8rem;
}
.history-item-delete:hover { background: #fee2e2; color: #b91c1c; }
.history-item img { width: 44px; height: 44px; object-fit: cover; border-radius: 4px; flex-shrink: 0; }
.history-item-info { min-width: 0; }
.history-item-name { font-size: 0.8rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.history-item-meta { font-size: 0.72rem; color: #777; }
.history-item-status { font-size: 0.68rem; padding: 1px 6px; border-radius: 10px; display: inline-block; margin-top: 2px; }
/* overflow-wrap : la date de transcription et le nombre de blocs tiennent sur une ligne etroite, mieux
   vaut les laisser passer a la ligne que les voir deborder hors du panneau */
.history-item-meta { overflow-wrap: anywhere; }
/* echeance de suppression (cf. echeanceSuppressionHtml dans app.js) : discrete, puis alarmante dans la
   derniere semaine - a ce moment-la, c'est une information dont l'utilisateur doit tenir compte */
.history-item-echeance { font-size: 0.68rem; color: #9ca3af; }
.history-item-echeance-proche { color: #b91c1c; font-weight: 600; }
/* regle de conservation, annoncee une fois au-dessus de la liste */
.history-retention { font-size: 0.7rem; color: #6b7280; margin: 0 0 8px; line-height: 1.35; }
.status-termine { background: #dcfce7; color: #166534; }
.status-termine_avec_erreurs { background: #ffedd5; color: #9a3412; }
.status-en_cours { background: #fef9c3; color: #854d0e; }
.status-zones_detectees { background: #e0e7ff; color: #3730a3; }
.status-erreur_analyse { background: #fee2e2; color: #991b1b; }

.btn-primary, .btn-secondary {
    border-radius: 6px; padding: 7px 14px; font-size: 0.82rem; font-weight: 600;
    cursor: pointer; border: 1px solid transparent; white-space: nowrap;
}
.btn-primary { background: #4fa066; color: #fff; }
.btn-primary:hover { background: #3d8552; }
.btn-primary:disabled { background: #93c5fd; cursor: default; }
.btn-secondary { background: #fff; border-color: #ccc; color: #333; }
.btn-secondary:hover { background: #f3f4f6; }
.btn-secondary:disabled { color: #aaa; cursor: default; }

.panel-result { display: flex; flex-direction: column; overflow: hidden; flex: 1 1 auto; min-width: 0; }
.result-toolbar { flex-shrink: 0; display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 8px; }
.result-toolbar-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.credits-info { font-size: 0.78rem; color: #555; }
.cost-estimate { font-size: 0.78rem; color: #9a3412; }

/* Bandeau de la transcription d'exemple servie aux visiteurs non connectes (cf. #demoBanniere dans
   index.php et afficherExempleTranscription() dans app.js). Teinte ambre volontairement distincte du vert
   du service et du bleu de la zone de depot : c'est un avertissement ("ce que vous lisez n'est pas a
   vous"), il doit se detacher sans pour autant ressembler a une erreur (rouge, cf. .error-msg).
   Aucune propriete `display` ici : le bandeau est masque/reaffiche par l'attribut HTML `hidden`, et la
   regle [hidden]{display:none !important} plus haut ne doit pas avoir a se battre contre une regle
   d'auteur - meme piege que celui documente pour .account-btn. */
/* Largeur plafonnee et compressible : le bandeau doit laisser la place aux boutons de droite sur la
   meme ligne. 62ch garde le texte lisible (une ligne de lecture confortable) sans jamais pousser les
   controles hors de l'ecran. */
.demo-banner { flex-shrink: 1; max-width: 62ch; margin: 0; padding: 4px 10px; border: 1px solid #fcd34d;
               border-radius: 6px; background: #fffbeb; color: #92400e;
               font-size: 0.8rem; font-weight: 600; line-height: 1.45; }

/* margin-left:auto pousse "Terminer l'edition" a l'extremite droite de la barre, les autres
   controles restant groupes a gauche. */
.btn-finish-edit { margin-left: auto; }
.lang-bar { flex-shrink: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; padding: 6px 10px; background: #f9fafb; border: 1px solid #eee; border-radius: 6px; font-size: 0.8rem; }
.lang-label { color: #444; }
.lang-select-label { margin: 0; font-weight: 600; font-size: 0.8rem; }
#langSelect { width: auto; margin-top: 0; }

/* zone edition : image (gauche, 2/3) + blocs (droite, 1/3) toujours cote a cote, meme hauteur, chacune
   avec son propre defilement interne - jamais besoin de faire defiler la PAGE. min-width:0 est
   necessaire sur les 2 colonnes : sans lui, un flex item ne peut pas se retrecir sous la taille
   intrinseque de son contenu (ici le canvas zoome), ce qui faisait deborder .image-col au-dela de sa
   part attendue. Le canvas zoome peut depasser l'espace visible de l'image (largeur fixe a 2/3, pas
   davantage) : on glisse alors l'image a la souris plutot que d'agrandir la colonne, cf. .image-wrap
   et le glisser-deposer dans app.js. */
.edit-area { flex: 1; min-height: 0; display: flex; flex-direction: row; gap: 12px; overflow: hidden; }
.image-col { position: relative; flex: 1 1 66.667%; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.text-col { flex: 1 1 33.333%; min-width: 0; min-height: 0; overflow-y: auto; }

@media (max-width: 1100px) {
    .edit-area { flex-direction: column; }
    .image-col { flex: 0 0 50%; }
}

/* controles de zoom : superposes en haut a gauche de l'image - fond clair semi-opaque pour rester
   lisibles quel que soit le contenu de l'image en dessous. Ancres sur .image-col (qui ne defile jamais)
   et non sur .image-wrap : .image-wrap defile (overflow:auto) quand l'image est zoomee, et un enfant
   position:absolute dont l'ancetre positionne est lui-meme le conteneur de defilement se deplace avec
   le contenu au scroll - les boutons disparaissaient donc du coin en glissant l'image. Etre un sibling
   de .image-wrap (cf. index.php) au lieu d'un enfant regle ca : les boutons restent fixes dans le coin
   quel que soit le defilement/zoom. */
.zoom-controls { position: absolute; top: 8px; left: 8px; z-index: 2; display: flex; align-items: center; gap: 6px; background: rgba(255,255,255,0.92); border: 1px solid #ddd; border-radius: 6px; padding: 4px 6px; box-shadow: 0 1px 4px rgba(0,0,0,0.15); }
.zoom-controls button { border: 1px solid #ccc; background: #fff; border-radius: 4px; width: 26px; height: 26px; cursor: pointer; font-size: 0.9rem; line-height: 1; }
.zoom-controls button:hover { background: #f3f4f6; }

/* image-wrap est le SEUL element qui defile quand l'image est zoomee (barres de defilement) ;
   en zoom "ajuste" (par defaut), le canvas se reduit pour tenir entierement dans l'espace visible
   (largeur ET hauteur), donc toujours visible sans avoir a faire defiler quoi que ce soit.
   align-items/justify-content:center est remplace par flex-start des que le contenu peut deborder
   (classe .zoomed) : centrer un enfant qui deborde dans un conteneur overflow:auto rend la moitie du
   depassement inaccessible au defilement (le haut/la gauche de l'image reste invisible malgre
   l'ascenseur) - bug classique du centrage flex avec overflow, cf. zoomStep()/applyZoom() dans app.js. */
.image-wrap {
    flex: 1; min-height: 0; overflow: auto; cursor: grab;
    border: 1px solid #eee; border-radius: 6px; margin-bottom: 10px; background: #fafafa;
    display: flex; align-items: center; justify-content: center;
}
.image-wrap.zoomed { align-items: flex-start; justify-content: flex-start; }
/* pleine largeur : l'image depasse en hauteur, on l'ancre en haut (meme raison que .zoomed) */
.image-wrap:not(.fit-page-mode) { align-items: flex-start; }
/* glisser-deposer actif (cf. app.js) : curseur "poing ferme", desactive la selection de texte de la
   page pendant le glissement (sinon un drag rapide selectionne aussi le texte alentour du navigateur) */
.image-wrap.dragging { cursor: grabbing; user-select: none; }
/* Par defaut l'image occupe toute la LARGEUR disponible et defile verticalement si elle est haute
   (demande utilisateur). L'ancien reglage la faisait tenir entierement en hauteur comme en largeur :
   sur un acte en portrait, elle se retrouvait minuscule au milieu d'une colonne a moitie vide, et il
   fallait zoomer avant de pouvoir lire quoi que ce soit. La vue "document entier" reste accessible
   par le 3e bouton de zoom (classe .fit-page posee par applyZoom). */
#imageCanvas { display: block; width: 100%; max-width: 100%; height: auto; }
#imageCanvas.fit-page { width: auto; max-height: 100%; }
.image-col textarea#contexte { flex-shrink: 0; margin-bottom: 0; }

/* Document sonore : prend la place de .image-wrap dans la meme colonne (cf. appliquerTypeDocument()
   dans app.js). Meme cadre et meme respiration que la zone image, mais rien a faire defiler ni a
   zoomer - juste le lecteur, centre, et le nom du fichier ecoute. */
.audio-wrap {
    flex: 1; min-height: 0; overflow: auto;
    border: 1px solid #eee; border-radius: 6px; margin-bottom: 10px; background: #fafafa;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 10px; padding: 20px; text-align: center;
}
.audio-doc-icon { font-size: 2.4rem; line-height: 1; }
.audio-doc-name {
    font-size: 0.85rem; font-weight: 600; color: #374151;
    max-width: 100%; overflow-wrap: anywhere;
}
/* width:100% : le lecteur natif s'etire sinon a sa largeur intrinseque (~300px), trop etroite pour
   viser un passage precis dans un enregistrement d'une heure. */
.audio-doc-player { width: 100%; max-width: 520px; }
.audio-doc-hint { font-size: 0.72rem; color: #6b7280; max-width: 420px; }
/* vignette de remplacement dans "Mes documents" pour un enregistrement (pas d'image a afficher) :
   memes dimensions que .history-item img, pour que la liste reste alignee quel que soit le type */
.history-item-audio {
    width: 44px; height: 44px; border-radius: 4px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: #eef2ff; font-size: 1.3rem;
}

.blocks-list { display: flex; flex-direction: column; gap: 8px; }
#btnExport { width: 100%; margin-top: 12px; }
.block-item { border: 1px solid #ddd; border-radius: 8px; padding: 8px 12px; }
.block-item.active { border-color: #4fa066; box-shadow: 0 0 0 1px #4fa066 inset; }
.block-header { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.block-item.active .block-header { margin-bottom: 6px; }
.block-badge { width: 22px; height: 22px; border-radius: 50%; color: #fff; font-size: 0.75rem; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.block-label { font-size: 0.8rem; font-weight: 600; color: #444; }
.block-credits { font-size: 0.7rem; color: #999; margin-left: auto; }
.block-text { width: 100%; min-height: 70px; font-size: 0.85rem; }

.block-audio { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.audio-btn {
    width: 26px; height: 26px; border: 1px solid #ccc; border-radius: 4px;
    background: #fff; cursor: pointer; font-size: 0.8rem; line-height: 1; padding: 0;
}
.audio-btn:hover:not(:disabled) { background: #f3f4f6; }
.audio-btn:disabled { color: #ccc; cursor: default; }
.block-error { color: #b91c1c; font-size: 0.82rem; margin: 6px 0 0; }

.block-lines { display: flex; flex-direction: column; gap: 3px; }
.block-line { display: flex; align-items: center; gap: 6px; padding: 3px; border-radius: 4px; cursor: pointer; }
.block-line:hover { background: #f3f4f6; }
.block-line.active { background: #fef9c3; }
.line-badge { width: 18px; height: 18px; border-radius: 50%; color: #fff; font-size: 0.66rem; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.line-text { flex: 1; min-width: 0; padding: 3px 6px; border: 1px solid #ddd; border-radius: 4px; font-family: inherit; font-size: 0.82rem; }
