/*
 * Styles propres à l'ERP.
 *
 * Tabler couvre l'essentiel : on n'ajoute ici que ce qu'il ne fournit pas,
 * en s'appuyant sur ses variables CSS (--tblr-*) plutôt que sur des valeurs
 * en dur. Voir https://tabler.io/docs
 */

/*
 * Tableau de saisie des lignes de devis.
 *
 * Ni `.table` ni `.row` de Tabler ne conviennent : il faut des colonnes de
 * largeur fixe qui restent alignées alors que chaque ligne contient des champs
 * de formulaire, un bloc de détail repliable et une poignée de déplacement.
 *
 * Les colonnes sont volontairement serrées : la sidebar consomme déjà 15rem,
 * et une grille trop large basculerait en mode empilé sur un écran d'ordinateur
 * portable — c'est-à-dire presque toujours.
 */
.quote-lines {
    --quote-grid: 1.25rem minmax(9rem, 1fr) 4.5rem 5.5rem 6rem 4.5rem 5rem 6rem 4rem;
    --quote-gap: 0.375rem;
}

/*
 * Type et intitulé sur une même ligne.
 *
 * Le type est un code court : lui laisser toute la largeur de la cellule
 * repoussait l'intitulé en dessous et doublait la hauteur de chaque ligne.
 */
.quote-line-title {
    display: flex;
    gap: var(--quote-gap);
    align-items: center;
}

.quote-line-category {
    flex: 0 0 7rem;
}

.quote-line-title > .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

/*
 * Un titre, un sous-total ou un commentaire n'a pas de type : sa place est
 * retirée plutôt que masquée, sinon l'intitulé partirait en retrait de 7rem.
 * Les colonnes chiffrées, elles, gardent leur place pour rester alignées.
 */
.quote-line:not([data-kind="service"]) .quote-line-category {
    display: none;
}

.quote-line {
    display: grid;
    grid-template-columns: var(--quote-grid);
    gap: var(--quote-gap);
    align-items: start;
    border-bottom: 1px solid var(--tblr-border-color);
    padding: 0.5rem 0;
}

/*
 * Une cellule de grille vaut `min-width: auto` par défaut : elle refuse de
 * descendre sous la largeur minimale de son contenu, et un élément large — la
 * barre d'outils de l'éditeur — pousse alors toute la ligne hors du cadre.
 */
.quote-line > * {
    min-width: 0;
}

.quote-line:last-child {
    border-bottom: 0;
}

.quote-line-handle {
    cursor: grab;
    color: var(--tblr-secondary);
    padding-top: 0.5rem;
    text-align: center;
}

.quote-line-handle:active {
    cursor: grabbing;
}

.quote-line-total {
    text-align: right;
    padding-top: 0.5rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Deux rangées de deux boutons : la colonne reste étroite. */
.quote-line-actions {
    display: grid;
    grid-template-columns: repeat(2, 1.75rem);
    gap: 0.125rem;
    justify-content: end;
}

/* Le détail est replié par défaut : un devis de dix lignes reste lisible. */
.quote-line-detail > summary {
    cursor: pointer;
    list-style: none;
    padding: 0.25rem 0;
}

.quote-line-detail > summary::-webkit-details-marker {
    display: none;
}

.quote-line-detail > summary::before {
    content: "\ea5f"; /* ti-chevron-right */
    font-family: "tabler-icons", sans-serif;
    margin-right: 0.25rem;
    display: inline-block;
    transition: transform 0.15s ease;
}

.quote-line-detail[open] > summary::before {
    transform: rotate(90deg);
}

/* En-tête de colonnes, calé sur la même grille que les lignes. */
.quote-lines-header {
    display: grid;
    grid-template-columns: var(--quote-grid);
    gap: var(--quote-gap);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--tblr-secondary);
    padding-bottom: 0.5rem;
    border-bottom: 2px solid var(--tblr-border-color);
}

.quote-lines-header > .text-end {
    text-align: right;
}

/* Champs compacts : la grille ne tient qu'à ce prix. */
.quote-line .form-control,
.quote-line .form-select {
    padding: 0.25rem 0.4rem;
    font-size: 0.8125rem;
}

.quote-line textarea.form-control {
    font-size: 0.8125rem;
}

/*
 * Une ligne de titre, de sous-total ou de commentaire n'a ni prix ni TVA :
 * ses colonnes chiffrées disparaissent, mais gardent leur place pour ne pas
 * décaler les lignes voisines.
 */
.quote-line [data-only="service"].invisible {
    visibility: hidden;
}

/* Les lignes de structure se distinguent au premier coup d'œil. */
.quote-line[data-kind="section"] {
    background: var(--tblr-bg-surface-secondary);
}

.quote-line[data-kind="section"] .form-control {
    font-weight: 600;
    text-transform: uppercase;
}

.quote-line[data-kind="comment"] .form-control {
    font-style: italic;
}

.quote-line[data-kind="subtotal"] {
    background: var(--tblr-bg-surface-tertiary, var(--tblr-bg-surface-secondary));
}

/*
 * Repli en dessous de la tablette seulement. Au-dessus, la grille tient : c'est
 * précisément ce qu'on veut, la saisie en ligne étant la raison d'être de cet écran.
 */
@media (max-width: 767.98px) {
    .quote-lines-header {
        display: none;
    }

    .quote-line {
        grid-template-columns: 1.25rem minmax(0, 1fr);
    }

    .quote-line > :not(.quote-line-handle):not(.quote-line-label) {
        grid-column: 2;
    }

    .quote-line-actions {
        justify-content: start;
    }
}

/* Le récapitulatif suit le défilement : sur un devis long, les totaux restent
   sous les yeux pendant la saisie. */
@media (min-width: 992px) {
    .quote-summary {
        position: sticky;
        top: 1rem;
    }
}

/*
 * Corps d'un mail relevé.
 *
 * Le texte est stocké brut, sauts de ligne compris : sans `pre-wrap` il
 * s'afficherait en un seul bloc. Tabler n'a pas d'utilitaire pour ça. La
 * césure forcée évite qu'une URL ou une signature encodée ne fasse déborder
 * la carte horizontalement.
 */
.mail-body {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/*
 * Éditeur de texte enrichi (Trix) dans le tableau de saisie.
 *
 * ATTENTION à la spécificité. La feuille de Trix est chargée par l'importmap
 * APRÈS celle-ci : à spécificité égale, c'est la sienne qui gagne. D'où la
 * classe `.app-trix-toolbar`, posée sur la barre d'outils par le contrôleur
 * Stimulus — elle donne le poids qu'il faut sans recourir à `!important`.
 */
trix-editor.app-trix-editor {
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    background: var(--tblr-bg-forms, var(--tblr-body-bg));
    color: var(--tblr-body-color);
    min-height: 6rem;
    padding: 0.4375rem 0.75rem;
    font-size: 0.8125rem;
}

trix-editor.app-trix-editor:focus {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 0.25rem rgba(var(--tblr-primary-rgb), 0.25);
    outline: 0;
}

/*
 * La barre doit tenir dans la colonne. Trix la règle en `flex-wrap: nowrap` avec
 * `overflow-x: auto` : dans une cellule étroite, les derniers boutons — annuler
 * et rétablir — se retrouvaient hors du cadre visible. Elle passe à la ligne.
 */
.app-trix-toolbar .trix-button-row {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 0.25rem;
    overflow-x: visible;
}

/* Les marges de Trix sont calées en `vw` : sans rapport avec la largeur réelle
   de la colonne, elles creusaient des écarts inutiles. */
.app-trix-toolbar .trix-button-group {
    margin-bottom: 0.375rem;
    border-color: var(--tblr-border-color);
}

.app-trix-toolbar .trix-button-group:not(:first-child) {
    margin-left: 0;
}

.app-trix-toolbar .trix-button {
    border-bottom: 0;
}

/* Largeur fixe : le calcul en `vw` de Trix étire les boutons sans raison. */
.app-trix-toolbar .trix-button--icon {
    width: 2rem;
    max-width: 2rem;
    height: 1.75rem;
}

/*
 * Le souligné n'étant pas un attribut natif de Trix, sa feuille ne fournit
 * aucune icône : le bouton sortait vide. Le glyphe vient du webfont Tabler,
 * comme partout ailleurs dans l'application.
 */
.app-trix-toolbar .trix-button--icon-underline::before {
    content: "\eba2"; /* ti-underline */
    font-family: "tabler-icons", sans-serif;
    font-size: 0.875rem;
    /* Le bouton masque son libellé par un `text-indent: -9999px` qui s'hérite :
       sans cette remise à zéro, le glyphe partirait hors de l'écran. */
    text-indent: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Le contenu enrichi, à l'affichage comme dans l'éditeur. */
.trix-content ul,
.trix-content ol {
    margin: 0.25rem 0;
    padding-left: 1.25rem;
}

.trix-content p:last-child,
.trix-content div:last-child {
    margin-bottom: 0;
}

/*
 * Visionneuse publique d'un devis.
 *
 * Ces règles n'ont pas d'équivalent Tabler : il s'agit de mettre en page un
 * document paginé rendu dans des <canvas>, ce que la bibliothèque ne couvre
 * pas. Tout le reste de l'écran — barre d'outils, boutons, alertes — reste du
 * Tabler standard.
 */
.quote-viewer {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    background: var(--tblr-bg-surface-secondary);
}

.quote-viewer-scroll {
    flex: 1;
    overflow-y: auto;
    overflow-x: auto;
    padding: 1.5rem 1rem 4rem;
    /* Le défilement doit rester fluide au doigt sur mobile, où la visionneuse
       occupe tout l'écran. */
    -webkit-overflow-scrolling: touch;
}

.quote-viewer-pages {
    /* Pilotée par le contrôleur Stimulus au zoom. La largeur de base est celle
       d'une A4 lisible sur un écran d'ordinateur portable ; le zoom la multiplie.
       Le `min()` est DANS le produit : sans lui, le zoom 1 déborderait déjà sur
       un téléphone, et au-delà de 1 le débordement horizontal est justement ce
       qu'on veut — le conteneur défile. */
    --quote-viewer-zoom: 1;
    width: calc(min(100%, 52rem) * var(--quote-viewer-zoom));
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/*
 * Chaque page réserve sa place AVANT d'être rendue, grâce à `aspect-ratio`
 * posé en ligne par le contrôleur. Sans cette réservation la barre de
 * défilement grandirait au fil des rendus et la lecture sauterait.
 */
.quote-viewer-page {
    background: #fff;
    box-shadow: var(--tblr-box-shadow-card);
    border-radius: var(--tblr-border-radius);
    overflow: hidden;
}

.quote-viewer-page canvas {
    display: block;
    width: 100%;
    height: auto;
}

/* À l'impression, seul le document sort : ni barre d'outils ni bandeau. */
@media print {
    .quote-viewer-toolbar,
    .quote-viewer-footer {
        display: none !important;
    }

    .quote-viewer,
    .quote-viewer-scroll {
        height: auto;
        overflow: visible;
        padding: 0;
        background: #fff;
    }

    .quote-viewer-page {
        box-shadow: none;
        border-radius: 0;
        break-after: page;
    }
}

/*
 * Suivi de lecture : histogramme du temps passé page par page.
 *
 * Une barre de progression Tabler par page aurait fait l'affaire à
 * l'horizontale, mais on veut lire d'un coup d'œil quelle page a retenu le
 * client — d'où des colonnes côte à côte, comparables entre elles.
 */
.quote-dwell {
    display: flex;
    align-items: flex-end;
    gap: 0.25rem;
    height: 7rem;
}

.quote-dwell-bar {
    flex: 1;
    min-width: 0.75rem;
    background: var(--tblr-primary);
    border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0;
    /* Une page vue une seconde doit rester visible, sinon la colonne disparaît
       et on croit la page jamais atteinte. */
    min-height: 0.25rem;
    opacity: 0.85;
}

.quote-dwell-bar:hover {
    opacity: 1;
}

/*
 * Panneau « à programmer » du calendrier.
 *
 * Les tâches se glissent de ce panneau sur le calendrier pour être
 * programmées. Chaque ligne est une cible de préhension : d'où la poignée
 * visible et le curseur, seuls indices qu'un élément se saisit — rien dans
 * Tabler ne le signale.
 */
.planning-backlog {
    /* La liste ne doit pas repousser le panneau de détail hors de l'écran :
       elle défile dans sa carte plutôt que d'étirer la colonne. */
    max-height: 24rem;
    overflow-y: auto;
}

.planning-backlog-item {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.5rem;
    margin-bottom: 0.375rem;
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    background: var(--tblr-bg-surface);
    cursor: grab;
}

.planning-backlog-item:last-child {
    margin-bottom: 0;
}

.planning-backlog-item:hover {
    border-color: var(--tblr-primary);
}

.planning-backlog-item:active {
    cursor: grabbing;
}

/*
 * Une cellule flex vaut `min-width: auto` : sans cette remise à zéro, un
 * intitulé long refuse de se tronquer et déborde de la colonne.
 */
.planning-backlog-body {
    flex: 1 1 auto;
    min-width: 0;
}

.planning-backlog-handle {
    color: var(--tblr-secondary);
    padding-top: 0.125rem;
}

/*
 * Le fantôme promené par FullCalendar pendant le glissé : sans transparence,
 * il masque le créneau sous lequel on vise.
 */
.fc-event-dragging {
    opacity: 0.75;
}

/*
 * Créneau déjà pointé. La couleur de fond est celle du poste, posée en ligne
 * par le contrôleur : la distinction passe donc par le contour, seul canal
 * encore libre.
 */
.fc-event-tracked {
    box-shadow: inset 0 0 0 2px var(--tblr-body-bg);
    opacity: 0.75;
}
