/* ==========================================================================
   Design tokens
   ========================================================================== */

:root {
    --bs-primary: #ef1c25;
    --bs-primary-rgb: 239, 28, 37;
    --bs-link-color: #ef1c25;
    --bs-link-color-rgb: 239, 28, 37;
    --bs-link-hover-color: #c8151d;
    --bs-link-hover-color-rgb: 200, 21, 29;
    --bs-body-bg: #f3f4f7;
    --bs-body-bg-rgb: 243, 244, 247;
    --bs-border-radius: .5rem;

    --app-sidebar-width: 250px;
    --app-sidebar-bg: #1a1d29;
    --app-sidebar-text: rgba(255, 255, 255, .68);
    --app-sidebar-text-active: #fff;
}

[data-bs-theme="dark"] {
    --bs-primary: #f04048;
    --bs-primary-rgb: 240, 64, 72;
    --bs-body-bg: #14161f;
    --bs-body-bg-rgb: 20, 22, 31;
    --app-sidebar-bg: #101219;
}

/* ==========================================================================
   Base: compact, neutral admin look
   ========================================================================== */

body {
    font-size: 12px;
}

/* Bootstrap fixe le font-size des champs/dropdowns en rem (relatif à la racine
   <html>, pas à body) : ils n'hériteraient pas du 12px ci-dessus sans cette
   surcharge explicite (même logique que .grid-view .form-control plus bas). */
.form-control,
.form-select {
    font-size: 12px;
}

.card {
    background-color: #fff;
    border: 0;
    border-radius: .75rem;
    box-shadow: 0 6px 20px rgba(20, 20, 30, .14);
}

[data-bs-theme="dark"] .card {
    box-shadow: 0 6px 20px rgba(0, 0, 0, .5);
}

.btn-primary {
    box-shadow: 0 2px 8px rgba(var(--bs-primary-rgb), .35);
}

/*
 * Bootstrap 5.3's per-component variables default to a hardcoded #0d6efd rather than
 * `var(--bs-primary)`, so re-theming requires overriding each component explicitly.
 */
.btn-primary {
    --bs-btn-bg: var(--bs-primary);
    --bs-btn-border-color: var(--bs-primary);
    --bs-btn-hover-bg: var(--bs-link-hover-color);
    --bs-btn-hover-border-color: var(--bs-link-hover-color);
    --bs-btn-active-bg: var(--bs-link-hover-color);
    --bs-btn-active-border-color: var(--bs-link-hover-color);
    --bs-btn-disabled-bg: var(--bs-primary);
    --bs-btn-disabled-border-color: var(--bs-primary);
    --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

.btn-outline-primary {
    --bs-btn-color: var(--bs-primary);
    --bs-btn-border-color: var(--bs-primary);
    --bs-btn-hover-bg: var(--bs-primary);
    --bs-btn-hover-border-color: var(--bs-primary);
    --bs-btn-active-bg: var(--bs-primary);
    --bs-btn-active-border-color: var(--bs-primary);
    --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

.dropdown-menu {
    --bs-dropdown-link-active-bg: var(--bs-primary);
}

.pagination {
    --bs-pagination-active-bg: var(--bs-primary);
    --bs-pagination-active-border-color: var(--bs-primary);
    --bs-pagination-font-size: 12px;
    --bs-pagination-padding-x: .6rem;
    --bs-pagination-padding-y: .3rem;
}

/* select2-krajee-bs5.css code en dur le bleu Bootstrap par défaut (#0d6efd)
   au lieu de suivre --bs-primary comme le reste de l'app. */
.select2-container--krajee-bs5 .select2-results__option--highlighted[aria-selected] {
    background-color: var(--bs-primary);
    color: #fff;
}

.select2-container--krajee-bs5 .select2-results__option.select2-results__option--selected,
.select2-container--krajee-bs5 .select2-results__option[aria-selected=true] {
    background-color: rgba(var(--bs-primary-rgb), .1);
    color: var(--bs-primary);
}

.form-check-input:checked {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
}

.form-check-input:focus {
    box-shadow: 0 0 0 .25rem rgba(var(--bs-primary-rgb), .25);
}

h1 {
    font-size: 1.4rem;
    font-weight: 600;
    margin-bottom: 1rem;
}

h2 {
    font-size: 1.1rem;
    font-weight: 600;
}

.card-title,
.card-header {
    font-size: 1rem;
}

.btn {
    font-size: 12px;
    text-align: center;
}

.breadcrumb {
    font-size: .8rem;
}

.breadcrumb a {
    text-decoration: none;
    color: var(--bs-secondary-color);
}

.breadcrumb a:hover {
    text-decoration: underline;
}

/* ==========================================================================
   GridView (kartik) tweaks
   ========================================================================== */

.grid-view th {
    white-space: nowrap;
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-secondary-color);
}

.grid-view th a {
    color: inherit;
    text-decoration: none;
}

.grid-view th a:hover {
    color: var(--bs-body-color);
}

/* this dev-master kartik-grid build still emits BS4's dropdown-menu-right */
.dropdown-menu-right {
    --bs-position: end;
    right: 0;
    left: auto;
}

/* kartik's export menu hardcodes a rainbow of text-* colors per format icon; keep one neutral tone
   and rein in FontAwesome's default relative sizing (1.33em+) which reads oversized in a menu */
.dropdown-menu .dropdown-item {
    font-size: .85rem;
}

.dropdown-menu .dropdown-item i {
    color: var(--bs-secondary-color) !important;
    font-size: .8rem;
    width: 1.1rem;
    text-align: center;
}

.dropdown-header {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .03em;
}

/* kartik grid action column icons (view/update/delete) - same oversizing issue */
.grid-view .kv-grid-group-header,
.grid-view td i.fas,
.grid-view td i.far {
    font-size: .8rem;
}

.grid-view td,
.grid-view th {
    vertical-align: middle;
}

/* Taille de police uniforme sur toutes les gridviews, y compris les champs de
   recherche de la ligne de filtre (form-control/form-select surchargent sinon
   leur propre font-size et n'hériteraient pas de celui de la grille). */
.grid-view {
    font-size: 12px;
}

.grid-view .form-control,
.grid-view .form-select {
    font-size: 12px;
}

/* With many columns, cells must never get squeezed down to illegible widths —
   force the table past its container so .table-responsive's horizontal scroll
   actually engages instead of Bootstrap letting each <td> shrink to fit. */
.grid-view td {
    white-space: nowrap;
}

/* La ligne de résumé de page (total prix, etc.) peut contenir un texte plus
   long que la donnée elle-même : plutôt que de forcer la colonne à s'élargir
   ou de retourner à la ligne, le texte sort du flux normal et déborde sur les
   colonnes voisines (vides sur cette ligne), aligné à droite comme les
   valeurs de la colonne "Prix" au-dessus. */
.grid-view .kv-page-summary > td {
    background-color: #ccc !important;
    box-shadow: none;
    position: relative;
}

.grid-view .kv-page-summary td .app-page-summary-note {
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    white-space: nowrap;
}

.grid-view tr.filters select,
.grid-view tr.filters input {
    min-width: 90px;
    background-color: #fff;
}

/* ==========================================================================
   DetailView: replace the default bordered/striped table with a clean,
   borderless key-value list (one subtle divider between rows)
   ========================================================================== */

.detail-view {
    width: 100%;
    border: 0;
    margin-bottom: 0;
}

.detail-view > tbody > tr > th,
.detail-view > tbody > tr > td {
    border: 0;
    border-bottom: 1px solid var(--bs-border-color);
    padding: .65rem .25rem;
    background-color: transparent;
}

.detail-view > tbody > tr:last-child > th,
.detail-view > tbody > tr:last-child > td {
    border-bottom: 0;
}

.detail-view > tbody > tr > th {
    width: 35%;
    color: var(--bs-secondary-color);
    font-weight: 600;
}

/* ==========================================================================
   Zébrage explicite blanc/gris clair, réutilisable partout où un tableau est
   affiché dans un contexte où --bs-table-bg hérite de --bs-body-bg
   (#f3f4f7, déjà gris) : le zébrage par défaut de .table-striped (5% de noir
   en overlay via box-shadow) donne alors deux gris au lieu de blanc/gris,
   quasi invisible à l'œil (voir historique).
   ========================================================================== */

.table-zebra > tbody > tr:nth-child(odd) > td {
    background-color: #ffffff;
}

.table-zebra > tbody > tr:nth-child(even) > td {
    background-color: #f2f3f5;
}

/* ==========================================================================
   Forms styled as the same label/value rows as the DetailView above,
   so an edit form reads as "the view page, but editable"
   ========================================================================== */

.form-rows .row-item {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem 1rem;
    min-height: 45px;
    padding: .3rem .25rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.form-rows .row-value .form-control,
.form-rows .row-value .form-select {
    padding-top: .3rem;
    padding-bottom: .3rem;
}

.form-rows .row-label {
    flex: 0 0 35%;
    width: 35%;
    color: var(--bs-secondary-color);
    font-weight: 600;
    margin-bottom: 0;
}

.form-rows .row-value {
    flex: 1 1 0;
    min-width: 200px;
}

.form-rows .row-value .invalid-feedback,
.form-rows .row-value .form-text {
    margin-top: .25rem;
}

.not-set {
    color: var(--bs-danger);
    font-style: italic;
}

/* sorting icons for gridview sort links */
a.asc:after, a.desc:after {
    content: '';
    left: 3px;
    display: inline-block;
    width: 0;
    height: 0;
    border: solid 5px transparent;
    margin: 4px 4px 2px 4px;
    background: transparent;
}

a.asc:after {
    border-bottom: solid 7px var(--bs-body-color);
    border-top-width: 0;
}

a.desc:after {
    border-top: solid 7px var(--bs-body-color);
    border-bottom-width: 0;
}

.hint-block {
    display: block;
    margin-top: 5px;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

.error-summary {
    color: var(--bs-danger-text-emphasis);
    background: var(--bs-danger-bg-subtle);
    border-left: 3px solid var(--bs-danger-border-subtle);
    padding: 10px 20px;
    margin: 0 0 15px 0;
}

/* ==========================================================================
   App shell: sidebar + topbar
   ========================================================================== */

.app-sidebar {
    width: var(--app-sidebar-width);
    flex: 0 0 var(--app-sidebar-width);
    background-color: var(--app-sidebar-bg);
    padding: 1rem .75rem 1.5rem;
    /* La sidebar est étirée à 100% de la hauteur de l'écran (.app-shell,
       h-100) mais son contenu (nav) n'était pas scrollable : plus les menus
       s'ajoutent (Outils, Configuration...), plus les derniers items
       débordent hors de l'écran sans aucun moyen d'y accéder. */
    min-height: 0;
    overflow-y: auto;
}

.app-sidebar-brand {
    padding: .5rem .5rem 1.25rem;
    margin-bottom: .5rem;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.app-sidebar-logo {
    max-width: 100%;
    height: auto;
    border-radius: .375rem;
}

.app-nav-section-label {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .35);
    padding: 1.1rem .75rem .4rem;
}

.app-nav-link {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .55rem .75rem;
    margin-bottom: .15rem;
    border-radius: .5rem;
    color: var(--app-sidebar-text);
    font-size: .85rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color .12s ease-in-out, color .12s ease-in-out;
}

.app-nav-link i {
    width: 1.1rem;
    text-align: center;
    font-size: .85rem;
    opacity: .85;
}

.app-nav-link:hover {
    background-color: rgba(255, 255, 255, .06);
    color: var(--app-sidebar-text-active);
}

.app-nav-link.active {
    background-color: var(--bs-primary);
    color: #fff;
    box-shadow: 0 2px 8px rgba(var(--bs-primary-rgb), .45);
}

.app-nav-sublink {
    padding-left: 2.35rem;
    font-size: .8rem;
}

.app-nav-caret {
    font-size: .65rem;
    transition: transform .15s ease-in-out;
}

.app-nav-link-parent.collapsed .app-nav-caret {
    transform: rotate(-90deg);
}

.app-main {
    min-width: 0;
}

/* Sidebar repliable en desktop (bouton burger de la topbar, js/sidebar-toggle.js) :
   on la fait glisser hors de l'écran par une marge négative plutôt que de
   réduire sa largeur (le contenu se tasserait pendant l'animation). En
   dessous de lg, la sidebar fixe n'existe pas (menu en offcanvas) : rien ne change. */
@media (min-width: 992px) {
    .app-sidebar {
        transition: margin-left .2s ease-in-out, visibility 0s linear 0s;
    }

    html.app-sidebar-collapsed .app-sidebar {
        margin-left: calc(-1 * var(--app-sidebar-width));
        visibility: hidden;
        transition: margin-left .2s ease-in-out, visibility 0s linear .2s;
    }
}

.app-topbar {
    padding: .6rem 1.25rem;
    background-color: #fff;
    border-bottom: 1px solid var(--bs-border-color);
}

.app-sidebar-toggle,
.app-icon-btn {
    color: var(--bs-body-color);
    font-size: 1rem;
}

.app-user-btn {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .85rem;
    font-weight: 500;
    background: transparent;
    border: 1px solid var(--bs-border-color);
}

.app-user-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    background: rgba(var(--bs-primary-rgb), .12);
    color: var(--bs-primary);
    font-size: .7rem;
    font-weight: 700;
}

.app-main-inner {
    padding: 1.25rem 1.5rem 2rem;
}

.app-sidebar-offcanvas {
    background-color: var(--app-sidebar-bg);
    color: var(--app-sidebar-text);
    width: var(--app-sidebar-width);
}

.app-sidebar-offcanvas .offcanvas-header {
    color: #fff;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.app-sidebar-offcanvas .btn-close {
    filter: invert(1);
}

/* Occupe toute la hauteur du header (stretch via .app-card-header), collée
   au bord gauche, sans padding ni marge par rapport au header. */
.app-stat-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    border-radius: .75rem 0 0 0;
    background: #fff;
    color: var(--bs-primary);
    font-size: .8rem;
    flex: none;
}

/* En-tête de card de la home : fond sombre uni distinct du corps de card
   (blanc / surface sombre) pour bien séparer titre+badge du contenu qui
   suit ; titre en blanc puisque le fond est foncé. */
.app-card-header {
    height: 2.2rem;
    padding: 0;
    background: #212529;
    border-radius: .75rem .75rem 0 0;
    box-shadow: 0 3px 8px rgba(0, 0, 0, .25);
    position: relative;
    z-index: 1;
}

.app-card-header-content {
    padding: .5rem .6rem;
}

.app-card-header h2 {
    color: #fff;
    font-size: .8rem;
}

.app-card-header + .card-body {
    padding-top: 1rem;
}

/* Zébrage des lignes successives dans les cards de la home, même logique
   que .table-zebra pour les GridViews. */
.app-card-list {
    margin-left: -1rem;
    margin-right: -1rem;
}

.app-card-row {
    padding: .45rem 1rem;
    position: relative;
}

.app-card-row:nth-child(odd) {
    background-color: #ffffff;
}

.app-card-row:nth-child(even) {
    background-color: #f2f3f5;
}

/* Ligne active comme lien, effet de survol identique aux lignes de
   GridView (.table-hover) : le lien interne est étiré (stretched-link) pour
   couvrir tout le <li>, cliquable sur toute sa surface. */
.app-card-list .app-card-row:hover {
    background-color: rgba(var(--bs-primary-rgb), .08);
    cursor: pointer;
}

/* Footer "Voir tout..." des cards home : bande gris clair, plein rouge au
   survol. */
.app-card-footer-link {
    display: flex;
    align-items: center;
    height: 2.2rem;
    padding: 0 1rem;
    background: #dedede;
    color: var(--bs-body-color);
    font-weight: 600;
    font-size: .7rem;
    text-decoration: none;
    border-radius: 0 0 .75rem .75rem;
    transition: background-color .15s ease, color .15s ease;
}

.app-card-footer-link:hover,
.app-card-footer-link:focus-visible {
    background: var(--bs-primary);
    color: #fff;
}

/* ==========================================================================
   Login page
   ========================================================================== */

.site-login {
    flex: 1;
}

.login-split-card {
    border-radius: .5rem;
    border: 1px solid var(--bs-border-color);
    background-color: var(--bs-body-bg);
    width: 100%;
    max-width: 860px;
}

.login-brand-panel {
    background-color: var(--bs-tertiary-bg);
    min-height: 440px;
}

.login-brand-title {
    font-size: 1.4rem;
    line-height: 1.3;
}

.login-brand-text {
    font-size: .875rem;
}

.login-split-card .input-group {
    border: var(--bs-border-width) solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    overflow: hidden;
}

.login-split-card .input-group .input-group-text {
    background: transparent;
    border: 0;
    padding-left: 1rem;
    padding-right: .75rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.login-split-card .input-group .form-control {
    border: 0;
    background: transparent;
}

.login-split-card .input-group .form-control:focus {
    box-shadow: none;
}

.login-split-card .input-group:focus-within {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb), .2);
}

@supports selector(.input-group:has(.is-invalid)) {
    .login-split-card .input-group:has(.is-invalid) ~ .invalid-feedback {
        display: block;
        margin-top: .35rem;
        margin-bottom: .5rem;
    }

    .login-split-card .input-group:has(.is-invalid) {
        border-color: var(--bs-danger);
    }
}

/* ==========================================================================
   Error page
   ========================================================================== */

.site-error {
    flex: 1;
}

.site-error .site-error-content {
    width: 100%;
    max-width: 90%;
    margin: 0 auto;
}

@media (min-width: 768px) {
    .site-error .site-error-content {
        max-width: 60%;
    }
}

/* ==========================================================================
   Messagerie
   ========================================================================== */

.app-unread-dot {
    display: inline-block;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background-color: var(--bs-primary);
}

.app-row-unread {
    font-weight: 600;
}

.app-notif-badge {
    position: absolute;
    top: -.2rem;
    right: -.2rem;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 .25rem;
    border-radius: 999px;
    background-color: var(--bs-primary);
    color: #fff;
    font-size: .65rem;
    font-weight: 700;
    line-height: 1.1rem;
    text-align: center;
}

.app-notif-dropdown {
    width: 340px;
    max-height: 400px;
    overflow-y: auto;
    white-space: normal;
}

.app-notif-dropdown .dropdown-item {
    white-space: normal;
}

/* ==========================================================================
   Produit réservé pour un devis non encore validé (Produit::isReservePourDevis) :
   même teinte orange sur la ligne de grille et sur l'alerte de /produit/view.
   box-shadow neutralisé + !important sur la ligne : .table-striped applique
   son zébrage par-dessus via box-shadow, sinon invisible (voir historique).
   ========================================================================== */

.grid-view .table-striped > tbody > tr.tr-reserve-devis > td {
    background-color: #ffbe6e !important;
    box-shadow: none;
}

.alert-reserve-devis {
    color: #7a3e00;
    background-color: #ffe8d1;
    border-color: #ffd7ad;
}

/* Produit vendu (Produit::vendu) : ligne rougeâtre dans la grille du stock. */
.grid-view .table-striped > tbody > tr.tr-vendu > td {
    background-color: #ef1c25 !important;
    box-shadow: none;
    color: #fff;
}

.grid-view .table-striped > tbody > tr.tr-vendu > td a,
.grid-view .table-striped > tbody > tr.tr-vendu > td i {
    color: #fff;
}

/* Double liste gauche/droite (voir views/priorite/create.php) : les <option>
   héritent d'une taille de police bien plus grosse que le reste de l'appli
   par défaut du navigateur. */
.dual-list, .dual-list option {
    font-size: 12px;
}

/* Légende de couleurs du planning des locations (voir views/location/planning.php). */
.location-planning-legende {
    display: inline-block;
    width: .85rem;
    height: .85rem;
    border-radius: .2rem;
    vertical-align: middle;
    margin-right: .3rem;
}

/* Tableau de bord : cards en masonry (CSS columns, pas de grille à hauteur
   uniforme) plutôt qu'en lignes Bootstrap — mêmes 4 paliers responsives
   qu'avant (col-md-6/col-xl-4/col-xxl-3), réordonnable en glisser-déposer
   (voir views/site/index.php). */
.home-masonry {
    columns: 1;
    column-gap: 1.5rem;
}

@media (min-width: 768px) {
    .home-masonry { columns: 2; }
}

@media (min-width: 1200px) {
    .home-masonry { columns: 3; }
}

@media (min-width: 1400px) {
    .home-masonry { columns: 4; }
}

.home-card-wrap {
    break-inside: avoid;
    margin-bottom: 1.5rem;
    cursor: move;
}

.home-card-dragging {
    opacity: .4;
}

/* Journal de primes (voir views/prime/_carte.php, _colonne.php,
   historique.php) : le corps de l'appli est déjà en 12px (voir plus haut),
   .small de Bootstrap (0.875em) le réduisait encore à ~10.5px — illisible
   pour un contenu que toute l'équipe consulte régulièrement, pas juste les
   admins. Remonté au moins au corps de l'appli, cartes un cran au-dessus. */
.prime-index .small,
.prime-historique .small {
    font-size: 12px;
}

.prime-carte,
.prime-feed {
    font-size: 13px;
}

/* Copie complète d'un texte coupé dans une grille (voir
   app\components\grid\TexteTronque) : invisible à l'écran, reprise par les exports. */
.export-seul {
    display: none;
}

/* Filtre Prix de la grille Stock : Min et Max l'un sous l'autre, à la
   largeur de la colonne (fixée par les montants), au lieu de deux champs
   côte à côte qui l'élargissaient. Le min-width de 90px commun à tous les
   filtres de grille est levé ici. */
.grid-view tr.filters .filtre-prix input {
    width: 100%;
    min-width: 0;
    padding-left: .4rem;
    padding-right: .25rem;
}

/* Filtres étroits de la grille Stock (Taille, Moteur, Sacrifié, Vendu) : la
   liste prend la largeur de la colonne (fixée par l'entête et les valeurs,
   éventuellement coupées) au lieu de sa valeur la plus longue ou des 90px
   minimum communs aux filtres. La liste ouverte garde les libellés complets. */
.grid-view tr.filters td.filtre-etroit select {
    width: 100%;
    min-width: 0;
    padding-left: .4rem;
    padding-right: 1.5rem;
    background-position: right .35rem center;
}

/* Boutons d'en-tête de la fiche produit : jamais de texte coupé sur deux
   lignes (icône au-dessus du texte) ; ils passent à la ligne en bloc. */
.fiche-actions .btn {
    white-space: nowrap;
}
