/* 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}

/* The compact iframe keeps its own layout; the full agenda uses agenda.css.
   Month headings carry the year so individual rows can show only the day. */
.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 iframe does not load Bootstrap, so it needs its own list reset. */
.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);
}
.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); }
