/* The town's theme (Bootstrap recoloured to the town's teal). */
/* Deliberately NOT the French state's blue: the town has its own identity. */
:root {
  --bs-primary: #0f766e;
  --bs-primary-rgb: 15, 118, 110;
  --bs-link-color: #0f766e;
  --bs-link-color-rgb: 15, 118, 110;
  --bs-link-hover-color: #0c5f59;
  --bs-link-hover-color-rgb: 12, 95, 89;
  --town: #0f766e;
  --town-dark: #0c5f59;
  /* Pastel palette (soft background + dark text of the same hue) — buttons and
     tags. Contrasts checked at AA. */
  --pastel-teal: #d4ece7;   --pastel-teal-fg: #0b544e;
  --pastel-green: #e0f2e6;  --pastel-green-fg: #1a6b3d;
  --pastel-amber: #fbe7cf;  --pastel-amber-fg: #8a5218;
  --pastel-yellow: #f7f3c8; --pastel-yellow-fg: #6a6410;
  --pastel-red: #fbe3e3;    --pastel-red-fg: #b02a2a;
  --pastel-blue: #dde8fb;   --pastel-blue-fg: #2b4c8c;
  --pastel-purple: #e7defa; --pastel-purple-fg: #5b3fa6;
  --pastel-pink: #fbe2ee;   --pastel-pink-fg: #a83a6f;
  --pastel-grey: #eef1f4;   --pastel-grey-fg: #55606b;
}
/* Primary button: pastel teal background, dark teal text (the soft style). */
.btn-primary {
  --bs-btn-bg: var(--pastel-teal); --bs-btn-border-color: #bfe0da;
  --bs-btn-color: var(--pastel-teal-fg);
  --bs-btn-hover-bg: #c2e3dd; --bs-btn-hover-border-color: #a6d4cc;
  --bs-btn-hover-color: #0a4740;
  --bs-btn-active-bg: #b3dbd3; --bs-btn-active-border-color: #a6d4cc;
  --bs-btn-active-color: #0a4740;
  --bs-btn-disabled-bg: #e9f4f2; --bs-btn-disabled-border-color: #e9f4f2;
  --bs-btn-disabled-color: #7ba9a3;
  --bs-btn-focus-shadow-rgb: 15, 118, 110;
}
.btn-outline-primary {
  --bs-btn-color: var(--pastel-teal-fg); --bs-btn-border-color: #7ec3ba;
  --bs-btn-hover-bg: var(--pastel-teal); --bs-btn-hover-border-color: #7ec3ba;
  --bs-btn-hover-color: var(--pastel-teal-fg);
  --bs-btn-active-bg: #c2e3dd; --bs-btn-active-border-color: #7ec3ba;
  --bs-btn-active-color: var(--pastel-teal-fg);
  --bs-btn-focus-shadow-rgb: 15, 118, 110;
}
.text-primary { color: #0f766e !important; }
.bg-primary { background-color: #0f766e !important; }
.link-primary { color: #0f766e !important; }
.form-control:focus, .form-select:focus {
  border-color: #5bb3aa; box-shadow: 0 0 0 .25rem rgba(15, 118, 110, .2);
}
.form-check-input:checked { background-color: #0f766e; border-color: #0f766e; }

/* Layout */
body { display: flex; flex-direction: column; min-height: 100vh; }
main { flex-grow: 1; padding-block: 2rem; }
.brandmark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; background: var(--town); color: #fff;
  font-weight: 700; border-radius: .4rem;
}
/* A two-level header: the top bar (brand + account), then a navigation band
   of its own underneath. */
.app-topbar { background: #fff; border-bottom: 1px solid #dee2e6; }
.app-brand .fw-bold { color: #161616; }
/* A vertical rule between the logo and the wording (the "official" logo block). */
.app-brand__text { border-left: 1px solid #d5d9dd; padding-left: .75rem; }
.app-account { color: var(--town); font-weight: 500; }
.app-account:hover { color: var(--town-dark); }
.app-nav { background: #fff; border-bottom: 1px solid #dee2e6; box-shadow: 0 2px 4px rgba(0, 0, 0, .04); }
.app-nav__link {
  color: #161616; padding: .85rem 1rem; border-radius: 0;
  border-bottom: 3px solid transparent; margin-bottom: -1px;
}
.app-nav__link:hover { color: var(--town); background: #f5f6f6; }
.app-nav__link.active {
  color: var(--town) !important; font-weight: 500;
  border-bottom-color: var(--town); background: transparent;
}
.nav-link.active { color: var(--town) !important; }
/* Category tabs: the dropdown joins onto its own tab. */
.app-nav .dropdown-menu {
  margin-top: -1px; border-color: #dee2e6; border-radius: 0 0 .4rem .4rem;
  box-shadow: 0 4px 10px rgba(0, 0, 0, .06);
}
.app-nav .dropdown-item.active,
.app-nav .dropdown-item:active {
  background: var(--pastel-teal); color: var(--pastel-teal-fg);
}
.app-nav .dropdown-item:hover:not(.disabled) { background: #f5f6f6; color: var(--town); }
/* On mobile (collapsed menu) the dropdown renders flat, with no frame. */
@media (max-width: 991.98px) {
  .app-nav .dropdown-menu { border: 0; box-shadow: none; padding-left: 1rem; }
}

/* Icons (Bootstrap Icons): dots and buttons, in the town's colours. */
/* The icon badge of a tile: a rounded square filled with a pastel hue, the icon
   in the dark version of the same hue. The hue changes from one tile to the
   next (rotation below). Beside the text on the home page, above it on the
   dashboard, whose tiles are half as many per row and can afford the height. */
.tile__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.9rem; height: 2.9rem; margin-bottom: .8rem; font-size: 1.45rem;
  border: 0; border-radius: .9rem;
  background: var(--pastel-teal); color: var(--pastel-teal-fg);
}
.tile--soon .tile__icon { background: var(--pastel-grey); color: var(--pastel-grey-fg); }
/* Rotating through the pastel hues: peach, cream, lavender, teal, pink, blue
   — the "coming soon" tiles stay grey (excluded). */
.row > div:nth-of-type(6n+1) .tile:not(.tile--soon) .tile__icon { background: var(--pastel-amber);  color: var(--pastel-amber-fg); }
.row > div:nth-of-type(6n+2) .tile:not(.tile--soon) .tile__icon { background: var(--pastel-yellow); color: var(--pastel-yellow-fg); }
.row > div:nth-of-type(6n+3) .tile:not(.tile--soon) .tile__icon { background: var(--pastel-purple); color: var(--pastel-purple-fg); }
.row > div:nth-of-type(6n+4) .tile:not(.tile--soon) .tile__icon { background: var(--pastel-teal);   color: var(--pastel-teal-fg); }
.row > div:nth-of-type(6n+5) .tile:not(.tile--soon) .tile__icon { background: var(--pastel-pink);   color: var(--pastel-pink-fg); }
.row > div:nth-of-type(6n+6) .tile:not(.tile--soon) .tile__icon { background: var(--pastel-blue);   color: var(--pastel-blue-fg); }
.tile { transition: border-color .12s, box-shadow .12s; }
.tile:hover { border-color: var(--town); box-shadow: 0 2px 10px rgba(15, 118, 110, .10); }
.list-group-item .bi { color: #495057; }
.list-group-item[aria-current="page"] .bi, .app-account .bi { color: inherit; }

/* Small pill tags (soft capitals): "à venir", statuses… */
.tag {
  display: inline-block; font-size: .7rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .03em;
  padding: .2rem .6rem; border-radius: 1rem; line-height: 1.4;
}
.tag-soon   { background: var(--pastel-grey);   color: var(--pastel-grey-fg); }
.tag-info   { background: var(--pastel-teal);   color: var(--pastel-teal-fg); }
.tag-warn   { background: var(--pastel-amber);  color: var(--pastel-amber-fg); }
.tag-ok     { background: var(--pastel-green);  color: var(--pastel-green-fg); }
.tag-danger { background: var(--pastel-red);    color: var(--pastel-red-fg); }
.tag-blue   { background: var(--pastel-blue);   color: var(--pastel-blue-fg); }
.tag-purple { background: var(--pastel-purple); color: var(--pastel-purple-fg); }
.tag-pink   { background: var(--pastel-pink);   color: var(--pastel-pink-fg); }
/* Audit log: a compact, collapsible detail of the changes. */
.audit td { vertical-align: top; }
.audit details summary { cursor: pointer; }

.list-group-item[aria-current="page"] {
  background-color: var(--town); border-color: var(--town); color: #fff; z-index: 2;
}

/* "Dans ma rue": status dots + maps */
.diamond { color: #dc3545; }
.dot { display: inline-block; width: .7rem; height: .7rem; border-radius: 50%; margin-right: .3rem; }
.dot-nouveau { background: #ce0500; }
.dot-en_cours { background: #b34000; }
.dot-resolu { background: #18753c; }
#map { height: 65vh; border: 1px solid #ced4da; }
#mini-map { height: 40vh; border: 1px solid #ced4da; }
#position { height: 30vh; border: 1px solid #ced4da; }
.thumbnail { width: 72px; height: 54px; object-fit: cover; border: 1px solid #ced4da; border-radius: .25rem; }
.report-photo { max-width: 100%; border: 1px solid #ced4da; }
.leaflet-container a { background-image: none; box-shadow: none; }

/* Room schedules: the times of day (shared colours) */
.cal .ev.morning,.wk .ev.morning,.ov .ev.morning{background:#fff3d4;border-left-color:#d68a00}
.cal .ev.afternoon,.wk .ev.afternoon,.ov .ev.afternoon{background:#e8edff;border-left-color:#1d4ed8}
.cal .ev.evening,.wk .ev.evening,.ov .ev.evening{background:#fff0e6;border-left-color:#b34700}
.cal .ev.night,.wk .ev.night,.ov .ev.night{background:#ece9f7;border-left-color:#6a4fb3}
.cal .ev.allday,.wk .ev.allday,.ov .ev.allday{background:#e3f4e8;border-left-color:#18753c}
.wk-band{z-index:0}
.wk-band-morning{background:rgba(214,138,0,.09)}
.wk-band-afternoon{background:rgba(29,78,216,.05)}
.wk-band-evening{background:rgba(179,71,0,.08)}
.wk-band-night{background:rgba(106,79,179,.09)}
/* A column booked for the whole day: green hatching over the full height. */
.wk-fullday{z-index:1;pointer-events:none;
  background:repeating-linear-gradient(45deg,rgba(24,117,60,.13) 0 7px,rgba(24,117,60,.03) 7px 14px)}
.pl-legend{display:flex;gap:1rem;flex-wrap:wrap;align-items:center;margin:.35rem 0}
.pl-legend span{white-space:nowrap}
.pl-sw{display:inline-block;width:.85rem;height:.85rem;border-radius:2px;vertical-align:-2px;border-left:3px solid}
.pl-sw.morning{background:#fff3d4;border-left-color:#d68a00}
.pl-sw.afternoon{background:#e8edff;border-left-color:#1d4ed8}
.pl-sw.evening{background:#fff0e6;border-left-color:#b34700}
.pl-sw.night{background:#ece9f7;border-left-color:#6a4fb3}
.pl-sw.allday{background:#e3f4e8;border-left-color:#18753c}

/* --- Back office: diary sources ------------------------------------------ */
/* A feed's address can be a query several hundred characters long with no
   space in it. Without column widths, the browser squashed the "Source"
   column until the URL broke character by character. */
.srcs__name     { width: 38%; }
.srcs__type    { width: 17%; }
.srcs__town { width: 13%; }
.srcs__state    { width: 20%; }
.srcs__actions { width: 12%; }
.srcs__url { display: block; overflow-wrap: anywhere; }
.srcs__row--error > td { border-bottom-width: 0; }
.srcs__detail > td { padding-top: 0; }
/* The technical detail takes the full width: on a single row it overflowed the
   table and ended up cut off on screen. */
.srcs__error {
  display: flex; gap: .5rem; align-items: flex-start;
  background: var(--pastel-red); color: var(--pastel-red-fg);
  border-radius: 6px; padding: .5rem .7rem; font-size: .85rem;
}
.srcs__error-msg {
  overflow-wrap: anywhere; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .78rem; margin-top: .15rem;
}

/* --- Back office: access to the modules ---------------------------------- */
/* One row per capability rather than three columns: in the back office's
   usable width, columns stretched every module over the full height. */
.access-grid { display: grid; grid-template-columns: 8.5rem 1fr; gap: .3rem .9rem; }
.access-grid dt { font-weight: 600; font-size: .85rem; padding-top: .15rem; }
.access-grid dd { margin: 0; display: flex; flex-wrap: wrap; gap: .3rem; font-size: .9rem; }
@media (max-width: 575.98px) {
  .access-grid { grid-template-columns: 1fr; gap: .1rem; }
  .access-grid dd { margin-bottom: .4rem; }
}
.chip {
  display: inline-flex; align-items: center; gap: .1rem;
  background: var(--pastel-teal); color: var(--pastel-teal-fg);
  border-radius: 999px; padding: .05rem .15rem .05rem .6rem; font-size: .85rem;
}
.chip__x {
  border: 0; background: none; color: inherit; opacity: .65;
  line-height: 1; padding: .1rem .3rem; cursor: pointer; border-radius: 999px;
}
.chip__x:hover, .chip__x:focus-visible { opacity: 1; background: rgba(0, 0, 0, .1); }

/* The published agenda (/reunions/): a column of dates the eye can run down,
   and the entry beside it. The month heading carries the month and the year, so
   each row repeats only the day — under "août 2026", "18" is unambiguous, while
   "18 août 2026" three lines running is not read, it is skipped. */
.agenda__month {
  margin: 1.75rem 0 .25rem; font-size: .8rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--pastel-grey-fg);
}
.agenda { margin-bottom: 0; }
.agenda__item {
  display: flex; gap: 1rem; align-items: baseline;
  padding: .8rem 0; border-top: 1px solid #e9ecef;
}
/* A fixed width, so the day numbers line up from one month to the next. */
.agenda__date { flex: 0 0 2.75rem; text-align: center; line-height: 1.15; }
.agenda__dow { display: block; font-size: .75rem; color: var(--pastel-grey-fg); }
.agenda__day { display: block; font-size: 1.5rem; font-weight: 600; color: var(--town); }
.agenda__body { min-width: 0; }  /* lets a long address wrap instead of stretching the row */
.agenda__title { margin: 0 0 .1rem; font-size: 1rem; font-weight: 600; }
.agenda__meta { margin: 0; font-size: .925rem; color: #55606b; }
/* The postal address Outlook appends: kept, but never competing with the name
   of the meeting itself. */
.agenda__detail { display: block; font-size: .825rem; color: #6c757d; }
.agenda__desc { margin: .25rem 0 0; font-size: .925rem; color: #55606b; }
/* Which of the two calendars an entry came from, shown only when the page
   mixes them. Quiet on purpose: a tint from the pastel palette, sized to sit
   inside the meta line rather than compete with the title. */
.agenda__source, .agenda__flag {
  display: inline-block; padding: 0 .45em; border-radius: .5rem;
  font-size: .75rem; font-weight: 600;
}
.agenda__source--municipale { background: var(--pastel-teal); color: var(--pastel-teal-fg); }
.agenda__source--evenements { background: var(--pastel-amber); color: var(--pastel-amber-fg); }
/* A marker staff wrote in the calendar ("[Evénement public]"), turned into a
   chip. Green, because it is an invitation — the one thing the page's header
   says a listed meeting is not by default. */
.agenda__flag--public { background: var(--pastel-green); color: var(--pastel-green-fg); }
/* The same origin, said in colour: a bar down the entry's left edge, because
   a word in the meta line is not read when the eye scans dates. Teal is the
   town, amber is local life, and the bar stays on the filtered pages so each
   keeps its colour identity. The amber is deliberately brighter than the
   badge's text tone (--pastel-amber-fg): both bars read dark when thin, and
   two dark stripes are the same stripe at a glance. The width was raised
   twice on the owner's eye — colour and width were both needed before the
   bars carried at arm's length on a phone. */
.agenda__item--municipale, .agenda__item--evenements { padding-left: .75rem; }
.agenda__item--municipale { border-left: 6px solid var(--town); }
.agenda__item--evenements { border-left: 6px solid #e8940a; }
/* The three addresses of the same agenda; the current one is plain text. */
.agenda__filters { font-size: .925rem; color: var(--pastel-grey-fg); }

/* Alerts: a white box with a coloured rule, the icon in a filled block of the
   same colour and white on it. That shape is the one the French
   administration's design system uses for its small, non-dismissible alerts —
   the staff meet it on every other public service they deal with, so it reads
   as "notice" before a word is read.
   Only the shape is taken. The colours stay the portal's: teal for information
   rather than the State's blue, and the red, amber and green are already
   "Dans ma rue"'s status colours, three declarations above. */
.alert {
  --alert-accent: #929292;
  background: #fff; border: 1px solid var(--alert-accent);
  color: #161616; border-radius: .25rem;
}
.alert-danger    { --alert-accent: #ce0500; }
.alert-warning   { --alert-accent: #b34000; }
.alert-success   { --alert-accent: #18753c; }
.alert-info      { --alert-accent: var(--town); }
.alert-secondary { --alert-accent: #929292; }
.alert-light     { --alert-accent: #cdd2d7; }
/* The icon is the only thing that carries the colour, so the message itself
   stays plain text on white and long copy does not sit on a tinted ground. */
.alert > .bi:first-child {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; width: 2rem; height: 2rem; border-radius: .2rem;
  background: var(--alert-accent); color: #fff; font-size: 1rem;
}
.alert .alert-link { color: var(--alert-accent); }
