/* Releve de terrain — servi par /site-survey.css.
   Mobile d abord : tout est dimensionne pour un pouce, pas pour un curseur.
   Trois themes : clair (defaut -- le releve se fait dehors), sombre, et
   soleil (contraste maximal). Le choix est une preference d affichage de CE
   navigateur, et rien d autre (ADR-0015). */
:root {
  /* LIGHT, the default: a survey happens outdoors, in daylight. */
  --fond: #eef2f7;
  --entete: #ffffff;
  --carte: #ffffff;
  --champ: #ffffff;
  --piste: #dde3ec;
  --bord: #cfd7e3;
  --bord-fort: #8e9bb0;
  --texte: #0f1b2d;
  --doux: #4a5a70;
  --accent: #1f5fd1;
  --accent-doux: #e3edff;
  --sur-accent: #ffffff;
  --ok: #1a7f45;
  --alerte: #a15c00;
  --refus: #c42b2b;
  --ombre: 0 1px 2px rgba(15, 27, 45, .06), 0 2px 10px rgba(15, 27, 45, .07);
  --epais: 1px;
  --rayon: 14px;
  /* 48 px is the minimum for a touch target reachable with a glove. */
  --cible: 48px;
  color-scheme: light;
}
:root[data-theme="dark"] {
  --fond: #0b1220; --entete: #0f182b; --carte: #16203a; --champ: #0d1730;
  --piste: #0a1226; --bord: #2b3a5e; --bord-fort: #4a5d88;
  --texte: #f2f6ff; --doux: #a9bbdb; --accent: #5b97ff; --accent-doux: #1a2b52;
  --sur-accent: #06101f; --ok: #34c77b; --alerte: #ffb020; --refus: #ff6b6b;
  --ombre: none;
  color-scheme: dark;
}
/* SUN: pure black on pure white, thick borders, larger text. No shadow and
   no tint -- both vanish in direct sunlight. */
:root[data-theme="sun"] {
  --fond: #ffffff; --entete: #ffffff; --carte: #ffffff; --champ: #ffffff;
  --piste: #c8c8c8; --bord: #000000; --bord-fort: #000000;
  --texte: #000000; --doux: #1a1a1a; --accent: #0038a8; --accent-doux: #ffffff;
  --sur-accent: #ffffff; --ok: #006b2d; --alerte: #8a4b00; --refus: #b00000;
  --ombre: none; --epais: 2px;
  color-scheme: light;
}
* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0;
  background: var(--fond); color: var(--texte);
  font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Prevents the accidental double-tap zoom, which moves the intended target. */
  touch-action: manipulation;
  -webkit-text-size-adjust: 100%;
}
:root[data-theme="sun"] body { font-size: 18px; }
/* The content area leaves room for the bottom action bar AND for the notch
   of recent phones. Without this padding, the last field of the form lives
   UNDER the button and nobody finds it. */
main { padding: 14px 14px calc(96px + env(safe-area-inset-bottom, 0px)); }
header {
  position: sticky; top: 0; z-index: 5;
  background: var(--entete); border-bottom: var(--epais) solid var(--bord);
  box-shadow: var(--ombre);
  padding: 6px 8px; padding-top: calc(6px + env(safe-area-inset-top, 0px));
  display: flex; align-items: center; gap: 6px;
}
header h1 {
  font-size: 18px; font-weight: 700; line-height: 1.2; margin: 0;
  flex: 1; min-width: 0; overflow-wrap: anywhere;
}
header .retour, header .theme {
  min-width: var(--cible); min-height: var(--cible); flex: none;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 12px;
  color: var(--texte); font-size: 24px; cursor: pointer;
}
header .theme { font-size: 20px; }
header .retour:active, header .theme:active { background: var(--accent-doux); }
.etiquette { color: var(--doux); font-size: 14px; }

/* One CARD per item: never a table. A three-column table on 375 px is read
   with a magnifying glass. */
.carte {
  display: block; width: 100%; text-align: left;
  background: var(--carte); border: var(--epais) solid var(--bord);
  border-radius: var(--rayon); box-shadow: var(--ombre);
  padding: 14px 16px; margin: 0 0 10px; color: var(--texte);
  min-height: var(--cible); font: inherit;
}
button.carte { cursor: pointer; }
button.carte:active { border-color: var(--accent); background: var(--accent-doux); }
.carte .titre { font-weight: 650; font-size: 17px; line-height: 1.3; }
.carte .sous { color: var(--doux); font-size: 14px; margin-top: 4px; }

/* Progress: the question every client who PAYS for a survey asks. */
.jauge { height: 8px; background: var(--piste); border-radius: 999px; overflow: hidden; margin-top: 12px; }
.jauge > i { display: block; height: 100%; background: var(--ok); border-radius: 999px; }

label { display: block; margin: 18px 0 6px; font-weight: 600; font-size: 15px; }
label .req { color: var(--refus); }
input, select, textarea {
  width: 100%; min-height: var(--cible);
  background: var(--champ); color: var(--texte);
  border: var(--epais) solid var(--bord-fort); border-radius: 12px;
  padding: 10px 14px; font: inherit;
}
input:focus, select:focus, textarea:focus {
  outline: 3px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}
/* The photo picker: the native button is a 20 px grey pill. */
input[type="file"] { padding: 6px; }
input[type="file"]::file-selector-button {
  min-height: 40px; margin-right: 12px; padding: 0 16px; cursor: pointer;
  border: var(--epais) solid var(--accent); border-radius: 10px;
  background: var(--accent-doux); color: var(--accent);
  font-family: inherit; font-size: 15px; font-weight: 600;
}
.aide { color: var(--doux); font-size: 14px; margin-top: 4px; }
.refus { color: var(--refus); font-size: 14px; margin-top: 4px; }

/* The ACTION bar is at the bottom: the zone reachable with the thumb of one
   hand. At the top, it requires re-gripping the phone. */
.actions {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 6;
  background: var(--entete); border-top: var(--epais) solid var(--bord);
  box-shadow: 0 -2px 10px rgba(15, 27, 45, .06);
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
  display: flex; gap: 10px;
}
/* font-family / size / weight, NOT the << font >> shorthand: << font: 600
   16px/1 inherit >> is INVALID (inherit cannot sit in a shorthand), so the
   whole declaration was dropped and every button fell back to the browser
   default. Seen on staging, not in a test. */
button.primaire, button.secondaire {
  flex: 1; min-height: var(--cible); border-radius: 12px; padding: 10px 16px;
  font-family: inherit; font-size: 16px; font-weight: 650; line-height: 1.2;
  border: var(--epais) solid var(--bord-fort); cursor: pointer;
}
button.primaire { background: var(--accent); color: var(--sur-accent); border-color: var(--accent); }
button.secondaire { background: var(--carte); color: var(--texte); }
button.primaire:active { filter: brightness(.9); }
button.secondaire:active { background: var(--accent-doux); }
button[disabled] { opacity: .5; cursor: default; }
button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* The GPS state. It is ALWAYS visible during entry: a surveyor must know
   BEFORE filling in whether their position will be accepted. */
.gps {
  display: flex; align-items: center; gap: 10px;
  background: var(--carte); border: var(--epais) solid var(--bord);
  border-left-width: 6px;
  border-radius: 12px; padding: 10px 14px; margin-bottom: 10px; font-size: 15px;
}
.gps.bon { border-color: var(--ok); }
.gps.faible { border-color: var(--alerte); }
.gps.absent { border-color: var(--refus); }
.pastille { width: 12px; height: 12px; border-radius: 50%; background: var(--doux); flex: none; }
.gps.bon .pastille { background: var(--ok); }
.gps.faible .pastille { background: var(--alerte); }
.gps.absent .pastille { background: var(--refus); }
/* On the form, the GPS line stays PINNED under the header: the accuracy
   changes while the surveyor scrolls to the last field, and that is where
   they tap Save. */
body[data-vue="actif"] .gps {
  position: sticky; top: calc(60px + env(safe-area-inset-top, 0px)); z-index: 4;
  box-shadow: var(--ombre);
}

/* CHIPS: yes/no, short choices, multiple choices. One tap, 48 px, every
   option in view. The pressed state is carried by aria-pressed -- the same
   attribute a screen reader announces. */
.puces { display: flex; flex-wrap: wrap; gap: 8px; }
.puce {
  min-height: var(--cible); min-width: 72px; padding: 8px 16px; cursor: pointer;
  background: var(--champ); color: var(--texte);
  border: var(--epais) solid var(--bord-fort); border-radius: 999px;
  font-family: inherit; font-size: 16px; font-weight: 600;
}
.puce[aria-pressed="true"] { background: var(--accent); color: var(--sur-accent); border-color: var(--accent); }
.puce:active { filter: brightness(.92); }

/* A required field left empty: outlined where it is, with the word. */
[data-erreur] > input, [data-erreur] > select, [data-erreur] .puce {
  border-color: var(--refus);
}
[data-erreur] > label { color: var(--refus); }
.msg-erreur { color: var(--refus); font-size: 14px; font-weight: 600; margin-top: 6px; }

.vide { color: var(--doux); text-align: center; padding: 40px 12px; }
/* The CSP carries << style-src 'self' >> WITHOUT << unsafe-inline >>: a
   style= attribute in the HTML is therefore BLOCKED. The CSSOM
   (element.style.x = ...) is not -- hence this class for the initial state,
   and JS assignments afterwards. */
.cachee { display: none; }
/* OFFLINE: said at the top of every screen, because the one gesture that
   loses everything -- a reload -- looks harmless. */
.hors-ligne { padding: 10px 14px; background: var(--alerte); color: var(--sur-accent);
  font-size: 15px; font-weight: 650; }
.hors-ligne.cachee { display: none; }
.carte-hors-ligne { display: none; }
body.mode-hors-ligne .carte-hors-ligne { display: block; }
body.mode-hors-ligne .volet-carte .carte-campagne { display: none; }
/* Scanning. The overlay covers the screen: outdoors, a small viewfinder is
   unusable, and the surveyor needs to see what the camera sees. */
.scan { width: 100%; min-height: 48px; margin: 0 0 10px; }
/* Proximity. No colour carries meaning here: the text says everything, and a
   coarse fix says so in words rather than showing a number it cannot back. */
.proche { margin: 4px 0 10px; }
.lien-locataire {
  background: var(--carte); border: var(--epais) solid var(--bord); border-radius: 999px;
  color: var(--texte); font-family: inherit; font-size: 14px; padding: 6px 12px;
  min-height: 40px; max-width: 42vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer;
}
.couverture { margin: 4px 0 12px; }
.carte-couverture {
  height: 260px; border-radius: var(--rayon); border: var(--epais) solid var(--bord);
  overflow: hidden; margin-top: 8px;
}
.suggestion { display: flex; align-items: center; gap: .5rem; margin: .3rem 0 .4rem;
              font-size: 14px; color: var(--accent); cursor: pointer; min-height: 32px; }
.suggestion .touche { border: 1px solid currentColor; border-radius: 4px; padding: 0 .35rem;
                      font-size: 12px; opacity: .8; }
.proche .lien-proche {
  width: 100%; min-height: 56px; text-align: left; cursor: pointer;
  background: var(--accent-doux); border: var(--epais) solid var(--accent); border-radius: var(--rayon);
  color: var(--texte); font-family: inherit; font-size: 16px; font-weight: 600; padding: 10px 16px;
}
.scan-overlay { position: fixed; inset: 0; background: #000; z-index: 50;
  display: flex; flex-direction: column; align-items: center; justify-content: center; }
.scan-overlay video { width: 100%; max-height: 70vh; object-fit: contain; }
.scan-cancel, .scan-manual {
  min-height: 48px; width: 80%; max-width: 420px; margin: 8px 0;
  background: #ffffff; color: #000000; border: 0; border-radius: 12px;
  font-family: inherit; font-size: 16px; font-weight: 600;
}
/* The queue indicator. It NEVER carries green: a green check would make the
   phone get put away while surveys are still waiting. */
.file-etat { padding: 8px 14px; background: var(--accent-doux); border-bottom: var(--epais) solid var(--bord); font-size: 15px; }
.file-etat .lien-file { background: none; border: 0; padding: 6px 0; min-height: 32px; font: inherit;
  color: var(--accent); font-weight: 600; text-decoration: underline; cursor: pointer; }
.file-refus { background: var(--carte); }
.file-refus .lien-file { color: var(--refus); }
.brouillon { color: var(--alerte); font-size: 14px; margin-top: 6px; font-weight: 600; }
/* The queue screen: one card per entry, its state in words on a pill, the
   refusal EXPLAINED above the technical line. */
.section-file { font-size: 15px; font-weight: 700; margin: 18px 0 8px; color: var(--doux); }
.pastille-etat {
  flex: none; font-size: 13px; font-weight: 700; padding: 3px 10px; border-radius: 999px;
  background: var(--accent-doux); color: var(--accent);
}
.pastille-etat.refuse { background: var(--refus); color: var(--sur-accent); }
.entree-file .raison { font-size: 15px; margin-top: 8px; font-weight: 600; }
.entree-file .rangee-actions { margin-top: 10px; }
.vignette { display: block; width: 100%; max-height: 180px; object-fit: cover;
  border-radius: 10px; margin-top: 8px; border: var(--epais) solid var(--bord); }
button.danger { color: var(--refus); border-color: var(--refus); }
.photos { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.photos img { width: 88px; height: 88px; object-fit: cover; border-radius: 10px; border: var(--epais) solid var(--bord); }
#annonce { position: fixed; left: 12px; right: 12px; bottom: calc(80px + env(safe-area-inset-bottom, 0px)); z-index: 7; }
#annonce div {
  background: var(--carte); color: var(--texte); box-shadow: var(--ombre);
  border: var(--epais) solid var(--accent); border-left-width: 6px;
  border-radius: 12px; padding: 12px 14px; margin-top: 6px;
}
#annonce div.mauvais { border-color: var(--refus); }

/* THE CAMPAIGN SCREEN: summary, one row of gestures, then list and map. */
.resume { margin: 0 0 10px; }
.resume .etiquette { margin: 0; }
.resume .jauge { margin-top: 8px; }
.rangee-actions { display: flex; gap: 8px; margin: 0 0 12px; }
.rangee-actions .scan { flex: 1; margin: 0; padding: 8px 6px; font-size: 15px; }
.bascule {
  display: flex; margin: 0 0 12px; overflow: hidden;
  border: var(--epais) solid var(--bord-fort); border-radius: 12px;
}
.bascule button {
  flex: 1; min-height: 44px; border: 0; cursor: pointer;
  background: var(--carte); color: var(--texte);
  font-family: inherit; font-size: 15px; font-weight: 600;
}
.bascule button[aria-pressed="true"] { background: var(--accent); color: var(--sur-accent); }
.volets[data-mode="liste"] .volet-carte, .volets[data-mode="carte"] .volet-liste { display: none; }
.carte-campagne {
  height: calc(100vh - 300px); min-height: 320px;
  border-radius: var(--rayon); border: var(--epais) solid var(--bord); overflow: hidden;
}
.recherche { margin: 0 0 10px; }
.carte .ligne-titre { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.distance { flex: none; font-size: 14px; font-weight: 700; color: var(--accent); }
/* Leaflet paints its popups white: in the dark theme the text vanished. */
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--carte); color: var(--texte); }
.popup-actif { min-width: 180px; font-size: 15px; }
.popup-actif .titre { font-weight: 650; }
.popup-actif .sous { color: var(--doux); margin-top: 2px; }
.popup-actif button { width: 100%; margin-top: 10px; }

/* TABLET. A 10-inch screen held in two hands: the lists become a grid of
   cards, the form keeps a readable line length, the bar centres its buttons.
   << data-vue >> is set by the router on body -- the grid applies to the
   LIST screens only; the form stays a single column. */
@media (min-width: 700px) {
  main { max-width: 1080px; margin: 0 auto; padding-left: 24px; padding-right: 24px; }
  header { padding-left: 16px; padding-right: 16px; }
  header h1 { font-size: 20px; }
  body[data-vue="campagnes"] main, body[data-vue="ville"] main {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 14px; align-content: start;
  }
  .liste-actifs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 14px; }
  .liste-actifs > .vide { grid-column: 1 / -1; }
  body[data-vue] main > :not(.carte), body[data-vue] main > div.carte { grid-column: 1 / -1; }
  body[data-vue="actif"] main, body[data-vue="file"] main { max-width: 760px; }
  .actions { justify-content: center; }
  .actions button { max-width: 420px; }
  .carte-couverture { height: 400px; }
  .lien-locataire { max-width: 320px; }
  #annonce { left: 50%; right: auto; width: 560px; transform: translateX(-50%); }
}
/* WIDE TABLET, landscape: list and map side by side, the map pinned. */
@media (min-width: 1000px) {
  body[data-vue="campagne"] main { max-width: 1400px; }
  .bascule { display: none; }
  .volets { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 16px; align-items: start; }
  .volets[data-mode] .volet-liste, .volets[data-mode] .volet-carte { display: block; }
  .volet-carte { position: sticky; top: 72px; }
  .carte-campagne { height: calc(100vh - 110px); }
  .liste-actifs { grid-template-columns: minmax(0, 1fr); }
}
