/* ═══════════════════════════════════════════════════════════
   CŒUR ASTRAL - NUIT ÉDITORIALE SHELL (ALS-1055)
   ═══════════════════════════════════════════════════════════

   App shell of the redesign: member masthead (64px desktop, 56px top bar
   on mobile), mobile tab bar and Menu sheet, account and « Plus » menus,
   language dialog rows, colophon, guest band, plus the v2 look and
   offsets of the cookie card, PWA bar and reCAPTCHA badge. Markup lives
   in templates/common/v2/, behaviour in js/v2/shell.js.

   Loaded on every base.html page, after modal.css. Every selector starts
   with `.ui-v2 ` or `body.ui-v2`; the legacy stylesheets
   (cookie-consent.css, pwa-install.css, style.css) stay untouched.
   Mobile-first: 1024px
   switches top bar + tab bar to the masthead, 1280px widens the nav,
   600px stacks the colophon and 768px is the legacy chat breakpoint.

   Legacy rules beaten here (each override says which one):
   - Materialize 1.0.0: nav { height 56/64px; line-height 56/64px;
     color #fff; width 100% }, nav ul a { display block; padding 0 15px;
     font-size 1rem; color #fff } and button:focus { background-color
     #2ab7a9 }. So .ca-*__nav resets height, line-height and colour, and
     every v2 button restates its background on :focus.
   - materialize-override.css:500-503 forces nav { background-color:
     transparent !important }, so chrome backgrounds sit on the header
     and the tab bar <div>, never on a <nav>.
   - style.css:73-120 sets font, colour and margins on a, p and span, and
     style.css:234-236 pads body.user-authenticated with the legacy header
     height. Shell parts set font, colour and margin explicitly, and the
     body offsets read --ca-header-height and --ca-bottom-inset only.
   - The hidden attribute is the only switch of nav items, overflow rows
     and popovers: no rule here sets display on them, and a safety rule
     keeps [hidden] hidden inside the masthead and the tab bar.

   !important appears only in the .ui-v2 .grecaptcha-badge rule: Google
   writes position, right and bottom inline on the reCAPTCHA badge, and
   only !important brings it back into the page flow (ALS-1190).

   --ca-bottom-offset is the height of the visible bottom chrome (the tab
   bar under 1024px, else 0). Every bottom-anchored overlay adds it.
   --ca-bottom-inset is the bottom padding the body reserves for that
   chrome. It equals the offset, except while the keyboard hides the
   chrome: the padding stays, and so does the inset. In-flow boxes sized
   to the viewport (.ca-layout, the chat) subtract the inset, so opening
   the keyboard never makes the page taller. */

/* ─────────────────────────────────────────────────────────────
   CHROME OFFSETS
   The fixed masthead pads members' pages; the guest band and the guest
   preview of the styleguide stay in flow. Under 1024px the tab bar adds
   its own clearance. It hides while the on-screen keyboard is open, and
   while a chat conversation fills the screen (768px and under, where
   css/v2/chat.css switches to its one-pane layout).
   ───────────────────────────────────────────────────────────── */
body.ui-v2 {
  --ca-bottom-offset: 0px;
  --ca-bottom-inset: 0px;
}

/* Beats style.css:234-236, which reads the legacy header height. */
body.ui-v2.user-authenticated {
  padding-top: var(--ca-header-height);
}

body.ui-v2.user-authenticated:has(> .ca-shell-guest) {
  padding-top: 0;
}

@media (max-width: 1023.98px) {
  body.ui-v2:has(.ca-tabbar) {
    --ca-bottom-offset: var(--tabbar-height);
    --ca-bottom-inset: var(--tabbar-height);
    padding-bottom: var(--ca-bottom-inset);
  }

  /* shell.js sets .ca-keyboard-open while a field has the keyboard up.
     Overlays drop to the bottom edge; the body keeps its padding (the
     inset) so the page does not jump under the field being typed in. */
  body.ui-v2.ca-keyboard-open:has(.ca-tabbar) {
    --ca-bottom-offset: 0px;
  }

  body.ui-v2.ca-keyboard-open .ca-tabbar {
    display: none;
  }
}

/* A conversation fills the viewport only in the chat's one-pane layout
   (css/v2/chat.css, 768px): from 769 to 1023px the list stays beside
   it, so the tab bar stays too. */
@media (max-width: 768px) {
  body.ui-v2:has(.chat-layout.chat-active) {
    --ca-bottom-offset: 0px;
    --ca-bottom-inset: 0px;
  }

  body.ui-v2:has(.chat-layout.chat-active) .ca-tabbar {
    display: none;
  }
}

/* Safety net: no shell rule may reveal an element the JS hid. */
.ui-v2 .ca-shell [hidden],
.ui-v2 .ca-tabbar [hidden] {
  display: none;
}

/* ─────────────────────────────────────────────────────────────
   PAGE LAYOUT - colophon at the viewport bottom on short pages (ALS-1190)
   base.html wraps the page in .ca-layout__page and ends .ca-layout after
   the colophon. The layout is at least the viewport minus the chrome the
   body pads (masthead or guest band, tab bar), and the page grows to fill
   it. Only these two wrappers are flex items: page roots keep block flow,
   so their margin: 0 auto and max-width still work. Never put overflow on
   them, so sticky sidebars (Recherche) keep the viewport as scroller.
   ───────────────────────────────────────────────────────────── */
body.ui-v2 .ca-layout {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - var(--ca-header-height) - var(--ca-bottom-inset));
  min-height: calc(100dvh - var(--ca-header-height) - var(--ca-bottom-inset));
}

/* Guests: the in-flow guest band replaces the fixed masthead. */
body.ui-v2 .ca-shell-guest ~ .ca-layout {
  min-height: calc(100vh - var(--ca-guest-header-height) - var(--ca-bottom-inset));
  min-height: calc(100dvh - var(--ca-guest-header-height) - var(--ca-bottom-inset));
}

body.ui-v2 .ca-layout__page {
  flex: 1 0 auto;
}

body.ui-v2 .ca-layout > .ca-colophon {
  flex: none;
}

/* ─────────────────────────────────────────────────────────────
   SKIP LINK - « Aller au contenu », visible on focus only
   The anchor is a zero-height span focused through the fragment, so it
   draws no ring and lands clear of the fixed masthead.
   ───────────────────────────────────────────────────────────── */
/* Parked above the viewport, over the masthead once focused. */
.ui-v2 .ca-skip {
  position: fixed;
  left: var(--sp-16);
  top: -64px;
  z-index: calc(var(--layer-chrome) + 1);
  padding: var(--sp-12) var(--sp-20);
  border-radius: var(--r-pill);
  background-color: var(--surface-2);
  color: var(--ivory-100);
  font: 600 14px/20px var(--font-ui);
  text-decoration: none;
}

.ui-v2 .ca-skip:focus {
  top: var(--sp-12);
}

.ui-v2 .ca-main-anchor {
  display: block;
  height: 0;
  scroll-margin-top: var(--ca-header-height);
}

.ui-v2 .ca-main-anchor:focus {
  outline: none;
}

/* ─────────────────────────────────────────────────────────────
   MASTHEAD - fixed ink band with a 4px brand strip and a gold rule
   Under 1024px it is the 56px top bar (logo, ✦ pill, bell); from
   1024px the 64px masthead adds the primary nav and the account menu.
   ───────────────────────────────────────────────────────────── */
.ui-v2 .ca-shell {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--layer-chrome);
  height: var(--ca-header-height);
  box-sizing: border-box;
  background-color: var(--masthead-strong);
  -webkit-backdrop-filter: blur(var(--blur-chrome));
  backdrop-filter: blur(var(--blur-chrome));
  border-bottom: 1px solid var(--rule-masthead);
  color: var(--ivory-300);
  font-family: var(--font-ui);
}

.ui-v2 .ca-shell::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--sp-4);
  background: var(--gradient-brand);
  pointer-events: none;
}

@media (min-width: 1024px) {
  .ui-v2 .ca-shell {
    background-color: var(--masthead);
    -webkit-backdrop-filter: blur(var(--blur-chrome)) saturate(140%);
    backdrop-filter: blur(var(--blur-chrome)) saturate(140%);
  }
}

/* Opaque ink when the user asks for less transparency or the browser
   cannot blur: text keeps its contrast over any page. */
@media (prefers-reduced-transparency: reduce) {
  .ui-v2 .ca-shell {
    background-color: var(--masthead-solid);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ui-v2 .ca-shell {
    background-color: var(--masthead-solid);
  }
}

/* The top padding keeps content clear of the brand strip. */
.ui-v2 .ca-shell__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-8);
  box-sizing: border-box;
  max-width: var(--container-wide);
  height: 100%;
  margin: 0 auto;
  padding: var(--sp-4) var(--sp-8) 0 var(--sp-16);
}

.ui-v2 .ca-shell__logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-width: 44px;
  height: 44px;
}

.ui-v2 .ca-shell__logo-img {
  display: block;
  width: auto;
  height: 32px;
}

/* Members reach the nav and the account menu through the tab bar and
   its Menu sheet under 1024px. */
.ui-v2 .ca-shell__nav,
.ui-v2 .ca-shell__account {
  display: none;
}

/* Under 1024px a « Retour » link may lead the top bar: back and logo
   stay together on the left, the actions on the right. */
@media (max-width: 1023.98px) {
  .ui-v2 .ca-shell__bar:has(.ca-shell__back) {
    padding-left: var(--sp-4);
  }

  .ui-v2 .ca-shell__back + .ca-shell__logo {
    margin-right: auto;
  }
}

@media (min-width: 1024px) {
  .ui-v2 .ca-shell__bar {
    gap: var(--sp-32);
    padding: var(--sp-4) var(--sp-32) 0;
  }

  /* Approved desktop mockups: 40px in the 64px masthead. */
  .ui-v2 .ca-shell__logo-img {
    height: 40px;
  }

  /* Materialize nav reset: height, line-height, width and colour. */
  .ui-v2 .ca-shell__nav {
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    width: auto;
    line-height: normal;
    color: inherit;
    background: none;
    box-shadow: none;
  }

  .ui-v2 .ca-shell__account {
    display: block;
    position: relative;
  }
}

@media (min-width: 1280px) {
  .ui-v2 .ca-shell__bar {
    padding: var(--sp-4) var(--sp-48) 0;
  }
}

/* Priority+ list. Without JS it scrolls sideways; once shell.js has
   moved what does not fit into « Plus », it lets the popover overflow.
   It fills the nav so its width is the room the links can use. */
.ui-v2 .ca-shell__links {
  display: flex;
  flex: 1 1 auto;
  align-items: stretch;
  gap: 20px;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}

.ui-v2 .ca-shell__links[data-ca-priority="ready"] {
  overflow: visible;
}

@media (min-width: 1280px) {
  .ui-v2 .ca-shell__links {
    gap: 32px;
  }
}

/* No display here: shell.js toggles [hidden] on these items. */
.ui-v2 .ca-shell__item {
  position: relative;
  flex: none;
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Beats Materialize nav ul a (block, 0 15px padding, 1rem white). */
.ui-v2 .ca-shell__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: transparent;
  color: var(--ivory-300);
  font: 500 var(--fs-nav)/var(--lh-nav) var(--font-ui);
  letter-spacing: var(--ls-nav);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--dur-1) var(--ease-out);
}

/* Beats Materialize button:focus { background-color: #2ab7a9 }. */
.ui-v2 .ca-shell__link:focus {
  background-color: transparent;
}

.ui-v2 .ca-shell__link:hover {
  color: var(--ivory-100);
}

/* Current page: ivory label over a 2px violet bar. shell.js puts
   .is-current and aria-current on « Plus » when the current entry sits
   in its menu. */
.ui-v2 .ca-shell__link[aria-current="page"],
.ui-v2 .ca-shell__link.is-current {
  color: var(--ivory-100);
}

.ui-v2 .ca-shell__link[aria-current="page"]::after,
.ui-v2 .ca-shell__link.is-current::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: var(--r-pill);
  background: var(--violet-400);
}

.ui-v2 .ca-shell__chevron {
  display: inline-flex;
  font-size: 0;
  line-height: 0;
  transition: transform var(--dur-1) var(--ease-out);
}

.ui-v2 .ca-shell__more-button[aria-expanded="true"] .ca-shell__chevron {
  transform: rotate(180deg);
}

/* --dur-1 stays 120ms under reduced motion for fades only: the chevron
   flips without turning. */
@media (prefers-reduced-motion: reduce) {
  .ui-v2 .ca-shell__chevron {
    transition: none;
  }
}

/* The legacy « Premium » bar link: a gold crown before the label, like
   the account menu's premium row (its « Plus » twin reuses
   .ca-menu__item--premium). */
.ui-v2 .ca-shell__link--premium .ca-icon {
  color: var(--gold-400);
}

/* Unread conversations: a 6px pink dot after « Échanges », in the bar
   and in the « Plus » menu, and after « Plus » while an unread Échanges
   sits in its menu; the text equivalent is a sr-only suffix. */
.ui-v2 .ca-unread-dot {
  display: inline-block;
  flex: none;
  width: 6px;
  height: 6px;
  margin-left: 6px;
  border-radius: var(--r-pill);
  background-color: var(--rose-500);
}

/* Popovers. .ca-menu caps max-width at 100% of its anchor, which is only
   the « Plus » item or the 44px avatar here. Both open just under the
   masthead: in a short viewport they stop above the bottom edge and
   scroll their rows. */
.ui-v2 .ca-shell__menu {
  position: absolute;
  top: calc(100% + var(--sp-8));
  right: 0;
  max-width: none;
  max-height: calc(100vh - var(--ca-header-height) - var(--sp-16));
  max-height: calc(100dvh - var(--ca-header-height) - var(--sp-16));
  overflow-y: auto;
}

.ui-v2 .ca-shell__more-menu {
  top: 100%;
  width: max-content;
  min-width: 220px;
  max-width: 320px;
}

.ui-v2 .ca-shell__account-menu {
  width: 300px;
}

/* « Voir mon profil »: a violet link under the first name, aligned with
   it (header padding 12 + avatar 48 + gap 12) rather than a full row. */
.ui-v2 .ca-shell__profile-link {
  margin-top: calc(-1 * var(--sp-12));
  padding-left: calc(var(--sp-12) * 2 + 48px);
  color: var(--violet-400);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.ui-v2 .ca-shell__menu-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Rows only: separators keep their components.css margin. No display:
   overflow rows are toggled with [hidden]. */
.ui-v2 .ca-shell__menu-list > li:not(.ca-menu__sep) {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Current page inside a menu, the sheet or the overflow list. */
.ui-v2 .ca-menu__item[aria-current="page"] {
  background-color: var(--violet-tint);
}

.ui-v2 .ca-shell__actions {
  display: flex;
  align-items: center;
  flex: none;
  gap: 2px;
}

@media (min-width: 1024px) {
  .ui-v2 .ca-shell__actions {
    gap: var(--sp-8);
  }
}

.ui-v2 .ca-shell__icon-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  background-color: transparent;
  color: var(--ivory-300);
  text-decoration: none;
}

.ui-v2 .ca-shell__icon-button:hover {
  background-color: var(--wash-hover);
  color: var(--ivory-100);
}

/* Bell badge, also when notifications-ws.js creates it. Restates every
   property of style.css:2157-2170 .notification-badge; display stays
   with the script, which toggles it inline. */
.ui-v2 .ca-shell__bell .notification-badge {
  position: absolute;
  top: 5px;
  right: 3px;
  box-sizing: border-box;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--gold-400);
  color: var(--night-900);
  font: 600 var(--fs-badge)/var(--lh-badge) var(--font-ui);
  font-variant-numeric: tabular-nums;
  text-align: center;
  box-shadow: 0 0 0 2px var(--night-900);
}

/* « Retour » leads the top bar of pages without a tab bar; the masthead
   offers the full nav from 1024px. */
@media (min-width: 1024px) {
  .ui-v2 .ca-shell__back {
    display: none;
  }
}

.ui-v2 .ca-shell__avatar-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: var(--r-pill);
  background-color: transparent;
  cursor: pointer;
}

/* Beats Materialize button:focus { background-color: #2ab7a9 }. */
.ui-v2 .ca-shell__avatar-button:focus {
  background-color: transparent;
}

/* ─────────────────────────────────────────────────────────────
   TAB BAR - fixed bottom, five tabs, under 1024px
   No blur: at most one blurred chrome per viewport (spec elevation).
   ───────────────────────────────────────────────────────────── */
.ui-v2 .ca-tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--layer-chrome);
  box-sizing: border-box;
  height: var(--tabbar-height);
  padding-bottom: env(safe-area-inset-bottom);
  background-color: var(--tabbar-bg);
  border-top: 1px solid var(--rule-tabbar);
}

@media (min-width: 1024px) {
  .ui-v2 .ca-tabbar {
    display: none;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .ui-v2 .ca-tabbar {
    background-color: var(--masthead-solid);
  }
}

/* Materialize nav reset: height, line-height, width and colour. */
.ui-v2 .ca-tabbar__nav {
  height: 100%;
  width: auto;
  line-height: normal;
  color: inherit;
  background: none;
  box-shadow: none;
}

.ui-v2 .ca-tabbar__list {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui-v2 .ca-tabbar__item {
  min-width: 0;
  margin: 0;
  list-style: none;
}

/* Icon over a label of up to two lines; links and the Menu button
   share the look. Top-aligned so icons line up whatever the label's
   line count; 4px + 24 + 4 + 2 × 14 leaves 3px above the bottom edge. */
.ui-v2 .ca-tabbar__tab {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: var(--sp-4);
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  min-height: 44px;
  margin: 0;
  padding: var(--sp-4) 2px 0;
  border: 0;
  background-color: transparent;
  color: var(--ivory-500);
  font: 500 var(--fs-tabbar)/var(--lh-tabbar) var(--font-ui);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

/* Beats Materialize button:focus { background-color: #2ab7a9 }. */
.ui-v2 .ca-tabbar__tab:focus {
  background-color: transparent;
}

/* Inset ring: the bar's edges would clip an outer one. */
.ui-v2 .ca-tabbar__tab:focus-visible {
  outline-offset: -2px;
}

.ui-v2 .ca-tabbar__icon {
  position: relative;
  display: block;
  flex: none;
  width: 24px;
  height: 24px;
  font-size: 0;
  line-height: 0;
}

/* Unread conversations: 8px pink dot ringed with the bar's ink. */
.ui-v2 .ca-tabbar__dot {
  position: absolute;
  top: 0;
  right: -2px;
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  background-color: var(--rose-500);
  box-shadow: 0 0 0 2px var(--masthead-solid);
}

.ui-v2 .ca-tabbar__label {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: 100%;
  font-size: var(--fs-tabbar);
  line-height: var(--lh-tabbar);
  overflow-wrap: anywhere;
  hyphens: auto;
}

/* Current tab: ivory label, violet-300 icon and a 32×4 violet pill on
   the top edge. The Menu button gets .is-current when the page lives in
   its sheet. */
.ui-v2 .ca-tabbar__tab[aria-current="page"],
.ui-v2 .ca-tabbar__tab.is-current {
  color: var(--ivory-100);
}

.ui-v2 .ca-tabbar__tab[aria-current="page"] .ca-tabbar__icon,
.ui-v2 .ca-tabbar__tab.is-current .ca-tabbar__icon {
  color: var(--violet-300);
}

.ui-v2 .ca-tabbar__tab[aria-current="page"]::before,
.ui-v2 .ca-tabbar__tab.is-current::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 32px;
  height: 4px;
  margin-left: -16px;
  border-radius: 0 0 4px 4px;
  background: var(--violet-500);
}

/* ─────────────────────────────────────────────────────────────
   MENU SHEET & LANGUAGE ROWS - inside dialog.ca-modal (modal.css)
   Sheet rows reuse .ca-menu__item; each language row is a 48px submit
   button: autonym, code, gold check on the active one.
   ───────────────────────────────────────────────────────────── */
.ui-v2 .ca-menu-sheet__list,
.ui-v2 .ca-language-list {
  display: grid;
  gap: 2px;
  margin: var(--sp-16) 0 0;
  padding: 0;
  list-style: none;
}

/* Rows only: separators keep their components.css margin. */
.ui-v2 .ca-menu-sheet__list > li:not(.ca-menu__sep) {
  margin: 0;
}

.ui-v2 .ca-language-option {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 20px;
  align-items: center;
  gap: var(--sp-12);
  box-sizing: border-box;
  width: 100%;
  min-height: 48px;
  margin: 0;
  padding: 0 var(--sp-12);
  border: 0;
  border-radius: var(--r-sm);
  background-color: transparent;
  color: var(--ivory-100);
  font: 500 15px/20px var(--font-ui);
  text-align: left;
  cursor: pointer;
}

/* Beats Materialize button:focus { background-color: #2ab7a9 }. */
.ui-v2 .ca-language-option:focus {
  background-color: transparent;
}

.ui-v2 .ca-language-option:hover,
.ui-v2 .ca-language-option:focus-visible {
  background-color: var(--surface-3);
}

.ui-v2 .ca-language-option__name {
  color: inherit;
  font: inherit;
}

.ui-v2 .ca-language-option__code {
  color: var(--ivory-500);
  font: 600 var(--fs-caption)/var(--lh-caption) var(--font-ui);
  font-variant-numeric: tabular-nums;
}

.ui-v2 .ca-language-option__check {
  grid-column: 3;
  color: var(--gold-400);
  font-size: 0;
  line-height: 0;
}

.ui-v2 .ca-language-option[aria-current="true"] .ca-language-option__name {
  font-weight: 600;
}

/* ─────────────────────────────────────────────────────────────
   COLOPHON - spec « Footer colophon »
   Top row: logo and tagline, « Plateforme » (guests), « Mentions
   légales » as one column, « Langue »; it wraps into a column on phones.
   Bottom row under a soft rule: copyright and staff links. The tab bar
   clearance comes from the body padding, not from here.
   ───────────────────────────────────────────────────────────── */
.ui-v2 .ca-colophon {
  background-color: var(--night-950);
  border-top: 1px solid var(--rule-colophon);
  color: var(--ivory-300);
}

.ui-v2 .ca-colophon__inner {
  display: flex;
  flex-direction: column;
  gap: var(--sp-24);
  box-sizing: border-box;
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: var(--sp-64) var(--gutter) var(--sp-32);
}

.ui-v2 .ca-colophon__top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-32) var(--sp-48);
}

.ui-v2 .ca-colophon__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-20);
}

.ui-v2 .ca-colophon__logo {
  display: inline-flex;
  flex: none;
  align-items: center;
  min-width: 44px;
  min-height: 44px;
}

/* 56px on phones and tablets, the spec's 72px from 1024px. */
.ui-v2 .ca-colophon__logo-img {
  display: block;
  width: auto;
  height: 56px;
}

@media (min-width: 1024px) {
  .ui-v2 .ca-colophon__logo-img {
    height: 72px;
  }
}

/* style.css colours and spaces every <p>. */
.ui-v2 .ca-colophon__tagline {
  max-width: 280px;
  margin: 0;
  color: var(--ivory-300);
  font: italic 500 20px/28px var(--font-display);
}

/* Materialize nav reset: height, line-height, width and colour. */
.ui-v2 .ca-colophon__group {
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
  height: auto;
  width: auto;
  line-height: normal;
  color: inherit;
  background: none;
  box-shadow: none;
}

/* The legal column keeps its links' width, like the other groups. */
.ui-v2 .ca-colophon__legal {
  flex: 0 1 auto;
  max-width: none;
}

.ui-v2 .ca-colophon__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--sp-24);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* « Mentions légales »: one link per row, 32px rows (44px on touch and
   narrow screens, below) at their natural width (ALS-1190). */
.ui-v2 .ca-colophon__links--column {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* Phones: every group in one column, the legal list full width. */
@media (max-width: 599.98px) {
  .ui-v2 .ca-colophon__top {
    flex-direction: column;
  }

  .ui-v2 .ca-colophon__legal {
    flex: none;
    width: 100%;
  }
}

/* Links and the « Gérer les cookies » button share one look. */
.ui-v2 .ca-colophon__link {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0;
  margin: 0;
  border: 0;
  background-color: transparent;
  color: var(--ivory-300);
  font: 500 14px/20px var(--font-ui);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

/* Beats Materialize button:focus { background-color: #2ab7a9 }. */
.ui-v2 .ca-colophon__link:focus {
  background-color: transparent;
}

.ui-v2 .ca-colophon__link:hover {
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* Touch screens and narrow widths: full 44px targets. */
@media (max-width: 1023.98px), (pointer: coarse) {
  .ui-v2 .ca-colophon__link {
    min-height: 44px;
  }
}

/* The mockups' 44px secondary button, also under a fine pointer. */
.ui-v2 .ca-colophon__language {
  --ca-btn-h: 44px;
  align-self: flex-start;
}

.ui-v2 .ca-colophon__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-8) var(--sp-24);
  padding-top: var(--sp-16);
  border-top: 1px solid var(--rule-soft);
}

.ui-v2 .ca-colophon__copyright {
  margin: 0;
  color: var(--ivory-500);
  font: 500 var(--fs-caption)/var(--lh-caption) var(--font-ui);
  font-variant-numeric: tabular-nums;
}

.ui-v2 .ca-colophon__staff {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--sp-24);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui-v2 .ca-colophon__link--small {
  color: var(--ivory-500);
  font-size: var(--fs-caption);
}

/* ─────────────────────────────────────────────────────────────
   GUEST BAND - transparent, in flow: logo, language, one auth link
   ───────────────────────────────────────────────────────────── */
.ui-v2 .ca-shell-guest {
  position: relative;
  z-index: 1;
  height: var(--ca-guest-header-height);
  background: transparent;
}

.ui-v2 .ca-shell-guest__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-16);
  box-sizing: border-box;
  max-width: var(--container-wide);
  height: 100%;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.ui-v2 .ca-shell-guest__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
}

.ui-v2 .ca-shell-guest__language {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  box-sizing: border-box;
  height: 44px;
  margin: 0;
  padding: 0 var(--sp-12);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background-color: transparent;
  color: var(--ivory-100);
  font: 600 13px/16px var(--font-ui);
  cursor: pointer;
}

/* Beats Materialize button:focus { background-color: #2ab7a9 }. */
.ui-v2 .ca-shell-guest__language:focus {
  background-color: transparent;
}

.ui-v2 .ca-shell-guest__language:hover {
  border-color: var(--line-strong);
}

/* The mockups' 44px secondary link, also under a fine pointer. */
.ui-v2 .ca-shell-guest__auth {
  --ca-btn-h: 44px;
}

/* A-Accueil-Desktop: 52px logo in the 72px band. */
@media (min-width: 1024px) {
  .ui-v2 .ca-shell-guest .ca-shell__logo {
    height: auto;
  }

  .ui-v2 .ca-shell-guest .ca-shell__logo-img {
    height: 52px;
  }
}

/* ─────────────────────────────────────────────────────────────
   OVERLAYS - cookie card, PWA bar, reCAPTCHA badge
   v2 look of the legacy markup (cookie-consent.css, pwa-install.css stay
   loaded and untouched). The cookie card and the PWA bar sit above the
   tab bar through --ca-bottom-offset; the reCAPTCHA badge joins the page
   flow (ALS-1190).
   ───────────────────────────────────────────────────────────── */

/* Beats cookie-consent.css: card above the tab bar on phones, 400px in
   the bottom-left corner from 1024px. */
.ui-v2 .ca-cookie-consent {
  inset: auto var(--sp-12) calc(var(--ca-bottom-offset) + var(--sp-12)) var(--sp-12);
  max-width: none;
  margin: 0;
}

@media (min-width: 1024px) {
  .ui-v2 .ca-cookie-consent {
    inset: auto auto var(--sp-24) var(--sp-24);
    width: 400px;
  }
}

/* While the card is open, the page ends above it at every width. From
   1024px, the 400px corner card would cover the colophon's language button
   at full scroll. max() keeps the tab bar's inset until cookie-consent.js
   has measured the card. Placed after CHROME OFFSETS: same specificity as
   body.ui-v2:has(.ca-tabbar). */
body.ui-v2:has(> .ca-cookie-consent--visible) {
  padding-bottom: max(var(--ca-bottom-inset), calc(var(--ca-cookie-consent-space, 0px) + var(--sp-12)));
}

.ui-v2 .ca-cookie-consent__panel {
  padding: var(--sp-24);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  box-shadow: var(--shadow-menu);
  color: var(--ivory-300);
}

.ui-v2 .ca-cookie-consent__title {
  margin: 0 0 var(--sp-8);
  color: var(--ivory-100);
  font: 500 22px/28px var(--font-display);
}

/* style.css colours every <p>, so the text restates its colour. */
.ui-v2 .ca-cookie-consent__text {
  margin: 0 0 var(--sp-16);
  color: var(--ivory-300);
  font: 400 var(--fs-body-small)/var(--lh-body-small) var(--font-ui);
}

.ui-v2 .ca-cookie-consent__text a {
  color: var(--violet-400);
  font: inherit;
  text-decoration: underline;
}

/* Side by side even on phones (cookie-consent.css stacks them). */
.ui-v2 .ca-cookie-consent__actions {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: var(--sp-12);
}

.ui-v2 .ca-cookie-consent__btn {
  flex: 1 1 0;
  box-sizing: border-box;
  min-height: 44px;
  padding: 0 var(--sp-20);
  border-radius: var(--r-pill);
  font: 600 var(--fs-button)/var(--lh-button) var(--font-ui);
}

/* Spec: « Refuser » and « Accepter » share one secondary look, so
   neither choice is nudged. :focus restates the fill against
   Materialize button:focus. */
.ui-v2 .ca-cookie-consent__btn--secondary,
.ui-v2 .ca-cookie-consent__btn--secondary:focus,
.ui-v2 .ca-cookie-consent__btn--primary,
.ui-v2 .ca-cookie-consent__btn--primary:focus {
  background-color: transparent;
  border: 1px solid var(--line-strong);
  color: var(--ivory-100);
}

.ui-v2 .ca-cookie-consent__btn--secondary:hover,
.ui-v2 .ca-cookie-consent__btn--primary:hover {
  background-color: var(--wash-hover);
  border-color: var(--ivory-300);
}

/* Beats pwa-install.css: v2 surface above the tab bar. The legacy
   slide animation, markup and script stay. */
.ui-v2 #pwa-install-banner,
.ui-v2 #pwa-ios-banner {
  bottom: var(--ca-bottom-offset);
  padding: var(--sp-12) var(--gutter);
  background: var(--surface-2);
  border-top: 1px solid var(--rule);
  box-shadow: var(--shadow-menu);
  color: var(--ivory-300);
  font-family: var(--font-ui);
}

.ui-v2 .pwa-install-icon {
  border-radius: var(--r-md);
}

.ui-v2 .pwa-install-text > strong {
  color: var(--ivory-100);
  font: 600 14px/20px var(--font-ui);
}

.ui-v2 .pwa-install-text > span {
  color: var(--ivory-300);
  font: 400 13px/18px var(--font-ui);
}

/* The iOS hint's inline « Sur l'écran d'accueil ». */
.ui-v2 .pwa-install-text > span strong {
  color: var(--ivory-100);
  font: inherit;
  font-weight: 600;
}

.ui-v2 .pwa-btn-dismiss,
.ui-v2 .pwa-btn-install {
  box-sizing: border-box;
  min-height: 44px;
  padding: 0 var(--sp-20);
  border-radius: var(--r-pill);
  font: 600 var(--fs-button)/var(--lh-button) var(--font-ui);
  transition:
    background-color var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out);
}

/* :focus restates the fill against Materialize button:focus. */
.ui-v2 .pwa-btn-dismiss,
.ui-v2 .pwa-btn-dismiss:focus {
  background: transparent;
  border: 1px solid var(--line-strong);
  color: var(--ivory-100);
}

.ui-v2 .pwa-btn-dismiss:hover {
  background: var(--wash-hover);
  border-color: var(--ivory-300);
  color: var(--ivory-100);
}

/* No glow and no lift on hover (spec elevation). */
.ui-v2 .pwa-btn-install,
.ui-v2 .pwa-btn-install:focus {
  background: var(--violet-600);
  border: 1px solid var(--violet-600);
  color: var(--on-accent);
}

.ui-v2 .pwa-btn-install:hover {
  background: var(--violet-800);
  border-color: var(--violet-800);
  box-shadow: none;
  transform: none;
}

/* Phones: icon and text on the first row, then the 44px buttons share
   the full width (the iOS hint's single button fills it), instead of
   squeezing the text beside two buttons (ALS-1190). */
@media (max-width: 599.98px) {
  .ui-v2 .pwa-install-content {
    flex-wrap: wrap;
    row-gap: var(--sp-12);
  }

  .ui-v2 .pwa-install-text {
    flex: 1 1 0;
  }

  .ui-v2 .pwa-install-actions {
    flex: 1 1 100%;
    justify-content: flex-end;
  }

  .ui-v2 .pwa-install-actions > button {
    flex: 1 1 0;
  }
}

/* reCAPTCHA v3 badge, in the page flow (ALS-1190). Google writes
   position: fixed; right: -186px; bottom: 14px in the badge's inline
   style attribute (recaptcha api.js) and appends its wrapper at the end
   of <body>; !important is the only way past an inline style (margin is
   not inline today and keeps it in case Google adds one). Static places
   it in flow under the colophon, above the tab bar padding: it stays
   fully visible, as Google requires, and covers no field. */
.ui-v2 .grecaptcha-badge {
  position: static !important;
  right: auto !important;
  bottom: auto !important;
  margin: 0 auto !important;
}

/* Google's wrapper div (the badge's parent, a child of <body>) takes the
   colophon fill and bottom spacing, so the page ends on the dark colophon
   with the badge inside it, never on a strip of sky. Until legal approves
   hiding the badge behind the mention _recaptcha_notice.html already
   renders (spec A « Cookies, PWA, reCAPTCHA », synthese.md). */
body.ui-v2 > div:has(> .grecaptcha-badge) {
  padding-block: 0 var(--sp-24);
  background-color: var(--night-950);
}

/* ─────────────────────────────────────────────────────────────
   PAGE INTEGRATION - temporary, until each page gets its v2 lot
   Legacy page layouts assume the old 70-80px header and no tab bar.
   ───────────────────────────────────────────────────────────── */

/* Échanges fills the space between the masthead and the tab bar. */
body.ui-v2 .chat-app {
  height: calc(100vh - var(--ca-header-height) - var(--ca-bottom-inset));
  height: calc(100dvh - var(--ca-header-height) - var(--ca-bottom-inset));
}

/* The open conversation docks under the v2 top bar; css/v2/chat.css
   overrides it with its full-screen overlay and keyboard rules. */
@media (max-width: 768px) {
  body.ui-v2 .chat-main {
    top: var(--ca-header-height);
    height: calc(100vh - var(--ca-header-height));
    height: calc(100dvh - var(--ca-header-height));
  }
}

/* The search toast stays above the tab bar. */
body.ui-v2 .search-toast {
  bottom: calc(var(--ca-bottom-offset) + var(--sp-24));
}

/* Beats style.css .section-2: its wave continued the legacy header and
   would paint a scalloped band under the masthead; the sky shows
   through instead (spec: waves removed). */
body.ui-v2 .section-2 {
  background: none;
}

/* ─────────────────────────────────────────────────────────────
   FORCED COLOURS - system rules and indicators
   The browser drops the translucent fills and the gradient strip, so
   the chrome keeps a CanvasText edge and current markers keep a
   Highlight fill.
   ───────────────────────────────────────────────────────────── */
@media (forced-colors: active) {
  .ui-v2 .ca-shell {
    border-bottom: 1px solid CanvasText;
  }

  .ui-v2 .ca-tabbar {
    border-top: 1px solid CanvasText;
  }

  .ui-v2 .ca-shell__link[aria-current="page"]::after,
  .ui-v2 .ca-shell__link.is-current::after,
  .ui-v2 .ca-tabbar__tab[aria-current="page"]::before,
  .ui-v2 .ca-tabbar__tab.is-current::before {
    forced-color-adjust: none;
    background: Highlight;
  }

  .ui-v2 .ca-shell__bell .notification-badge {
    forced-color-adjust: none;
    background: Highlight;
    color: HighlightText;
  }
}
