Files
lidar_rendu/lidar_pipeline/web/map.css

230 lines
15 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Carte LiDAR — tuiles XYZ, habillage minimal type carte grand public. */
/* Réglages communs : toute règle y puise (couleurs, texte, arrondis,
espacements, ombres, superpositions). Deux palettes : claire par défaut,
sombre si le système le demande (sauf clair forcé) ou si elle est forcée. */
:root {
color-scheme: light;
--bg: #eef0f3;
--surface: rgba(251, 251, 250, 0.96);
--surface-2: #eef0f3; /* champs, segments, boutons neutres */
--border: #d6d9de;
--text: #1d232b;
--muted: #5b6573;
--accent: #1f6fb2;
--on-accent: #ffffff;
--track: #cfd4da;
--print: #d99a00;
--gen-running: #d9730d;
--gen-pending: #0b8fc0;
--gen-failed: #c8452c;
--gen-sel: var(--accent);
--fs-xs: 11px; --fs-sm: 12px; --fs-md: 13px; --fs-lg: 16px;
--r-sm: 6px; --r-md: 10px; --r-full: 999px;
--sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.18);
--shadow-lg: 0 6px 24px rgba(0, 0, 0, 0.28);
--z-map-ui: 800; --z-panel: 900; --z-popup: 950;
--z-loading: 960; --z-toast: 1000; --z-modal: 1100;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
color-scheme: dark;
--bg: #0b0e13; --surface: rgba(16, 20, 27, 0.95); --surface-2: rgba(255, 255, 255, 0.06);
--border: rgba(255, 255, 255, 0.12); --text: #d9dee6; --muted: #8b94a3;
--accent: #5aa9e6; --on-accent: #0b0e13; --track: rgba(255, 255, 255, 0.18);
--print: #ffd166; --gen-running: #f4a261; --gen-pending: #4cc9f0; --gen-failed: #e76f51;
--shadow-sm: 0 4px 16px rgba(0, 0, 0, 0.4); --shadow-lg: 0 6px 24px rgba(0, 0, 0, 0.45);
}
}
:root[data-theme="dark"] {
color-scheme: dark;
--bg: #0b0e13; --surface: rgba(16, 20, 27, 0.95); --surface-2: rgba(255, 255, 255, 0.06);
--border: rgba(255, 255, 255, 0.12); --text: #d9dee6; --muted: #8b94a3;
--accent: #5aa9e6; --on-accent: #0b0e13; --track: rgba(255, 255, 255, 0.18);
--print: #ffd166; --gen-running: #f4a261; --gen-pending: #4cc9f0; --gen-failed: #e76f51;
--shadow-sm: 0 4px 16px rgba(0, 0, 0, 0.4); --shadow-lg: 0 6px 24px rgba(0, 0, 0, 0.45);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }
html, body { height: 100%; overflow: hidden; background: var(--bg); color: var(--text);
font: var(--fs-md)/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
#map { position: absolute; inset: 0; background: var(--bg); }
.leaflet-container { background: var(--bg); font: inherit; }
/* Fond OSM assombri pour laisser ressortir les rendus LiDAR. Filtre posé sur
le conteneur de la couche, pas sur chaque tuile : même rendu (opérations
par pixel), mais une seule passe de filtre au lieu d'une par tuile —
−30 % de CPU (moteur de rendu + GPU) en déplacement, mesuré sous Chrome. */
.leaflet-tile-pane .leaflet-layer.base-dark { filter: brightness(0.38) contrast(1.1) saturate(0.7); }
.card { position: fixed; z-index: var(--z-panel); background: var(--surface); color: var(--text);
border: 1px solid var(--border); border-radius: var(--r-md);
box-shadow: var(--shadow-lg);
backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
#layercard { left: 12px; bottom: 12px; width: 320px; max-width: calc(100vw - 24px); }
#tilecard { left: 12px; top: 12px; width: 340px; max-width: calc(100vw - 24px);
max-height: calc(100vh - 24px); overflow-y: auto; }
.info-sec { margin-top: 10px; }
.info-sec h4 { margin: 0 0 4px; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.06em;
text-transform: uppercase; color: var(--muted); }
.info-kv { display: grid; grid-template-columns: max-content 1fr; gap: 2px 10px; font-size: var(--fs-sm); }
.info-kv dt { color: var(--muted); }
.info-kv dd { margin: 0; overflow-wrap: anywhere; }
.info-dl { display: inline-block; margin-top: 6px; padding: 6px 10px; border-radius: var(--r-sm);
background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--text); text-decoration: none; font-weight: 600; }
.info-dl:hover { background: color-mix(in srgb, var(--accent) 30%, transparent); }
#rose { right: 12px; bottom: 190px; padding: 8px 8px 6px; display: flex; flex-direction: column;
align-items: center; gap: 2px; z-index: var(--z-map-ui); }
#rose canvas { width: 132px; height: 132px; }
.rose-cap { font-size: var(--fs-xs); text-align: center; color: var(--text); line-height: 1.3; }
.rose-cap span { color: var(--muted); font-size: var(--fs-xs); }
#usecard { left: 50%; top: 12px; transform: translateX(-50%); width: min(560px, calc(100vw - 24px)); z-index: var(--z-popup); }
.card-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.card-title { font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.card-stat { margin-left: auto; font-size: var(--fs-xs); color: var(--muted); }
.card-body { padding: 6px 8px 8px; max-height: min(60vh, 520px); overflow-y: auto; }
#layercard.collapsed .card-body { display: none; }
#layercard.collapsed #cardToggle { transform: rotate(-90deg); }
.card-foot { display: flex; gap: 8px; padding: 8px 4px 2px; margin-top: 6px; border-top: 1px solid var(--border); }
/* --- composants communs --------------------------------------------------- */
.btn, button { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-1);
min-height: 32px; padding: 0 var(--sp-3); border-radius: var(--r-sm); border: 1px solid var(--border);
background: var(--surface-2); color: var(--text); font: inherit; font-size: var(--fs-sm); cursor: pointer; }
.btn:hover, button:hover { border-color: var(--accent); }
.btn:disabled, button:disabled { opacity: 0.5; cursor: default; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn-primary:hover { filter: brightness(1.08); }
.btn-ghost { background: transparent; }
.btn-icon { min-height: 0; padding: var(--sp-1) var(--sp-2); border: none; background: none;
color: var(--muted); font-size: var(--fs-lg); }
.btn-icon:hover { color: var(--text); }
.row { display: flex; gap: var(--sp-2); align-items: center; }
.row > .btn, .row > .field { flex: 1; min-width: 0; }
.field { height: 32px; min-width: 0; width: 100%; padding: 0 var(--sp-2); border-radius: var(--r-sm);
border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
font: inherit; font-size: var(--fs-sm); }
select.field[multiple] { height: auto; padding: var(--sp-1); }
.field option { background-color: var(--surface); color: var(--text); }
.seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border: 1px solid var(--border);
border-radius: var(--r-sm); overflow: hidden; }
.seg button { min-height: 32px; border: none; border-radius: 0; background: var(--surface-2); color: var(--muted); }
.seg button + button { border-left: 1px solid var(--border); }
.seg button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.seg button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.hint { font-size: var(--fs-sm); color: var(--muted); margin: var(--sp-1) 0; }
input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 20px;
background: transparent; cursor: pointer; }
input[type="range"]::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: var(--track); }
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px;
margin-top: -5px; border-radius: 50%; background: var(--accent); border: 2px solid var(--surface); }
input[type="range"]::-moz-range-track { height: 4px; border-radius: 2px; background: var(--track); }
input[type="range"]::-moz-range-thumb { width: 10px; height: 10px; border-radius: 50%;
background: var(--accent); border: 2px solid var(--surface); }
@media (max-width: 720px) {
.btn, button, .field, .seg button { min-height: 40px; }
.field { height: 40px; }
}
/* Ligne du fond de carte : œil, nom, opacité. */
.base-row { display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; align-items: center;
gap: var(--sp-2); padding: var(--sp-1) 0; }
.base-row .base-ctl { grid-column: 2 / -1; display: grid; grid-template-columns: minmax(0, 1fr) 40px;
gap: var(--sp-2); align-items: center; }
/* Affichage : une couche principale, la précision seule ou superposée. */
.view-row { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center;
gap: 8px; padding: 8px 4px 4px; border-top: 1px solid var(--border); margin-top: 4px; }
.view-label { font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.view-row .layer-name { color: var(--text); }
.prec-ctl { display: grid; grid-template-columns: auto minmax(0, 1fr) 34px; gap: 8px;
align-items: center; padding: 6px 4px 0; font-size: var(--fs-xs); color: var(--muted); }
.prec-legend { padding: 8px 4px 2px; }
.prec-bar { display: grid; grid-template-columns: repeat(16, 1fr); height: 10px;
border: 1px solid var(--border); border-radius: 3px; overflow: hidden; }
.prec-ticks { display: flex; justify-content: space-between; font-size: var(--fs-xs); color: var(--muted);
font-variant-numeric: tabular-nums; margin-top: 2px; }
.prec-cap { font-size: var(--fs-xs); color: var(--muted); margin-top: 2px; }
.eye { width: 24px; height: 24px; padding: 0; border: none; background: none; color: var(--muted);
display: flex; align-items: center; justify-content: center; }
.eye.on { color: var(--accent); }
.eye svg { width: 16px; height: 16px; }
.layer-name { font-size: var(--fs-sm); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pct { font-size: var(--fs-xs); color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
#tools { position: fixed; right: 12px; bottom: 12px; z-index: var(--z-panel); display: flex; flex-direction: column; gap: 6px; }
#tools button { width: 38px; height: 38px; padding: 0; font-size: var(--fs-lg); background: var(--surface);
border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
/* Indicateur de chargement : tuiles restantes pour finir la vue courante
(fond + LiDAR), barre de progression du lot en cours. */
.tileload { position: fixed; left: 50%; top: 12px; transform: translateX(-50%); z-index: var(--z-loading);
display: flex; align-items: center; gap: 8px; padding: 5px 12px; border-radius: var(--r-full);
background: var(--surface); border: 1px solid var(--border); font-size: var(--fs-sm);
box-shadow: var(--shadow-sm); pointer-events: none;
transition: opacity 0.3s ease; white-space: nowrap; }
.tileload.done { opacity: 0; }
.tl-spin { width: 12px; height: 12px; border-radius: var(--r-full); flex: none;
border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent); border-top-color: var(--accent);
animation: tlspin 0.8s linear infinite; }
.tileload.done .tl-spin { animation: none; border-color: var(--accent); }
@keyframes tlspin { to { transform: rotate(360deg); } }
.tl-bar { width: 60px; height: 4px; border-radius: var(--r-sm); background: var(--track);
overflow: hidden; flex: none; }
.tl-bar span { display: block; height: 100%; width: 0; background: var(--accent);
transition: width 0.2s ease; }
.toast { position: fixed; left: 50%; bottom: 76px; transform: translateX(-50%); z-index: var(--z-toast);
background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm);
padding: 7px 12px; font-size: var(--fs-sm); color: var(--text); max-width: 80vw; text-align: center; }
.meta { font-size: var(--fs-xs); color: var(--muted); margin: 2px 0; }
.meta b { color: var(--text); font-weight: 600; }
.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: var(--fs-xs);
background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm);
padding: 6px 8px; word-break: break-all; margin: 4px 0 8px; }
.use-note { font-size: var(--fs-xs); color: var(--muted); line-height: 1.5; }
.leaflet-control-attribution { background: var(--surface) !important; color: var(--muted) !important; }
.leaflet-control-attribution a { color: var(--accent) !important; }
/* --- génération de tuiles ------------------------------------------------ */
#gencard { right: 12px; top: 56px; width: 340px; max-width: calc(100vw - 24px); }
#printcard { right: 60px; bottom: 12px; width: 340px; max-width: calc(100vw - 84px); }
.print-msg { font-size: var(--fs-sm); margin-left: 8px; }
.print-handle { display: flex; align-items: center; justify-content: center; cursor: move;
font-size: var(--fs-lg); color: #1b1b1b; background: var(--print); border: 2px solid #1b1b1b;
border-radius: var(--r-full); box-shadow: 0 1px 6px rgba(0,0,0,0.5); }
body.drawing { cursor: crosshair !important; }
body.drawing .leaflet-container { cursor: crosshair !important; }
/* Barre de génération : en HAUT à droite de l'écran, boutons accentués —
c'est l'entrée principale du traitement, elle ne se confond pas avec les
icônes de navigation (zoom/GPS) du coin bas droit. */
#gentools { position: fixed; top: 12px; right: 12px; z-index: var(--z-panel); display: flex; gap: 8px; }
#gentools button { background: var(--surface); color: var(--accent); border: 1px solid var(--accent);
border-radius: var(--r-md); padding: 8px 14px; font: inherit; font-size: var(--fs-md); font-weight: 600;
box-shadow: var(--shadow-sm); }
#gentools button:hover { background: var(--accent); color: var(--on-accent); }
#gentools button.accent { background: var(--accent); color: var(--on-accent); }
.gen-row { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 6px;
align-items: center; margin: 4px 0; font-size: var(--fs-xs); color: var(--muted); }
.chk { display: flex; gap: 7px; align-items: center; font-size: var(--fs-xs);
color: var(--muted); margin: 4px 0; cursor: pointer; }
.chk input { accent-color: var(--accent); }
.gen-log { font: var(--fs-xs)/1.5 ui-monospace, "SF Mono", Menlo, monospace; color: var(--muted);
background: rgba(0,0,0,0.35); border: 1px solid var(--border); border-radius: var(--r-sm);
padding: 6px 8px; max-height: 130px; overflow-y: auto; white-space: pre-wrap;
word-break: break-all; margin: 6px 0; }
#tools button.accent { color: var(--accent); border-color: var(--accent); }
#tools button.busy { color: var(--accent); border-color: var(--accent); }
/* Cadres des dalles du run : orange pulsant = rendu en cours, bleu = en
attente, rouge = échec. Les dalles faites n'ont pas de cadre. */
@keyframes genpulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.gen-frame-running { stroke: var(--gen-running); fill: color-mix(in srgb, var(--gen-running) 13%, transparent); animation: genpulse 1.4s ease-in-out infinite; }
.gen-frame-pending { stroke: var(--gen-pending); fill: color-mix(in srgb, var(--gen-pending) 8%, transparent); stroke-dasharray: 6 4; }
.gen-frame-failed { stroke: var(--gen-failed); fill: color-mix(in srgb, var(--gen-failed) 20%, transparent); }
.gen-sel { stroke: var(--accent); fill: color-mix(in srgb, var(--accent) 12%, transparent); cursor: pointer; }
@media (max-width: 720px) {
#layercard { width: calc(100vw - 24px); }
#tilecard { width: calc(100vw - 24px); }
#gencard { width: calc(100vw - 24px); }
#printcard { width: calc(100vw - 84px); }
}