/* ============================================================
   GALogix Brand Theme — Palette & Variables (galogix.ca)
   Navy blue palette derived from galogix.ca
   Variable names kept (--forest-*) for backward compatibility.
   ============================================================ */
:root {
    /* Primary GALogix navy blues */
    --forest-900: #0f2840;
    --forest-800: #1c3d56;
    --forest-700: #2c5577;
    --forest-600: #3a6e94;
    --forest-500: #5b8db0;
    --forest-400: #86adcb;
    --forest-300: #b3cce0;
    --forest-200: #d6e3ee;
    --forest-100: #eef3f8;

    /* Neutral cool grays */
    --bark-900: #2c3e50;
    --bark-700: #4a5d70;
    --bark-500: #6b7d90;
    --bark-300: #b0bdc9;
    --bark-100: #ecf0f4;

    /* Backgrounds */
    --bg-warm: #f5f7fa;
    --bg-card: #ffffff;
    --bg-topbar: #eef3f8;

    /* Accent — vibrant blue (galogix.ca title underline) */
    --accent-gold: #1d6dd0;
    --accent-gold-light: #d6e8fa;

    /* Semantic */
    --color-primary: var(--forest-800);
    --color-primary-hover: var(--forest-700);
    --color-primary-dark: var(--forest-900);
    --color-link: var(--forest-700);
    --color-success: #2d7a4f;
    --color-danger: #c1121f;
    --color-warning: #e09f3e;
    --color-info: #457b9d;
    --color-muted: #7f8c8d;

    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
    --shadow-card: 0 2px 8px rgba(15, 40, 64, 0.08);
    --shadow-card-hover: 0 4px 16px rgba(15, 40, 64, 0.14);
    --transition-fast: 0.2s ease;
}

html, body {
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    background-color: var(--bg-warm);
    color: #1f2d3d;
    /* Désactive le pull-to-refresh natif (Chrome Android) : un refresh complet
       casse le circuit Blazor Server et perd l'état UI, et les déclenchements
       accidentels sont fréquents au-dessus des cartes Leaflet et grilles. */
    overscroll-behavior-y: contain;
}

a, .btn-link {
    color: var(--color-link);
}

a:hover, .btn-link:hover {
    color: var(--forest-700);
}

.btn-primary {
    color: #fff;
    background-color: var(--color-primary);
    border-color: var(--color-primary);
    border-radius: var(--radius-sm);
}

.btn-primary:hover, .btn-primary:active {
    background-color: var(--color-primary-hover) !important;
    border-color: var(--color-primary-hover) !important;
}

.btn-outline-primary {
    color: var(--color-primary);
    border-color: var(--color-primary);
    border-radius: var(--radius-sm);
}

.btn-outline-primary:hover {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
}

.btn-success {
    background-color: var(--color-success);
    border-color: var(--color-success);
}

.btn {
    border-radius: var(--radius-sm);
    font-weight: 500;
    transition: all var(--transition-fast);
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem var(--forest-500);
}

.form-control:focus, .form-select:focus {
    border-color: var(--forest-600);
    box-shadow: 0 0 0 0.2rem rgba(58, 110, 148, 0.25);
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

/* Cards — soft & warm */
.card {
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    transition: box-shadow var(--transition-fast), transform var(--transition-fast);
    border-width: 1px;
    background: var(--bg-card);
}

.card:hover {
    box-shadow: var(--shadow-card-hover);
}

/* Badges */
.badge.bg-danger {
    background-color: var(--color-danger) !important;
}

.badge.bg-success {
    background-color: var(--color-success) !important;
}

/* Tables */
.table {
    border-radius: var(--radius-sm);
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--color-success);
}

.invalid {
    outline: 1px solid var(--color-danger);
}

.validation-message {
    color: var(--color-danger);
}

/* Text utilities override */
.text-primary {
    color: var(--color-primary) !important;
}

.text-success {
    color: var(--color-success) !important;
}

.text-danger {
    color: var(--color-danger) !important;
}

.text-info {
    color: var(--color-info) !important;
}

.text-warning {
    color: var(--color-warning) !important;
}

/* Border utilities override */
.border-primary {
    border-color: var(--forest-400) !important;
}

.border-success {
    border-color: var(--forest-500) !important;
}

.border-info {
    border-color: var(--color-info) !important;
}

.border-danger {
    border-color: var(--color-danger) !important;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

/* Leaflet marker styles */
.marker-icon {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 12px;
    color: white;
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
}

.marker-icon.start {
    background-color: #28a745;
}

.marker-icon.end {
    background-color: #dc3545;
}

/* Fix Leaflet container height */
.leaflet-container {
    height: 100%;
    width: 100%;
}

/* Position de l'utilisateur (marqueur créé par map-interop, hors du DOM Blazor :
   les styles doivent être globaux). Bleu accent, distinct des couleurs de traces
   attribuées aux machines. */
.user-location-marker {
    background: transparent !important;
    border: none !important;
}

.user-location-dot {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--accent-gold, #1d6dd0);
    border: 3px solid #fff;
    box-shadow: 0 0 0 1px rgba(29, 109, 208, 0.5), 0 1px 4px rgba(0, 0, 0, 0.4);
}

/* ==================== Mise en page des listes — défauts globaux ====================
   .page-header / .header-actions / .empty-state / .list-footer sont utilisés par toutes les
   pages de liste, mais n'étaient définis que dans le CSS isolé de chacune. Les pages sans
   fichier .razor.css (ContractorList, formulaires dynamiques) affichaient donc ces classes
   sans aucun style — en-tête non aligné sur grand écran et rien à adapter sur téléphone.
   Ces règles servent de défaut : un .razor.css de page reste plus spécifique (Blazor y ajoute
   son attribut de portée) et continue de gagner là où une page veut son propre agencement. */
.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1.5rem;
    flex-wrap: wrap;
    gap: 1rem;
}

.page-header h3 {
    margin: 0;
}

.header-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.empty-state {
    text-align: center;
    padding: 3rem;
    color: #666;
}

.empty-state i {
    font-size: 4rem;
    margin-bottom: 1rem;
    opacity: 0.5;
}

.list-footer {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid #dee2e6;
    color: #666;
    font-size: 0.875rem;
}

/* Conteneur des pages de formulaires dynamiques — jamais défini non plus, le contenu
   touchait le bord de l'écran. Même cadrage que les .*-list-container des autres pages. */
.page-content {
    padding: 1rem;
}

/* ==================== Vue cartes mobile ====================
   Une grille DevExpress ne se restyle pas en cartes : sous 576px les pages de liste
   remplacent la grille par ces cartes (voir responsiveHelper + _isMobileView). Ce bloc était
   copié à l'identique dans cinq CSS isolés ; il est ici une fois pour les seize pages qui
   l'utilisent. Les copies isolées existantes restent plus spécifiques et gardent la main. */
.mobile-cards {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Variante virtualisée : bloc simple, pas de flex-gap. <Virtualize> injecte ses propres div
   d'espacement comme enfants du conteneur — un `gap` s'appliquerait aussi à elles et
   fausserait le calcul de hauteur. L'écart entre cartes passe donc par une marge. */
.mobile-cards-virtual .mobile-card {
    margin-bottom: 0.5rem;
}

.mobile-card {
    /* Ancre pour la zone cliquable étirée de .mobile-card-title. */
    position: relative;
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 8px;
    padding: 0.75rem;
    transition: box-shadow 0.15s;
}

/* ===== Carte cliquable — patron « stretched link » =====
   Avant : la carte entière portait role="button" + tabindex + un handler clavier maison, et
   contenait les boutons d'action. Deux problèmes : de l'interactif imbriqué dans un
   role="button" (ARIA invalide), et un clavier à moitié implémenté.

   Ici c'est le TITRE qui est un vrai <button> — d'où un nom accessible utile (le titre de la
   carte, pas « Modifier ») et Entrée/Espace/focus gérés nativement par le navigateur. Son
   ::after étire la zone cliquable sur toute la carte, ce qui garde le confort du tap
   n'importe où. Les boutons d'action sont des frères, plus des descendants : plus besoin de
   stopPropagation.

   Le <button> ne peut pas envelopper le contenu de la carte : son modèle de contenu n'admet
   que du phrasing, et les cartes contiennent des <div>. D'où l'overlay plutôt qu'un wrapper. */
.mobile-card-title {
    appearance: none;
    -webkit-appearance: none;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.mobile-card-title::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: 8px;
}

/* Chevron d'affordance. Depuis le retrait du bouton crayon, plus rien n'indiquait que la carte
   est tapable : le titre-bouton ressemble à du texte gras. Dessiné en bordures CSS et non avec
   une glyphe Bootstrap Icons, pour ne dépendre d'aucun codepoint de police.

   Positionné contre .mobile-card et non contre la ligne d'en-tête : les deux pseudo-éléments
   de .mobile-card-title partagent le même bloc conteneur, et rendre .card-header-row
   positionné casserait l'étirement de ::after sur toute la carte.

   Le 1.35rem aligne le chevron sur la ligne du titre : 0.75rem de padding haut de la carte
   (identique dans les cinq variantes isolées) + une demi-hauteur de ligne. */
.mobile-card-title::before {
    content: "";
    position: absolute;
    top: 1.35rem;
    right: 0.85rem;
    width: 0.45rem;
    height: 0.45rem;
    border-right: 2px solid #adb5bd;
    border-bottom: 2px solid #adb5bd;
    transform: translateY(-50%) rotate(-45deg);
}

/* Réserve la gouttière du chevron : sans ça un badge de statut long passerait dessous.
   Repli sans :has() — le badge peut chevaucher le chevron, c'est cosmétique. */
.card-header-row:has(.mobile-card-title) {
    padding-right: 1.1rem;
}

/* Retour tactile sur toute la carte, et seulement quand c'est la zone étirée qui est pressée
   (pas quand on appuie sur un bouton d'action). */
.mobile-card-title:active::after {
    background: rgba(0, 0, 0, 0.03);
}

.mobile-card-title:focus-visible {
    outline: 2px solid var(--forest-600, #3a6e94);
    outline-offset: 2px;
    border-radius: 2px;
}

.card-header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
}

.card-details {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    font-size: 0.85rem;
    color: #555;
    margin: 0.25rem 0;
    /* Les courriels et identifiants de formulaire n'ont pas d'espace où se couper. */
    overflow-wrap: anywhere;
}

.card-details i {
    width: 1.2rem;
    text-align: center;
    margin-right: 0.25rem;
}

.card-actions {
    /* Au-dessus de la zone étirée du titre, sinon les actions deviennent inatteignables. */
    position: relative;
    z-index: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid #f0f0f0;
}

.card-actions .btn {
    min-height: 44px;
    min-width: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Une grille DevExpress est bien plus large qu'un téléphone. Sept pages neutralisaient déjà
   le débordement page par page via ::deep ; c'est maintenant le défaut partout, sinon les
   grilles d'administration élargissent tout le document au lieu de défiler sur elles-mêmes. */
.dxbl-grid {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* ==================== Mobile / Touch improvements ==================== */
@media (max-width: 768px) {
    /* En-tête de liste : le titre et les actions ne tiennent pas côte à côte — on empile
       plutôt que de comprimer les boutons jusqu'à l'illisibilité. */
    .page-header {
        flex-direction: column;
        align-items: flex-start;
        margin-bottom: 1rem;
    }

    .header-actions {
        width: 100%;
    }

    .empty-state {
        padding: 2rem 1rem;
    }

    .empty-state i {
        font-size: 3rem;
    }

    /* Touch-friendly form controls */
    .form-control,
    .form-select {
        min-height: 44px;
        font-size: 16px; /* Prevents iOS zoom on focus */
    }

    /* Touch-friendly buttons */
    .btn {
        min-height: 44px;
        padding: 0.5rem 1rem;
    }

    .btn-sm {
        min-height: 36px;
        padding: 0.4rem 0.75rem;
    }

    /* Touch-friendly checkboxes */
    .form-check-input {
        width: 1.25em;
        height: 1.25em;
    }

    /* Reduce content padding on mobile */
    .content {
        padding-top: 0.5rem;
    }

    /* Modal responsive */
    .modal-dialog {
        margin: 0.5rem;
    }
}

@media (max-width: 576px) {
    .content {
        padding-top: 0.25rem;
    }

    .page-header h3 {
        font-size: 1.25rem;
    }
}

/* ============================================================
   Waypoint Markers (ForestLogix-style icons on Leaflet map)
   ============================================================ */
.waypoint-marker {
    background: transparent !important;
    border: none !important;
}

.waypoint-icon-img {
    width: 32px;
    height: 32px;
    object-fit: contain;
    filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.4));
    cursor: pointer;
}

.waypoint-popup {
    font-size: 0.85rem;
    line-height: 1.4;
}

.waypoint-popup strong {
    color: var(--forest-800);
}

.waypoint-popup .text-muted {
    font-size: 0.75rem;
    color: #888;
}

/* Identification d'une entité d'un fond vectoriel (bulle Leaflet, hors composant). */
/* Outil « ID » de la Cartographie : curseur, liste des entités sous le clic. */
.carte-mode-identif,
.carte-mode-identif .leaflet-interactive {
    cursor: help !important;
}

.identif-vecteur .identif-sous-titre {
    font-weight: 600;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6c757d;
    padding-top: 6px;
}

.identif-vecteur .identif-total {
    font-size: 0.8rem;
    color: #6c757d;
    margin-bottom: 4px;
}

.identif-vecteur .identif-entite {
    cursor: pointer;
    border-left: 3px solid transparent;
    padding-left: 4px;
    margin-bottom: 6px;
}

/* Éléments superposés : liste de choix — seul l'élément choisi montre ses attributs. */
.identif-vecteur.identif-plusieurs .identif-entite:not(.identif-active) table {
    display: none;
}

.identif-vecteur.identif-plusieurs .identif-entite:not(.identif-active) .identif-couche {
    opacity: 0.75;
}

.identif-vecteur.identif-plusieurs .identif-entite:not(.identif-active) .identif-couche::after {
    content: " ›";
}

.identif-vecteur .identif-entite.identif-active {
    border-left-color: #00b8d4;
}

.identif-vecteur .identif-pastille {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 5px;
    vertical-align: middle;
}

.identif-vecteur .identif-couche {
    margin-bottom: 0.3rem;
    font-weight: 700;
    color: #1b4b6b;
}

.identif-vecteur table {
    border-collapse: collapse;
    font-size: 0.78rem;
}

.identif-vecteur th {
    padding: 1px 8px 1px 0;
    color: #6c757d;
    font-weight: 600;
    text-align: left;
    vertical-align: top;
}

.identif-vecteur td {
    padding: 1px 0;
    word-break: break-word;
}

/* Polygone de production : étiquettes de l'outil Mesurer (largeur de bande…). */
.leaflet-tooltip.prod-mesure-etiquette {
    background: rgba(0, 0, 0, .75);
    color: #ffeb3b;
    border: none;
    box-shadow: none;
    font-weight: 600;
    padding: 1px 6px;
}
.leaflet-tooltip.prod-mesure-etiquette::before { display: none; }
.leaflet-tooltip.prod-mesure-total { color: #fff; }
