/* 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;
  /* Neutrals, taken from the town's own design system for its website so the
     two read as one authority's work: a near-black for a rule that has to be
     seen, the hairline between rows, the tint behind a hovered one, and the
     grey of a secondary line. The identity colour is NOT taken from there —
     the teal above stays the town's, and no font moves. */
  --ink: #181818;
  --line: #d6dce1;
  --surface: #f2f4f6;
  --muted: #4f5a63;
}
/* 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);
}
/* 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 .tile__icon { background: var(--pastel-amber);  color: var(--pastel-amber-fg); }
.row > div:nth-of-type(6n+2) .tile .tile__icon { background: var(--pastel-yellow); color: var(--pastel-yellow-fg); }
.row > div:nth-of-type(6n+3) .tile .tile__icon { background: var(--pastel-purple); color: var(--pastel-purple-fg); }
.row > div:nth-of-type(6n+4) .tile .tile__icon { background: var(--pastel-teal);   color: var(--pastel-teal-fg); }
.row > div:nth-of-type(6n+5) .tile .tile__icon { background: var(--pastel-pink);   color: var(--pastel-pink-fg); }
.row > div:nth-of-type(6n+6) .tile .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;
}


/* 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 (/agenda/): a column of dates the eye can run down, and
   the entry beside it. The column is the decision this layout is built around
   rather than in place of — a grid of tiles would read left-to-right and lose
   the chronology, which is the one thing an agenda is for. 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.

   Square throughout, and flat: rules between the rows rather than boxes round
   them, a bordered box for the date, no rounded corner anywhere. That is the
   shape the owner asked for, against the look the town's own agenda is moving
   to — and it is why the row gives up its outline, since a boxed row around a
   boxed date is a box in a box and the date is the one that has to carry. */
.agenda-page { max-width: 60rem; }
.agenda__notice {
  display: flex; gap: .5rem; margin: .9rem 0 0; padding: .6rem .8rem;
  background: var(--pastel-grey);
  font-size: .925rem; color: var(--pastel-grey-fg);
}
.agenda__notice .bi { flex-shrink: 0; margin-top: .15rem; }
/* The three addresses of the same agenda, as a segmented control: the current
   one is filled and not a link, which is also what `aria-current` says for
   anything that cannot see the fill. Square, like everything else on this
   page — the shape was settled on the owner's eye against the look the town's
   own agenda is moving to, and a row of pills was the one thing in it that
   read as a different family. */
.agenda__filters { display: flex; flex-wrap: wrap; gap: .35rem; margin: 1.25rem 0 0; }
.agenda__filter {
  padding: .3rem .9rem; border: 1px solid var(--line);
  font-size: .9rem; font-weight: 600; text-decoration: none;
  background: #fff; color: var(--pastel-grey-fg);
}
a.agenda__filter:hover, a.agenda__filter:focus-visible {
  border-color: var(--town); color: var(--town-dark);
}
.agenda__filter--on { background: var(--ink); border-color: var(--ink); color: #fff; }
.agenda__section { margin-top: 2rem; }
.agenda__section-title { margin: 0 0 .25rem; font-size: 1.35rem; font-weight: 700; }
.agenda__month {
  margin: 1.5rem 0 .4rem; font-size: .8rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--pastel-grey-fg);
}
/* The list reset is here rather than borrowed from Bootstrap's
   `.list-unstyled`: the embeddable page (/agenda/integration/) loads this
   stylesheet without Bootstrap's, and a widget in somebody else's page is not
   worth 200 kB of framework. The class stays in the markup, harmlessly, for
   the portal's own pages. */
.agenda {
  display: flex; flex-direction: column;
  margin-bottom: 0; padding-left: 0; list-style: none;
}
/* Rules between the rows, not boxes around them. A boxed card and a boxed date
   put a box inside a box, and the date is the one that has to carry — so the
   row gives up its own outline and keeps a hairline above it. Nothing here is
   rounded: that is the shape, settled on the owner's eye. */
.agenda__item {
  display: flex; gap: 1rem; align-items: flex-start;
  padding: .85rem 0; border-top: 1px solid var(--line);
  transition: background-color .15s;
}
.agenda__item:hover { background: var(--surface); }
/* A fixed width, so the day numbers line up from one month to the next. */
.agenda__date {
  flex: 0 0 3.5rem; text-align: center; line-height: 1.1;
  padding: .35rem 0; border: 1px solid var(--ink);
}
.agenda__dow {
  display: block; font-size: .7rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--muted);
}
.agenda__day { display: block; font-size: 1.6rem; font-weight: 700; color: var(--town); }
.agenda__body { min-width: 0; }  /* lets a long address wrap instead of stretching the row */
.agenda__title { margin: 0; font-size: 1.05rem; font-weight: 600; }
/* A flex row, which is what disposes of the blank gaps the single-sentence
   version printed wherever one of its conditional branches was false:
   whitespace-only text between flex items is ignored, so the gaps ARE the
   separators and none of them has to be conditional. */
.agenda__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .8rem;
  margin: .2rem 0 0; font-size: .9rem; color: #55606b;
}
.agenda__when, .agenda__where { display: inline-flex; align-items: center; gap: .3rem; }
.agenda__when { font-weight: 600; color: #3d4852; }
.agenda__meta .bi { color: var(--pastel-grey-fg); }
/* The postal address Outlook appends: kept, but never competing with the name
   of the meeting itself. */
.agenda__detail { margin: .15rem 0 0; font-size: .825rem; color: #6c757d; }
.agenda__desc { margin: .35rem 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: .1em .5em;
  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); }
/* Today, which is the question most visitors arrive with. Said by a filled
   chip and a whisper of the teal behind the card — not by the border, which
   already carries the calendar's colour and must keep it. */
.agenda__flag--today { background: var(--town); color: #fff; }
.agenda__item--today, .agenda__item--today:hover { background: #f2faf8; }
.agenda__item--today .agenda__date { background: var(--pastel-teal); }
/* 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; }
.agenda__item--evenements .agenda__day { color: var(--pastel-amber-fg); }
/* The poster an event brought from the town website. Last in the markup — the
   title and the time come first for a screen reader — and pulled to the end of
   the row by `order`, so on a wide screen it sits where a thumbnail belongs
   without the document saying it matters more than the text. `object-fit`
   because these are the town's own posters, in whatever shape the person who
   made them chose. */
.agenda__image {
  flex: 0 0 auto; order: 3; align-self: flex-start;
  width: 7.5rem; height: 5rem; object-fit: cover;
  background: var(--pastel-grey);
}
/* Twelve months of history, folded away. <details> does it without a line of
   JavaScript and keeps the entries in the document, so the browser's own
   search still finds them. The marker is drawn here because `display: flex` on
   a summary drops the native triangle. */
.agenda__past { margin-top: 2.5rem; border-top: 2px solid var(--ink); padding-top: 1rem; }
.agenda__past > summary {
  display: flex; align-items: center; gap: .6rem;
  cursor: pointer; list-style: none;
}
.agenda__past > summary::-webkit-details-marker { display: none; }
.agenda__past > summary::after {
  content: ""; flex: 0 0 auto; width: .45rem; height: .45rem;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(-45deg); transition: transform .15s;
}
.agenda__past[open] > summary::after { transform: rotate(45deg); }
.agenda__count {
  padding: .1em .55em;
  background: var(--pastel-grey); color: var(--muted);
  font-size: .8rem; font-weight: 600;
}
.agenda__empty, .agenda__freshness { font-size: .9rem; color: var(--pastel-grey-fg); }
.agenda__freshness { margin-top: 2.5rem; }
/* In the field, on a phone, checking tonight's meeting: the row keeps its
   shape, the date column gives back what it can. */
@media (max-width: 575.98px) {
  .agenda__item { padding: .7rem 0; gap: .75rem; }
  .agenda__date { flex-basis: 3rem; }
  .agenda__day { font-size: 1.4rem; }
  /* Kept, not hidden: a poster is most of what makes a fête worth reading
     about, and the phone is where the page is read. Just smaller. */
  .agenda__image { width: 4.5rem; height: 3rem; }
}

/* 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 the pastel
   palette's, defined on `:root`. */
.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); }
