/* ═══════════════════════════════════════════════════════════════
   organigramme.app

   L'IDENTITE VIENT DU SITE, ET NON PLUS DE cles.app

   Cette feuille a eu deux vies avant celle-ci : d'abord un style invente — bleu
   marine et or — puis les jetons de cles.app, accent presque noir sur fond blanc.

   Le site organigramme-de-cle.fr est desormais la reference : c'est la que le
   client arrive, et l'application est le meme produit. Un serrurier qui passe du
   site a l'application ne doit pas avoir l'impression de changer de maison.

   LES VALEURS SONT DANS `jetons.css`, QUI EST UNE COPIE DU SITE

   Copie, et non feuille partagee : l'application doit s'ouvrir sans reseau, et
   dependre d'une feuille servie par un autre domaine ferait un ecran blanc au
   fond d'une cave. `verifier.mjs` compare les deux octet par octet quand les deux
   depots sont la. Le fichier lui-meme explique l'arrangement.

   LE SITE NE SE RESUME PAS A SES COULEURS : QUATRE TRAITS DE FORME

   Reprendre les seuls jetons aurait donne l'ancienne application repeinte. Ce qui
   fait le site, en le lisant :

     1. LES OBJETS SE SEPARENT PAR LA SURFACE, PAS PAR UNE BORDURE. `.card` du
        site n'a aucun trait : du blanc sur un fond gris. Ici tout etait cercle
        d'un trait de 1,5 px — le reflexe d'une application, pas de ce site.

     2. LES GRAISSES VONT DE 300 A 600, ET S'ARRETENT LA. Le site charge
        300;400;500;600 et ses titres sont en 600. Cette feuille montait a 900.
        C'est le changement qui se voit le plus.

     3. LES CODES SONT EN GEIST MONO. Le site met ses reperes — K-01, un numero de
        telephone, l'intitule d'une section — dans la police a chasse fixe, en
        capitales espacees. Les abreviations d'ici (BTN, PG, PP) sont exactement
        cela, et elles se parcourent mieux en colonne.

     4. LES INTITULES SONT DES « EYEBROW ». Petits, en mono, en capitales, gris.
        C'est la forme unique de tous les intitules du site, et elle remplace les
        quatre formes que cette feuille avait inventees.

   LES POLICES SONT HEBERGEES ICI, ET C'EST UNE OBLIGATION

   Le site charge Geist chez Google. L'application ne peut pas : sa politique de
   securite ne laisse passer qu'elle-meme, et une police distante manquerait
   justement dans la cave ou l'application sert. Les deux fichiers sont donc dans
   `polices/`, 113 Ko en tout, gardes par le service worker — avec leur licence,
   qui est une SIL OFL et voyage avec eux.

   UN SEUL RAYON, A 10 px, ET PARTOUT

   Le site en a trois (24, 16, 12) et ses boutons sont des pilules. Ici Francois a
   demande 10 px sur les boutons, les cartes et le tableau, pour une raison qui
   tient : sur des elements qui se touchent — une carte, le tableau dedans, les
   boutons dessous — deux rayons se voient. La consigne est gardee telle quelle.
   Seules les pastilles d'etat restent rondes, comme les `chip` du site : ce sont
   des etiquettes, pas des boutons.

   LA COQUILLE A UNE HAUTEUR FIXE, ET UNE SEULE CHOSE DEFILE

   `html` et `body` sont verrouilles, les barres flottent au-dessus, et `.views`
   est le seul element qui defile. `height:100%` sur un corps verrouille est
   stable sur iOS, contrairement a `100dvh` qui bouge avec la barre d'adresse.

   UN SEUL JEU DE REGLES POUR LE TELEPHONE ET POUR L'ECRAN

   Le bloc « GRAND ECRAN », a la fin, change la disposition et rien d'autre : la
   barre du bas devient un rail a gauche, la lecture se centre. Deux feuilles
   auraient voulu dire deux corrections a faire a chaque fois, et une des deux
   oubliee.
   ═══════════════════════════════════════════════════════════════ */

/* Geist en variable : un fichier par famille couvre toute la plage de graisses, la
   ou six fichiers statiques auraient pese le triple. `swap` pour que le texte
   s'affiche tout de suite dans la police de secours plutot que de laisser un
   blanc — la plage de secours est declaree dans `jetons.css`. */
@font-face{
    font-family:'Geist';
    src:url('../polices/Geist-Variable.woff2') format('woff2');
    font-weight:300 700;
    font-style:normal;
    font-display:swap;
}
@font-face{
    font-family:'Geist Mono';
    src:url('../polices/GeistMono-Variable.woff2') format('woff2');
    font-weight:400 600;
    font-style:normal;
    font-display:swap;
}

:root{
    /* CE QUE `jetons.css` N'A PAS : LES COULEURS D'ETAT.

       Le site n'a aucun etat a montrer — il ne fait rien qui reussisse ou echoue.
       L'application, si : un devis demande, un refus de chiffrage, un hors-reseau.

       Ces valeurs sont donc PROPRES a l'application, choisies pour tenir sur le
       fond gris du site et pour rester lisibles sur leur propre fond clair. Elles
       ne sont pas dans `jetons.css` parce que ce fichier est une copie exacte du
       site, et qu'y ajouter quoi que ce soit ferait echouer la comparaison. Le
       jour ou le site aura des etats, elles remonteront la-bas. */
    --stop:#B0271D;         --stop-fond:#FBEAE8;
    --attention:#8A5A00;    --attention-fond:#FBF1DC;
    --ok:#0B6B38;           --ok-fond:#E4F3EA;
    --accent-fort:#0058B0;  --accent-fond:#E3F0FD;

    /* UN SEUL RAYON, A 10 px. Voir l'en-tete. */
    --radius:10px;

    --tabbar-h:64px;
    --topbar-h:54px;
    --rail-w:236px;
    font-synthesis-weight:none;
}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
[hidden]{display:none !important;}
html,body{margin:0;padding:0;height:100%;overflow:hidden;}
body{
    font-family:var(--sans);
    background:var(--bg);color:var(--ink);
    font-weight:400;
    -webkit-font-smoothing:antialiased;
    overscroll-behavior-y:none;
}
button{font-family:inherit;cursor:pointer;color:inherit;}
img{max-width:100%;}
.muted{color:var(--muted);}
.xs{font-size:.76rem;}
.center{text-align:center;}

/* L'INTITULE DU SITE — SA FORME, ET NON UNE CLASSE.
   Mono, capitales, un peu d'espace, gris : c'est l'« eyebrow » du site, et tous
   les intitules d'ici en sont — `.lbl`, `.resume-label`, `.visu th`, la legende
   des fonctions, `.etat`, `.pastille`. Il n'y a PAS de classe `.eyebrow` : elle
   n'aurait eu aucun consommateur, puisque chaque emploi a sa taille et sa
   couleur, et une regle que rien n'emploie finit par mentir. */

/* ===== controles ===== */
.lbl{display:block;font-family:var(--mono);font-size:.68rem;font-weight:400;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:18px 0 7px;}
.inp{width:100%;border:1px solid var(--line-2);border-radius:var(--radius);padding:13px 14px;font-family:inherit;font-size:1rem;font-weight:400;background:var(--surface);color:var(--ink);transition:border-color .15s,box-shadow .15s;}
/* Le halo remplace l'epaississement du trait : un champ qui passe de 1 a 1,5 px
   au focus decale de 1 px tout ce qui le suit. `--accent-soft` existe pour cela. */
.inp:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);}
select.inp{appearance:none;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236E6E73' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center;background-size:18px;padding-right:36px;}
.err{color:var(--stop);font-weight:500;font-size:.86rem;margin:10px 0 0;}
.hint{color:var(--muted);font-size:.8rem;line-height:1.45;margin:8px 0 0;}

/* Les boutons du site sont des pilules de 52 px en graisse 500. La graisse et la
   hauteur sont reprises ; le rayon reste a 10 px, par la consigne. */
.btn{
    display:inline-flex;align-items:center;justify-content:center;gap:9px;
    min-height:50px;padding:0 24px;border:1px solid var(--line-2);border-radius:var(--radius);
    font-size:1rem;font-weight:500;background:var(--surface);color:var(--ink);
    transition:opacity .15s,transform .08s;
}
.btn:active{transform:scale(.985);}
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);}
/* `.btn.validate`, un bouton vert, a ete retire : rien ne l'employait. « Demander
   un devis » est un `.btn` ordinaire, et c'est juste — ce n'est pas une
   validation, c'est un envoi qui attend une reponse. */
.btn.danger{background:var(--surface);border-color:var(--stop);color:var(--stop);}
.btn.block{display:flex;width:100%;}
.btn:disabled{opacity:.45;}
.btn + .btn{margin-top:10px;}

/* ===== CONNEXION ===== */
.login{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--bg);overflow-y:auto;}
.login-card{width:100%;max-width:400px;text-align:center;}
/* LA MARQUE DU SITE, ET LE NOM ECRIT A COTE.

   `images/marque.svg` est une COPIE octet pour octet de
   `odc/dist/assets/favicon.svg` — le meme embleme que porte le site, et non un
   dessin refait. Meme arrangement que pour les jetons : `verifier.mjs` compare
   les deux quand les deux depots sont la.

   Le NOM reste ecrit. `images/logo.png` de ce depot est le logo de mrcle:run,
   repris par erreur ; il n existe aucun logo texte pour organigramme.app, et un
   nom ecrit dit la verite la ou une image empruntee dit le nom d un autre
   produit.

   La graisse suit celle du site : son `.logo` est en 600, pas en 900.

   `inline-flex` plutot qu une regle par taille : la marque et l espace qui la
   separe du nom sont en `em`, donc ils suivent le nom du plus petit au plus
   grand sans qu on ait a les regler trois fois.

   L ESPACE EST UNE MARGE SUR LA MARQUE, ET NON UN `gap`.

   Un `gap` se met entre TOUS les enfants du flex, et « organigramme » et
   « <em>.app</em> » en sont deux : le nom se lisait « organigramme .app », coupe
   en deux par un blanc. Une marge ne separe que ce qu on voulait separer. */
.nom{display:inline-flex;align-items:center;font-weight:600;letter-spacing:-.03em;line-height:1;}
/* Le `.app` prend l ACCENT du site. Il etait gris pale : le nom du produit y
   perdait sa seconde moitie, et c est justement celle qui le distingue du site. */
.nom em{font-style:normal;color:var(--accent);font-weight:400;}
.marque{flex:0 0 auto;width:1.1em;height:1.1em;margin-right:.4em;}
.login-logo{font-size:2rem;margin:0 0 10px;}
.home-nom{font-size:2.1rem;margin:10px 0 20px;}
.topbar-nom{font-size:1.02rem;}
.login-tag{font-family:var(--mono);font-size:.7rem;font-weight:400;color:var(--muted);letter-spacing:.16em;text-transform:uppercase;margin:0 0 26px;}
.login form{text-align:left;}
.login .btn{margin-top:24px;}
.login .muted{margin-top:18px;}

/* ===== LA COQUILLE ===== */
.app{position:relative;height:100%;overflow:hidden;}

/* Le verre depoli du site, aux memes valeurs : .85 d'opacite, flou de 20, un
   trait de 1 px en dessous. */
.topbar{
    position:absolute;top:0;left:0;right:0;z-index:10;
    display:flex;align-items:center;gap:8px;padding:0 10px;
    padding-top:env(safe-area-inset-top);height:calc(var(--topbar-h) + env(safe-area-inset-top));
    background:rgba(255,255,255,.85);
    -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px);
    border-bottom:1px solid var(--line);
}
.topbar-title{flex:1;display:flex;align-items:center;justify-content:center;min-width:0;}
.topbar-title.texte{font-weight:500;font-size:1.02rem;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.topbar-spacer{width:38px;flex:0 0 auto;}

.iconbtn{width:38px;height:38px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;background:transparent;border:0;border-radius:var(--radius);}
.iconbtn:active{background:var(--fill);}
.iconbtn svg{width:22px;height:22px;fill:none;stroke:var(--ink);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}

/* La place du retour reste RESERVEE quand il est cache, sinon le titre se
   decale de 38 px a chaque changement d ecran. */
.topbar .back{visibility:hidden;}
.topbar .back.show{visibility:visible;}

.views{
    position:absolute;inset:0;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
    padding:calc(var(--topbar-h) + env(safe-area-inset-top) + 16px) 16px calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 18px);
}
.view-title{font-size:1.5rem;font-weight:600;letter-spacing:-.025em;margin:4px 2px 14px;}
.view-hint{color:var(--muted);font-size:.88rem;line-height:1.45;margin:-8px 2px 18px;}

.tabbar{
    position:absolute;left:0;right:0;bottom:0;z-index:10;display:grid;grid-template-columns:repeat(4,1fr);
    background:rgba(255,255,255,.85);
    -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px);
    border-top:1px solid var(--line);padding-bottom:env(safe-area-inset-bottom);
}
.tab{
    height:var(--tabbar-h);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    background:transparent;border:0;color:var(--faint);font-size:.64rem;font-weight:500;letter-spacing:.01em;
}
.tab svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}
/* L'onglet courant prend l'accent, comme le lien courant du site :
   `.nav a[aria-current=page]{color:var(--accent)}`. */
.tab.active{color:var(--accent);}

/* ===== ACCUEIL ===== */
.home{max-width:560px;margin:0 auto;padding:8px 4px 0;text-align:center;}
.home-title{font-size:1.65rem;line-height:1.14;font-weight:600;letter-spacing:-.03em;margin:0 0 12px;}
.home-sub{color:var(--muted);font-size:.96rem;line-height:1.55;margin:0 auto 28px;max-width:40ch;}

.steps{list-style:none;margin:0 0 28px;padding:0;text-align:left;position:relative;}
.steps:before{content:"";position:absolute;left:34px;top:24px;bottom:24px;width:1px;background:var(--line-2);}
.step{display:grid;grid-template-columns:auto auto 1fr;align-items:center;gap:14px;padding:12px 0;position:relative;}
.step-num{width:30px;height:30px;border-radius:50%;background:var(--accent);color:var(--accent-ink);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-weight:500;font-size:.84rem;z-index:1;}
.step-ico{width:44px;height:44px;border-radius:var(--radius);background:var(--surface);display:flex;align-items:center;justify-content:center;}
.step-ico svg{width:22px;height:22px;fill:none;stroke:var(--ink);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;}
.step-txt h3{margin:0 0 2px;font-size:.98rem;font-weight:500;}
.step-txt p{margin:0;color:var(--muted);font-size:.84rem;line-height:1.45;}

/* Le resume du haut d accueil : combien de chantiers, et combien attendent.
   Une surface blanche sur le fond gris, sans trait — la `card` du site. */
.resume{text-align:left;background:var(--surface);border-radius:var(--radius);padding:15px 17px;margin:0 0 24px;}
.resume-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;}
.resume-label{font-family:var(--mono);font-size:.66rem;font-weight:400;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);}
.resume-gros{font-weight:600;font-size:1.3rem;letter-spacing:-.03em;font-variant-numeric:tabular-nums;}
.resume-sub{color:var(--muted);font-size:.82rem;margin:5px 0 0;}
/* Un chantier qui attend un devis se signale par la COULEUR DU NOMBRE, et non
   par un cadre : sur un fond gris, une carte cerclee d'ambre crie. */
.resume.attente .resume-gros{color:var(--attention);}
.resume.attente .resume-label{color:var(--attention);}

.compte{margin:30px 0 8px;padding-top:20px;border-top:1px solid var(--line-2);text-align:left;}
.compte-qui{display:flex;flex-direction:column;gap:3px;margin-bottom:16px;}
.compte-nom{font-weight:500;font-size:.96rem;}

/* ===== LES LISTES DE CHANTIERS ===== */
.cartes{display:flex;flex-direction:column;gap:12px;}
.carte{
    display:block;width:100%;text-align:left;background:var(--surface);border:0;
    border-radius:var(--radius);padding:15px 17px;transition:transform .08s,box-shadow .15s;
}
.carte:active{transform:scale(.99);}
.carte-tete{display:flex;align-items:baseline;justify-content:space-between;gap:10px;}
.carte-nom{font-weight:500;font-size:1.05rem;letter-spacing:-.015em;}
.carte-sous{color:var(--muted);font-size:.82rem;margin:3px 0 0;}
.carte-pied{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:11px;padding-top:11px;border-top:1px solid var(--line);}
.carte-total{font-weight:600;font-size:1.05rem;letter-spacing:-.02em;font-variant-numeric:tabular-nums;}

/* ===== LES ETATS ===== */
/* Rondes, comme les `chip` du site : ce sont des etiquettes, pas des boutons —
   la consigne des 10 px porte sur les boutons, les cartes et le tableau. */
.etat{display:inline-block;padding:3px 10px;border-radius:999px;font-family:var(--mono);font-size:.62rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;}
/* « En cours » reste neutre : un chantier en cours n est pas un retard. */
.etat-brouillon{background:var(--fill);color:var(--muted);}
.etat-devis_demande{background:var(--attention-fond);color:var(--attention);}
.etat-traite{background:var(--ok-fond);color:var(--ok);}

/* ═══════════════════════════════════════════════════════════════
   LE CHANTIER EN TABLEAU

   Un organigramme SE LIT en tableau, et c'est ainsi qu'un serrurier le connait :
   une ligne par porte, les cotes et les fonctions en colonnes. Des cartes
   empilees obligeaient a comparer deux portes de memoire.

   Le tableau defile HORIZONTALEMENT dans son propre conteneur, jamais la page :
   sur un telephone six colonnes ne tiennent pas, et une page qui part de cote
   emporte la barre du haut avec elle.
   ═══════════════════════════════════════════════════════════════ */

.visu{border-radius:var(--radius);overflow:hidden;background:var(--surface);}
.visu-defile{overflow-x:auto;-webkit-overflow-scrolling:touch;}

.visu table{width:100%;border-collapse:collapse;font-size:.86rem;}
/* L EN-TETE SE LIT COMME SES CELLULES, ET NON COMME UNE NOTE DE BAS DE PAGE.
   Il etait a .62rem sous des cellules a .86 : l intitule d une colonne etait plus
   petit que tout le reste du tableau, et on cherchait a quoi correspondait la
   colonne qu on lisait. La forme reste celle du site — mono, capitales, espace —
   mais a une taille qui en fait le PAIR de ses nombres.

   L ESPACE ET LA MARGE INTERIEURE SE RESSERRENT D AUTANT. Sur un telephone, un
   en-tete plus gros elargit chaque colonne, et le tableau se mettait a deborder
   la ou il tenait : la colonne des prix etait coupee au repos. Elle defile, mais
   un prix tronque a l ouverture n est pas ce qu on vient voir. */
.visu th{
    position:sticky;top:0;background:var(--fill);padding:10px 9px;text-align:left;white-space:nowrap;
    font-family:var(--mono);font-size:.7rem;font-weight:500;text-transform:uppercase;letter-spacing:.02em;color:var(--muted);
}
/* Le trait au-DESSUS de chaque cellule, et non en dessous : la derniere ligne n'a
   donc aucun trait a retirer sous elle, et le bas de la carte reste net. */
.visu td{padding:11px;border-top:1px solid var(--line);vertical-align:top;}
.visu tbody tr{cursor:pointer;}
.visu tbody tr:active{background:var(--fill);}

/* La premiere colonne reste visible quand on fait defiler : sans elle on lit des
   chiffres sans savoir de quelle porte ils sont. */
.visu .col-porte{position:sticky;left:0;background:var(--surface);border-right:1px solid var(--line);min-width:134px;}
.visu th.col-porte{background:var(--fill);z-index:2;}
.visu tbody tr:active .col-porte{background:var(--fill);}

.col-nb{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;}
.col-prix{text-align:right;font-variant-numeric:tabular-nums;font-weight:500;white-space:nowrap;}
/* L'EN-TETE SUIT SA COLONNE.
   `.visu th` pose `text-align:left` avec deux classes, `.col-nb` le contredit avec
   une seule : l'en-tete restait donc a gauche pendant que ses nombres etaient a
   droite. Sur « ÉT. », « CLÉS » et « HT », l'intitule ne surmontait plus rien. */
.visu th.col-nb,.visu th.col-prix{text-align:right;}
.visu-nom{font-weight:500;}
.visu-repere{display:block;font-family:var(--mono);color:var(--faint);font-size:.7rem;margin-top:2px;}

/* Le pied du tableau porte les totaux, et ne defile pas avec les lignes. Il porte
   des SOMMES : les afficher plus petit que les prix de chaque ligne revenait a
   dire qu elles comptent moins. */
.visu-pied{display:flex;flex-wrap:wrap;gap:4px 16px;padding:12px 13px;background:var(--fill);font-size:.86rem;color:var(--muted);}
.visu-pied strong{color:var(--ink);font-weight:500;font-variant-numeric:tabular-nums;}

/* ===== LE TOTAL D UN CHANTIER ===== */
/* L en-tete du total : COMPACT. Il etait haut comme une carte de tableau de
   bord pour trois nombres, et poussait le tableau — ce qu on vient voir — sous
   la ligne de flottaison.

   Le nombre reprend le `.big` du site : graisse 600, interlettrage tres serre.
   C'est ce qui donne au chiffre son poids, et non une graisse de 900.

   UN FILET, ICI, ET NON LA SEULE SURFACE.

   Le site separe ses objets par la surface, et cette feuille a suivi partout. Mais
   une carte BLANCHE sur un fond GRIS CLAIR tient par un ecart de luminosite de
   trois pour cent : la liste et le tableau s'en passent parce qu'ils sont larges
   et pleins, tandis que ce bloc-ci est court, isole, et se mettait a flotter.

   Le meme trait que les boutons et les champs — `--line-2` — pour que ce soit le
   filet de la maison et non un troisieme gris invente. */
.somme{background:var(--surface);border:1px solid var(--line-2);border-radius:var(--radius);padding:12px 14px;margin:0 0 12px;}
.somme-tete{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:3px;}
.somme-gamme{font-family:var(--mono);font-size:.68rem;font-weight:400;letter-spacing:.04em;color:var(--muted);}
.somme-gros{font-size:1.5rem;font-weight:600;letter-spacing:-.04em;line-height:1.08;font-variant-numeric:tabular-nums;}
.somme-gros small{font-family:var(--mono);font-size:.66rem;font-weight:400;color:var(--muted);letter-spacing:.04em;}
.somme-details{display:flex;flex-wrap:wrap;gap:2px 12px;margin-top:8px;padding-top:8px;border-top:1px solid var(--line);font-size:.76rem;color:var(--muted);}
.somme-details strong{color:var(--ink);font-weight:500;font-variant-numeric:tabular-nums;}
.somme-note{margin:6px 0 0;font-size:.7rem;color:var(--faint);}
/* Un refus prend la place du total : afficher zero euro laisserait croire a un prix. */
.somme-refus{font-size:.92rem;font-weight:500;color:var(--stop);line-height:1.4;}

/* ===== LES FONCTIONS ===== */
.fonctions{margin:20px 0 0;padding:18px 0 0;border:0;border-top:1px solid var(--line-2);}
.fonctions legend{padding:0;font-family:var(--mono);font-size:.68rem;font-weight:400;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);}
.fonction-choix{display:flex;align-items:center;gap:12px;min-height:46px;padding:5px 0;border-bottom:1px solid var(--line);cursor:pointer;}
.fonction-choix:last-child{border-bottom:0;}
.fonction-choix input{width:20px;height:20px;flex-shrink:0;accent-color:var(--accent);}
.fonction-nom{flex:1;min-width:0;font-size:.92rem;}
.fonction-prix{color:var(--muted);font-size:.85rem;font-variant-numeric:tabular-nums;}
/* Une fonction que la gamme ne propose plus reste VISIBLE et barree quand une
   porte la retient : la faire disparaitre changerait le prix sans rien dire. */
.fonction-retiree{opacity:.5;text-decoration:line-through;}

.puces{display:flex;flex-wrap:wrap;gap:4px;}
/* Des abreviations : « P-INT » et non « protection intemperies ». En Geist Mono,
   comme les reperes du site — une colonne de codes a chasse fixe se parcourt du
   regard, la ou une chasse variable la fait onduler. */
.puce{display:inline-block;padding:2px 6px;border-radius:5px;background:var(--fill);font-family:var(--mono);font-size:.66rem;font-weight:500;letter-spacing:.02em;color:var(--ink-2);white-space:nowrap;}
.puce-retiree{background:var(--stop-fond);color:var(--stop);text-decoration:line-through;}

/* ===== MESSAGES ===== */
.avis{border-left:3px solid var(--line-2);border-radius:var(--radius);padding:12px 14px;font-size:.86rem;font-weight:400;line-height:1.45;margin:0 0 14px;background:var(--surface);}
.avis.stop{border-left-color:var(--stop);color:var(--stop);background:var(--stop-fond);}
.avis.attention{border-left-color:var(--attention);color:var(--attention);background:var(--attention-fond);}
.avis p{margin:0 0 4px;}
.avis p:last-child{margin-bottom:0;}
.avis strong{font-weight:500;}

.vide{padding:36px 16px;text-align:center;color:var(--muted);font-size:.92rem;line-height:1.5;}

/* ===== PASTILLES DE LA BARRE ===== */
.pastilles{display:flex;gap:6px;justify-content:center;margin:0 0 14px;}
.pastille{padding:4px 11px;border-radius:999px;font-family:var(--mono);font-size:.64rem;font-weight:500;letter-spacing:.04em;text-transform:uppercase;}
.pastille-hors{background:var(--fill);color:var(--muted);}
.pastille-attente{background:var(--attention-fond);color:var(--attention);}

/* ===== RANGEES DE CHAMPS ===== */
.rangee{display:flex;gap:10px;}
.rangee > div{flex:1;min-width:0;}
.rangee .lbl{margin-top:18px;}
@media (max-width:360px){
    .rangee{flex-wrap:wrap;}
    .rangee > div{flex:1 1 100%;}
}

/* Le total d une porte colle au bas pendant la saisie : c est le chiffre qu on
   regarde en tapant, et le faire defiler le rendrait inutile. Il lui faut un fond
   OPAQUE, sinon les lignes passent derriere ; l ombre dit qu il y a du contenu
   dessous, ce qu une bordure faisait avant. */
.somme.collee{position:sticky;bottom:0;background:var(--surface);z-index:5;margin-top:16px;box-shadow:0 -8px 16px -8px rgba(29,29,31,.10);}

.actions{margin-top:20px;}

@media (prefers-reduced-motion:reduce){
    *{animation:none !important;transition:none !important;}
}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}


/* ═══════════════════════════════════════════════════════════════
   LE MENU DES FONCTIONS

   Un serrurier choisit « PP » ou « SAT » dans une liste de cases a cocher. Les
   abreviations rendent le tableau lisible, mais elles ne disent pas ce que la
   fonction EST — et plusieurs sont des codes que le fabricant emploie sans les
   developper nulle part.

   Cette page met les trois cote a cote : l abreviation, le nom entier, le prix.
   ═══════════════════════════════════════════════════════════════ */

.fnc{background:var(--surface);border-radius:var(--radius);overflow:hidden;}
.fnc-ligne{display:flex;align-items:center;gap:12px;padding:12px 14px;border-top:1px solid var(--line);}
.fnc-ligne:first-child{border-top:0;}
.fnc-code{flex:0 0 70px;font-family:var(--mono);font-size:.7rem;font-weight:500;letter-spacing:.03em;color:var(--ink-2);
    background:var(--fill);border-radius:5px;padding:4px 0;text-align:center;}
.fnc-nom{flex:1;min-width:0;font-size:.9rem;}
.fnc-prix{font-size:.85rem;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;}
/* Une fonction que la gamme ne propose plus reste LISTEE et barree : elle peut
   etre retenue par une porte relevee avant, et la faire disparaitre laisserait
   chercher d ou vient son prix. */
.fnc-ligne.retiree{opacity:.5;}
.fnc-ligne.retiree .fnc-nom{text-decoration:line-through;}

/* Le lien depuis l editeur : discret, mais a portee du pouce au moment ou la
   question se pose — devant les cases a cocher. Le `.link` du site est en accent
   et en 500, sans soulignement ; il ne se souligne qu au survol. */
.fnc-lien{background:transparent;border:0;padding:6px 0;font-size:.82rem;font-weight:500;color:var(--accent);}

/* ═══════════════════════════════════════════════════════════════
   CINQ ONGLETS
   ═══════════════════════════════════════════════════════════════ */

.tabbar-5{grid-template-columns:repeat(5,1fr);}
/* A cinq, « Organigrammes » deborde sur un petit telephone. */
.tabbar-5 .tab{font-size:.6rem;}
.tabbar-5 .tab span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 2px;}

/* ═══════════════════════════════════════════════════════════════
   LES TROIS ACTIONS D UNE CARTE

   Modifier, Partager, Supprimer — la ou l on CHOISIT un chantier, donc la ou
   l on decide quoi en faire. Dans la barre du haut il fallait d abord l ouvrir.

   Trois teintes CLAIRES et non trois couleurs franches : ce sont des actions
   ordinaires, pas des alertes. Seule la suppression tire vers le rouge, parce
   qu elle est la seule qui ne se defait pas.

   Les teintes viennent de la palette du site — le bleu de l accent pour
   « modifier » — et non de trois familles empruntees ailleurs. Sans bordure : la
   teinte suffit a separer, comme partout ici.
   ═══════════════════════════════════════════════════════════════ */

/* QUATRE ACTIONS, DONC DEUX RANGEES SUR UN TELEPHONE.
   A quatre de front sur un ecran de 390 px, chaque bouton fait 76 px alors que
   « Supprimer » avec son icone en demande 81 : le mot se coupait. Deux par deux
   jusqu'a 560 px, quatre de front au-dela, ou la place existe. */
.carte-actions{display:grid;grid-template-columns:repeat(2,1fr);gap:6px;margin-top:11px;padding-top:11px;border-top:1px solid var(--line);}
@media (min-width:560px){ .carte-actions{grid-template-columns:repeat(4,1fr);} }
.acte{
    display:flex;align-items:center;justify-content:center;gap:6px;
    min-height:38px;padding:0 6px;border:0;border-radius:var(--radius);
    font-size:.76rem;font-weight:500;background:var(--fill);color:var(--muted);
    transition:transform .08s,filter .15s;
}
.acte svg{width:15px;height:15px;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;}
.acte:active{transform:scale(.97);}

/* L'ACCENT VA A « PORTES », ET NON PLUS A « MODIFIER ».
   C'est le geste pour lequel on ouvre l'application ; modifier le nom d'un
   chantier est une correction occasionnelle. Celle-ci redevient donc neutre, ce
   qui laisse trois teintes pour trois intentions : faire, partager, detruire. */
.acte-portes{background:var(--accent-fond);color:var(--accent-fort);}
.acte-modifier{background:var(--fill);color:var(--ink-2);}
.acte-partager{background:var(--ok-fond);color:var(--ok);}
.acte-supprimer{background:var(--stop-fond);color:var(--stop);}

/* ═══════════════════════════════════════════════════════════════
   LE RAPPEL AVANT DE SUPPRIMER
   ═══════════════════════════════════════════════════════════════ */

.modale{position:fixed;inset:0;z-index:50;display:flex;align-items:flex-end;justify-content:center;
    background:rgba(29,29,31,.40);padding:16px;padding-bottom:max(16px,env(safe-area-inset-bottom));}
/* Par le BAS sur un telephone : c est la ou le pouce est. */
@media (min-width:560px){ .modale{align-items:center;} }

.modale-boite{width:100%;max-width:420px;background:var(--surface);border-radius:var(--radius);padding:20px;}
.modale-titre{margin:0 0 8px;font-size:1.08rem;font-weight:600;letter-spacing:-.02em;}
.modale-texte{margin:0 0 6px;font-size:.92rem;line-height:1.5;}
.modale-note{margin:0 0 18px;font-size:.8rem;color:var(--stop);font-weight:500;}
.modale-actions{display:flex;flex-direction:column;gap:8px;}

/* ═══════════════════════════════════════════════════════════════
   LES FICHES DE FONCTIONS

   Ce qu une fonction EST, et non seulement ce qu elle coute. Les textes viennent
   de l ancienne application, ou quelqu un qui savait les avait ecrits.
   ═══════════════════════════════════════════════════════════════ */

.fiche{background:var(--surface);border-radius:var(--radius);margin-bottom:8px;overflow:hidden;}
.fiche-tete{display:flex;align-items:center;gap:10px;width:100%;padding:12px 14px;background:transparent;border:0;text-align:left;}
.fiche-tete:active{background:var(--fill);}
.fiche-code{flex:0 0 68px;font-family:var(--mono);font-size:.68rem;font-weight:500;letter-spacing:.03em;color:var(--ink-2);
    background:var(--fill);border-radius:5px;padding:4px 0;text-align:center;}
.fiche-titre{flex:1;min-width:0;font-size:.92rem;font-weight:500;}
.fiche-prix{font-size:.84rem;font-weight:400;font-variant-numeric:tabular-nums;color:var(--muted);white-space:nowrap;}
.fiche-chevron{flex:0 0 auto;width:16px;height:16px;fill:none;stroke:var(--faint);stroke-width:1.9;
    stroke-linecap:round;stroke-linejoin:round;transition:transform .15s;}
.fiche.ouverte .fiche-chevron{transform:rotate(180deg);}

/* Le corps est REPLIE par defaut : dix-sept fiches depliees font une page qu on
   ne parcourt pas, et on vient chercher UNE fonction. */
.fiche-corps{padding:0 14px 14px;font-size:.88rem;line-height:1.55;color:var(--ink-2);white-space:pre-line;}
.fiche:not(.ouverte) .fiche-corps{display:none;}
.fiche-sans{padding:0 14px 14px;font-size:.84rem;color:var(--faint);font-style:italic;}

/* La zone qui ouvre le chantier : un vrai bouton, pleine largeur, sans decor —
   la carte porte deja la surface. */
.carte-ouvrir{display:block;width:100%;padding:0;border:0;background:transparent;text-align:left;color:inherit;font:inherit;}
.carte-ouvrir:active{opacity:.7;}
.carte-sous{display:block;}


/* ═══════════════════════════════════════════════════════════════
   GRAND ECRAN

   UNE SEULE APPLICATION, DEUX DISPOSITIONS

   Francois voulait l'application aussi sur un ecran de bureau, atteignable depuis
   le site. Deux codes auraient voulu dire deux corrections a chaque fois, et une
   des deux oubliee — c'est le meme raisonnement que pour les jetons.

   Ce bloc ne change QUE la disposition. Aucune couleur, aucune graisse, aucun
   libelle : si une regle ici touchait a autre chose, l'application de bureau
   commencerait a diverger de celle du telephone sans que rien ne le signale.

   CE QUI CHANGE, ET POURQUOI

     - La barre du bas devient un RAIL A GAUCHE. Une barre d'onglets collee en bas
       d'un ecran de 27 pouces met les commandes a un demi-metre du regard ; c'est
       une forme qui n'a de sens que sous le pouce.

     - La lecture se CENTRE, a 1040 px au plus. Une ligne de texte de 1400 px ne
       se lit pas, et un tableau de six colonnes etale sur toute la largeur oblige
       a balayer la tete. `padding-inline` avec `max()` centre sans ajouter de
       conteneur — donc sans toucher aux vues, qui sont les memes.

     - Le nom passe A GAUCHE, comme le logo du site. Centre, il flottait au milieu
       d'une barre vide de 1400 px.

     - La liste des chantiers passe a DEUX COLONNES. C'est l'ecran ou l'on
       cherche ; une carte seule par ligne y laissait la moitie du vide.

   900 px EST LE SEUIL, ET NON 768

   A 768 px on est encore sur une tablette tenue en main, ou la barre du bas est
   la bonne forme. Le rail suppose une souris, ou une tablette posee.
   ═══════════════════════════════════════════════════════════════ */

@media (min-width:900px){
    /* La barre du haut tient toute la largeur, le rail est SOUS elle — comme le
       site garde son en-tete au-dessus de tout. */
    .topbar{padding:0 20px;}
    .topbar-title{justify-content:flex-start;padding-left:4px;}
    .topbar-nom{font-size:1.1rem;}
    .topbar-spacer{display:none;}

    /* `env(safe-area-inset-top)` est REPRIS ici, et ce n'est pas une precaution
       inutile : un iPad en paysage depasse 900 px ET a une zone sure. Sans lui, le
       rail commencait sous la barre du haut — donc masque par elle — et le premier
       titre de chaque ecran passait derriere l'encoche. */
    .tabbar,.tabbar-5{
        top:calc(var(--topbar-h) + env(safe-area-inset-top));bottom:0;right:auto;width:var(--rail-w);
        display:flex;flex-direction:column;align-items:stretch;gap:2px;
        padding:14px 10px calc(14px + env(safe-area-inset-bottom));
        background:var(--surface);
        -webkit-backdrop-filter:none;backdrop-filter:none;
        border-top:0;border-right:1px solid var(--line);
    }
    .tab,.tabbar-5 .tab{
        height:44px;flex-direction:row;justify-content:flex-start;gap:12px;
        padding:0 12px;border-radius:var(--radius);font-size:.92rem;font-weight:400;letter-spacing:0;
    }
    .tabbar-5 .tab span{max-width:none;overflow:visible;padding:0;}
    .tab svg{width:20px;height:20px;}
    /* Au rail, la couleur seule ne suffit pas a dire « vous etes ici » : l'oeil
       balaie une colonne de cinq lignes identiques. Le fond tenu que le site
       reserve a son accent (`--accent-soft`) le dit sans crier. */
    .tab.active{background:var(--accent-soft);color:var(--accent);font-weight:500;}

    .views{
        left:var(--rail-w);
        padding-top:calc(var(--topbar-h) + env(safe-area-inset-top) + 28px);
        padding-bottom:40px;

        /* CENTRE LA LECTURE A 1040 px, SANS CONTENEUR : la vue est la meme.

           `100vw` ET NON `100%`, ET CE N'EST PAS UN DETAIL.

           Un pourcentage dans un `padding` se resout contre le BLOC CONTENEUR,
           qui est ici `.app` — la fenetre entiere, rail compris. Avec `100%`, la
           marge valait (fenetre - 1040)/2 de chaque cote d'un element qui ne fait
           que (fenetre - rail) de large : la lecture restait figee a 804 px quelle
           que soit la taille de l'ecran. Elle tombait centree par chance, si bien
           que rien ne le signalait — seule la mesure l'a montre.

           `100vw` est la largeur de la fenetre, dont on retire le rail a la main.
           Il n'y a pas de barre de defilement de fenetre a craindre : `body` est
           en `overflow:hidden`, et c'est `.views` qui defile. */
        padding-inline:max(32px,calc((100vw - var(--rail-w) - 1040px) / 2));
    }
    .view-title{font-size:1.9rem;margin-bottom:18px;}

    .cartes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;}

    /* Le tableau respire : c'est ce qu'on vient voir, et la place existe. */
    .visu table{font-size:.9rem;}
    .visu td{padding:13px 14px;}
    .visu th{padding:12px 14px;font-size:.78rem;}
    .visu-pied{padding:13px 14px;font-size:.88rem;}
    .visu .col-porte{min-width:190px;}

    .somme{padding:16px 20px;}
    .somme-gros{font-size:2rem;}
    .somme-details{gap:2px 24px;font-size:.8rem;}

    .home{max-width:640px;}
    .home-title{font-size:2.1rem;}
    .modale-boite{padding:24px;}

    /* Les formulaires ne s'etirent pas sur 1040 px : un champ « nom du chantier »
       large d'un metre se remplit mal. */
    #formChantier,.fonctions{max-width:620px;}

    /* LES BOUTONS D'ACTION PASSENT EN RANGEE, A LEUR LARGEUR NATURELLE.

       Empiles et pleine largeur, ils avaient l'air d'un formulaire de telephone
       pose sous un tableau de bureau ; bornes a 620 px sous un tableau de 1040,
       ils avaient l'air d'une erreur de mise en page. C'est la `.row` du site :
       des boutons cote a cote, alignes a gauche, a la largeur de leur texte.

       `flex-wrap` et `align-items:center` parce que `.actions` ne contient pas
       toujours deux boutons : quand le devis est parti, le second est remplace
       par une phrase, qui se range alors a cote du bouton restant. */
    .actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px;}
    .actions .btn.block{width:auto;min-width:240px;}
    .actions .btn + .btn{margin-top:0;}
    .actions .hint{margin:0;}
}

/* Le survol n'existe qu'a la souris. Sur un telephone il n'y a que `:active` ;
   a la souris, un objet qui ne repond pas au survol semble mort. Les teintes
   sortent des jetons — aucune valeur inventee ici. */
@media (hover:hover) and (pointer:fine){
    .btn:hover{opacity:.88;}
    .carte:hover{box-shadow:inset 0 0 0 1px var(--line-2);}
    .tab:hover{color:var(--ink);}
    .tab.active:hover{color:var(--accent);}
    .acte:hover{filter:brightness(.97);}
    .iconbtn:hover{background:var(--fill);}
    .fiche-tete:hover{background:var(--bg);}
    .visu tbody tr:hover{background:var(--bg);}
    .visu tbody tr:hover .col-porte{background:var(--bg);}
    .fnc-lien:hover{text-decoration:underline;}
}
