/* Habillage de l'éditeur visuel de propositions.
 *
 * Rien de ce qui est ici ne s'imprime : les règles de la page et des éléments
 * vivent dans templates/proposal/_styles.html.twig, partagées avec le moteur
 * PDF. Ce fichier ne décrit que l'atelier — la table de travail, les poignées,
 * les repères. On ne doit jamais y toucher à la géométrie d'un élément, sous
 * peine de faire mentir l'aperçu.
 *
 * Les couleurs viennent des variables Tabler, jamais de valeurs en dur : le
 * thème clair et le thème sombre de l'application suivent ainsi tout seuls.
 */

.proposal-workbench {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
}

/* ─────────────────────────────────────────────────────── la table ──────── */

/* `position: relative` : le rectangle du lasso s'y pose en coordonnées de
 * défilement, sans quoi il suivrait la fenêtre au lieu du canevas. */
.proposal-canvas {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    background: var(--tblr-bg-surface-secondary);
    border-radius: var(--tblr-border-radius);
    padding: 1.5rem;
    overflow: auto;
    max-height: calc(100vh - 12rem);
}

/* Une page à l'échelle. L'enveloppe réserve la place du zoom ; la feuille, elle,
 * garde ses 210 × 297 mm réels — c'est ce qui fait que ses millimètres sont
 * ceux du papier, et non une approximation en pixels. */
.proposal-page {
    position: relative;
    margin: 0 auto 1.25rem;
    width: calc(210mm * var(--zoom));
    height: calc(297mm * var(--zoom));
}

/* Une page tenue de travers — le plan de site trop large pour le portrait,
 * voir `SiteTreeComposer` — inverse largeur et hauteur : sans ce
 * modificateur, l'enveloppe garderait la taille portrait pendant que la
 * feuille qu'elle contient, elle, s'affiche en 297 × 210 mm — débordement et
 * centrage faux, la feuille suivante mordue par la sienne. */
.proposal-page--landscape {
    width: calc(297mm * var(--zoom));
    height: calc(210mm * var(--zoom));
}

.proposal-page > .sheet {
    transform: scale(var(--zoom));
    transform-origin: top left;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 8px 24px rgba(0, 0, 0, .12);
}

.proposal-page__label {
    position: absolute;
    top: -1.2rem;
    left: 0;
    font-size: .75rem;
    color: var(--tblr-secondary);
}

.proposal-page--current > .sheet {
    outline: 2px solid var(--tblr-primary);
    outline-offset: 2px;
}

/* Repères de marge, dessinés au-dessus de la page mais jamais imprimés. */
.proposal-guides {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 9998;
}

.proposal-guides::before {
    content: "";
    position: absolute;
    left: calc(18mm * var(--zoom));
    right: calc(18mm * var(--zoom));
    top: calc(22mm * var(--zoom));
    bottom: calc(26mm * var(--zoom));
    border: 1px dashed rgba(125, 125, 125, .45);
}

/* ────────────────────────────────────────────────────── les éléments ───── */

.el--live {
    cursor: move;
    outline: 1px solid transparent;
}

.el--live:hover {
    outline-color: rgba(125, 125, 125, .5);
}

.el--live.is-selected {
    outline: 1px solid var(--tblr-primary);
}

/* Les poignées ne s'affichent qu'à la sélection. Leur taille est en pixels et
 * compense le zoom : à 40 %, une poignée de 8 px resterait attrapable. */
.el-handle {
    display: none;
    position: absolute;
    width: calc(9px / var(--zoom));
    height: calc(9px / var(--zoom));
    background: var(--tblr-primary);
    border: calc(1px / var(--zoom)) solid #fff;
    z-index: 10000;
}

.el--live.is-selected > .el-handle { display: block }

.el-handle--nw { top: calc(-5px / var(--zoom)); left: calc(-5px / var(--zoom)); cursor: nwse-resize }
.el-handle--ne { top: calc(-5px / var(--zoom)); right: calc(-5px / var(--zoom)); cursor: nesw-resize }
.el-handle--sw { bottom: calc(-5px / var(--zoom)); left: calc(-5px / var(--zoom)); cursor: nesw-resize }
.el-handle--se { bottom: calc(-5px / var(--zoom)); right: calc(-5px / var(--zoom)); cursor: nwse-resize }
.el-handle--w  { top: 50%; left: calc(-5px / var(--zoom)); margin-top: calc(-4px / var(--zoom)); cursor: ew-resize }
.el-handle--e  { top: 50%; right: calc(-5px / var(--zoom)); margin-top: calc(-4px / var(--zoom)); cursor: ew-resize }

/* Un élément en cours de saisie ne se déplace plus : on écrit dedans. */
.el--live.is-editing {
    cursor: text;
    outline: 1px solid var(--tblr-primary);
}

.el--live.is-editing > .el-handle { display: none }

.el-placeholder,
.el-orphan {
    display: block;
    font-size: 8pt;
    color: #b04a3a;
    font-style: italic;
}

/* ──────────────────────────────────────────── le panneau de réglages ───── */

.proposal-panel {
    flex: 0 0 21rem;
    max-width: 21rem;
    position: sticky;
    top: 1rem;
}

.proposal-panel .form-label { margin-bottom: .25rem }

.proposal-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

.proposal-swatch {
    width: 1.4rem;
    height: 1.4rem;
    border-radius: var(--tblr-border-radius);
    border: 1px solid var(--tblr-border-color);
    cursor: pointer;
    padding: 0;
}

.proposal-swatch.is-active {
    outline: 2px solid var(--tblr-primary);
    outline-offset: 1px;
}

/* ──────────────────────────────────────── l'agent, ancré à droite ─────── */

/* Le panneau de l'agent : une colonne de plus, à droite des réglages, et non
 * une boîte de dialogue. Une boîte se ferme dès que l'agent a écrit — il faut
 * recharger le canevas — et la conversation avec. Ici le fil reste, et l'on
 * regarde l'agent poser ses gestes sur la page à côté. */
.proposal-agent {
    flex: 0 0 22rem;
    max-width: 22rem;
    position: sticky;
    top: 1rem;
}

/* Le fil prend la hauteur de l'écran, moins le formulaire : dans une colonne,
 * les 60 vh de l'assistant de projet laissent la moitié du panneau vide. */
.proposal-agent .assistant-thread {
    max-height: calc(100vh - 22rem);
}

body.proposal-focus .proposal-agent .assistant-thread {
    max-height: calc(100vh - 19rem);
}

/* Les bulles peuvent prendre toute la largeur : à 22 rem, 85 % ne laisse plus
 * qu'une colonne de mots. */
.proposal-agent .assistant-bubble {
    max-width: 100%;
}

/* Quatre colonnes ne tiennent pas sur un portable : quand le panneau de
 * l'agent est ouvert, la barre latérale du devis s'efface sous 1600 px. Ce
 * qu'elle montre, l'agent le sait déjà, et le canevas est ce qu'on regarde. */
@media (max-width: 1599.98px) {
    .proposal-workbench.has-agent .proposal-outline { display: none }
}

/* Le temps d'un tour, le canevas est gelé : l'agent lit des références
 * d'éléments que le moindre enregistrement automatique renuméroterait. On le
 * voit — pas de curseur, pages estompées — sans rien cacher. */
.proposal-canvas.is-agent-busy .proposal-page {
    pointer-events: none;
    opacity: .7;
    transition: opacity .2s;
}

/* Sur écran étroit, l'atelier passe en colonnes : le canevas d'abord, les
 * réglages dessous. Composer une page sur un téléphone n'a pas de sens, mais
 * relire un document en a un. */
@media (max-width: 991.98px) {
    .proposal-workbench { flex-direction: column }
    .proposal-panel,
    .proposal-agent,
    .proposal-outline { position: static; flex-basis: auto; max-width: none; width: 100% }
    .proposal-canvas { max-height: none; width: 100% }
}

/* ─────────────────────────────────────────── l'aperçu d'un bloc ────────── */

/* Une vignette de bibliothèque, au même prix qu'une page à l'échelle.
 *
 * L'aperçu est un RENDU, pas une image : il passe par le même partiel et la
 * même feuille de style que l'éditeur et que le PDF. Une vignette générée à
 * part vieillirait dès la première retouche du bloc, sans que rien ne le dise —
 * et il faudrait la stocker, la régénérer, la purger.
 *
 * L'enveloppe réserve la place du zoom ; la feuille garde ses millimètres
 * réels, exactement comme `.proposal-page`. `--block-width` et `--block-height`
 * sont posés par le gabarit, en millimètres. */
.block-preview {
    position: relative;
    overflow: hidden;
    width: calc(var(--block-width) * var(--zoom));
    height: calc(var(--block-height) * var(--zoom));
    background: #fff;
}

.block-preview > .sheet {
    position: absolute;
    top: 0;
    left: 0;
    width: var(--block-width);
    height: var(--block-height);
    transform: scale(var(--zoom));
    transform-origin: top left;
    overflow: hidden;
}

/* Un bloc vide, ou dont le rendu ne donne rien de visible : on le dit plutôt
 * que de laisser un rectangle blanc qui se lit comme un défaut d'affichage. */
.block-preview--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--tblr-border-color);
    color: var(--tblr-secondary);
    font-size: .75rem;
}

/* Un élément joint à la sélection par Maj + clic.
 *
 * Un trait distinct de celui de l'élément principal : le panneau ne règle que
 * ce dernier, et deux marques identiques laisseraient croire qu'on peut régler
 * le groupe entier. */
.el--live.is-grouped {
    outline: 2px dashed var(--tblr-teal);
    outline-offset: 1px;
}

/* Le rectangle du lasso.
 *
 * Dessiné en PIXELS D'ÉCRAN, dans le repère du canevas : il ne représente pas
 * une surface de papier et n'a donc pas à passer par l'échelle. Ce sont les
 * boîtes des éléments qu'on compare, lues au même repère. */
.el-lasso {
    position: absolute;
    z-index: 20000;
    pointer-events: none;
    border: 1px solid var(--tblr-primary);
    background: color-mix(in oklab, var(--tblr-primary) 12%, transparent);
    border-radius: 2px;
}

/* Pendant un déplacement, la feuille laisse voir ce qui en sort.
 *
 * `.sheet` est en `overflow: hidden` — c'est ce qui fait qu'un élément débordant
 * du papier est coupé à l'écran comme il le sera au PDF, et cela ne se discute
 * pas. Mais tant qu'on TIENT un élément, ce même écrêtage le fait disparaître
 * dès qu'il franchit le bord, et passer un élément d'une page à l'autre revient
 * alors à viser en aveugle. La règle ne vaut donc que le temps du geste, et elle
 * vit ici, dans la feuille de l'éditeur : `_styles.html.twig` est partagée avec
 * le PDF, où il n'y a pas de pointeur. */
.proposal-canvas.is-dragging .sheet {
    overflow: visible;
}

/* Les flèches d'un total vers les prix qu'il additionne.
 *
 * Un calque au-dessus des pages, en pixels d'écran : une flèche relie parfois
 * deux éléments qui ne vivent pas sur la même feuille, elle n'a donc sa place
 * dans aucune. `pointer-events: none` est essentiel — sans lui, le calque
 * couvrirait le canevas et plus aucun élément ne serait saisissable. */
.el-arrows {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 9997;
    color: var(--tblr-primary);
    overflow: visible;
}

.el-arrow {
    fill: none;
    stroke: var(--tblr-primary);
    stroke-width: 1.5;
    stroke-dasharray: 4 3;
    opacity: .85;
}

/* L'élément compté par le total sélectionné. Un liseré, pas un fond : le
 * document doit rester lisible tel qu'il s'imprimera. */
.el--live.is-counted {
    outline: 1.5px solid var(--tblr-primary);
    outline-offset: 1px;
}

/* ─────────────────────────────────── la barre latérale du devis ────────── */

/* Le devis à gauche du canevas : ce qu'il chiffre, d'où l'on compose.
 *
 * Étroite à dessein — elle ne montre que des intitulés et des montants, et
 * chaque millimètre pris ici l'est au papier. Collante comme le panneau de
 * droite : on pose des prestations tout en faisant défiler un document de vingt
 * pages. */
.proposal-outline {
    flex: 0 0 17rem;
    max-width: 17rem;
    position: sticky;
    top: 1rem;
}

/* Sans `min-width: 0`, un enfant de flex refuse de rétrécir sous la largeur de
 * son contenu : un intitulé long pousserait la colonne des prix hors du cadre
 * au lieu de se faire tronquer. C'est la seule règle non évidente du bloc. */
.proposal-outline__grow {
    min-width: 0;
}

.proposal-outline__price {
    width: 6.5rem;
    flex-shrink: 0;
}

.proposal-outline__meta {
    font-size: .75rem;
}

/* La ligne d'ajout ne se distingue qu'une fois qu'on y touche : trois champs
 * mis en avant à chaque chapitre feraient une barre plus bruyante que le devis
 * qu'elle montre. */
.proposal-outline__new {
    opacity: .55;
    transition: opacity .12s ease-in-out;
}

.proposal-outline__new:hover,
.proposal-outline__new:focus-within {
    opacity: 1;
}

/* ─────────────────────────────────────────────── le plein écran ────────── */

/* Composer prend de la place, et l'application en mange : une barre de
 * navigation de 15 rem à gauche, un en-tête de page en haut. Le mode plein
 * écran les efface le temps de la mise en page.
 *
 * Une classe sur `<body>` et non un `:fullscreen` natif : l'API plein écran du
 * navigateur masque aussi ses propres barres — on perd l'adresse, les onglets et
 * le raccourci d'impression — pour un écran qu'on garde ouvert des heures. Ici
 * on ne cache que NOTRE cadre.
 *
 * `!important` sur la marge : elle est posée par une règle de Tabler d'égale
 * spécificité (`.navbar-vertical ~ .page-wrapper`), et l'ordre de chargement
 * ferait dépendre le résultat du fichier compilé. C'est le seul de ce bloc. */
body.proposal-focus .navbar-vertical,
body.proposal-focus .page-header {
    display: none;
}

body.proposal-focus .page-wrapper {
    margin-left: 0 !important;
}

/* La grille de Tabler borne la largeur du contenu ; en plein écran, cette borne
 * est précisément ce dont on veut se passer. */
body.proposal-focus .page-body > .container-xl {
    max-width: none;
}

/* L'en-tête parti, le canevas récupère sa hauteur. */
body.proposal-focus .proposal-canvas {
    max-height: calc(100vh - 9rem);
}

/* La mention du zoom garde sa largeur : sans elle, « 100 % » et « 55 % » font
 * sauter les deux boutons qui l'encadrent à chaque cran. */
.proposal-zoom-label {
    min-width: 3.2rem;
    text-align: center;
}

/* ─────────────────────────────────────────── le point d'insertion ──────── */

/* Cliquer une zone vide y pose un repère : l'élément suivant s'y place, et le
 * repère descend sous lui. On clique une fois, puis on empile.
 *
 * Posé DANS la feuille, en millimètres : il suit le zoom sans calcul. Et sans
 * `pointer-events: none` il intercepterait le clic suivant — on ne pourrait
 * plus le déplacer une fois posé. */
.el-caret {
    position: absolute;
    width: 0;
    height: 6mm;
    pointer-events: none;
    z-index: 9997;
    border-left: 2px solid var(--tblr-primary);
}

/* La barre horizontale qui dit « ça commence ici » : un simple trait vertical
 * se confond avec un curseur de saisie. */
.el-caret::before {
    content: '';
    position: absolute;
    left: -2px;
    top: 0;
    width: 12mm;
    border-top: 2px solid var(--tblr-primary);
}
