/* ============================================================
   Monitora — App shell & design system
   Light interface built on a five-colour brand palette: Dark
   Amethyst, Indigo Bloom, Green, Orange, Pale Amber (re-cut
   2026-09-06 — to-do10 Task 1; see the Tier 1 block below for what
   moved and why). Layered on top of CDN Bootstrap 5; only adds what
   utilities cannot express cleanly (shell layout, cards, icon
   buttons, completion ring) plus the Bootstrap colour overrides,
   since Bootstrap's own defaults are blue.

   Colour rule: rules below reference Tier 2 semantic tokens only.
   Raw palette values live in Tier 1 and nowhere else. Translucent
   overlays -- rgba(255,255,255,x) scrims and rgba(0,0,0,x) shadows
   -- are the deliberate exception: they are opacity, not hue.
   ============================================================ */

/* ============================================================
   TIER 1 — Raw palette
   The five brand colours and their derived steps, plus two
   functional neutrals that sit outside the five on purpose: --ink
   (the app's body text, decision D9a) and --red (destructive
   actions, kept apart from every brand and type colour so "delete"
   never shares a colour with anything else). This is the ONLY block
   allowed to contain colour literals. Nothing in the rest of the
   stylesheet (nor any view) may reference these directly — always go
   through a Tier 2 semantic alias, so the palette can be re-cut (or
   inverted for dark mode) in one place.
   ============================================================ */
:root {
  /* Neutral extremes — not brand colours, but the palette's
     text-on-dark and card-surface anchors. */
  --white: #ffffff;

  /* Ink — near-black body text (decision D9a). Bootstrap's own
     default body colour, taken as "the most common black used on
     websites" over a brand hue, so all five brand colours are free
     to spend on surfaces, actions and content types instead of also
     carrying text. --ink-muted is derived, not borrowed: Bootstrap's
     own muted grey (#6c757d) measures 4.69:1 on white but only 4.36:1
     on this app's canvas (--shell-bg) and fails AA there. */
  --ink: #212529;
  --ink-muted: #5c636a;

  /* Dark Amethyst — dark chrome and the article type colour (D9).
     No longer the app's ink (see --ink above) — the -50/-100/-200/-300
     steps remain the neutral scale: the canvas, the hover wash and the
     borders all still carry a trace of the brand hue rather than the
     cool grey they'd otherwise be. */
  --amethyst-50: #f7f6fa;
  --amethyst-100: #efedf5;
  --amethyst-200: #e3dfec;
  --amethyst-300: #d2cbe1;
  --amethyst: #2f195f;
  --amethyst-800: #241348;

  /* Indigo Bloom — the CTA, links and active states, and — as its
     lighter/darker steps — badges, the decorative divider and the
     progress sweep (D10). Indigo now carries every role Burgundy and
     Lavender Purple used to split between them; there is no longer a
     second purple hue anywhere in the file. -050/-100 are light tints
     (badge fill, hero backdrop), -200 is the mid-light step the
     progress sweep used to reach via Lavender Purple (same lightness,
     same hue family), -800 is the dark ink step for badge text.

     Re-hued 2026-09-06, same day as the rest of Task 1: the user's own
     spec (#5525b5, H 260°) filled a whole button and read as purple, not
     blue, once it became the CTA rather than a thin outline or a link.
     Shifted to H 225° at the same saturation and lightness -- same
     recipe, same steps below, just less red in the mix. */
  --indigo-050: #f5f7fd;
  --indigo-100: #e9edfa;
  --indigo-200: #6583df;
  --indigo: #2549b5;
  --indigo-800: #1d3b94;

  /* Pale Amber — warm emphasis surface, replacing Almond Cream (D10).
     -100/-200 are lighter steps for the two emphasis surfaces
     (--surface-alt / its hover); -300 is the darker hover step for
     --surface-warm. */
  --amber-100: #fbebca;
  --amber-200: #f7e2b7;
  --amber: #fedc97;
  --amber-300: #e8c57d;

  /* Categorical scale — a SEPARATE axis from the brand palette above.
     These encode which kind of content a card holds; they are data,
     so they need to stay mutually distinguishable (decision D9). The
     trio now separates by LIGHTNESS — 14.7 / 5.3 / 3.25 as a border
     against white — rather than by hue, which is what keeps it usable
     under red-green CVD; the old #12794a / #9a5b06 pair sat at 5.4 and
     5.3, nearly identical, which is exactly the confusable pairing
     that CVD produces. Orange cannot itself be a border at 4.5:1, so
     --orange-800 is a darker step of the SAME hue and saturation —
     the same recipe as every other "-800" step in this file — built
     to clear the 3:1 boundary gate; the base --orange is fill-only,
     the same shape --lavender used to be for badges. */
  --green: #297957;
  --orange: #ff9b71;
  --orange-800: #e64400;

  /* Type tints (to-do10b D1). One pale step per content type, all three
     derived at the SAME lightness and saturation (HSL L 90%, S 63%) from
     their own base hue, so the three legend pills read at equal weight
     rather than one looking bolder because its hue is naturally darker.
     --indigo-150 sits between --indigo-050 and --indigo-100 on purpose:
     --indigo-100 (#e9edfa, L 94.7%) is too light to match the other two,
     and it is already spoken for as --accent-soft/--cta-soft.

     These are FILLS ONLY and cannot carry meaning on their own: measured
     against the canvas they are 1.07 / 1.26 / 1.19 -- a hue difference,
     not a luminance one, so a colour-blind user sees three near-identical
     pale pills. That is why D1 puts the type on the border and the icon
     too, at 4.92-7.23 on canvas, and why D2 refuses to carry selection
     with colour at all. */
  --green-100: #d5f6e8;
  --indigo-150: #d5ddf6;
  --orange-100: #f6dfd5;

  /* Destructive red — its own hue, deliberately not Indigo and not a
     type colour, and set apart from all of them by lightness so
     "delete" never wears the colour of "enregistrer" or of a card
     type. (Previously justified as "not Burgundy" — Burgundy is gone,
     but the need for a colour distinct from the CTA is sharper now:
     the CTA and the saved heart are both Indigo Bloom, so danger has
     to separate from that, not from a colour the file no longer has.) */
  --red: #c2183a;
  --red-800: #9d1330;

  /* Alert tints — subtle fill / border / emphasis ink per intent.
     Bootstrap builds its alerts from a three-part set like this, so
     supplying ours is what re-skins every .alert- variant at once.
     Independent literals, not derived from the five brand colours
     above — unchanged by this palette re-cut. */
  --tint-success-bg: #e7f3ed;
  --tint-success-border: #bcdccb;
  --tint-success-ink: #0b4d2f;
  --tint-warning-bg: #f9efdf;
  --tint-warning-border: #e6cfa8;
  --tint-warning-ink: #6b3f04;
  --tint-danger-bg: #fdecef;
  --tint-danger-border: #f2c3cd;
  --tint-danger-ink: #8f1129;
  --tint-info-bg: #f2ecfb;
  --tint-info-border: #d9c8f0;
  --tint-info-ink: #4d2b7a;

  /* RGB triplets. Bootstrap composes its utilities as
     rgba(var(--bs-*-rgb), opacity), so it needs channels rather than
     hex — these must be kept in sync with the hex values above by
     hand, since CSS cannot decompose a custom property. */
  --indigo-rgb: 37, 73, 181;
  --amethyst-rgb: 47, 25, 95;
  --ink-muted-rgb: 92, 99, 106;
  --green-rgb: 41, 121, 87;
  --orange-800-rgb: 230, 68, 0;
  --amber-100-rgb: 251, 235, 202;
  --indigo-800-rgb: 29, 59, 148;
  --danger-rgb: 194, 24, 58;
}

/* ============================================================
   TIER 2 — Semantic aliases
   What the UI actually speaks: surfaces, ink, borders, intent.
   ============================================================ */
:root {
  /* Surfaces. Per decision D1(b) [to-do4] the canvas stays a
     near-neutral — a faint amethyst wash, not Pale Amber. Amber is
     reserved for emphasis surfaces (--surface-warm), which is what
     keeps it reading as emphasis instead of as the product's base
     colour. */
  --shell-bg: var(--amethyst-50);
  --surface: var(--white);
  --surface-alt: var(--amber-100);
  --surface-alt-hover: var(--amber-200);
  --surface-hover: var(--amethyst-100);
  --surface-warm: var(--amber);
  --surface-warm-hover: var(--amber-300);
  --sidebar-bg: var(--surface);

  /* Borders */
  --border: var(--amethyst-200);
  --border-strong: var(--amethyst-300);
  --border-warm: var(--amber-300);

  /* Ink (D9a). --text-muted is derived (see Tier 1): it clears AA on
     all three surfaces we put it on — 6.09:1 on white, 5.66:1 on the
     canvas, 4.61:1 on the warm amber surface. */
  --text: var(--ink);
  --text-muted: var(--ink-muted);
  --text-on-accent: var(--white);
  --text-on-cta: var(--white);

  /* Accent — secondary actions, active states, links */
  --accent: var(--indigo);
  --accent-rgb: 37, 73, 181;
  --accent-soft: var(--indigo-100);
  --accent-strong: var(--indigo-800);

  /* CTA — the one committing action per screen (D10). White text on
     Indigo Bloom measures 9.06:1. */
  --cta: var(--indigo);
  --cta-strong: var(--indigo-800);
  --cta-soft: var(--indigo-100);
  --cta-rgb: 37, 73, 181;

  /* Saved / favourite (D10). Indigo, not the new Orange: three of the
     five colours are now spent on content types, and Orange is one of
     them — a filled orange heart on an orange-bordered appel-à-projet
     card would read as a type marker, not a state. Indigo reads as
     "something you did, or can do", the same colour as links and the
     CTA, and cannot be confused with any card type. A state mark, not
     a control — it does not spend the CTA's scarcity. Reversible on
     this one line if it proves too heavy. */
  --saved: var(--accent);

  /* Destructive / alert — its own hue, kept apart from the CTA and
     saved-heart Indigo by lightness (a mid red against a near-black
     maroon-free palette) because they do co-occur: the parameters
     overlay stacks a primary submit above two destructive controls. */
  --danger: var(--red);
  --danger-strong: var(--red-800);
  --danger-soft: var(--tint-danger-bg);

  /* Focus. Two rings, because one cannot serve both backdrops: Indigo
     Bloom reads at 8.42:1 on the canvas but collapses to 1.63:1 on the
     Dark Amethyst chrome, where Pale Amber takes over at 11.16:1. */
  --focus-ring: var(--accent);
  --focus-ring-inverse: var(--amber);

  /* Content-type categorical scale (separate axis from the brand
     palette — these encode data, not hierarchy). Colour is never the
     only channel: every chip and pill carries its type as text too.
     Per D9, the ink for all three types is the app's neutral --text —
     the colour survives only in the card's edge band and the dot (see
     .content-card, re-cut post-Task-5 from a border to a right-edge
     colour band per the user's own reference: a coloured border read as
     dated, a solid band plus elevation shadow reads as modern).

     --type-article moved from Dark Amethyst to Indigo (--accent) at the
     user's request, after Dark Amethyst read as too close to Green on the
     live border. Dark Amethyst stays in the file as the dark chrome only
     now (--bs-dark) -- it carries no card-type meaning any more.
     Trade-off, stated plainly: --type-article is the exact same value as
     --cta/--accent/--saved, so a blue card band, the primary button and a
     filled saved-heart all share one hue.

     ⚠️ WHAT DEFENDS THAT CHANGED IN to-do10b (D5). This comment used to say
     the sharing was safe because "every card still names its type in text".
     Task 4 deleted that text, so that sentence is no longer true and must
     not be restored. What defends it now is SHAPE, not hue: the type is
     carried by the band's glyph -- postcard / calendar / lightbulb -- which
     WCAG 1.4.1 is satisfied by, and which the toolbar legend teaches. The
     hue is free to be shared precisely because it is not what carries the
     meaning.

     The condition attached to that: .content-card-type-icon must keep a
     real accessible name (role="img" + aria-label, see content-card.hbs).
     If that is ever removed, nothing carries the type and --type-article
     has to leave --accent -- which was D5's rejected option (b). */
  --type-event: var(--green);
  --type-article: var(--accent);
  --type-appel: var(--orange-800);

  /* Soft companions, for the legend pills' fill (to-do10b D1). */
  --type-event-soft: var(--green-100);
  --type-article-soft: var(--indigo-150);
  --type-appel-soft: var(--orange-100);

  /* Decorative divider on emphasis surfaces */
  --divider-soft: var(--indigo);

  /* Progress sweep — the palette's one gradient */
  --progress-from: var(--indigo);
  --progress-to: var(--indigo-200);

  /* Soft badge — tint fill, mid-tone edge, dark ink (D10; same shape
     Lavender Purple used to serve, now a lighter/darker step of
     Indigo instead of a second hue). */
  --badge-bg: var(--indigo-050);
  --badge-border: var(--indigo);
  --badge-ink: var(--indigo-800);

  /* Landing hero backdrop — a light Indigo wash to a paler one; the
     same two-pale-stops shape the original Indigo-Bloom-to-Lavender
     sweep already used (both of those were pale tints too). */
  --hero-from: var(--indigo-100);
  --hero-to: var(--indigo-050);

  /* Geometry */
  --sidebar-width: 264px;
  --sidebar-rail: 76px;
  --radius: 14px;
  --radius-sm: 10px;
}

body {
  background-color: var(--shell-bg);
  color: var(--text);
}

/* ============================================================
   Bootstrap theme variables
   Every Bootstrap colour utility resolves through a :root variable
   — .text-muted reads --bs-secondary-color, .bg-primary reads
   rgba(var(--bs-primary-rgb), …), .alert-* read the -bg-subtle /
   -border-subtle / -text-emphasis trio. Redefining that set here
   re-skins roughly fifty utility usages across the views at once,
   instead of rewriting fifty class attributes.

   Note --bs-success / --bs-warning: in this product those two are
   not "success" and "warning" at all. The agenda rows and their
   legend use them to mean *event* and *appel à projet*, so they are
   mapped onto the content-type scale. That was the fourth place the
   type colours were defined. This is also the one place the palette
   re-cut leaves a known rough edge: those rows force white button
   text (see the .btn-warning/.btn-success override below), and white
   on the new Orange step measures 4.05:1 — just under AA, better than
   near-black's 3.81:1 but not clean. The agenda/legend redesign is
   explicitly out of scope here (see Explicitly out of scope §3) and
   is the right place to fix it properly.
   ============================================================ */
:root {
  --bs-body-color: var(--text);
  --bs-body-bg: var(--shell-bg);
  --bs-secondary-color: var(--text-muted);
  --bs-border-color: var(--border);

  --bs-primary-rgb: var(--indigo-rgb);
  --bs-secondary-rgb: var(--ink-muted-rgb);
  --bs-dark-rgb: var(--amethyst-rgb);
  --bs-light-rgb: var(--amber-100-rgb);
  --bs-success-rgb: var(--green-rgb);
  --bs-warning-rgb: var(--orange-800-rgb);
  --bs-danger-rgb: var(--danger-rgb);
  --bs-info-rgb: var(--indigo-800-rgb);

  --bs-link-color: var(--accent);
  --bs-link-color-rgb: var(--indigo-rgb);
  --bs-link-hover-color: var(--accent-strong);

  --bs-success-bg-subtle: var(--tint-success-bg);
  --bs-success-border-subtle: var(--tint-success-border);
  --bs-success-text-emphasis: var(--tint-success-ink);
  --bs-warning-bg-subtle: var(--tint-warning-bg);
  --bs-warning-border-subtle: var(--tint-warning-border);
  --bs-warning-text-emphasis: var(--tint-warning-ink);
  --bs-danger-bg-subtle: var(--tint-danger-bg);
  --bs-danger-border-subtle: var(--tint-danger-border);
  --bs-danger-text-emphasis: var(--tint-danger-ink);
  --bs-info-bg-subtle: var(--tint-info-bg);
  --bs-info-border-subtle: var(--tint-info-border);
  --bs-info-text-emphasis: var(--tint-info-ink);
}


/* ---------- Focus visibility ----------
   The custom controls here are <a> and <button> elements that strip
   their own borders and backgrounds, leaving the UA's default ring to
   land on whatever backdrop happens to be behind it. One token-driven
   ring keeps the keyboard path legible and identical across the shell.
   :focus-visible only, so pointer users never see it. */
.sidebar-link:focus-visible,
.sidebar-brand:focus-visible,
.sidebar-collapse-btn:focus-visible,
.btn-icon:focus-visible,
.back-arrow:focus-visible,
.filter-pill:focus-visible,
.filter-dd-toggle:focus-visible,
.content-card:focus-visible,
.agenda-item:focus-visible,
.hero-cta:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
/* On the detail page's dark chrome the indigo ring would disappear. */
.card-header .btn:focus-visible {
  outline: 2px solid var(--focus-ring-inverse);
  outline-offset: 2px;
}

/* Both fills are now dark enough to need light labels; Bootstrap's
   near-black default text would land at 2.91:1 on Green and 3.81:1 on
   the Orange step -- both fail AA. White clears Green at 5.29:1;
   Orange still falls short at 4.05:1, the residual gap the Bootstrap
   theme variables comment above names. */
.btn-warning,
.btn-success {
  --bs-btn-color: var(--text-on-accent);
  --bs-btn-hover-color: var(--text-on-accent);
  --bs-btn-active-color: var(--text-on-accent);
}

/* ---------- Bootstrap button overrides ----------
   Two tiers, per the 60-30-10 split. .btn-primary is the committing
   action and wears Burgundy; it is meant to be rare, so anything that
   merely loads more rows or opens a panel uses the Indigo secondary
   instead. Bootstrap's own blue is never allowed through. */
.btn-primary {
  --bs-btn-bg: var(--cta);
  --bs-btn-border-color: var(--cta);
  --bs-btn-color: var(--text-on-cta);
  --bs-btn-hover-bg: var(--cta-strong);
  --bs-btn-hover-border-color: var(--cta-strong);
  --bs-btn-hover-color: var(--text-on-cta);
  --bs-btn-active-bg: var(--cta-strong);
  --bs-btn-active-border-color: var(--cta-strong);
  --bs-btn-active-color: var(--text-on-cta);
  --bs-btn-disabled-bg: var(--cta);
  --bs-btn-disabled-border-color: var(--cta);
  --bs-btn-focus-shadow-rgb: var(--cta-rgb);
}

/* Secondary: "Charger plus", "Plus d'articles", panel toggles. */
.btn-outline-primary {
  --bs-btn-color: var(--accent);
  --bs-btn-border-color: var(--accent);
  --bs-btn-hover-bg: var(--accent);
  --bs-btn-hover-border-color: var(--accent);
  --bs-btn-hover-color: var(--text-on-accent);
  --bs-btn-active-bg: var(--accent-strong);
  --bs-btn-active-border-color: var(--accent-strong);
  --bs-btn-active-color: var(--text-on-accent);
  --bs-btn-disabled-color: var(--accent);
  --bs-btn-disabled-border-color: var(--accent);
  --bs-btn-focus-shadow-rgb: var(--accent-rgb);
}

/* Neutral chrome button ("Ajuster mes préférences", the topbar toggle).
   Bootstrap's .btn-light is a cool grey that reads dirty next to the
   warmer surfaces, so it borrows the card tokens instead. */
.btn-light {
  --bs-btn-bg: var(--surface);
  --bs-btn-border-color: var(--border);
  --bs-btn-color: var(--text);
  --bs-btn-hover-bg: var(--surface-hover);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--text);
  --bs-btn-active-bg: var(--surface-hover);
  --bs-btn-active-border-color: var(--border-strong);
  --bs-btn-active-color: var(--text);
}

/* Destructive. Separated from the CTA by lightness, not hue. */
.btn-danger {
  --bs-btn-bg: var(--danger);
  --bs-btn-border-color: var(--danger);
  --bs-btn-hover-bg: var(--danger-strong);
  --bs-btn-hover-border-color: var(--danger-strong);
  --bs-btn-active-bg: var(--danger-strong);
  --bs-btn-active-border-color: var(--danger-strong);
  --bs-btn-disabled-bg: var(--danger);
  --bs-btn-disabled-border-color: var(--danger);
}
.btn-outline-danger {
  --bs-btn-color: var(--danger);
  --bs-btn-border-color: var(--danger);
  --bs-btn-hover-bg: var(--danger);
  --bs-btn-hover-border-color: var(--danger);
  --bs-btn-active-bg: var(--danger-strong);
  --bs-btn-active-border-color: var(--danger-strong);
  --bs-btn-disabled-color: var(--danger);
  --bs-btn-disabled-border-color: var(--danger);
}
a {
  color: var(--accent);
}

/* ---------- Bootstrap form controls ----------
   Bootstrap ships checkboxes, switches, ranges and every focus ring in
   its own default blue and hardcodes those values rather than exposing
   them as variables, so each control has to be named explicitly. Without
   this block the profile form keeps rendering Bootstrap's blue checkboxes
   and switch next to this product's own, different blue. */
.form-check-input:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}
.form-check-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 0.25rem rgba(var(--accent-rgb), 0.25);
}
/* The switch knob is an SVG carried in a data URI, and a data URI cannot
   read a custom property — so these two are the one place outside Tier 1
   where a palette value is written literally. Keep them in sync with
   --indigo by hand. */
.form-switch .form-check-input:focus {
  --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%232549b5'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:checked {
  --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}
.form-control:focus,
.form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 0.25rem rgba(var(--accent-rgb), 0.2);
}
.form-range::-webkit-slider-thumb {
  background-color: var(--accent);
}
.form-range::-moz-range-thumb {
  background-color: var(--accent);
}
.form-range::-webkit-slider-runnable-track {
  background-color: var(--border);
}
.form-range::-moz-range-track {
  background-color: var(--border);
}
.form-range:focus::-webkit-slider-thumb {
  box-shadow: 0 0 0 1px var(--surface), 0 0 0 0.25rem rgba(var(--accent-rgb), 0.25);
}
.form-range:focus::-moz-range-thumb {
  box-shadow: 0 0 0 1px var(--surface), 0 0 0 0.25rem rgba(var(--accent-rgb), 0.25);
}

/* ============================================================
   App shell
   ============================================================ */
.app-shell {
  display: flex;
  min-height: 100vh;
}

/* Shared visual styling for both the desktop sidebar and the mobile
   offcanvas. Intentionally NO position/flex here so it never overrides
   Bootstrap's fixed-position offcanvas (which would otherwise reserve a
   phantom column on desktop). */
.app-sidebar {
  width: var(--sidebar-width);
  background: var(--sidebar-bg);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 1.25rem 0.875rem;
}

/* Desktop-only: turn the sidebar into a sticky flex column. */
.app-sidebar-fixed {
  flex: 0 0 var(--sidebar-width);
  width: var(--sidebar-width);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  transition: flex-basis 0.2s ease, width 0.2s ease;
}

.app-main {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  /* Fluid: the content fills the space next to the sidebar. A fixed max-width
     left an empty band on one side on wide screens (centered → gap by the
     sidebar; left-aligned → gap on the right). The 2rem padding keeps edge
     breathing room; the inner Bootstrap grid handles column proportions. */
  padding: 1.75rem 2rem 3rem;
}

@media (max-width: 991.98px) {
  .app-main {
    padding: 1.25rem 1rem 2.5rem;
  }
}

/* ---------- Sidebar brand ---------- */
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.25rem 0.6rem 1rem;
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--text);
  text-decoration: none;
}
/* The mark is a ~5.6:1 wordmark, not the 28px square icon this box was
   built for: it is sized by height and left to take the width it needs. */
.sidebar-brand img {
  height: 26px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}
.sidebar-brand-topbar img {
  height: 22px;
}
.navbar-brand-logo img {
  height: 28px;
  width: auto;
}

/* ---------- Sidebar navigation ---------- */
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sidebar-label {
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0.75rem 0.6rem 0.35rem;
}
button.sidebar-link {
  width: 100%;
  border: none;
  background: none;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
  font-size: 0.925rem;
  font-weight: 500;
  line-height: 1.2;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.sidebar-link i {
  font-size: 1.05rem;
  color: var(--text-muted);
  width: 1.2rem;
  text-align: center;
}
.sidebar-link:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.sidebar-link.active {
  background: var(--accent-soft);
  color: var(--accent-strong);
}
.sidebar-link.active i {
  color: var(--accent);
}

/* ---------- Two-level navigation ---------- */
.sidebar-list,
.sidebar-sublist {
  list-style: none;
  margin: 0;
  padding: 0;
}
.sidebar-parent {
  display: flex;
  align-items: center;
}
.sidebar-parent .sidebar-link {
  flex: 1 1 auto;
  min-width: 0;
}
.sidebar-parent .sidebar-link span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-chevron {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-right: 0.15rem;
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 0.8rem;
}
.sidebar-chevron:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.sidebar-chevron i {
  transition: transform 0.15s ease;
}

/* Sub-items are hidden unless their section is marked open on <html>. Driven
   from there rather than from a class on the group because this markup is
   rendered twice per page (fixed sidebar + mobile offcanvas) and both copies
   must agree. Adding a section means adding it to this selector list. */
.sidebar-sublist {
  display: none;
}
html.nav-open-channels .sidebar-group[data-nav-section='channels'] > .sidebar-sublist,
html.nav-open-library .sidebar-group[data-nav-section='library'] > .sidebar-sublist {
  display: block;
}
html.nav-open-channels .sidebar-group[data-nav-section='channels'] .sidebar-chevron i,
html.nav-open-library .sidebar-group[data-nav-section='library'] .sidebar-chevron i {
  transform: rotate(180deg);
}

.sidebar-sublink {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  /* Indented to sit under the parent's label rather than its icon. */
  padding: 0.4rem 0.65rem 0.4rem 2rem;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.2;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.sidebar-sublink i {
  font-size: 0.95rem;
  width: 1.1rem;
  text-align: center;
}
.sidebar-sublink:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.sidebar-sublink.active {
  background: var(--accent-soft);
  color: var(--accent-strong);
}
.sidebar-sublink:focus-visible,
.sidebar-chevron:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.sidebar-spacer {
  flex: 1 1 auto;
}

/* ---------- Sidebar user block ---------- */
.sidebar-user {
  border-top: 1px solid var(--border);
  padding-top: 0.85rem;
  margin-top: 0.5rem;
}
.sidebar-user-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.25rem 0.6rem 0.6rem;
}
.sidebar-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 34px;
  background: var(--accent);
  color: var(--text-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 0.85rem;
}
.sidebar-user-name {
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Channel status bar ---------- */
/* Activation banner pinned above the title on every Canaux de diffusion page.
   Presented as the page's headline parameter rather than a row in a form, so a
   user can see at a glance whether the channel is delivering (to-do5 D3).

   Colours are Tier 2 semantic tokens only. The state change animates via a class
   swap from channel-newsletter.js -- never a reload -- so the transition is what
   tells the user the write landed. */
.channel-status-bar {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.15rem;
  margin-bottom: 1.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

.channel-status-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 2.25rem;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  font-size: 1.05rem;
  background: var(--surface);
  border: 1px solid var(--border);
}

.channel-status-text {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
  flex: 1 1 auto;
}
.channel-status-title {
  font-weight: 600;
  line-height: 1.2;
}
.channel-status-detail {
  font-size: 0.825rem;
  opacity: 0.85;
}

.channel-status-control {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex: 0 0 auto;
}
.channel-status-state {
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
}
/* The switch is the control; the form-check label would duplicate the state text. */
.channel-status-bar .form-check-input {
  width: 2.6rem;
  height: 1.35rem;
  margin: 0;
  cursor: pointer;
}
.channel-status-bar .form-check-input:disabled {
  cursor: not-allowed;
}

/* ----- States ----- */
.channel-status-bar.is-active {
  background: var(--tint-success-bg);
  border-color: var(--tint-success-border);
  color: var(--tint-success-ink);
}
.channel-status-bar.is-active .channel-status-icon {
  background: var(--tint-success-bg);
  border-color: var(--tint-success-border);
  color: var(--tint-success-ink);
}

.channel-status-bar.is-paused {
  background: var(--tint-warning-bg);
  border-color: var(--tint-warning-border);
  color: var(--tint-warning-ink);
}
.channel-status-bar.is-paused .channel-status-icon {
  background: var(--tint-warning-bg);
  border-color: var(--tint-warning-border);
  color: var(--tint-warning-ink);
}

.channel-status-bar.is-disabled {
  background: var(--surface-alt);
  border-color: var(--border);
  color: var(--text-muted);
}
.channel-status-bar.is-disabled .channel-status-icon {
  background: var(--surface-alt);
  color: var(--text-muted);
}

/* ----- Overview variant: the whole row is the link ----- */
/* On /channels each row carries the banner's design but is itself the way into
   the channel, so there is no "Configurer" button and no separate banner saying
   the same thing twice. */
.channel-card {
  position: relative;
  margin-bottom: 0.85rem;
}
.channel-card .channel-status-title {
  color: inherit;
  text-decoration: none;
}
/* The stretched link covers the row, so the switch has to be lifted above it or
   toggling activation would navigate instead. */
.channel-card .channel-status-control {
  position: relative;
  z-index: 2;
}
.channel-card:hover {
  border-color: var(--border-strong);
}
.channel-card.is-active:hover {
  border-color: var(--tint-success-ink);
}
.channel-card.is-paused:hover {
  border-color: var(--tint-warning-ink);
}
.channel-card:focus-within {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
/* The row already shows a focus ring via :focus-within; a second ring drawn on
   the stretched link's overlay box would sit in the wrong place. */
.channel-card .stretched-link:focus-visible {
  outline: none;
}

/* ----- Motion ----- */
/* Opt-in rather than opt-out: no transition is declared unless the user has not
   asked for reduced motion, so the reduced-motion path is the plain default. */
@media (prefers-reduced-motion: no-preference) {
  .channel-status-bar,
  .channel-status-icon {
    transition:
      background-color 0.25s ease,
      border-color 0.25s ease,
      color 0.25s ease;
  }
  /* Hover on a card row should feel immediate, not ease in over a quarter second. */
  .channel-card {
    transition: border-color 0.12s ease;
  }
  /* A short pulse on the icon marks the moment the write landed, which a colour
     fade alone is easy to miss on a wide banner. */
  .channel-status-bar.state-changed .channel-status-icon {
    animation: channel-status-pulse 0.45s ease;
  }
}

@keyframes channel-status-pulse {
  0% {
    transform: scale(1);
  }
  45% {
    transform: scale(1.18);
  }
  100% {
    transform: scale(1);
  }
}

/* ---------- Mobile top bar ---------- */
.app-topbar {
  display: none;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 1rem;
  background: var(--sidebar-bg);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 1030;
}
@media (max-width: 991.98px) {
  .app-sidebar.app-sidebar-fixed {
    display: none;
  }
  .app-topbar {
    display: flex;
  }
}

/* ============================================================
   Sidebar collapse (desktop) — Notion-style icon rail
   State is driven by `html.sidebar-collapsed`; only the fixed
   desktop sidebar reacts (the mobile offcanvas is unaffected).
   ============================================================ */
.sidebar-collapse-row {
  display: flex;
  justify-content: flex-end;
  padding: 0 0.25rem 0.25rem;
}
.sidebar-collapse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.sidebar-collapse-btn:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.sidebar-collapse-btn i {
  font-size: 1rem;
  transition: transform 0.2s ease;
}

/* Fade the textual labels in sync with the width transition. */
.app-sidebar-fixed .sidebar-brand img,
.app-sidebar-fixed .sidebar-link span,
.app-sidebar-fixed .sidebar-user-name,
.app-sidebar-fixed .sidebar-label {
  transition: opacity 0.15s ease;
}

/* The mobile offcanvas never collapses, so its content is not hidden here. */
@media (min-width: 992px) {
  html.sidebar-collapsed .app-sidebar-fixed {
    flex-basis: var(--sidebar-rail);
    width: var(--sidebar-rail);
  }
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-collapse-row {
    justify-content: center;
  }
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-collapse-btn i {
    transform: rotate(180deg);
  }
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-brand img,
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-link span,
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-user-name,
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-label {
    opacity: 0;
    pointer-events: none;
  }
  /* The rail is ~48px of usable width; a 5.6:1 wordmark squeezed into it
     would render about 8px tall, so it is dropped rather than shrunk.
     A square glyph variant of the mark would let the rail keep a brand
     presence here — we only have the wordmark today. */
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-brand {
    padding-bottom: 0.5rem;
  }

  /* The rail hides labels, so sub-items and chevrons must go with them --
     otherwise the rail fills with unlabelled rows that cannot be told apart,
     and a chevron that expands into nothing readable.

     The selector is deliberately as specific as the nav-open-* rules above:
     those win on specificity, not order, so a shorter selector here would be
     silently overridden for whichever section happens to be expanded. */
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-group[data-nav-section] > .sidebar-sublist,
  html.sidebar-collapsed .app-sidebar-fixed .sidebar-parent .sidebar-chevron {
    display: none;
  }
}

/* ============================================================
   Page header
   ============================================================ */
.page-title {
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
}
@media (max-width: 575.98px) {
  .page-title {
    font-size: 1.55rem;
  }
}

/* Back control: a single, subordinate arrow */
.back-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  color: var(--text-muted);
  background: transparent;
  border: 1px solid var(--border);
  text-decoration: none;
  font-size: 1.15rem;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.back-arrow:hover {
  background: var(--surface-hover);
  color: var(--text);
}

/* ============================================================
   Icon button (icon-only action)
   ============================================================ */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.btn-icon:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.btn-icon.is-saved {
  color: var(--saved);
}
.btn-icon.is-read {
  color: var(--type-event);
}

/* ============================================================
   Content filter bar (segmented pills)
   ============================================================ */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1.5rem;
}
.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  border-radius: 999px;
  padding: 0.38rem 0.85rem;
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease,
    color 0.12s ease;
}
.filter-pill:hover {
  border-color: var(--border-strong);
  background: var(--surface-hover);
}
.filter-pill.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-on-accent);
}
.filter-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}

/* ---------- Lavender badge ----------
   For NON-categorical tags only ("Nouveau", "Pro", counts) — never for
   a content type, which must stay on the categorical scale.
   Built tint-fill + ink-label rather than lavender-fill + light-label:
   the base tone reaches only 3.8:1 against white and 3.9:1 against Dark
   Amethyst, so it cannot sit under small text. Here it is confined to
   the border and the dot, where 3:1 for a non-text boundary is enough,
   and the label runs at 6.3:1. */
.badge-soft {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--badge-bg);
  border: 1px solid var(--badge-border);
  color: var(--badge-ink);
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.4;
}
.badge-soft .filter-dot {
  background: var(--badge-border);
}

/* ---- Library filter toolbar ---- */
.library-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.toolbar-spacer {
  flex: 1 1 auto;
}
.toolbar-sep {
  width: 1px;
  align-self: stretch;
  min-height: 1.5rem;
  background: var(--border);
  margin: 0 0.25rem;
}
.filter-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* Category dropdown: click a pill to reveal its checkbox list */
.filter-dd {
  position: relative;
}
.filter-dd-toggle .bi-chevron-down {
  font-size: 0.7rem;
  transition: transform 0.15s ease;
}
.filter-dd.open .filter-dd-toggle .bi-chevron-down {
  transform: rotate(180deg);
}
.filter-dd-toggle.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-on-accent);
}
.filter-dd-count {
  display: inline-block;
  background: var(--accent);
  color: var(--text-on-accent);
  border-radius: 999px;
  font-size: 0.7rem;
  line-height: 1;
  padding: 0.15rem 0.4rem;
  margin-left: 0.35rem;
}
.filter-dd-toggle.active .filter-dd-count {
  background: rgba(255, 255, 255, 0.25);
}
.filter-dd-panel {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 30;
  min-width: 220px;
  max-width: 320px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
  padding: 0.75rem;
}
.filter-dd.open .filter-dd-panel {
  display: block;
}
.filter-checks {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  max-height: 260px;
  overflow-y: auto;
  padding-right: 0.25rem;
}
.filter-check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.88rem;
  cursor: pointer;
  margin: 0;
  white-space: nowrap;
}
.filter-check input {
  cursor: pointer;
  flex-shrink: 0;
}

/* ============================================================
   Content card
   ============================================================ */
.content-card {
  --card-band-width: 56px;
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  /* Re-cut from a coloured border to a right-edge colour band, at the
     user's request against a reference image: the band is the "large
     band on the right", the resting shadow below is what gives the "3D
     impression" they asked for, and dropping the border (D3's original
     device, then thickened twice, then gradiented) is deliberate -- they
     called the border treatment dated, and a shadow-defined edge plus a
     solid colour panel is the more modern one. D9's principle still
     holds: colour is never the only channel, every card still names its
     type in text, and the dot still repeats it in miniature.
     overflow: hidden clips the ::after band below to the card's own
     border-radius, so the band's outer corners never need separate
     radius math -- much simpler than matching a pseudo-element's radius
     to its parent's by hand. */
  overflow: hidden;
  border: none;
  border-radius: var(--radius);
  background: var(--surface);
  /* Resting elevation, not just on :hover any more -- a tight, low-blur
     shadow for a crisp edge close in, plus a softer, wider one further
     out for the "lifted off the page" depth. */
  box-shadow:
    0 1px 3px rgba(20, 20, 40, 0.07),
    0 10px 28px rgba(20, 20, 40, 0.1);
  padding: 1.1rem calc(var(--card-band-width) + 1.15rem) 1.05rem 1.15rem;
  text-decoration: none;
  color: var(--text);
  transition: box-shadow 0.14s ease, transform 0.14s ease;
}
/* Phones: 56px is a wide band to give up on a 300-320px-wide card, and it
   eats into the content column twice (once as its own width, once again in
   the padding that clears it). 40px keeps it clearly "large" per the
   reference without crowding a 360px card. */
@media (max-width: 575.98px) {
  .content-card {
    --card-band-width: 40px;
  }
}
.content-card::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--card-band-width);
  background: var(--border);
}
/* content-card.hbs:4 already stamps data-type from the same Airtable Type
   value the chip below reads, so no new markup is needed here either. */
.content-card[data-type='event']::after {
  background: var(--type-event);
}
.content-card[data-type='article']::after {
  background: var(--type-article);
}
.content-card[data-type='AAP']::after {
  background: var(--type-appel);
}
.content-card:hover {
  box-shadow:
    0 2px 6px rgba(20, 20, 40, 0.1),
    0 16px 36px rgba(20, 20, 40, 0.14);
  transform: translateY(-2px);
  color: var(--text);
}
/* Belt and braces: overflow:hidden (needed to clip the band above to the
   card's own radius) is a known browser inconsistency for an element's OWN
   outline -- some clip it, some don't. The shared outline rule above still
   applies; this box-shadow ring is a fallback that overflow can't touch,
   since box-shadow (unlike descendant content) isn't part of what an
   element's own overflow clips. Layered with the resting elevation so focus
   doesn't flatten the card back out. */
.content-card:focus-visible {
  box-shadow:
    0 1px 3px rgba(20, 20, 40, 0.07),
    0 10px 28px rgba(20, 20, 40, 0.1),
    0 0 0 2px var(--surface),
    0 0 0 4px var(--focus-ring);
}
/* The card's top row: field pictograms left, read/save controls right.

   Settled 2026-09-09 after trying the alternative. The controls spent one
   commit on the title's line; the user preferred them back up here, top
   right. Keep them here.

   space-between does the work, and D3's placeholder is what makes it safe:
   .field-badges always renders something -- a real badge, or the empty-slot
   ring -- so there is always a left-hand child to push the controls right.
   Were that row ever allowed to render empty, the controls would slide left,
   which is precisely the misalignment that prompted this change.

   gap matters at 360px: three 2.25rem badges plus a "+N" plus two 36px icon
   buttons is the widest this row ever gets, on a card already 56px narrower
   for the colour band. */
.content-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.65rem;
}
/* .type-chip and its dot sizing were deleted with the chip itself (to-do10b
   Task 4). The .dot-* rules below are NOT orphaned and must stay: the
   newsletter split bar still uses them as its own legend
   (views/channels/newsletter.hbs, alongside .split-dot). */
.dot-event {
  background: var(--type-event);
}
.dot-article {
  background: var(--type-article);
}
.dot-appel {
  background: var(--type-appel);
}

/* ---- Type filter pills: the app's legend (to-do10b D1/D2) ----
   The three type pills stopped being neutral chips with a coloured dot and
   became the one place the app teaches its colour+icon language, which is
   what lets Task 4 take the type words off the cards. Each pill carries its
   type as a soft fill, a full-strength border and the SAME glyph the card's
   band shows -- teaching the exact mark the user has to recognise later.

   Selection is deliberately NOT a hue change (D2). --type-article resolves
   to the very same value as --accent (see Tier 2), so a "selected" blue
   would be indistinguishable from "article". Instead the active pill thickens its
   border to 2px, bolds its ink and reveals a check. All three are
   perceivable without colour vision, and the border grows via an inset
   shadow rather than border-width so nothing reflows on click.

   "Tous" is not a type and keeps the plain --accent active fill above: it
   must not look like a fourth category. Two selection languages now coexist
   in this toolbar, on purpose. */
.filter-pill[data-filter='event'] {
  background: var(--type-event-soft);
  border-color: var(--type-event);
}
.filter-pill[data-filter='article'] {
  background: var(--type-article-soft);
  border-color: var(--type-article);
}
.filter-pill[data-filter='AAP'] {
  background: var(--type-appel-soft);
  border-color: var(--type-appel);
}
.filter-pill[data-filter='event'] .filter-pill-icon {
  color: var(--type-event);
}
.filter-pill[data-filter='article'] .filter-pill-icon {
  color: var(--type-article);
}
.filter-pill[data-filter='AAP'] .filter-pill-icon {
  color: var(--type-appel);
}
.filter-pill-icon {
  font-size: 1rem;
  line-height: 1;
}
/* Reserved, not conditionally rendered: visibility keeps the glyph's width
   in the layout, so selecting a pill cannot re-wrap the toolbar under it --
   which at 360px would otherwise move the pill out from under the pointer. */
.filter-pill-check {
  visibility: hidden;
  font-size: 0.85rem;
  line-height: 1;
}
.filter-pill[data-filter='event'].active,
.filter-pill[data-filter='article'].active,
.filter-pill[data-filter='AAP'].active {
  color: var(--text);
  font-weight: 700;
}
.filter-pill[data-filter='event'].active {
  background: var(--type-event-soft);
  box-shadow: inset 0 0 0 1px var(--type-event);
}
.filter-pill[data-filter='article'].active {
  background: var(--type-article-soft);
  box-shadow: inset 0 0 0 1px var(--type-article);
}
.filter-pill[data-filter='AAP'].active {
  background: var(--type-appel-soft);
  box-shadow: inset 0 0 0 1px var(--type-appel);
}
.filter-pill.active .filter-pill-check {
  visibility: visible;
}

.content-date {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
}
.content-title {
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.3;
  margin: 0 0 0.6rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.content-meta {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--text-muted);
  margin-bottom: 0.9rem;
}
/* Decorative type icon inside the colour band. z-index:1 is enough to clear
   the band's own ::after (z-index:auto), and pointer-events:none takes it
   out of hit-testing entirely -- unlike .field-badge below, it has no
   tooltip that needs to win a hover, so there's nothing to fight the
   stretched-link overlay over. */
.content-card-type-icon {
  position: absolute;
  top: 50%;
  right: 0;
  width: var(--card-band-width);
  transform: translateY(-50%);
  text-align: center;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--surface);
  z-index: 1;
  pointer-events: none;
}
@media (max-width: 575.98px) {
  .content-card-type-icon {
    font-size: 1.2rem;
  }
}
/* Field pictogram row (D4/D6/D7). Raised above the stretched-link overlay
   the same way .content-card .btn-icon already is -- otherwise the
   invisible full-card link wins every hover and the native title tooltip
   D6 relies on would never fire. The accepted cost, same trade-off the
   save/read buttons already make: a click landing on a badge is swallowed
   rather than navigating, in exchange for the tooltip working at all.

   Sized up 2026-09-09 (1.6rem/0.9rem -> 2.25rem/1.3rem) on live feedback:
   at 14.4px the glyph took several seconds to identify, which defeats the
   point of a pictogram. 20.8px sits just under the band's own 24px type
   icon, so the type still leads the hierarchy. Note the cost this raises:
   the swallowed-click area above grows with it. */
.field-badges {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  position: relative;
  z-index: 2;
  /* to-do10b Task 5 -- the decision this task was asked to price, resolved
     in favour of the card. These badges used to be hit-testable so their
     native `title` could beat the stretched-link overlay (to-do10 D6's
     desktop-hover half). Two things changed: D4 made the OVERLAY the place
     field names are read, and it lists every field uncapped -- so both the
     badge tooltip and the "+N" tooltip now repeat something a tap away --
     and Task 5 moved this row to the card's most prominent slot while the
     glyphs had just grown to 2.25rem. Keeping it would have handed roughly
     a third of the card's top row to a dead zone that swallows clicks.
     So: click-through, `title` removed rather than left as markup that can
     never fire, and the names reach assistive tech via role="img" +
     aria-label, which pointer-events does not affect. z-index stays for
     paint order only; it no longer does any hit-testing work. */
  pointer-events: none;
}
.field-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--surface-hover);
  color: var(--text-muted);
  font-size: 1.3rem;
  cursor: default;
}
.field-badge-overflow {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
}
/* D3's empty slot. Deliberately NOT .field-badge: an unfilled dashed ring
   against the card, where a real domain is a filled circle. That difference
   is the whole decision -- if this reads as a domain, most of the grid says
   every content is "about nothing". Muted glyph measures 6.09:1 on
   --surface, well clear of the 3:1 its role="img" makes it subject to. */
.field-badge-empty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 1px dashed var(--border-strong);
  background: none;
  color: var(--text-muted);
  font-size: 1.1rem;
}
.content-card-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  /* Never squeezed by a long title: the title takes the slack instead
     (flex:1 1 auto + min-width:0 above). */
  flex: 0 0 auto;
}
.content-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
}
.seen-flag {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  color: var(--type-event);
  font-weight: 500;
}
/* The "Déjà vu" flag only shows once the card is marked read; the eye button
   toggles .is-read on the card for instant optimistic feedback. */
.content-card-foot .seen-flag {
  display: none;
}
.content-card.is-read .content-card-foot .seen-flag {
  display: inline-flex;
}
/* Read toggle in the content detail header (labeled .btn on dark chrome).
   Scoped to .btn so the icon-only .btn-icon variant in cards is unaffected. */
/* Both "active state" buttons on the detail page's Dark Amethyst
   chrome work the same way: a near-white scrim carrying the state's
   own colour. Neither state colour can sit directly on the chrome —
   the categorical green lands at 2.78:1 on Dark Amethyst and Indigo
   (--saved) at 1.63:1 — so the light fill is what makes them legible,
   at 5.29:1 and 9.06:1 respectively. */
.btn.read-btn.is-read {
  background: rgba(255, 255, 255, 0.92);
  color: var(--type-event);
  border-color: rgba(255, 255, 255, 0.92);
}
/* Was .btn-saved, a separate class name swapped in server-side when the
   detail page's save control was a real <form> submit (to-do10 Task 9
   converted it to the same save-btn/is-saved AJAX toggle the card already
   uses, to fix a bug: submitting that form navigated away from the modal
   overlay). Renamed to match .read-btn.is-read's own pattern above -- one
   base class, .is-saved as the sole state modifier -- rather than keep two
   different conventions for the same shape of thing. */
.btn.save-btn.is-saved {
  background: rgba(255, 255, 255, 0.92);
  color: var(--saved);
  border: 1px solid rgba(255, 255, 255, 0.92);
  font-weight: 600;
}
.btn.save-btn.is-saved:hover,
.btn.save-btn.is-saved:focus-visible {
  background: var(--surface);
  color: var(--cta-strong);
  border-color: var(--surface);
}
/* keep the save control above the card-wide link */
.content-card .btn-icon {
  position: relative;
  z-index: 2;
}

/* Field pictograms in the detail overlay (to-do10 Task 8, D6). Unlike the
   card's icon-only row, the name is always visible here, so there's no
   stretched-link to out-stack and no tooltip to defend -- these are plain
   inline badges. */
.detail-field-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.detail-field-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  background: var(--surface-hover);
  font-size: 0.85rem;
}

/* Type marker in the detail overlay header (to-do10b D6). The overlay had
   no type marker of any kind, so removing the card chip would have left a
   user who opens a content unable to see its type anywhere.

   It reuses Task 3's legend tokens on purpose: the badge and the filter
   pill are visibly the same object, which is what makes the toolbar's
   lesson transfer here. It cannot use the base type colours: measured
   against the dark header (--bs-dark) they are 2.78 / 1.89 / 3.64, so two
   of the three fail even the 3:1 non-text gate. The tint fill clears it at
   10.88-12.75, with near-black ink on the tint at 11.39-13.35. */
.detail-type-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.detail-type-badge[data-type='event'] {
  background: var(--type-event-soft);
}
.detail-type-badge[data-type='article'] {
  background: var(--type-article-soft);
}
.detail-type-badge[data-type='AAP'] {
  background: var(--type-appel-soft);
}

/* Content detail overlay (to-do10 D1/Task 9). The injected fragment is the
   same .card the full page renders, complete with its own shadow and
   rounded corners -- .modal-content is stripped to transparent/borderless so
   that card is the only visible surface, not a card nested inside a second
   one. Close button floats above it in the strip padding-top clears. */
#contentDetailModal .modal-content {
  position: relative;
  background: transparent;
  border: 0;
  padding-top: 2.75rem;
}
#contentDetailModal .content-detail-modal-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 1;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background-color: var(--surface);
  opacity: 1;
}
#contentDetailModal .content-detail-modal-close:hover {
  background-color: var(--surface-hover);
}

/* ============================================================
   Ma Start-up — profile layout
   ============================================================ */
.section-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.25rem 1.35rem;
  height: 100%;
}
.section-card-title {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 700;
  margin-bottom: 1rem;
}
/* Center column: the newsletter-impacting fields, visually distinguished.
   Used to be a warm cream wash (D1(b) [to-do4]); Pale Amber reads as
   Orange's close hue-neighbour, which now means "appel à projet"
   elsewhere on the same screen, so a warm gradient here started reading
   as an unrelated type colour. Removed 2026-09-06 at the user's request
   during to-do10 Task 1 -- the left accent border is now the section's
   only visual distinguisher, still --accent (Indigo), unchanged. */
.section-newsletter {
  border-left: 4px solid var(--accent);
  background: var(--surface);
}
.section-newsletter .section-card-title {
  color: var(--text);
}
/* Soft lavender rules inside the emphasis surface, per the palette's
   "borders & dividers on decorated surfaces" role. */
.section-newsletter hr {
  border-color: var(--divider-soft);
  opacity: 0.35;
}

/* ---------- Profile completion ring ---------- */
/* The filled arc sweeps Indigo Bloom -> Lavender Purple: the palette's
   one gradient, spent on the single element that is genuinely about
   progress. The trailing `var(--border) 0` clamps to the previous stop,
   which is what gives the hard edge between arc and track. */
.completion-ring {
  --p: 0;
  --ring: var(--progress-from);
  --ring-end: var(--progress-to);
  width: 132px;
  height: 132px;
  border-radius: 50%;
  margin: 0.25rem auto 1rem;
  display: grid;
  place-items: center;
  background: conic-gradient(
    var(--ring) 0deg,
    var(--ring-end) calc(var(--p) * 3.6deg),
    var(--border) 0
  );
}
.completion-ring__hole {
  width: 102px;
  height: 102px;
  border-radius: 50%;
  background: var(--surface);
  display: grid;
  place-items: center;
  text-align: center;
}
.completion-ring__value {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
}
.completion-ring__label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-top: 0.2rem;
}

.profile-avatar-lg {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--accent);
  color: var(--text-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  font-weight: 700;
}

/* ============================================================
   Split repartition bar
   ============================================================ */
.split-bar-wrapper {
  position: relative;
  height: 44px;
  display: flex;
  align-items: center;
}
.split-bar-track {
  position: absolute;
  left: 0; right: 0;
  height: 8px;
  border-radius: 4px;
  background: var(--border);
  overflow: hidden;
}
.split-bar-fill {
  position: absolute;
  inset: 0;
  border-radius: 4px;
  transition: background 0.1s linear;
}
.split-bar-thumb {
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  border: none;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  pointer-events: none;
}
.split-bar-thumb::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
  box-shadow: 0 1px 4px rgba(0,0,0,0.18);
  cursor: pointer;
  pointer-events: all;
}
.split-bar-thumb::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
  box-shadow: 0 1px 4px rgba(0,0,0,0.18);
  cursor: pointer;
  pointer-events: all;
}
.split-bar-thumb:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.split-bar-legend {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.6rem;
  font-size: 0.82rem;
  color: var(--text-muted);
}
.split-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}

/* ---------- Agenda rows — À venir / En cours (Mes enregistrements) ---------- */
.agenda-item {
  background: var(--surface-alt);
  transition: background-color 0.12s ease, transform 0.12s ease;
}
.agenda-item:hover {
  background: var(--surface-alt-hover);
  transform: translateX(2px);
}

/* ============================================================
   Landing page (views/home/index.hbs)
   Lifted out of a <style> block inside the template, where ~30 colour
   literals sat beyond the reach of the token layer — including two
   leaks of Bootstrap's own blue in the mad-libs inputs and the value
   icons, which is why the public page never matched the product.
   ============================================================ */
.hero-section {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: linear-gradient(
    160deg,
    var(--hero-from) 0%,
    var(--surface) 55%,
    var(--hero-to) 100%
  );
  padding: 4rem 1rem;
}
.hero-section img {
  display: block;
}
.hero-tagline {
  font-size: clamp(2rem, 5vw, 3.25rem);
  font-weight: 800;
  color: var(--text);
  line-height: 1.15;
  max-width: 700px;
}
.hero-sub {
  max-width: 520px;
  font-size: 1.05rem;
}
.hero-values {
  max-width: 900px;
  width: 100%;
}

/* The page's one committing action wears the CTA; "Connexion" is the
   quieter twin and takes an outline rather than a second fill. */
.hero-cta {
  background: var(--cta);
  color: var(--text-on-cta);
  border-radius: 50px;
  padding: 0.85rem 2.5rem;
  font-size: 1rem;
  font-weight: 600;
  border: 2px solid var(--cta);
  text-decoration: none;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.hero-cta:hover {
  background: var(--cta-strong);
  border-color: var(--cta-strong);
  color: var(--text-on-cta);
}
.hero-cta-secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--text);
}
.hero-cta-secondary:hover {
  background: var(--surface-hover);
  border-color: var(--text);
  color: var(--text);
}

/* ---------- Value cards ---------- */
.value-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 2rem 1.5rem;
  text-align: center;
  opacity: 0;
  transform: translateY(30px);
  animation: fadeInUp 0.6s ease forwards;
}
.value-card:nth-child(1) { animation-delay: 0.1s; }
.value-card:nth-child(2) { animation-delay: 0.25s; }
.value-card:nth-child(3) { animation-delay: 0.4s; }
@keyframes fadeInUp {
  to { opacity: 1; transform: translateY(0); }
}
/* Honour a reduced-motion preference: the cards animate in from
   opacity 0, so without this they would simply never appear. */
@media (prefers-reduced-motion: reduce) {
  .value-card {
    animation: none;
    opacity: 1;
    transform: none;
  }
}
.value-icon {
  font-size: 2.25rem;
  color: var(--accent);
  margin-bottom: 1rem;
}
.value-card h5 {
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.5rem;
}
.value-card p {
  color: var(--text-muted);
  font-size: 0.93rem;
  margin: 0;
}

/* ---------- Try-it section ----------
   The landing page's Almond Cream band — the same emphasis role cream
   plays on the newsletter card, at full width. */
.tryit-section {
  background: var(--surface-warm);
  padding: 5rem 1rem;
}
.tryit-container {
  max-width: 860px;
}
.tryit-section h2 {
  font-size: clamp(1.6rem, 3.5vw, 2.4rem);
  font-weight: 800;
  color: var(--text);
  margin-bottom: 0.5rem;
}
.tryit-section .lead {
  color: var(--text-muted);
}

/* ---------- Mad-libs inline inputs ---------- */
.madlib-sentence {
  font-size: 1.2rem;
  color: var(--text);
  line-height: 2.2;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
}
.madlib-input,
.madlib-select {
  display: inline-block;
  border: none;
  border-bottom: 2px solid var(--accent);
  background: transparent;
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--accent);
  outline: none;
  padding: 0 0.25rem;
  min-width: 120px;
  border-radius: 0;
}
.madlib-select {
  cursor: pointer;
}
.madlib-input::placeholder {
  color: var(--text-muted);
  font-weight: 400;
}
/* These drop Bootstrap's outline via `outline: none`, so they need a
   focus indicator of their own or keyboard users lose the caret. */
.madlib-input:focus-visible,
.madlib-select:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: 3px;
}

.generate-btn {
  background: var(--border-strong);
  color: var(--text-muted);
  border-radius: 50px;
  padding: 0.8rem 2.2rem;
  font-size: 1rem;
  font-weight: 600;
  border: none;
  cursor: not-allowed;
}

/* ---------- Newsletter preview mockup ---------- */
.preview-card {
  background: var(--surface);
  border: 2px dashed var(--border-strong);
  border-radius: 20px;
  padding: 2rem 2.5rem;
}
.preview-card .preview-title {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 1.25rem;
}
.skeleton-line {
  height: 12px;
  background: linear-gradient(
    90deg,
    var(--border) 25%,
    var(--surface-hover) 50%,
    var(--border) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.6s infinite;
  border-radius: 6px;
  margin-bottom: 0.75rem;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-line {
    animation: none;
  }
}
.skeleton-badge {
  display: inline-block;
  border: 2px dashed var(--border-strong);
  border-radius: 50px;
  padding: 0.35rem 1.2rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-style: italic;
}

/* ---------- Access code page (to-do6 Task 7) ----------
   Rendered by the public branch of the layout, so it has no sidebar and sets
   its own measure. Tokens only: no hex enters this block. */
.access-code-page {
  max-width: 30rem;
  margin: 0 auto;
  padding: 1.5rem 0 3rem;
}

/* Upper-case and English on purpose — this is the brand mark, not a heading
   that slipped translation (D6). */
.access-code-title {
  margin: 0 0 1.5rem;
  color: var(--text);
  font-size: clamp(1.25rem, 5vw, 1.75rem);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-align: center;
}

.access-code-info {
  position: relative;
  padding: 1.75rem 1.25rem 1.5rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
}
.access-code-lede {
  margin: 0;
  color: var(--text);
}

.access-code-hint-trigger {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--accent);
  cursor: pointer;
  font-size: 1rem;
}
.access-code-hint-trigger:hover {
  background: var(--accent-soft);
}
.access-code-hint-trigger:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* In flow, below the lede — not a floating bubble. Overlaying the card meant
   the warning covered the very sentence it qualifies, so opening it now pushes
   the card taller instead.

   Shown on hover *and* on plain :focus. Not :focus-visible: a tap on a phone
   focuses the button without matching it, and touch is exactly where this must
   work — there is no hover there at all. */
.access-code-hint-bubble {
  display: none;
  margin: 0.9rem 0 0;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--tint-warning-border);
  border-radius: var(--radius-sm);
  background: var(--tint-warning-bg);
  color: var(--tint-warning-ink);
  font-size: 0.85rem;
  line-height: 1.4;
  text-align: left;
}
.access-code-hint-trigger:hover ~ .access-code-hint-bubble,
.access-code-hint-trigger:focus ~ .access-code-hint-bubble {
  display: block;
}

.access-code-alert {
  margin: 1rem 0 0;
  padding: 0.75rem 1rem;
  border: 1px solid var(--tint-danger-border);
  border-radius: var(--radius-sm);
  background: var(--tint-danger-bg);
  color: var(--tint-danger-ink);
  font-size: 0.9rem;
  text-align: center;
}
/* Locked is a wait, not a mistake — amber rather than red. */
.access-code-alert.is-locked {
  border-color: var(--tint-warning-border);
  background: var(--tint-warning-bg);
  color: var(--tint-warning-ink);
}

.access-code-form {
  display: grid;
  gap: 1rem;
  margin-top: 1.5rem;
}
/* Codes are shown upper-case (D7). The allowlist accepts either case and
   normalises, so this is presentation — it never decides acceptance. */
.access-code-input {
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.access-code-input::placeholder {
  text-transform: none;
  letter-spacing: normal;
}
/* Once the field is focused the hint has done its job and is competing with
   what the user is typing. */
.access-code-input:focus::placeholder {
  opacity: 0.4;
}

/* ============================================================
   Shared toast (MonitoraUI.showToast) -- mainly session.js's expired-
   session notice, which can fire from any AJAX surface (the grid, a save
   button, the content overlay), so it needs one landing spot that isn't
   tied to a specific button or container.
   ============================================================ */
.monitora-toast {
  position: fixed;
  top: 1rem;
  left: 50%;
  transform: translateX(-50%) translateY(-0.5rem);
  z-index: 2000;
  max-width: min(90vw, 420px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.monitora-toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
