/* Auto-generated by fulgore:css:bundle — do not edit manually */

/* fulgore: auth/mfa_challenge_form.css */
.auth-mfa-challenge-form {
  max-width: 28rem;
  margin: var(--space-16) auto;
  display: grid;
  gap: var(--space-6);
}

.auth-mfa-challenge-form h2 {
  margin: 0;
}

.auth-mfa-challenge-form form {
  display: grid;
  gap: var(--space-5);
}


/* fulgore: auth/mfa_disable_modal.css */
.mfa-disable-modal__icon {
  text-align: center;
  font-size: 2rem;
  margin-bottom: var(--space-2);
}

.mfa-disable-modal__warning {
  color: var(--color-text-subtle);
  text-align: center;
  line-height: var(--line-height-loose);
}


/* fulgore: auth/mfa_setup_form.css */
/* LE QR A BESOIN D'UN FOND CLAIR, SINON IL NE SE SCANNE PAS.
   RQRCode le peint en `#000` et ne pose aucun fond (Mfa::Enroll, `color: "000"`).
   Un consumer dont le gabarit d'accès est sombre obtient donc du noir sur noir :
   mesuré au rendu WebKit sur Fatima le 2026-08-31, 1,03:1 de contraste. Le QR
   était bien là, bien centré, bien dimensionné — et parfaitement inscannable,
   donc personne ne s'enrôlait et personne n'entrait dans l'admin.

   Aucun spec ne pouvait le voir : la couleur des modules vit dans les octets du
   SVG, pas dans un style calculé. C'est la capture qui l'a sorti.

   La marge n'est pas décorative : les lecteurs de QR attendent une zone de
   silence autour du motif pour l'accrocher. */
.auth-mfa-setup-form {
  .mfa-qr-code {
    display: flex;
    justify-content: center;
    margin-block: var(--space-4);
    margin-inline: auto;
    width: fit-content;
    background: #fff;
    padding: var(--space-4);
    border-radius: var(--radius-md);
  }
}


/* fulgore: fulgore/shop/admin/countries/country_code.css */
.fulgore-shop-admin-countries-country-code {
  font-size: var(--font-size-5xl);
}


/* fulgore: fulgore/shop/admin/countries/country_infos.css */
.fulgore-shop-admin-countries-country-infos {
  width: 100%;
  font-size: var(--font-size-base);
}


/* fulgore: fulgore/shop/admin/countries/main_section.css */
.fulgore-shop-admin-countries-main-section .section-cell {
  display: flex;
}


/* fulgore: fulgore/shop/admin/countries/percentage.css */
.fulgore-shop-admin-countries-percentage {
  margin-left: auto;
  font-size: var(--font-size-5xl);
  text-align: right;
}


/* fulgore: fulgore/shop/admin/formats/form.css */
/* ── Inline create form ── */

.fulgore-shop-admin-formats-form--inline.ui-form {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.fulgore-shop-admin-formats-form--inline .ui-bases-input {
  flex: 1;
  margin-bottom: 0;
}

.fulgore-shop-admin-formats-form--inline .form-actions {
  margin-top: 0;
}


/* fulgore: fulgore/shop/admin/formats/row.css */
/* ── Inline form (display: contents to not break table layout) ── */

.fulgore-shop-admin-formats-row__form {
  display: contents;
}

/* ── Inline inputs ── */

.fulgore-shop-admin-formats-row__input {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-size: var(--font-size-sm);
  background: var(--color-surface);
}

.fulgore-shop-admin-formats-row__input--text {
  width: 100%;
}

.fulgore-shop-admin-formats-row__input--number {
  width: 5rem;
  text-align: right;
}

.fulgore-shop-admin-formats-row__right {
  text-align: right;
}

/* ── Ligne implicite : cellules sans champ (nom, max par panier) ── */

.fulgore-shop-admin-formats-row__placeholder {
  color: var(--color-text-muted);
  font-style: italic;
}

/* ── Save button ── */

.fulgore-shop-admin-formats-row__save {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1);
  cursor: pointer;
  font-size: var(--font-size-sm);
  line-height: 1;
}

.fulgore-shop-admin-formats-row__save:hover {
  background: var(--color-surface-subtle);
}

/* ── Delete link ── */

.fulgore-shop-admin-formats-row__delete {
  font-size: var(--font-size-sm);
  color: var(--color-danger);
  text-decoration: none;
  padding: var(--space-1);
}

.fulgore-shop-admin-formats-row__delete:hover {
  text-decoration: underline;
}


/* fulgore: fulgore/shop/admin/order_line_items/row.css */
.fulgore-shop-admin-order-line-items-row__product {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}


/* fulgore: fulgore/shop/admin/orders/amounts.css */
.fulgore-shop-admin-orders-amounts {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* ── Group titles ── */

.fulgore-shop-admin-orders-amounts__group-title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0 0 var(--space-2) 0;
}

/* ── Stats grid ── */

.fulgore-shop-admin-orders-amounts__stats {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin: 0;
}

.fulgore-shop-admin-orders-amounts__stat-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  font-weight: var(--font-weight-medium);
  position: relative;
}

.fulgore-shop-admin-orders-amounts__stat-icon {
  font-size: var(--font-size-base);
}

.fulgore-shop-admin-orders-amounts__stat-value {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
  text-align: right;
}

/* ── Group variants ── */

.fulgore-shop-admin-orders-amounts__group--incomes .fulgore-shop-admin-orders-amounts__stat-value {
  color: var(--color-success);
}

.fulgore-shop-admin-orders-amounts__group--expenses .fulgore-shop-admin-orders-amounts__stat-value {
  color: var(--color-danger);
}

.fulgore-shop-admin-orders-amounts__group--bottom_line {
  border-top: 1px solid var(--color-border-strong);
  padding-top: var(--space-4);
}

.fulgore-shop-admin-orders-amounts__group--bottom_line .fulgore-shop-admin-orders-amounts__stat-value {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
}

/* ── Tooltip repositioning ── */

.fulgore-shop-admin-orders-amounts .ui-help-tooltip__panel {
  top: calc(100% + var(--space-1));
  right: auto;
  left: 0;
  transform: none;
}


/* fulgore: fulgore/shop/admin/orders/items_section.css */
.fulgore-shop-admin-orders-items-section__summary {
  display: flex;
  gap: var(--space-6);
  justify-content: flex-end;
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-4);
}

.fulgore-shop-admin-orders-items-section__summary-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}


/* fulgore: fulgore/shop/admin/orders/show.css */
/* Le pied d'un panneau (lien « voir le client ») se range à droite. Le sélecteur
   vise la classe de la gem posée sur la disposition (`layout_class`), pas celle
   de la racine : une sous-classe du site porte un autre nom de racine. */
.fulgore-shop-admin-orders-show__layout .ui-section__footer {
  justify-content: flex-end;
}


/* fulgore: fulgore/shop/admin/prices/form.css */
/* ── Inline create form ── */

.fulgore-shop-admin-prices-form--inline.ui-form {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.fulgore-shop-admin-prices-form--inline .ui-bases-input {
  flex: 1;
  margin-bottom: 0;
}

.fulgore-shop-admin-prices-form--inline .form-actions {
  margin-top: 0;
}


/* fulgore: fulgore/shop/admin/prices/row.css */
/* ── Active row highlight ── */

.fulgore-shop-admin-prices-row--active {
  background: var(--color-success-surface);
}

.fulgore-shop-admin-prices-row__right {
  text-align: right;
}


/* fulgore: fulgore/shop/admin/products/card.css */
/* ── Header left (status under title) ── */

.fulgore-shop-admin-products-card__header-left {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-start;
}


/* fulgore: fulgore/shop/admin/products/form.css */
/* ── Field groups ── */

.fulgore-shop-admin-products-form__group {
  border: none;
  padding: 0;
  margin: 0;
}

.fulgore-shop-admin-products-form__separator {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-3) 0;
}


/* fulgore: fulgore/shop/admin/products/formats_form_section.css */
/* ⚠️ NE RIEN REDÉCLARER ICI DE CE QUE `ui-list-table` FOURNIT DÉJÀ — largeur,
   fusion des bordures, `font-size`, et le padding / l'alignement / la bordure
   basse des cellules viennent de fulgore (`ui/bases/list.css`), avec en prime
   la bascule en pile de cartes sous 768 px. Ne restent ci-dessous que ce que
   la gem ne donne pas. */

.fulgore-shop-admin-products-formats-form-section__table {
  margin-top: var(--space-3);
}

.fulgore-shop-admin-products-formats-form-section__right {
  text-align: right;
}


/* fulgore: fulgore/shop/admin/products/formats_section.css */
/* ⚠️ NE RIEN REDÉCLARER ICI DE CE QUE `ui-list-table` FOURNIT DÉJÀ — largeur,
   fusion des bordures, `font-size`, et le padding / l'alignement / la bordure
   basse des cellules viennent de fulgore (`ui/bases/list.css`), avec en prime
   la bascule en pile de cartes sous 768 px. Les règles `__table`, `__table th`
   et `__table td` qui vivaient ici faisaient exactement ce doublon, et au même
   poids de sélecteur : à spécificité égale, c'est l'ordre de concaténation du
   paquet qui aurait tranché, donc en silence.
   Ne restent ci-dessous que ce que la gem ne donne pas. */

.fulgore-shop-admin-products-formats-section__table tr:last-child td {
  border-bottom: none;
}

.fulgore-shop-admin-products-formats-section__right {
  text-align: right;
}

/* ── Ligne implicite : nom et max n'ont pas de valeur propre ── */

.fulgore-shop-admin-products-formats-section__placeholder {
  color: var(--color-text-muted);
  font-style: italic;
}


/* fulgore: fulgore/shop/admin/products/pictures_form_section.css */
/* ── Grid ── */

.fulgore-shop-admin-products-pictures-form-section__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

/* ── Ghost (drop indicator) ── */

.fulgore-shop-admin-products-pictures-form-section__ghost {
  aspect-ratio: 1;
  border: 2px dashed var(--color-brand);
  border-radius: var(--radius-md);
  background: var(--color-surface-subtle);
}

/* ── Card ── */

.fulgore-shop-admin-products-pictures-form-section__card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
  cursor: grab;
}

.fulgore-shop-admin-products-pictures-form-section__card--main {
  outline: 3px solid var(--color-brand);
  outline-offset: -3px;
}

.fulgore-shop-admin-products-pictures-form-section__card--dragging {
  opacity: 0.3;
}

/* ── Image wrapper (position context for overlays) ── */

.fulgore-shop-admin-products-pictures-form-section__image-wrapper {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
}

.fulgore-shop-admin-products-pictures-form-section__image,
.fulgore-shop-admin-products-pictures-form-section__image-wrapper picture,
.fulgore-shop-admin-products-pictures-form-section__image-wrapper img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── Overlay buttons (appear on hover) ── */

.fulgore-shop-admin-products-pictures-form-section__overlay-btn {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  margin: 0;
  border: none;
  border-radius: 50%;
  font-size: 14px;
  line-height: 1;
  color: var(--color-text-inverted);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.fulgore-shop-admin-products-pictures-form-section__card:hover .fulgore-shop-admin-products-pictures-form-section__overlay-btn {
  opacity: 1;
}

.fulgore-shop-admin-products-pictures-form-section__overlay-btn--presets {
  top: var(--space-2);
  left: var(--space-2);
  background: rgba(0, 0, 0, 0.6);
}

.fulgore-shop-admin-products-pictures-form-section__overlay-btn--presets:hover {
  background: rgba(0, 0, 0, 0.85);
}

.fulgore-shop-admin-products-pictures-form-section__overlay-btn--delete {
  top: var(--space-2);
  right: var(--space-2);
  background: var(--color-danger);
}

.fulgore-shop-admin-products-pictures-form-section__overlay-btn--delete:hover {
  background: var(--color-danger-dark);
}

/* ── Main badge (overlay bottom-left) ── */

.fulgore-shop-admin-products-pictures-form-section__main-badge {
  position: absolute;
  bottom: var(--space-2);
  left: var(--space-2);
  z-index: 1;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--color-text-inverted);
  background: var(--color-brand);
  border-radius: var(--radius-sm);
}

/* ── "Définir" button (overlay bottom-left, same position as badge) ── */

.fulgore-shop-admin-products-pictures-form-section__main-btn {
  position: absolute;
  bottom: var(--space-2);
  left: var(--space-2);
  z-index: 1;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--color-text-inverted);
  background: rgba(0, 0, 0, 0.5);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.fulgore-shop-admin-products-pictures-form-section__card:hover .fulgore-shop-admin-products-pictures-form-section__main-btn {
  opacity: 1;
}

.fulgore-shop-admin-products-pictures-form-section__main-btn:hover {
  background: var(--color-brand);
}

/* ── Alt form (below image) ── */

.fulgore-shop-admin-products-pictures-form-section__alt-form {
  padding: var(--space-2);
}

/* ── Mobile ── */

@media (max-width: 640px) {
  .fulgore-shop-admin-products-pictures-form-section__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
  }

  .fulgore-shop-admin-products-pictures-form-section__alt-form {
    display: none;
  }

  .fulgore-shop-admin-products-pictures-form-section__overlay-btn {
    opacity: 1;
    width: 22px;
    height: 22px;
    font-size: 12px;
  }

  .fulgore-shop-admin-products-pictures-form-section__main-badge {
    font-size: 9px;
    padding: 1px 4px;
  }

  .fulgore-shop-admin-products-pictures-form-section__main-btn {
    opacity: 1;
    font-size: 9px;
    padding: 1px 4px;
  }
}


/* fulgore: fulgore/shop/admin/products/pictures_section.css */
.fulgore-shop-admin-products-pictures-section__main {
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: var(--space-4);
}

.fulgore-shop-admin-products-pictures-section__main picture {
  display: block;
  aspect-ratio: 1;
}

.fulgore-shop-admin-products-pictures-section__main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.fulgore-shop-admin-products-pictures-section__thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: var(--space-2);
}

.fulgore-shop-admin-products-pictures-section__thumb {
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 2px solid var(--color-border);
}

.fulgore-shop-admin-products-pictures-section__thumb picture {
  display: block;
  aspect-ratio: 1;
}

.fulgore-shop-admin-products-pictures-section__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* fulgore: fulgore/shop/admin/products/prices_form_section.css */
/* ⚠️ NE RIEN REDÉCLARER ICI DE CE QUE `ui-list-table` FOURNIT DÉJÀ — largeur,
   fusion des bordures, `font-size`, et le padding / l'alignement / la bordure
   basse des cellules viennent de fulgore (`ui/bases/list.css`), avec en prime
   la bascule en pile de cartes sous 768 px. Ne restent ci-dessous que ce que
   la gem ne donne pas. */

.fulgore-shop-admin-products-prices-form-section__table {
  margin-top: var(--space-3);
}

.fulgore-shop-admin-products-prices-form-section__right {
  text-align: right;
}


/* fulgore: fulgore/shop/admin/products/prices_section.css */
/* ⚠️ NE RIEN REDÉCLARER ICI DE CE QUE `ui-list-table` FOURNIT DÉJÀ — largeur,
   fusion des bordures, `font-size`, et le padding / l'alignement / la bordure
   basse des cellules viennent de fulgore (`ui/bases/list.css`), avec en prime
   la bascule en pile de cartes sous 768 px. Les règles `__table`, `__table th`
   et `__table td` qui vivaient ici faisaient exactement ce doublon, et au même
   poids de sélecteur : à spécificité égale, c'est l'ordre de concaténation du
   paquet qui aurait tranché, donc en silence.
   Ne restent ci-dessous que ce que la gem ne donne pas. */

.fulgore-shop-admin-products-prices-section__table tr:last-child td {
  border-bottom: none;
}

.fulgore-shop-admin-products-prices-section__right {
  text-align: right;
}


/* fulgore: fulgore/shop/admin/products/progression_section.css */
.fulgore-shop-admin-products-progression-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* ── Checklist ── */

.fulgore-shop-admin-products-progression-section__checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.fulgore-shop-admin-products-progression-section__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

.fulgore-shop-admin-products-progression-section__item--validated {
  color: var(--color-success);
}

.fulgore-shop-admin-products-progression-section__item--pending {
  color: var(--color-text-subtle);
}


/* fulgore: fulgore/shop/admin/products/seo_translations_section.css */
.fulgore-shop-admin-products-seo-translations-section__seo-title {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-brand);
  margin-bottom: var(--space-1);
}

.fulgore-shop-admin-products-seo-translations-section__seo-keywords {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  margin-bottom: var(--space-1);
}

.fulgore-shop-admin-products-seo-translations-section__seo-description {
  font-size: var(--font-size-sm);
  color: var(--color-text);
}


/* fulgore: fulgore/shop/admin/products/stats_section.css */
.fulgore-shop-admin-products-stats-section__stats {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0;
}

.fulgore-shop-admin-products-stats-section__stat-label {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  font-weight: var(--font-weight-medium);
}

/* Reposition tooltips below trigger (default opens left, clipped by sidebar) */
.fulgore-shop-admin-products-stats-section .ui-help-tooltip__panel {
  top: calc(100% + var(--space-1));
  right: auto;
  left: 0;
  transform: none;
}

.fulgore-shop-admin-products-stats-section__stat-icon {
  font-size: var(--font-size-base);
}

.fulgore-shop-admin-products-stats-section__stat-value {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
  text-align: right;
}


/* fulgore: fulgore/shop/admin/products/stripe_section.css */
.fulgore-shop-admin-products-stripe-section__inspect {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: none;
  padding: var(--space-1);
  cursor: pointer;
  border-radius: var(--radius-md);
  font-size: var(--font-size-sm);
  color: var(--color-text);
}

.fulgore-shop-admin-products-stripe-section__inspect::after {
  content: "▸";
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  transition: transform var(--duration-fast);
}

.fulgore-shop-admin-products-stripe-section[data-collapsible-collapsed-value="false"] .fulgore-shop-admin-products-stripe-section__inspect::after {
  transform: rotate(90deg);
}

.fulgore-shop-admin-products-stripe-section__inspect:hover {
  background: var(--color-surface-subtle);
}

.fulgore-shop-admin-products-stripe-section__stripe-id {
  font-family: var(--font-family-mono);
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
}

.fulgore-shop-admin-products-stripe-section__code {
  margin-top: var(--space-3);
  padding: var(--space-3);
  background: var(--color-surface-subtle);
  border-radius: var(--radius-md);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-mono);
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-all;
}


/* fulgore: fulgore/shop/admin/shipping_rates/rates_table.css */
.fulgore-shop-admin-shipping-rates-rates-table {
  margin-block: var(--space-6);
}

.fulgore-shop-admin-shipping-rates-rates-table__title {
  font-size: var(--font-size-lg);
  margin-bottom: var(--space-3);
}


/* fulgore: fulgore/shop/admin/shipping_rates/unit_amount.css */
.fulgore-shop-admin-shipping-rates-unit-amount {
  text-align: right;
}


/* fulgore: fulgore/shop/admin/stocks/count_form.css */
/* Le `<p>` d'introduction : marge basse maîtrisée, plus de blanc hérité. */
.fulgore-shop-admin-stocks-count-form__intro {
  margin: 0 0 var(--space-4);
}

/* Solde en base, rappelé avant la saisie du comptage. */
.fulgore-shop-admin-stocks-count-form__balance {
  margin: 0 0 var(--space-4);
  color: var(--color-text-muted);
}


/* fulgore: fulgore/shop/admin/stocks/index.css */
/* La barre de filtre (un `<form>` fulgore sans classe) touchait le tableau. */
.fulgore-shop-admin-stocks-index__filters {
  margin-bottom: var(--space-4);
}


/* fulgore: fulgore/shop/admin/stocks/movements_panel.css */
.fulgore-shop-admin-stocks-movements-panel {
  font-size: var(--font-size-sm);
}

.fulgore-shop-admin-stocks-movements-panel--empty {
  color: var(--color-text-subtle);
  font-style: italic;
}

/* ── Disclosure ── */

.fulgore-shop-admin-stocks-movements-panel__summary {
  cursor: pointer;
  color: var(--color-text-subtle);
}

.fulgore-shop-admin-stocks-movements-panel__summary:hover {
  color: var(--color-text);
}

.fulgore-shop-admin-stocks-movements-panel__summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ── Journal ── */

.fulgore-shop-admin-stocks-movements-panel__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: var(--space-2) 0 0;
  padding: 0 0 0 var(--space-5);
  list-style: none;
}

.fulgore-shop-admin-stocks-movements-panel__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-3);
}

.fulgore-shop-admin-stocks-movements-panel__date {
  white-space: nowrap;
  color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
}

/* Une entrée et une sortie se lisent au signe, pas au chiffre. */
.fulgore-shop-admin-stocks-movements-panel__quantity {
  min-width: 4ch;
  text-align: right;
  white-space: nowrap;
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}

.fulgore-shop-admin-stocks-movements-panel__quantity--positive {
  color: var(--color-success);
}

.fulgore-shop-admin-stocks-movements-panel__quantity--negative {
  color: var(--color-danger);
}

.fulgore-shop-admin-stocks-movements-panel__location {
  color: var(--color-text-subtle);
}

.fulgore-shop-admin-stocks-movements-panel__nature {
  color: var(--color-text-subtle);
}


/* fulgore: fulgore/shop/admin/stocks/product_group.css */
/* ── Groupe de produit : en-tête repliable + une ligne par taille ── */

/* Replié : seul l'en-tête reste. Couvre les lignes de solde ET les lignes de
   journal des tailles. `.ui-list-table` en préfixe : sous 768 px fulgore passe
   chaque `tr` en `display: block` (`.ui-list-table tbody tr`, (0,1,2)) ; cette
   règle est à (0,4,1) et gagne dans les deux modes. */
.ui-list-table .fulgore-shop-admin-stocks-product-group.collapsed > tr:not(.fulgore-shop-admin-stocks-product-group__header) {
  display: none;
}

/* Bouton : reset visuel, même mise en page que la cellule produit de `Row`. */
.fulgore-shop-admin-stocks-product-group__toggle {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.fulgore-shop-admin-stocks-product-group__arrow {
  display: inline-flex;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}

.fulgore-shop-admin-stocks-product-group__arrow .svg {
  width: 100%;
  height: 100%;
}

.fulgore-shop-admin-stocks-product-group:not(.collapsed) .fulgore-shop-admin-stocks-product-group__arrow {
  transform: rotate(90deg);
}

/* Titre du produit en gras : c'est une ligne de synthèse, pas une taille. */
.fulgore-shop-admin-stocks-product-group__header td:first-child {
  font-weight: var(--font-weight-semibold);
}

/* ── Lignes de taille (Row nested) ── */
.fulgore-shop-admin-stocks-row--nested .fulgore-shop-admin-stocks-row__variant {
  padding-left: var(--space-6);
}

/* La cellule produit vide ne sert à rien : elle garde sa colonne sur
   desktop, disparaît sous 768 px. */
@media (max-width: 768px) {
  .fulgore-shop-admin-stocks-row--nested td.fulgore-shop-admin-stocks-row__product-cell--empty {
    display: none;
  }

  .fulgore-shop-admin-stocks-row--nested .fulgore-shop-admin-stocks-row__variant {
    padding-left: var(--space-4);
  }
}


/* fulgore: fulgore/shop/admin/stocks/row.css */
/* ── Cellule produit : la vignette fulgore (40 px) à gauche du nom ── */
.fulgore-shop-admin-stocks-row__product {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* ── Cellules de quantité (soldes par lieu + total) ──
   `td.` et non la classe seule : fulgore pose `text-align: left` par
   `.ui-list-table td` (une classe + un type), qui bat une classe nue — les
   soldes restaient à gauche sous un en-tête aligné à droite (vu en capture
   le 2026-09-22, en corrigeant le même défaut sur la page de dépôt). Les
   trois sélecteurs gardent la même spécificité pour que l'ordre des règles
   continue de trancher le conflit de fond `__total` / `--zero`. */

td.fulgore-shop-admin-stocks-row__quantity {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Le solde puis les deux boutons-icônes « donner » / « recevoir », alignés à
   droite comme le reste de la colonne. */
.fulgore-shop-admin-stocks-row__cell {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-1);
}

/* La colonne Total est une somme, pas une donnée de lieu : un fond en
   retrait suffit à la distinguer, sans redessiner l'en-tête — le `<thead>`
   fulgore porte déjà ce même fond sur toute sa largeur (`ui/bases/list.css`),
   donc l'alignement visuel entre l'en-tête et cette colonne existe déjà. */
td.fulgore-shop-admin-stocks-row__total {
  background-color: var(--color-surface-subtle);
  font-weight: var(--font-weight-semibold);
}

/* Un solde à zéro est l'information que cet écran existe pour donner : une
   puce discrète, jamais un fond alarmant. Placée après `__total` pour
   gagner le conflit de fond quand la colonne Total elle-même tombe à zéro. */
td.fulgore-shop-admin-stocks-row__quantity--zero {
  border-radius: var(--radius-sm);
  color: var(--color-warning-text);
  background-color: var(--color-warning-surface);
}

/* ── Ligne de journal — ne doit pas se lire comme une ligne de stock ──
   Spécificité à égalité avec `.ui-list-table th, td { border-bottom: … }`
   (`ui/bases/list.css`) : une classe + un type de chaque côté. Le paquet
   concatène fulgore d'abord, l'appli ensuite (`css:bundle`), donc cette
   règle gagne par ordre de source — même mécanisme que
   `admin/products/formats_section.css`. */
.fulgore-shop-admin-stocks-row__journal-row td {
  padding: var(--space-2) var(--space-4);
  border-bottom: none;
  background-color: var(--color-surface-subtle);
}

@media (max-width: 768px) {
  /* Sous 768 px, fulgore bascule CHAQUE `<tr>` en carte bordée + ombrée
     (`.ui-list-table tbody tr` — une classe, deux types de sélecteur,
     spécificité (0,1,2)). Deux classes suffisent à passer devant sans
     `!important` : la ligne de journal n'est pas une carte de plus. */
  .ui-list-table .fulgore-shop-admin-stocks-row__journal-row {
    border: none;
    box-shadow: none;
    margin-bottom: var(--space-2);
    padding: 0;
  }

  /* Même égalité de spécificité que la règle desktop ci-dessus, contre
     `.ui-list-table td { display: flex; … }` du même bloc fulgore. */
  .fulgore-shop-admin-stocks-row__journal-row td {
    display: block;
  }

  /* Ce `<td>` enveloppe le `<details>` du journal, colspan sur toute la
     largeur : il n'a pas de `data-label`, contrairement aux cellules de
     donnée. Sans cette règle, `td::before { content: attr(data-label) }`
     (générique fulgore) réserve quand même sa marge pour un label vide. */
  .fulgore-shop-admin-stocks-row__journal-row td::before {
    content: none;
  }
}


/* fulgore: fulgore/shop/admin/stocks/table.css */
/* ── Ligne titre de catégorie ──
   `th.` + classe : fulgore pose `text-align: left`, `color` et `font-size`
   par `.ui-list-table th` (une classe + un type) ; même spécificité ici, et le
   paquet concatène l'appli après fulgore, donc l'ordre tranche. */
th.fulgore-shop-admin-stocks-table__category-title {
  text-align: left;
  font-weight: var(--font-weight-semibold);
  background-color: var(--color-surface-subtle);
}

@media (max-width: 768px) {
  /* Le `<tr>` du titre est une carte comme les autres ; le `<th>` reste un
     bloc pleine largeur, sans `data-label`. */
  .ui-list-table .fulgore-shop-admin-stocks-table__category tr {
    margin-bottom: 0;
  }

  /* Le trait bas des cellules de carte (fulgore) traçait une ligne orpheline
     sous le titre, seul dans sa carte (capture du 2026-09-29). */
  .ui-list-table th.fulgore-shop-admin-stocks-table__category-title {
    border-bottom: none;
  }
}


/* fulgore: shared/errors/base.css */
.shared-errors-not-found,
.shared-errors-internal-server {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
  text-align: center;
  gap: var(--space-6);
  padding: var(--space-10);
}

.shared-errors-not-found__code,
.shared-errors-internal-server__code {
  display: block;
  font-size: 8rem;
  font-weight: var(--font-weight-bold);
  color: var(--color-text-subtle);
  line-height: 1;
}

.shared-errors-not-found__title,
.shared-errors-internal-server__title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
}

.shared-errors-not-found__description,
.shared-errors-internal-server__description {
  color: var(--color-text-subtle);
  margin: 0;
}

/* Raccourcis facultatifs sous le bouton de retour. Ils s'enroulent plutôt que
   de déborder : sur un écran étroit, quatre libellés ne tiennent pas sur une
   ligne. */
.shared-errors-not-found__links,
.shared-errors-internal-server__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) var(--space-4);
  max-width: 100%;
}


/* fulgore: shared/flash.css */
@keyframes flash-enter {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes flash-exit {
  from {
    opacity: 1;
    transform: translateY(0);
  }

  to {
    opacity: 0;
    transform: translateY(-4px);
  }
}

.flash-container {
  
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  position: fixed;
  top: calc(var(--navbar-height) + var(--space-4));
  right: var(--space-6);
  z-index: 1000;

  
  min-width: 280px;
  max-width: 400px;
}

.flash-item {
  
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: var(--space-3);

  .svg {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
  }

  
  min-width: 280px;
  max-width: 400px;
  padding: var(--space-4);
  margin-bottom: var(--space-2);
  border-left: 3px solid;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md, 0 4px 12px rgba(0, 0, 0, 0.12));

  
  animation: flash-enter var(--duration-normal) var(--easing-default) both;

  &:last-child {
    margin-bottom: 0;
  }

  &.flash-item--exiting {
    animation: flash-exit var(--duration-fast) var(--easing-default) forwards;
  }
}

.flash-notice {
  background: var(--color-success-surface);
  color: var(--color-success);
  border-color: var(--color-success);
}

.flash-alert {
  background: var(--color-danger-surface);
  color: var(--color-danger);
  border-color: var(--color-danger);
}

.flash-warning {
  background: var(--color-warning-surface);
  color: var(--color-warning);
  border-color: var(--color-warning);
}

.flash-info {
  background: var(--color-info-surface);
  color: var(--color-info);
  border-color: var(--color-info);
}

.flash-icon {
  
  flex-shrink: 0;

  
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  margin-top: 1px;
}

.flash-body {
  
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-1);
}

.flash-message {
  
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;

  flex: 1;
}

.flash-dismiss {
  
  flex-shrink: 0;

  
  padding: 0;
  border: none;

  
  line-height: 1;

  
  color: inherit;
  background: none;

  
  cursor: pointer;
  opacity: 0.6;
  transition: opacity var(--duration-fast) var(--easing-default);

  &:hover {
    opacity: 1;
  }

  .svg {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
  }

  svg {
    display: block;
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
  }
}


/* fulgore: surveys/base_completion_screen.css */
.surveys-base-completion-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  margin-block-start: var(--space-8);
}

.surveys-base-completion-screen__heading {
  font-size: var(--font-size-4xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text);
  margin: 0;
}

.surveys-base-completion-screen__description {
  font-size: var(--font-size-xl);
  color: var(--color-text-subtle);
  margin: 0;
  white-space: pre-line;
}

.surveys-base-completion-screen__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  margin-block-start: var(--space-4);
  margin-block-end: var(--space-8);
}

.surveys-base-completion-screen__footer {
  align-self: flex-start;
}


/* fulgore: surveys/context_block.css */
.surveys-context-block {
  display: flex;
  flex-direction: column;
}

.surveys-context-block > * {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* ── Heading ── */

.surveys-context-block h2 {
  margin: 0;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-brand);
}

/* ── Description ── */

.surveys-context-block p {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-loose);
  color: var(--color-text-subtle);
}

/* ── Label / Value pairs ── */

.surveys-context-block div > span:first-child {
  display: block;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-brand-light);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: var(--space-1);
}

.surveys-context-block div > span:last-child {
  display: block;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-normal);
  color: var(--color-text-subtle);
}

/* ── Lists (steps, units) ── */

.surveys-context-block ol,
.surveys-context-block ul {
  margin: 0;
  padding-left: var(--space-5);
}

.surveys-context-block li {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-loose);
  color: var(--color-text-subtle);
  margin-bottom: var(--space-1);
}

.surveys-context-block ol li::marker {
  color: var(--color-brand-light);
  font-weight: var(--font-weight-semibold);
}


/* fulgore: surveys/inputs/base.css */
.surveys-inputs-base {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}


/* fulgore: surveys/inputs/boolean_card.css */
.ui-form:has(.surveys-inputs-boolean-card) {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
}

.ui-form:has(.surveys-inputs-boolean-card) .form-actions,
.ui-form:has(.surveys-inputs-boolean-card) .ui-input {
  grid-column: 1 / -1;
}

.surveys-inputs-boolean-card__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-3);
  border: 1.5px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  background: var(--color-brand-surface);
  cursor: pointer;
  transition: border-color 200ms ease-out, box-shadow 200ms ease-out, transform 150ms ease-out;
  text-align: center;
}

.surveys-inputs-boolean-card__card:hover {
  border-color: var(--color-brand-light);
  box-shadow: 0 0 0 3px var(--color-brand-a10);
  transform: translateY(-2px);
}

.surveys-inputs-boolean-card__card:active {
  transform: translateY(0);
  box-shadow: none;
}

.surveys-inputs-boolean-card__checkbox:checked + .surveys-inputs-boolean-card__card {
  border-color: var(--color-brand);
  box-shadow: 0 0 0 3px var(--color-brand-a20);
}

.surveys-inputs-boolean-card__checkbox {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  overflow: hidden;
}

.surveys-inputs-boolean-card__icon {
  font-size: var(--font-size-2xl);
  line-height: 1;
}

.surveys-inputs-boolean-card__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

@media (max-width: 767px) {
  .ui-form:has(.surveys-inputs-boolean-card) {
    grid-template-columns: repeat(2, 1fr);
  }
}


/* fulgore: surveys/inputs/choice_card.css */
.surveys-inputs-choice-card__form {
  display: contents;
}

.surveys-inputs-choice-card__button {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);

  padding: var(--space-5) var(--space-4);
  border: 1.5px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  background: var(--color-brand-surface);

  cursor: pointer;
  transition: border-color 200ms ease-out, box-shadow 200ms ease-out, transform 150ms ease-out;
}

.surveys-inputs-choice-card__button:hover {
  border-color: var(--color-brand-light);
  box-shadow: 0 0 0 3px var(--color-brand-a10);
  transform: translateY(-2px);
}

.surveys-inputs-choice-card__button:active {
  transform: translateY(0);
  box-shadow: none;
}

.surveys-inputs-choice-card__icon {
  font-size: var(--font-size-2xl);
  line-height: 1;
}

.surveys-inputs-choice-card__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  text-align: center;
}


/* fulgore: surveys/inputs/descriptive_choice.css */
.surveys-inputs-descriptive-choice {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
}

.surveys-inputs-descriptive-choice__form {
  display: contents;
}

.surveys-inputs-descriptive-choice__card {
  flex: 0 1 240px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-3);
  border: 1.5px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  background: var(--color-brand-surface);
  cursor: pointer;
  transition: border-color 200ms ease-out, box-shadow 200ms ease-out, transform 150ms ease-out;
  text-align: center;
}

.surveys-inputs-descriptive-choice__card:hover {
  border-color: var(--color-brand-light);
  box-shadow: 0 0 0 3px var(--color-brand-a10);
  transform: translateY(-2px);
}

.surveys-inputs-descriptive-choice__card:active {
  transform: translateY(0);
  box-shadow: none;
}

.surveys-inputs-descriptive-choice__card--selected {
  border-color: var(--color-brand);
  box-shadow: 0 0 0 3px var(--color-brand-a20);
}

.surveys-inputs-descriptive-choice__icon {
  font-size: var(--font-size-2xl);
  line-height: 1;
}

.surveys-inputs-descriptive-choice__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.surveys-inputs-descriptive-choice__description {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  line-height: var(--line-height-loose);
}



/* fulgore: surveys/map.css */
.surveys-map {
  --stop-height: 40px;
  --badge-size: 24px;

  position: relative;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--color-surface-subtle);
}

.surveys-map__list {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* ── SVG paths overlay ── */

.surveys-map__stops-wrapper {
  position: relative;
}

.surveys-map__paths {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--badge-size);
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 1;
}

.surveys-map__list {
  position: relative;
  z-index: 2;
}

/* ── Collapsible body ── */

.surveys-map__details {
  position: relative;
  z-index: 20;
  margin-top: var(--space-3);
}

.surveys-map__toggle {
  display: none;
}

.surveys-map__body {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 400ms ease-out, opacity 400ms ease-out;
  opacity: 1;
}

.surveys-map__details:not([open]) .surveys-map__body {
  grid-template-rows: 0fr;
  opacity: 0;
}

.surveys-map__body > * {
  overflow: visible;
}

/* ── SVG path draw animation ── */

.surveys-map__segment {
  stroke-dasharray: var(--segment-length);
  stroke-dashoffset: var(--segment-length);
  animation: map-draw 500ms ease-out forwards;
}

.surveys-map__arc-segment {
  stroke-dasharray: var(--segment-length);
  stroke-dashoffset: var(--segment-length);
  animation: map-draw 800ms ease-in-out forwards;
  animation-delay: 200ms;
}

@keyframes map-draw {
  to { stroke-dashoffset: 0; }
}

/* Mobile — collapsed by default, toggle visible */
@media (max-width: 767px) {
  .surveys-map__toggle {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-brand);
    cursor: pointer;
    list-style: none;
    margin-bottom: var(--space-3);
  }

  .surveys-map__toggle::-webkit-details-marker {
    display: none;
  }

  .surveys-map__toggle::before {
    content: "▸ ";
  }

  .surveys-map__details[open] > .surveys-map__toggle::before {
    content: "▾ ";
  }
}


/* fulgore: surveys/map/arc.css */
/* Arc — loop-back indicator connecting a later stop back to an earlier one.
   Rendered as a left bracket with an arrow pointing up at the target. */

.surveys-map-arc {
  position: absolute;

  /* Vertical span: from target badge center to source badge center */
  top: calc(var(--space-6) + var(--space-3) + (var(--arc-to) + 0.5) * var(--stop-height));
  height: calc((var(--arc-from) - var(--arc-to)) * var(--stop-height));

  /* Horizontal: dedicated rail left of forks.
     Arc sits in the --arc-rail zone, forks sit in the --arc-indent zone. */
  left: 6px;
  right: calc(100% - var(--arc-rail) - var(--arc-indent) - var(--space-6) - var(--badge-size) / 2);

  /* Thinner than forks (2px vs 3px) to reduce visual noise */
  border: 2px solid var(--color-border);
  border-right: none;
  border-radius: var(--radius-md) 0 0 var(--radius-md);

  z-index: var(--arc-z);
  pointer-events: none;
}

/* Arrow pointing UP at the target stop */
.surveys-map-arc::before {
  content: "";
  position: absolute;
  top: -5px;
  right: -6px;

  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 6px solid var(--color-border);
}

/* Brand fill overlay — animates top-to-bottom (visual: "going back up") when loop is active */
.surveys-map-arc--active {
  border-color: var(--color-brand);
}

.surveys-map-arc--active::before {
  border-bottom-color: var(--color-brand);
}

.surveys-map-arc--active::after {
  content: "";
  position: absolute;
  top: -2px;
  left: -2px;
  bottom: -2px;
  right: 0;

  border: 2px solid var(--color-brand);
  border-right: none;
  border-radius: var(--radius-md) 0 0 var(--radius-md);

  clip-path: inset(100% 0 0 0);
  animation: arc-fill 800ms ease-out forwards;
  animation-delay: 400ms;
}

@keyframes arc-fill {
  0% { clip-path: inset(100% 0 0 0); }
  100% { clip-path: inset(0 0 0 0); }
}

/* Hide when map is collapsed on mobile */
@media (max-width: 767px) {
  .surveys-map__details:not([open]) ~ .surveys-map-arc {
    display: none;
  }
}


/* fulgore: surveys/map/fork.css */
/* Fork — left bracket connecting two badges (skip path) */

.surveys-map-fork {
  position: absolute;

  /* Top edge at fork-from badge center, bottom edge at fork-to badge center */
  top: calc(var(--space-6) + var(--space-3) + (var(--fork-from) + 0.5) * var(--stop-height));
  height: calc((var(--fork-to) - var(--fork-from)) * var(--stop-height));

  /* Left bracket in the arc-indent gutter (after the arc rail), right edge at badge center */
  left: calc(var(--arc-rail) + var(--space-6));
  right: calc(100% - var(--arc-rail) - var(--arc-indent) - var(--space-6) - var(--badge-size) / 2);

  border: 3px solid var(--color-border);
  border-right: none;
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);
  z-index: 10;
}

/* Brand fill overlay — progressive top-to-bottom reveal when taken */
.surveys-map-fork--taken::after {
  content: "";
  position: absolute;
  top: -3px;
  left: -3px;
  bottom: -3px;
  right: 0;

  border: 3px solid var(--color-brand);
  border-right: none;
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);

  clip-path: inset(0 0 100% 0);
  animation: fork-fill 1200ms ease-in-out forwards;
  animation-delay: 300ms;
}

@keyframes fork-fill {
  0% { clip-path: inset(0 0 100% 0); }
  100% { clip-path: inset(0 0 0 0); }
}

/* Hide when map is collapsed on mobile */
@media (max-width: 767px) {
  .surveys-map__details:not([open]) ~ .surveys-map-fork {
    display: none;
  }
}


/* fulgore: surveys/map/progress.css */
.surveys-map-progress {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);

  padding: var(--space-2) var(--space-3);
  border: 1.5px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  background: var(--color-brand-surface);

  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--color-brand);
}


/* fulgore: surveys/map/stop.css */
.surveys-map-stop {
  --badge-size: 24px;

  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: var(--stop-height);
  position: relative;
}

/* ── Badge ── */

.surveys-map-stop__badge {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  width: var(--badge-size);
  height: var(--badge-size);
  border-radius: var(--radius-full);

  position: relative;
  z-index: 20;

  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
}

/* ── Label ── */

.surveys-map-stop__label {
  font-size: var(--font-size-sm);
  line-height: var(--line-height-tight);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── States ── */

/* Completed */
.surveys-map-stop--completed .surveys-map-stop__badge {
  background: var(--color-brand);
  color: var(--color-text-inverted);
}

.surveys-map-stop--completed .surveys-map-stop__label {
  color: var(--color-text-subtle);
}

.surveys-map-stop--completed .surveys-map-stop__badge .ui-icon {
  width: 14px;
  height: 14px;
}

/* Animated — pulse + check reveal (only on just-completed stop) */
.surveys-map-stop--animate .surveys-map-stop__badge {
  animation: badge-complete-pulse 250ms ease-out;
  animation-delay: calc(var(--stop-index, 0) * 150ms);
}

.surveys-map-stop--animate .surveys-map-stop__badge .ui-icon {
  opacity: 0;
  clip-path: inset(0 100% 0 0);
  animation: check-reveal 800ms ease-out forwards;
  animation-delay: calc(var(--stop-index, 0) * 150ms + 400ms);
}

@keyframes badge-complete-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.3); }
}

@keyframes check-reveal {
  0% {
    opacity: 0;
    clip-path: inset(0 100% 0 0);
  }
  20% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    clip-path: inset(0 0 0 0);
  }
}

/* Current */
.surveys-map-stop--current .surveys-map-stop__badge {
  background: var(--color-brand);
  color: var(--color-text-inverted);

  animation-name: badge-activate, survey-map-pulse;
  animation-duration: 300ms, 2s;
  animation-timing-function: ease-out, ease-in-out;
  animation-delay:
    calc(var(--stop-index, 0) * 150ms + 600ms),
    calc(var(--stop-index, 0) * 150ms + 900ms);
  animation-iteration-count: 1, infinite;
  animation-fill-mode: backwards, none;
}

@keyframes badge-activate {
  from {
    background: var(--color-surface-subtle);
    outline: 2px solid var(--color-border);
    outline-offset: -2px;
    color: transparent;
    box-shadow: none;
  }
  to {
    background: var(--color-brand);
    outline: 2px solid transparent;
    outline-offset: -2px;
    color: var(--color-text-inverted);
    box-shadow: none;
  }
}

.surveys-map-stop--current .surveys-map-stop__label {
  color: var(--color-text);
  font-weight: var(--font-weight-semibold);
}

@keyframes survey-map-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 var(--color-brand-a20);
  }
  50% {
    box-shadow: 0 0 0 6px var(--color-brand-a20);
  }
}

/* Upcoming */
.surveys-map-stop--upcoming .surveys-map-stop__badge {
  background: var(--color-surface-subtle);
  outline: 2px solid var(--color-border);
  outline-offset: -2px;
}

.surveys-map-stop--upcoming .surveys-map-stop__label {
  color: var(--color-text-disabled);
}

/* Skipped */
.surveys-map-stop--skipped .surveys-map-stop__badge {
  background: var(--color-surface-subtle);
  outline: 2px dashed var(--color-border);
  outline-offset: -2px;
}

.surveys-map-stop--skipped .surveys-map-stop__label {
  color: var(--color-text-disabled);
  text-decoration: line-through;
}

/* ── End stop ── */

.surveys-map-stop--end .surveys-map-stop__badge {
  width: calc(var(--badge-size) * 0.6);
  height: calc(var(--badge-size) * 0.6);
  margin-left: calc(var(--badge-size) * 0.2);
}

.surveys-map-stop--end.surveys-map-stop--completed .surveys-map-stop__badge {
  width: var(--badge-size);
  height: var(--badge-size);
  margin-left: 0;
  background: var(--color-success-surface);
  outline: none;
  font-size: var(--font-size-base);
  animation: tada-pop 600ms ease-out;
}

@keyframes tada-pop {
  0% { transform: scale(0); opacity: 0; }
  50% { transform: scale(1.4); opacity: 1; }
  70% { transform: scale(0.9); }
  100% { transform: scale(1); opacity: 1; }
}

.surveys-map-stop--end .surveys-map-stop__label {
  font-style: italic;
}

/* ── Clickable wrapper (jump_path active) ── */

.surveys-map-stop__form {
  display: contents;
}

.surveys-map-stop__button {
  all: unset;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  cursor: pointer;
}

.surveys-map-stop__button:hover .surveys-map-stop__label {
  color: var(--color-text);
}


/* fulgore: surveys/question_forms/footer.css */
.surveys-question-forms-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-6);
}

.surveys-question-forms-footer__submit {
  margin-left: auto;
}


/* fulgore: surveys/question_label.css */
.surveys-question-label {
  font-family: var(--font-family-display);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);

  color: var(--color-text);

  margin-bottom: var(--space-8);
}


/* fulgore: surveys/question_layout.css */
.surveys-question-layout {
  display: grid;
  /* start : la map et le bloc contexte gardent la hauteur de leur contenu
     au lieu de s'étirer à la hauteur de la colonne principale */
  align-items: start;
  gap: var(--space-6);
}

/* Le frame survey n'est pas un formulaire simple : lever le plafond 48rem
   posé par record-view sur son enfant unique, sinon la grille multi-colonnes
   ci-dessous s'applique dans 768px et écrase la colonne principale. */
.ui-bases-record-view__body > turbo-frame:only-child:has(.surveys-question-layout) {
  max-width: none;
}

.surveys-question-layout__context-block {
  min-height: var(--space-16);
  padding: var(--space-5) var(--space-6);
  border: 1.5px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  background: var(--color-brand-surface);
}

.surveys-question-layout__main {
  position: relative;
  z-index: 1;
}

/* ── Transitions ── */

.surveys-question-layout__main {
  opacity: 1;
}

@keyframes surveys-question-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.surveys-question-layout__main {
  animation: surveys-question-enter 320ms cubic-bezier(0.4, 0, 0.2, 1) both;
}

@media (prefers-reduced-motion: reduce) {
  .surveys-question-layout__main {
    animation: none;
  }
}

@media (min-width: 768px) {
  .surveys-question-layout {
    grid-template-columns: 3fr 2fr;
    /* 3e rangée 1fr : absorbe l'excédent de hauteur de la colonne
       principale (section dépliée), sinon il se répartit sur la rangée 1
       et le bloc contexte tombe en bas de page. */
    grid-template-rows: auto auto 1fr;
    gap: var(--space-8);
  }

  .surveys-question-layout__main {
    grid-column: 1;
    grid-row: 1 / 4;
  }

  .surveys-map {
    grid-column: 2;
  }

  .surveys-question-layout__context-block {
    grid-column: 2;
  }
}

@media (min-width: 1440px) {
  .surveys-question-layout {
    grid-template-columns: 1fr 280px 280px;
    grid-template-rows: none;
  }

  .surveys-question-layout__main {
    grid-row: auto;
  }

  .surveys-map {
    grid-column: auto;
  }

  .surveys-question-layout__context-block {
    grid-column: auto;
  }
}


/* fulgore: ui/bases/button.css */
.ui-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-md);
  font-family: var(--font-family-base);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  cursor: pointer;
  border: 1.5px solid transparent;
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
  transition:
    background var(--duration-fast) var(--easing-default),
    color var(--duration-fast) var(--easing-default),
    border-color var(--duration-fast) var(--easing-default),
    box-shadow var(--duration-fast) var(--easing-default),
    opacity var(--duration-fast) var(--easing-default);

  .svg {
    height: var(--space-4);
    fill: currentColor;
  }

  &:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }

  

  &.ui-button--primary {
    background: var(--color-brand);
    color: var(--color-text-inverted);
    border-color: var(--color-brand);

    &:hover:not(:disabled):not(.ui-button--disabled) {
      background: var(--color-brand-dark);
      border-color: var(--color-brand-dark);
    }

    &:active:not(:disabled):not(.ui-button--disabled) {
      background: var(--color-brand-dark);
      box-shadow: none;
    }
  }

  &.ui-button--secondary {
    background: transparent;
    color: var(--color-brand);
    border-color: var(--color-brand);

    &:hover:not(:disabled):not(.ui-button--disabled) {
      background: var(--color-brand-surface);
    }
  }

  &.ui-button--danger {
    background: var(--color-danger);
    color: var(--color-text-inverted);
    border-color: var(--color-danger);

    &:hover:not(:disabled):not(.ui-button--disabled) {
      background: var(--color-danger-dark);
      border-color: var(--color-danger-dark);
    }

    &:active:not(:disabled):not(.ui-button--disabled) {
      background: var(--color-danger-dark);
      box-shadow: none;
    }

    &:focus-visible {
      box-shadow: var(--focus-ring-danger);
    }
  }

  &.ui-button--ghost {
    background: transparent;
    color: var(--color-text-subtle);
    border-color: transparent;

    &:hover:not(:disabled):not(.ui-button--disabled) {
      background: var(--color-surface-raised);
      color: var(--color-text);
    }

    &:focus-visible {
      box-shadow: var(--focus-ring-neutral);
    }
  }

  

  &.ui-button--sm {
    font-size: var(--font-size-xs);
    padding: var(--space-1) var(--space-3);
  }

  &.ui-button--lg {
    font-size: var(--font-size-base);
    padding: var(--space-3) var(--space-6);
  }

  &.ui-button--icon-only {
    padding: var(--space-2);

    /* Shield the icon from consumer resets like `svg { max-width: 100% }`:
       100% of a shrink-to-fit content box computes to 0 width and hides
       the icon entirely — same trap as the sortable grip (cf. row.css). */
    .svg {
      width: var(--space-4);
      min-width: var(--space-4);
      max-width: none;
    }

    &.ui-button--sm {
      padding: var(--space-1);
    }

    &.ui-button--lg {
      padding: var(--space-3);
    }
  }



  /* L'ÉTAT DÉSACTIVÉ SE LIT « INACTIF », PAS « CASSÉ ». `opacity: 0.45` délave
     la couleur de marque du consumer sans rien garantir : sur le terracotta de
     FBordes, le libellé blanc tombait à ~2,6:1 (contre 6,44:1 à l'état actif) —
     sous les deux planchers WCAG. Et c'est le PREMIER état que voit un visiteur
     d'un écran de connexion, dont `form-validation` désactive le bouton tant que
     les champs sont vides.
     Des couleurs franches le disent sans ambiguïté et ne dépendent plus de la
     teinte de marque : mesuré 5,69:1 au navigateur le 2026-08-03, dans les deux
     moteurs et aux deux tailles d'écran.
     ⚠️ CE SIDECAR EST LA COPIE SERVIE — voir la note jumelle dans
     `ui/inputs/password.css`. `app/assets/stylesheets/fulgore/button.css` porte
     une seconde définition qui n'atteint aucun consumer. */
  &:disabled,
  &.ui-button--disabled {
    background: var(--color-surface-raised);
    border-color: var(--color-border);
    color: var(--color-text-subtle);
    cursor: not-allowed;
    pointer-events: none;
  }
}


/* fulgore: ui/bases/card.css */
.ui-bases-card {
  box-sizing: border-box;
  margin-inline: auto;
  padding: var(--space-8);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  background: var(--color-surface);
}

.ui-bases-card__heading {
  display: grid;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  grid-template-columns: min-content auto;
  align-items: end;
}

.ui-bases-card__title {
  font: inherit;
}

.ui-bases-card__details {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: var(--space-2) var(--space-6);
}

@media (max-width: 480px) {
  .ui-bases-card {
    padding: var(--space-4);
  }

  .ui-bases-card__details {
    grid-template-columns: 1fr;
  }
}


/* fulgore: ui/bases/card_row.css */
.ui-bases-card-row__dt {
  grid-column: 1;
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  font-weight: var(--font-weight-medium);
}

.ui-bases-card-row__dd {
  grid-column: 2;
  margin: 0;
  font-size: var(--font-size-sm);
}

@media (max-width: 480px) {
  .ui-bases-card-row__dt {
    grid-column: auto;
  }

  .ui-bases-card-row__dd {
    grid-column: auto;
  }
}


/* fulgore: ui/bases/context_block.css */
.ui-bases-context-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-6);
  border: 1.5px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  background: var(--color-brand-surface);

  .ui-bases-context-block__heading {
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    color: var(--color-brand);
  }

  .ui-bases-context-block__description {
    font-size: var(--font-size-sm);
    color: var(--color-text-subtle);
  }

  .ui-bases-context-block__list {
    margin: 0;
    padding-left: var(--space-5);

    & li {
      font-size: var(--font-size-sm);
      color: var(--color-text-subtle);
      margin-bottom: var(--space-1);
    }
  }
}

.ui-bases-context-block--warning {
  background: var(--color-warning-surface);
  border-color: var(--color-warning-a10);
  margin-bottom: var(--space-6);

  .ui-bases-context-block__heading {
    color: var(--color-warning);
  }
}


/* fulgore: ui/bases/edit.css */
.ui-bases-edit__header {
  margin-block-end: var(--space-6);
}

.ui-bases-edit__body {
}


/* fulgore: ui/bases/filter_bar.css */
/* `flex-start` et non `center` : dès qu'une barre porte des champs de hauteurs
   différentes (un multi-select à huit options est bien plus haut qu'une
   recherche), le centrage aligne chaque champ sur le milieu de sa ligne et
   dessine un escalier. Sur une barre à champs de même hauteur — le cas de tous
   les consumers jusqu'ici — les deux valeurs rendent à l'identique. */
.ui-filter-bar__fields {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.filter-field__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-subtle);
  margin-right: var(--space-2);
}

/* ⚠️ `flex` ET NON `inline-flex`, et c'est le contraire d'un détail. Un
   `inline-flex` se dimensionne sur son CONTENU : sa largeur est « indéfinie »
   au sens de CSS, et tout `width: %` d'un enfant s'y résout alors contre rien
   — l'input retombe sur sa taille intrinsèque quelle que soit la place qu'on
   lui offre. Mesuré le 2026-08-03 : 302 px pris dans un conteneur de 328,
   et 302 px dans une piste de grille de 416 chez RatsAndFrogs, où la barre
   paraissait décentrée alors que la GRILLE était juste.
   Le passage en `flex` (donc de niveau bloc) ne change RIEN aux barres à
   plusieurs champs : `.filter-field--search` y est un élément flex de
   `.ui-filter-bar__fields`, dimensionné sur son `max-content` — vérifié au
   rendu avant/après, à 1280 et 390 px, sur `UI::Bases::ExampleFilterBar`. */
.filter-search-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.filter-search {
  padding: var(--space-2) var(--space-8) var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--font-size-sm);
  background: var(--color-surface);
  color: var(--color-text);
  min-width: 16rem;

  /* ⚠️ `flex: 1` EST LA SECONDE MOITIÉ DU CORRECTIF, et sans elle la première
     ne sert à rien : passer le conteneur en `flex` lui donne une largeur
     définie, mais l'input reste `flex: 0 1 auto`, donc dimensionné sur son
     contenu. Mesuré le 2026-08-03 par injection : conteneur porté à 600 px,
     input toujours à 302. Les deux règles se tiennent — ne pas en retirer une
     en croyant l'autre suffisante.
     ⚠️⚠️ `flex: 1` ET NON `width: 100%`, essayé d'abord et REVERTÉ : un `100%`
     oblige à déclarer `box-sizing: border-box` (la gem n'a aucune remise à
     zéro globale — chaque composant le déclare chez lui), et ce border-box
     fait alors compter les 46 px de padding et de bordure DANS le `min-width:
     16rem` ci-dessus, qui a toujours été écrit en largeur de contenu. Mesuré :
     les champs des barres passaient de 302 à 256 px, soit 46 px perdus dans
     les dix-sept barres de la flotte. Le flex, lui, dimensionne sur la boîte
     de bordure quel que soit le `box-sizing` — rien à compenser. */
  flex: 1;

  &:focus {
    outline: none;
    border-color: var(--color-brand);
  }
}

.filter-search-clear {
  position: absolute;
  right: var(--space-2);
  display: none;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  background: var(--color-neutral-300);
  color: var(--color-neutral-700);
  border: none;
  border-radius: 999px;
  font-size: var(--font-size-xs);
  line-height: 1;
  cursor: pointer;
  padding: 0;

  &:hover {
    background: var(--color-neutral-400);
  }
}

.filter-search:not(:placeholder-shown) ~ .filter-search-clear {
  display: flex;
}

/* `min-width: 0` est le remède au piège WebKit : un item flex garde par défaut
   `min-width: auto` et refuse de se rétrécir sous son `min-content` — un
   multi-select à beaucoup d'options débordait alors sa case et se dessinait
   PAR-DESSUS le champ voisin. Mesuré en WebKit : recouvrement du champ de
   recherche par les options de type, ramené à zéro par cette règle. */
.filter-field--multi-select {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  min-width: 0;
  max-width: 100%;
}

.filter-multi-select {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.filter-multi-select__option {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-subtle);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast);

  input[type="checkbox"] {
    display: none;
  }

  &:hover {
    border-color: var(--color-brand);
    color: var(--color-brand);
  }

  &.is-active {
    background: var(--color-brand-surface);
    border-color: var(--color-brand);
    color: var(--color-brand);
    font-weight: var(--font-weight-semibold);
  }

  /* Le badge se teinte par `currentColor` plutôt qu'en dur : l'option prend
     l'une des 12 teintes de `UI::Pill` quand elle est active, et le compteur
     suit sans qu'on redéclare douze règles. */
  .filter-multi-select__count {
    margin-left: var(--space-2);
    min-width: 1.25em;
    padding: 0 var(--space-1);
    border-radius: 999px;
    background: color-mix(in srgb, currentColor 15%, transparent);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: 1.5;
    text-align: center;
    font-variant-numeric: tabular-nums;
  }
}

.filter-multi-select__option.is-active.ui-pill--violet {
  background: var(--color-violet-100);
  color: var(--color-violet-700);
  border-color: var(--color-violet-100);
}

.filter-multi-select__option.is-active.ui-pill--blue {
  background: var(--color-blue-100);
  color: var(--color-blue-700);
  border-color: var(--color-blue-100);
}

.filter-multi-select__option.is-active.ui-pill--green {
  background: var(--color-green-100);
  color: var(--color-green-700);
  border-color: var(--color-green-100);
}

.filter-multi-select__option.is-active.ui-pill--red {
  background: var(--color-red-100);
  color: var(--color-red-700);
  border-color: var(--color-red-100);
}

.filter-field--switch {
  display: flex;
  align-items: center;
}

.filter-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  cursor: pointer;

  input[type="checkbox"] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--color-brand);
    cursor: pointer;
  }
}


/* fulgore: ui/bases/form.css */
.ui-bases-form {
  form {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
  }
}

.ui-form {
  display: grid;

  /* Un champ caché ne compte pas : pas de marge pour lui, ni pour le champ
     qui le suit s'il n'y a aucun champ visible avant. Même poids que
     `.ui-form .ui-input + .ui-input`, que les consumers surchargent. */
  :where(.ui-input:not(.ui-input--hidden)) ~ .ui-input:not(.ui-input--hidden) {
    margin-top: var(--space-6);
  }
}

.ui-form__footer {
  margin: var(--space-4) 0 0;
  text-align: center;
  font-size: var(--font-size-sm);

  a {
    color: var(--color-text-subtle);
    transition: color var(--duration-fast) var(--easing-default);

    &:hover {
      color: var(--color-brand);
    }
  }
}

.form-error-summary {
  padding: var(--space-3) var(--space-4);
  background: var(--color-danger-a10);
  border: 1.5px solid var(--color-danger);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);

  .form-error-summary__title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-danger);
    margin-bottom: var(--space-2);
  }

  ul {
    margin: 0;
    padding-left: var(--space-4);

    li {
      font-size: var(--font-size-sm);
      color: var(--color-danger);
    }
  }
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
  justify-content: flex-end;
}


/* fulgore: ui/bases/input.css */
.ui-input {
  display: grid;
  gap: var(--space-2);

  label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* gap : espace minimal entre le texte et le tooltip quand le label est
       à largeur de contenu (checkbox) — space-between n'y suffit pas */
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text);
  }

  input,
  textarea {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    color: var(--color-text);
    background: var(--color-surface);
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md);
    outline: none;
    box-sizing: border-box;
    transition:
      border-color var(--duration-fast) var(--easing-default),
      box-shadow var(--duration-fast) var(--easing-default);

    &::placeholder {
      color: var(--color-text-disabled);
    }

    &:focus {
      border-color: var(--color-brand);
      box-shadow: var(--focus-ring);
    }
  }

  textarea {
    resize: vertical;
    min-height: 6rem;
    line-height: var(--line-height-normal);
  }

  .ui-input__required {
    color: var(--color-danger);
    margin-left: var(--space-1);
  }

  .ui-input__hint {
    font-size: var(--font-size-xs);
    color: var(--color-text-subtle);
  }

  .ui-input__error {
    font-size: var(--font-size-xs);
    color: var(--color-danger);
  }

  

  &.ui-input--error {
    label {
      color: var(--color-danger);
    }

    input,
    textarea {
      border-color: var(--color-danger);

      &:focus {
        box-shadow: 0 0 0 3px var(--color-danger-a10);
      }
    }
  }

  

  &.ui-input--disabled {
    opacity: 0.5;
    cursor: not-allowed;

    input,
    textarea {
      cursor: not-allowed;
    }
  }
}


/* fulgore: ui/bases/list.css */
.ui-bases-list {
  padding: var(--space-8);
  display: grid;
  gap: var(--space-6);

  h1 {
    margin: 0;
  }
}

.ui-list-sort-disabled-notice {
  margin: var(--space-2) 0 0;
  color: var(--color-text-subtle);
  font-size: var(--font-size-sm);
}

.ui-list-table-wrapper {
  overflow-x: auto;
}

.ui-list-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;

  th,
  td {
    padding: var(--space-3) var(--space-4);
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--color-border);
    font-size: var(--font-size-sm);
  }

  th {
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-subtle);
    font-size: var(--font-size-sm);
  }

  /* ⚠️ MONTÉES ICI LE 2026-09-02, ET ELLES CHANGENT L'ASPECT DE TOUTES LES
     LISTES DU PARC. C'étaient les deux seules choses qu'une table de la gem ne
     donnait pas, et deux sidecars de Fatima les recopiaient donc à l'identique.
     Les laisser dehors condamnait chaque consumer à les réécrire pour obtenir
     un tableau d'apparence ordinaire.
     Sous 768 px, `thead` est masqué par la bascule en cartes : la première
     règle y est inerte, la seconde teinte la carte survolée. */
  thead {
    background-color: var(--color-surface-subtle);
  }

  tbody tr:hover {
    background-color: var(--color-surface-subtle);
  }

  .ui-list-table__th--sortable {
    padding: 0;
  }

  .ui-col--spacer {
    width: 100%;
  }

  .ui-col--thumb {
    width: 3rem;
  }

  /* ⚠️ `white-space: nowrap` A CESSÉ D'ÊTRE LE DÉFAUT DE TOUTE CELLULE — NE PAS
     LE REMETTRE SUR `th, td`. Il l'a été jusqu'au 2026-08-02, et il fabriquait
     un débordement là où il n'y avait aucune raison d'en avoir un : la largeur
     du tableau devenait la somme de ses contenus les plus longs tenus sur UNE
     ligne. Mesuré en production sur un tableau de cinq colonnes dans 880 px de
     large — 1010 px de contenu, donc 130 px cachés, à cause d'une seule cellule
     de texte libre (« Me contacter (différents packs proposés) »).

     Et ce débordement n'était pas qu'un défilement de plus : il décalait la
     colonne d'actions collée à droite, qui RECOUVRAIT alors la dernière colonne
     de données. Chez le consumer c'était « Publiée », le champ qui dit si une
     fiche est en ligne — 7 en-têtes dans le DOM, 6 visibles à l'écran, dans les
     deux moteurs. Rien ne rougissait : le `<th>` est bien rendu, il n'est ni
     clippé ni hors cadre, il est simplement PEINT DESSOUS.

     La colonne collée n'était donc pas le défaut, elle en était le symptôme.
     Le `nowrap` général était la cause, et il aurait rejoué sur le prochain
     tableau du prochain site.

     Il reste juste là où couper serait pire que replier : un libellé d'en-tête,
     une vignette, la poignée, le rang, et la cellule d'actions — tous courts ou
     atomiques. Pour une cellule de données qui ne doit jamais se couper (une
     date, un montant, une référence), l'opt-in est `ui-col--nowrap`, dans la
     même famille que `ui-col--optional` / `--important` / `--thumb`.

     Borné à partir de 769 px : en dessous, le tableau devient une pile de
     cartes et TOUT doit se replier (cf. le bloc `max-width: 768px`). */
  @media (min-width: 769px) {
    th,
    .ui-col--nowrap,
    .ui-col--thumb,
    .ui-bases-row__grip,
    .ui-bases-row__position,
    .ui-list-table__td--actions,
    .ui-bases-row__actions {
      white-space: nowrap;
    }
  }

  .ui-list-table__th--right {
    text-align: right;
  }

  .sort-link {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-4);
    color: var(--color-text-subtle);
    text-decoration: none;
    white-space: nowrap;

    &:hover {
      color: var(--color-brand);
    }

    &.sort-link--active {
      color: var(--color-brand);
    }
  }

  .sort-arrow {
    font-size: var(--font-size-xs);
    opacity: 0.5;
  }

  .sort-link--active .sort-arrow {
    opacity: 1;
  }

  .ui-list-table__th--actions,
  .ui-list-table__td--actions,
  .ui-bases-row__actions {
    position: sticky;
    right: 0;
    background: var(--color-surface);
    box-shadow: -4px 0 8px -2px rgb(0 0 0 / 0.04);
  }

  /* `position: sticky` ALWAYS creates a stacking context, so every Actions
     cell is its own layer painted in DOM order — and a RowActionsMenu's
     `z-index: var(--z-dropdown)` only ever ranks INSIDE its own cell. Result:
     an open kebab menu is painted over by the next row's Actions cell (33% of
     the panel covered, measured WebKit + Chromium). Raising just the cell that
     holds an open menu lifts its whole layer above its siblings, which are all
     at `z-index: auto`. Floating mode (`position: fixed`, dropdown_controller)
     escapes CLIPPING, not stacking — it does not help here.
     Keep this rule INSIDE the `.ui-list-table` block: flattened out it drops
     from (0,2,0) to (0,1,0) and is silently outranked. */
  .ui-list-table__td--actions:has(.ui-row-actions-menu.is-open),
  .ui-bases-row__actions:has(.ui-row-actions-menu.is-open) {
    z-index: 1;
  }

}

/* ⚠️ ICI VIVAIT UNE RÈGLE QUI ÉTEIGNAIT L'OMBRE DE LA COLONNE COLLÉE AU-DESSUS
   DE 1025 px — NE PAS LA REMETTRE. L'ombre est le SEUL indice qui dise que
   cette colonne flotte au-dessus du reste et qu'il reste du contenu à sa
   gauche. La couper aux largeurs de bureau, c'est la couper exactement là où
   on regarde : le 2026-08-02, en production à 1280, une colonne de données
   entière était recouverte sans qu'aucun signe ne l'indique — et la barre de
   défilement du cadre mesure 0 px de haut (barre superposée macOS, invisible
   tant qu'on ne fait pas le geste). Aucun indice, donc, d'aucune sorte.

   Le pari de cette règle était « à cette largeur le tableau tient, l'ombre
   serait du bruit ». Il ne tient pas : un tableau déborde en fonction de son
   CONTENU, pas de la largeur de l'écran. Et le bruit est faible — l'ombre vaut
   4 % d'opacité, invisible quand la colonne est à sa place naturelle. */

@media (max-width: 1024px) {
  .ui-list-table .ui-col--optional {
    display: none;
  }
}

@media (max-width: 768px) {
  .ui-list-table {
    display: block;
    width: 100%;

    thead {
      display: none;
    }

    tbody {
      display: block;
      width: 100%;
    }

    .ui-col--optional,
    .ui-col--important {
      display: flex;
    }

    tbody tr {
      display: block;
      width: 100%;
      box-sizing: border-box;
      border: 1px solid var(--color-border);
      border-radius: var(--radius-md);
      margin-bottom: var(--space-3);
      padding: var(--space-2);
      box-shadow: var(--shadow-md);
    }

    td {
      display: flex;
      width: 100%;
      box-sizing: border-box;
      justify-content: space-between;
      align-items: center;
      border-bottom: 1px solid var(--color-border);
      white-space: normal;
    }


    td:last-child {
      border-bottom: none;
    }

    .ui-col--spacer {
      display: none;
    }

    .ui-col--card-hidden {
      display: none;
    }

    td::before {
      content: attr(data-label);
      font-weight: var(--font-weight-semibold);
      color: var(--color-text-subtle);
      font-size: var(--font-size-sm);
      flex-shrink: 0;
      margin-right: var(--space-3);
    }

    .ui-list-table__td--actions {
      position: static;
      box-shadow: none;
    }
  }
}

@media (max-width: 480px) {
  .ui-bases-list {
    padding: var(--space-3);
  }
}


/* fulgore: ui/bases/modal.css */
.ui-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  align-items: center;
  justify-content: center;

  &.is-open {
    display: flex;

    .ui-modal__backdrop {
      animation: fade-in var(--duration-normal) var(--easing-out) both;
    }

    .ui-modal__dialog {
      animation: scale-in var(--duration-normal) var(--easing-spring) both;
    }
  }
}

.ui-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.ui-modal__dialog {
  position: relative;
  white-space: normal;
  background: var(--color-surface);
  border-radius: var(--radius-xl);
  padding: var(--space-8);
  width: 100%;
  max-width: 32rem;
  max-height: calc(100vh - var(--space-8) * 2);
  margin: var(--space-4);
  box-shadow: var(--shadow-xl);
  overflow-x: hidden;
  overflow-y: auto;
}

@media (max-width: 1023px) {
  .ui-modal {
    padding-top: var(--navbar-height);
  }

  .ui-modal__dialog {
    max-height: calc(100vh - var(--navbar-height) - var(--space-8));
  }
}

.ui-modal__dialog > .ui-button {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
}

.ui-modal__body {
  max-width: 100%;
  overflow-wrap: break-word;
  text-align: center;
}

.ui-modal__header {
  margin-bottom: var(--space-4);
  text-align: center;
}

.ui-modal__footer {
  margin-top: var(--space-6);
}

.ui-modal__footer .form-actions {
  justify-content: center;
}

.ui-modal__footer .form-actions:has(> :nth-child(2)) {
  justify-content: space-between;
}

@media (max-width: 480px) {
  .ui-modal__dialog {
    padding: var(--space-5);
    margin: var(--space-2);
  }
}


/* fulgore: ui/bases/navbar.css */
.ui-bases-navbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: var(--space-4);
  height: var(--navbar-height);
  padding: var(--space-1) var(--space-4);
  box-sizing: border-box;
  align-items: center;
  background: var(--color-brand);
  color: var(--color-text-inverted);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

.ui-bases-navbar a {
  display: block;
  color: inherit;
  text-decoration: none;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--easing-default);
}

.ui-bases-navbar a:hover {
  background: rgba(255, 255, 255, 0.15);
}

/* ── Left section ── */

.navbar-left {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.navbar-brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: inherit;
  text-decoration: none;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--easing-default);
  width: fit-content;
}

.navbar-brand:hover {
  background: rgba(255, 255, 255, 0.15);
}

.navbar-brand svg {
  width: 2rem;
  height: 2rem;
  flex-shrink: 0;
}

/* ── Hamburger ── */

.navbar-hamburger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: none;
  background: transparent;
  border-radius: var(--radius-md);
  color: var(--color-text-inverted);
  cursor: pointer;
  transition: background var(--duration-fast) var(--easing-default);
}

.navbar-hamburger:hover {
  background: rgba(255, 255, 255, 0.15);
}

.navbar-hamburger:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ── Center section ── */

.navbar-nav {
  display: flex;
  justify-content: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.navbar-link {
  display: block;
  color: inherit;
  text-decoration: none;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--easing-default);
}

.navbar-link:hover {
  background: rgba(255, 255, 255, 0.15);
}

.navbar-link--active {
  background: rgba(255, 255, 255, 0.25);
  font-weight: var(--font-weight-semibold);
}

/* ── Right section ── */

.navbar-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
}

/* ── Responsive ── */

@media (max-width: 1023px) {
  .ui-bases-navbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
  }
}


/* fulgore: ui/bases/new.css */
.ui-bases-new__header {
  margin-block-end: var(--space-6);
}

.ui-bases-new__body {
}


/* fulgore: ui/bases/page_header.css */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}

.page-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.page-header--size-md .page-title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  margin: 0;
}

.page-header--size-sm .page-title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  margin: 0;
}

@media (max-width: 480px) {
  .page-header {
    flex-direction: column;
    gap: var(--space-3);
  }
}


/* fulgore: ui/bases/progress_bar.css */
.ui-bases-progress-bar {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.ui-bases-progress-bar__label {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-subtle);
}

.ui-bases-progress-bar__track {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.ui-bases-progress-bar__bar {
  flex: 1;
  height: var(--space-2);
  border-radius: var(--radius-full);
  background-color: var(--color-surface-subtle);
  overflow: hidden;
}

.ui-bases-progress-bar__fill {
  height: 100%;
  border-radius: var(--radius-full);
  background-color: var(--color-text-subtle);
  transition: width var(--duration-normal) var(--easing-default);
}

.ui-bases-progress-bar--brand .ui-bases-progress-bar__fill {
  background-color: var(--color-brand);
}

.ui-bases-progress-bar--accent .ui-bases-progress-bar__fill {
  background-color: var(--color-accent);
}

.ui-bases-progress-bar--sm .ui-bases-progress-bar__bar {
  height: var(--space-1);
}

.ui-bases-progress-bar--sm .ui-bases-progress-bar__percentage {
  font-size: var(--font-size-xs);
}

.ui-bases-progress-bar__percentage {
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
  min-width: 3ch;
  text-align: right;
}


/* fulgore: ui/bases/public_navbar.css */
/* ============================================================
   PUBLIC NAVBAR — structure seulement
   La gem pose la mise en page et le tiroir mobile ; chaque site
   habille (couleurs, polices, fond, hauteur du logo) en redéfinissant
   les custom properties --public-navbar-* sur sa propre classe.

   Seuil desktop : 900px, valeur par défaut. Une media query ne peut
   pas lire de variable : un site qui veut un autre seuil redéfinit
   les règles du bloc @media (min-width: 900px) dans son propre CSS.
   ============================================================ */

.ui-bases-public-navbar {
  --public-navbar-bg: var(--color-surface);
  --public-navbar-fg: var(--color-text);
  --public-navbar-border: var(--color-border);
  --public-navbar-min-height: 64px;
  --public-navbar-gutter: var(--space-4);

  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  border-bottom: 1px solid var(--public-navbar-border);
  color: var(--public-navbar-fg);
  background-color: var(--public-navbar-bg);
  transition: box-shadow var(--duration-normal) var(--easing-default);
}

.ui-bases-public-navbar.is-scrolled {
  box-shadow: var(--shadow-md);
}

.ui-bases-public-navbar__container {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  position: relative;
  min-height: var(--public-navbar-min-height);
  padding-inline: var(--public-navbar-gutter);
}

.ui-bases-public-navbar__brand {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  text-decoration: none;
  color: inherit;
}

/* Mobile : menu masqué, tiroir pleine largeur sous la barre à l'ouverture. */
.ui-bases-public-navbar__menu {
  display: none;
}

.ui-bases-public-navbar__menu.is-open {
  display: block;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  padding: var(--space-2) var(--public-navbar-gutter) var(--space-4);
  border-bottom: 1px solid var(--public-navbar-border);
  /* Opaque : un fond translucide laisse transparaître la page derrière
     les liens. */
  background-color: var(--public-navbar-bg);
}

.ui-bases-public-navbar__list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui-bases-public-navbar__item {
  list-style: none;
}

.ui-bases-public-navbar__link {
  display: inline-block;
  white-space: nowrap;
  text-decoration: none;
  color: inherit;
}

.ui-bases-public-navbar__menu.is-open .ui-bases-public-navbar__link {
  display: block;
  min-height: 44px;
  padding: var(--space-3) var(--space-2);
}

.ui-bases-public-navbar__link--active {
  text-decoration: underline;
  text-underline-offset: var(--space-1);
}

.ui-bases-public-navbar__actions {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

/* Burger fourni par UI::MenuToggle : ne s'ovalise pas, poussé à droite
   en mobile, icône calibrée (le SVG n'a pas de taille intrinsèque). */
.ui-bases-public-navbar .ui-menu-toggle {
  flex-shrink: 0;
  margin-left: auto;
}

.ui-bases-public-navbar .ui-menu-toggle .svg {
  height: var(--space-5);
  width: auto;
}

@media (min-width: 900px) {
  .ui-bases-public-navbar .ui-menu-toggle {
    display: none;
  }

  .ui-bases-public-navbar__menu,
  .ui-bases-public-navbar__menu.is-open {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: flex-end;
    position: static;
    padding: 0;
    border-bottom: none;
    background: none;
  }

  .ui-bases-public-navbar__list {
    flex-direction: row;
    align-items: center;
    gap: var(--space-1);
  }

  .ui-bases-public-navbar__menu.is-open .ui-bases-public-navbar__link {
    display: inline-block;
    min-height: 0;
    padding: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ui-bases-public-navbar {
    transition: none;
  }
}


/* fulgore: ui/bases/record_view.css */
.ui-bases-record-view__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* wrap + min-width 0 : sans eux, une zone d'actions plus large que
     l'espace restant déborde du viewport mobile (flex min-width:auto). */
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}

.ui-bases-record-view__header > * {
  min-width: 0;
}

.ui-bases-record-view__title-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin: var(--space-6) 0 var(--space-8) 0;
}

.ui-bases-record-view__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6);
  align-items: start;
}

.ui-bases-record-view__body > :only-child {
  grid-column: 1 / -1;
  max-width: 48rem;
  margin-inline: auto;
  width: 100%;
}

.ui-bases-record-view__body > .ui-bases-record-view__layout {
  max-width: none;
  margin-inline: 0;
}

/* ── Layout (used by Show/Edit body_content) ── */

.ui-bases-record-view__layout {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* ── Row (2-column grid) ── */

.ui-bases-record-view__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6);
  align-items: start;
}

@media (max-width: 768px) {
  .ui-bases-record-view__body {
    grid-template-columns: 1fr;
  }

  .ui-bases-record-view__row {
    grid-template-columns: 1fr;
  }
}


/* fulgore: ui/bases/record_view_title.css */
.ui-bases-record-view-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  color: var(--color-text);
  margin: 0;
}


/* fulgore: ui/bases/row.css */
.ui-bases-row__actions-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

@media (max-width: 480px) {
  .ui-bases-row__actions-inner {
    justify-content: flex-end;
    flex-wrap: wrap;
  }
}


@keyframes position-flip {
  0%   { transform: perspective(120px) rotateX(0deg);   opacity: 1; }
  45%  { transform: perspective(120px) rotateX(-90deg); opacity: 0; }
  55%  { transform: perspective(120px) rotateX(-90deg); opacity: 0; }
  100% { transform: perspective(120px) rotateX(0deg);   opacity: 1; }
}

.ui-bases-row__position {
  color: var(--color-text-subtle);
  font-size: var(--font-size-sm);
  user-select: none;
}

.ui-bases-row__position.is-flipping {
  animation: position-flip 300ms ease-in-out;
  will-change: transform;
}

/* td-qualified: must outrank `.ui-list-table td` (list.css) or its padding
   collapses the cell content box to 0 and hides the handle. */
td.ui-bases-row__grip {
  width: 1.25rem;
  padding-right: 0;
  color: var(--color-text-subtle);
  user-select: none;
  cursor: grab;

  &:active {
    cursor: grabbing;
  }

  /* Shield the handle from consumer resets like `svg { max-width: 100% }`
     (100% of a zero-width content box renders the handle invisible). */
  & svg {
    width: 10px;
    min-width: 10px;
    max-width: none;
  }
}

/* The handle is a real button so it can be reached by Tab and driven by the
   arrow keys — mouse dragging is not the only way to reorder. It must not look
   like one: no native chrome, it inherits the cell's colour and grab cursor.
   The focus ring is the one thing it keeps, and it must stay visible — it is
   the only cue telling a keyboard user which row the arrows will move. */
button.ui-bases-row__grip-button {
  display: inline-flex;
  align-items: center;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: inherit;
  font: inherit;
  line-height: 0;

  /* Même anneau que partout ailleurs dans la gem (bouton, menu d'actions,
     lien de barre latérale) : `--focus-ring`, jamais un outline maison. */
  &:focus-visible {
    outline: none;
    border-radius: var(--radius-sm);
    box-shadow: var(--focus-ring);
  }
}

tr[draggable="true"] {
  cursor: grab;

  
  & td:not(:has(a, button)) {
    cursor: grab;
  }

  &:active,
  &:active td:not(:has(a, button)) {
    cursor: ns-resize;
  }
}

tr.sortable--dragging,
tr.sortable--dragging td {
  cursor: ns-resize;
}

tr.sortable--dragging {
  opacity: 0.7;
  background: var(--color-surface-raised);
  outline: 1.5px dashed var(--color-border-strong);
  outline-offset: -1px;
  box-shadow: var(--shadow-md);
}


/* fulgore: ui/bases/show.css */
.ui-bases-show__header {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  margin-block-end: var(--space-6);

  .ui-links-back {
    margin-block: 0;
  }
}

.ui-bases-show__body {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: var(--space-8);
}

.ui-bases-show__list {
  width: 100%;
  margin-block-start: var(--space-8);
}

.ui-bases-show__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-block-start: var(--space-8);
}

@media (max-width: 767px) {
  .ui-bases-show__body {
    grid-template-columns: 1fr;
  }

  .ui-bases-show__header {
    grid-template-columns: 1fr;
  }
}


/* fulgore: ui/bases/sidebar.css */
/* Le panneau reçoit le focus à l'ouverture en mobile (cf. nav_sidebar_controller
   #enableFocusTrap) : ce n'est pas un contrôle, aucun anneau ne doit s'y
   dessiner. Sélecteur d'attribut et non de classe — la règle doit valoir pour
   toute sidebar branchée sur le contrôleur, y compris les panneaux propres aux
   consumers qui n'utilisent pas .sidebar. */
[data-nav-sidebar-target="sidebar"]:focus {
  outline: none;
}

.sidebar {
  position: fixed;
  top: var(--navbar-height);
  left: 0;
  bottom: 0;
  width: var(--sidebar-width);
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  padding: var(--space-4) 0;
  overflow-y: auto;
  z-index: var(--z-raised);
  box-sizing: border-box;
}

.sidebar nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  color: var(--color-text-subtle);
  text-decoration: none;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  transition: background var(--duration-fast), color var(--duration-fast);
  border-left: 3px solid transparent;
}

.sidebar-link:hover {
  background: var(--color-surface-subtle);
  color: var(--color-text);
}

.sidebar-link:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.sidebar-link svg {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
}

.sidebar-link--active {
  color: var(--color-brand);
  background: var(--color-brand-surface);
  border-left-color: var(--color-brand);
  font-weight: var(--font-weight-semibold);
}

/* ── Responsive ── */

@media (max-width: 1023px) {
  .sidebar {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-link {
    transition: none;
  }
}


/* fulgore: ui/bases/stat_card.css */
.ui-stat-card {
  padding: var(--space-8);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  background: var(--color-surface);
}

.ui-stat-card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.ui-stat-card__title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  line-height: 1.2;
  margin: 0;
}


/* fulgore: ui/bases/view_actions.css */
.ui-bases-view-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}


/* fulgore: ui/buttons/switch.css */
.ui-buttons-switch {
  display: inline-flex;
  cursor: pointer;
  align-items: center;

  form,
  button {
    display: contents;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    cursor: pointer;
  }
}

.ui-buttons-switch__track {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 2.75rem;
  height: 1.5rem;
  border-radius: var(--radius-full);
  background-color: var(--color-border);
  transition: background-color var(--duration-slow) var(--easing-default);
  padding: 0 var(--space-1);
  box-sizing: border-box;
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.18),
    inset 0 1px 2px rgba(0, 0, 0, 0.10);
}

.ui-buttons-switch--checked .ui-buttons-switch__track {
  background-color: var(--color-brand);
}

.ui-buttons-switch__thumb {
  position: absolute;
  left: var(--space-1);
  width: 1.25rem;
  height: 1.25rem;
  border-radius: var(--radius-full);
  background: radial-gradient(circle at 35% 30%, #ffffff, #c8c8c8);
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.22),
    0 1px 2px rgba(0, 0, 0, 0.14),
    0 0 0 1px rgba(0, 0, 0, 0.06);
  transition:
    transform var(--duration-slow) var(--easing-spring),
    width var(--duration-fast) var(--easing-out);
}

.ui-buttons-switch--checked .ui-buttons-switch__thumb {
  transform: translateX(1rem);
}

.ui-buttons-switch:active .ui-buttons-switch__thumb {
  width: 1.5rem;
}


/* fulgore: ui/calendar.css */
.ui-calendar {
  min-width: 0;
  max-width: 100%;
}

/* Navigator */

.ui-calendar__navigator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.ui-calendar__month-title {
  min-width: calc(var(--space-24) * 2);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  text-align: center;
  color: var(--color-text);
}

/* Les liens portent aussi `.ui-link` (UI::Links::Plain : color inherit, opacity
   0.7 au survol, rayon sm au focus). `.ui-link` en second sélecteur relève la
   spécificité pour l'emporter quel que soit l'ordre de chargement. */
.ui-calendar__nav-link.ui-link {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-10);
  height: var(--space-10);
  border-radius: var(--radius-full);
  font-size: var(--font-size-lg);
  text-decoration: none;
  color: var(--color-text-subtle);
  background: transparent;
  transition: background var(--duration-fast) var(--easing-default),
              color var(--duration-fast) var(--easing-default);

  &:hover {
    background: var(--color-surface-raised);
    color: var(--color-text);
    opacity: 1;
  }

  &:focus-visible {
    outline: none;
    border-radius: var(--radius-full);
    box-shadow: var(--focus-ring);
  }
}

/* Grid */

.ui-calendar__grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

/* La grille tient toujours dans la largeur disponible, sans défilement
   horizontal : les colonnes se resserrent (minmax(0, 1fr)) et le texte des
   cases passe à la ligne. */

/* Weekday headers */

.ui-calendar__weekday {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-subtle);
  background: var(--color-surface-subtle);
}

/* Day cells */

.ui-calendar__day {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  min-height: var(--space-24);
  padding: var(--space-1);
  border-right: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  transition: background var(--duration-fast) var(--easing-default);

  &:hover {
    background: var(--color-surface-subtle);
  }

  &:nth-child(7n + 7) {
    border-right: none;
  }
}

/* Pas de double bordure sur la dernière ligne (7 cases par ligne, en-têtes exclus) */
.ui-calendar__grid > .ui-calendar__day:nth-last-child(-n+7) {
  border-bottom: none;
}

.ui-calendar__day--weekend {
  background: var(--color-surface-subtle);

  &:hover {
    background: var(--color-surface-raised);
  }
}

.ui-calendar__day--other-month {
  background: var(--color-surface-subtle);
  opacity: 0.45;
}

.ui-calendar__day--today {
  background: var(--color-brand-a10);

  &:hover {
    background: var(--color-brand-a20);
  }
}

/* Day header */

.ui-calendar__day-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Le « + » n'apparaît qu'au survol sur écran à souris ; sans survol possible
   (téléphone), il reste visible en permanence — voir le bloc hover: none. */
.ui-calendar__day-add.ui-link {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-6);
  height: var(--space-6);
  border-radius: var(--radius-full);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
  color: var(--color-text-subtle);
  opacity: 0;
  transition: opacity var(--duration-fast) var(--easing-default),
              background var(--duration-fast) var(--easing-default);

  &:hover {
    background: var(--color-brand-a20);
    color: var(--color-brand);
    opacity: 1;
  }

  &:focus-visible {
    outline: none;
    border-radius: var(--radius-full);
    box-shadow: var(--focus-ring);
    opacity: 1;
  }
}

.ui-calendar__day:hover .ui-calendar__day-add {
  opacity: 1;
}

@media (hover: none) {
  .ui-calendar__day-add.ui-link {
    opacity: 1;
  }
}

/* Day number */

.ui-calendar__day-number {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  color: var(--color-text-subtle);
}

.ui-calendar__day--today .ui-calendar__day-number {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--space-6);
  height: var(--space-6);
  border-radius: var(--radius-full);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-inverted);
  background: var(--color-brand);
}

/* Day content — le rendu des événements appartient à l'app */

.ui-calendar__day-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Libellé accessible des liens ◀ ▶ et « + » : lu par les lecteurs d'écran,
   invisible à l'écran (le glyphe visible est dans un span aria-hidden). */

.ui-calendar__sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Mobile : cases et en-têtes plus serrés pour gagner de la largeur. */
@media (max-width: 768px) {
  .ui-calendar__weekday {
    padding: var(--space-1);
  }

  .ui-calendar__day {
    padding: var(--space-1);
  }
}


/* fulgore: ui/chat/bubble.css */
.ui-chat-bubble {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-width: 75%;
}

.ui-chat-bubble--sent {
  align-self: flex-end;
  align-items: flex-end;
}

.ui-chat-bubble--received {
  align-self: flex-start;
  align-items: flex-start;
}

.ui-chat-bubble__author {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.ui-chat-bubble__meta {
  display: flex;
  justify-content: flex-end;
}

.ui-chat-bubble__time {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
}

.ui-chat-bubble__body {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-loose);
  word-break: break-word;
}

.ui-chat-bubble--sent .ui-chat-bubble__body {
  background: var(--color-brand-surface);
  color: var(--color-text);
  border-bottom-right-radius: var(--radius-sm);
}

.ui-chat-bubble--received .ui-chat-bubble__body {
  background: var(--color-surface-subtle);
  color: var(--color-text);
  border-bottom-left-radius: var(--radius-sm);
}


/* fulgore: ui/chat/conversation_item.css */
.ui-chat-conversation-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3) var(--space-4);
  text-decoration: none;
  color: var(--color-text);
  border-radius: var(--radius-md);
  transition: background var(--duration-fast) var(--easing-default);

  &:hover {
    background: var(--color-surface-raised);
  }

  &--unread {
    background: var(--color-brand-surface);

    &:hover {
      background: var(--color-brand-a10);
    }

    .ui-chat-conversation-item__names {
      font-weight: var(--font-weight-semibold);
    }

    .ui-chat-conversation-item__preview {
      color: var(--color-text);
    }
  }
}

/* --- Avatars --- */

.ui-chat-conversation-item__avatars {
  display: flex;
  flex-direction: row;
  align-items: center;
  align-self: center;
}

.ui-chat-conversation-item__avatar {
  margin-left: -6px;

  &:first-child {
    margin-left: 0;
  }

  .ui-user-badge {
    gap: 0;
  }

  .ui-user-badge__text {
    display: none;
  }

  .ui-user-badge__circle {
    width: 1.75rem !important;
    height: 1.75rem !important;
    font-size: 0.6875rem !important;
    border: 2px solid var(--color-surface);
  }
}

/* --- Content --- */

.ui-chat-conversation-item__content {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ui-chat-conversation-item__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.ui-chat-conversation-item__names {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-chat-conversation-item__time {
  font-size: 0.625rem;
  color: var(--color-text-subtle);
  white-space: nowrap;
  flex-shrink: 0;
}

.ui-chat-conversation-item__subject {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-chat-conversation-item__preview {
  margin: 0;
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Unread badge --- */

.ui-chat-conversation-item__unread-badge {
  display: inline-block;
  min-width: 1.25rem;
  height: 1.25rem;
  line-height: 1.25rem;
  padding-inline: 5px;
  border-radius: var(--radius-full);
  background: var(--color-danger);
  color: var(--color-text-inverted);
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.6875rem;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
  align-self: center;
}


/* fulgore: ui/chat/empty_state.css */
.ui-chat-empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-8);
  color: var(--color-text-subtle);

  .svg {
    width: var(--icon-size-lg);
    height: var(--icon-size-lg);
    opacity: 0.4;
  }
}

.ui-chat-empty-state__text {
  margin: 0;
  font-size: var(--font-size-sm);
  text-align: center;
}


/* fulgore: ui/chat/input.css */
.ui-chat-input {
  flex-shrink: 0;
  border-top: 1px solid var(--color-border);
  padding: var(--space-3) var(--space-4);
}

.ui-chat-input__form {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.ui-chat-input__textarea {
  flex: 1;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  font-size: 16px;
  font-family: inherit;
  resize: none;
  outline: none;
  transition: border-color var(--duration-fast) var(--easing-default);

  &:focus {
    border-color: var(--color-brand);
    box-shadow: var(--focus-ring);
  }
}

.ui-chat-input__submit {
  padding: var(--space-2) var(--space-4);
  border: none;
  border-radius: var(--radius-lg);
  background: var(--color-brand);
  color: var(--color-text-inverted);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--easing-default);

  &:hover {
    background: var(--color-brand-dark);
  }

  &:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }

  &:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }
}


/* fulgore: ui/chat/list.css */
.ui-chat-list {
  flex: 1;
  min-height: 20rem;
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.ui-chat-list[data-full-height="true"] {
  min-height: 0;
  max-height: none;
}


/* fulgore: ui/directions_dropdown.css */
/* "Directions" dropdown — anchors the absolute menu under the trigger.
   Stimulus `dropdown` toggles .is-open on this root element, not the menu. */

.ui-directions-dropdown {
  position: relative;
  display: inline-block;
}

.ui-directions-dropdown__toggle::after {
  content: "▾";
  margin-left: var(--space-1);
  font-size: 0.75em;
}

.ui-directions-dropdown__menu {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  z-index: var(--z-dropdown);
  min-width: 12rem;
  padding: var(--space-1) 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
  box-shadow: var(--shadow-md);
}

.ui-directions-dropdown.is-open .ui-directions-dropdown__menu {
  display: block;
}

.ui-directions-dropdown__item {
  display: block;
  padding: var(--space-2) var(--space-4);
  font-size: var(--font-size-sm);
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
}

.ui-directions-dropdown__item:hover,
.ui-directions-dropdown__item:focus {
  background: var(--color-surface-alt);
}


/* fulgore: ui/display/code.css */
.code-container {
  display: grid;
  user-select: text;
}

/* ── Toggle button ── */

.code-container .collapse-toggle {
  background-color: var(--color-neutral-900);
  border: 1px solid var(--color-neutral-900);
  border-radius: var(--radius-lg);
  color: var(--color-text-inverted);
  cursor: pointer;
  font-size: var(--font-size-2xl);
  margin: 0 var(--space-4) 0 auto;
  padding: var(--space-2);
  position: relative;
  top: var(--space-6);
  transition: background-color var(--duration-normal) var(--easing-default),
              border-color var(--duration-normal) var(--easing-default);
  width: fit-content;
  z-index: var(--z-raised);
}

.code-container .collapse-toggle:hover {
  background-color: var(--color-surface);
  border-color: var(--color-neutral-900);
  color: var(--color-text);
}

/* ── Code block ── */

.code-container .code {
  background-color: var(--color-neutral-900);
  color: var(--color-neutral-0);
  overflow: scroll;
  padding: var(--space-2);
  transition: height var(--duration-normal) var(--easing-default);
  z-index: 1;
}

.code-container pre.collapsed {
  height: 5rem;
  overflow: hidden;
  cursor: pointer;
  padding: 0;
}

.code-container pre.expanded {
  height: 100%;
  overflow: scroll;
}


/* fulgore: ui/display/counter.css */
.ui-display-counter {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-3);
  border-radius: 999px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  background: var(--color-surface-raised);
  color: var(--color-text-subtle);
}

.ui-display-counter .ui-icon {
  width: 0.875rem;
  height: 0.875rem;
}


/* fulgore: ui/display/datetime.css */
.ui-display-datetime {
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  white-space: nowrap;
}


/* fulgore: ui/display/distribution_bar.css */
.ui-display-distribution-bar {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.ui-display-distribution-bar {
  min-width: 0;
}

.ui-display-distribution-bar__row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto minmax(40px, 80px);
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.ui-display-distribution-bar__emoji {
  font-size: var(--font-size-base);
  line-height: 1;
}

.ui-display-distribution-bar__label {
  font-size: var(--font-size-sm);
  color: var(--color-text);
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-display-distribution-bar__count {
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-subtle);
  text-align: right;
}

.ui-display-distribution-bar__track {
  height: 8px;
  background-color: var(--color-surface-subtle);
  border-radius: 999px;
  overflow: hidden;
}

.ui-display-distribution-bar__fill {
  height: 100%;
  background-color: var(--color-brand);
  transition: width 200ms ease;
}


/* fulgore: ui/display/iban.css */
.ui-display-iban {
  font-variant-numeric: tabular-nums;
}


/* fulgore: ui/display/image_skeleton.css */
/* .ui-image-skeleton — classe utility skeleton image partagée.
 * Pose un shimmer en background + un spinner via ::before sur l'élément porteur.
 * Réutilise @keyframes skeleton-shimmer et @keyframes spin (fulgore/animations.css).
 * Le wrapper doit définir ses propres dimensions (aspect-ratio, width, height,
 * border-radius, overflow).
 *
 * Deux usages possibles (selon la présence d'un wrapper) :
 *
 *   1. Sur un wrapper <div> qui contient un <picture> rendu par UI::Display::Picture
 *      → le shimmer + spinner sont sur le wrapper, l'image enfant le masque
 *        une fois chargée (z-index:1 sur le picture/img).
 *
 *   2. Directement sur le <picture> lui-même (via css_class de Picture, pour les
 *      cas sans wrapper parent — ex. miniatures en ligne dans un Row)
 *      → le ::before n'aurait pas d'effet sur un <img> seul (replaced element),
 *        mais le <picture> n'est PAS replaced, donc ::before fonctionne ;
 *        le <img> enfant masque le skeleton via z-index.
 *
 * Caveat asset transparent : le contract suppose un asset opaque (JPEG/WebP en
 * object-fit:cover). Pour un SVG/PNG transparent avec object-fit:contain,
 * les zones transparentes laissent voir le shimmer en permanence — préférer
 * dans ce cas un wrapper neutre sans skeleton (cf. show.css logo).
 */

.ui-image-skeleton {
  position: relative;
  overflow: hidden;
  background: linear-gradient(
    90deg,
    var(--color-surface-raised) 25%,
    var(--color-surface-subtle) 50%,
    var(--color-surface-raised) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
}

.ui-image-skeleton::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  margin: -12px 0 0 -12px;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-brand);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  z-index: 0;
}

.ui-image-skeleton > picture,
.ui-image-skeleton > picture > img,
picture.ui-image-skeleton,
picture.ui-image-skeleton > img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* fulgore: ui/display/money.css */
.ui-display-money {
  display: block;
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
}

.ui-display-money--default {
  color: var(--color-brand);
}

.ui-display-money--positive {
  color: var(--color-success);
}

.ui-display-money--negative {
  color: var(--color-danger);
}


/* fulgore: ui/display/range_bar.css */
.ui-display-range-bar {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

.ui-display-range-bar__labels {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: 500;
  color: var(--color-text-subtle);
}

.ui-display-range-bar__min,
.ui-display-range-bar__max {
  margin: 0;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

.ui-display-range-bar__max {
  text-align: right;
}

.ui-display-range-bar__track {
  position: relative;
  height: 6px;
  border-radius: 999px;
  background: linear-gradient(
    to right,
    var(--color-surface-subtle) 0%,
    var(--color-brand-surface) 50%,
    var(--color-surface-subtle) 100%
  );
  overflow: hidden;
}

.ui-display-range-bar__marker {
  position: absolute;
  top: 50%;
  width: 12px;
  height: 12px;
  background-color: var(--color-brand);
  border-radius: 50%;
  transform: translateY(-50%) translateX(-50%);
}

.ui-display-range-bar__marker-label {
  position: absolute;
  top: 100%;
  white-space: nowrap;
  margin-top: var(--space-1);
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  transform: translateX(-50%);
}


/* fulgore: ui/display/rna.css */
.ui-display-rna {
  font-variant-numeric: tabular-nums;
}


/* fulgore: ui/display/simple_format.css */
.simple-format {
  white-space: pre-line;
}

.simple-format p {
  margin: 0 0 1em;
}

.simple-format br {
  display: inline;
}


/* fulgore: ui/display/siret.css */
.ui-display-siret {
  font-variant-numeric: tabular-nums;
}


/* fulgore: ui/display/stat_block.css */
.ui-display-stat-block {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
  min-width: 0;
  text-align: center;
}

/* Large variant — default */
.ui-display-stat-block--large {
  .ui-display-stat-block__value {
    font-size: var(--font-size-3xl);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
    margin: 0;
  }

  .ui-display-stat-block__label {
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-subtle);
    margin: 0;
  }
}

/* Compact variant */
.ui-display-stat-block--compact {
  min-width: 0;

  .ui-display-stat-block__value {
    font-size: var(--font-size-lg);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.3;
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .ui-display-stat-block__label {
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-subtle);
    margin: 0;
  }
}


/* fulgore: ui/display/thumbnail.css */
.ui-display-thumbnail {
  width: 40px;
  height: 40px;
  overflow: hidden;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.ui-display-thumbnail picture,
.ui-display-thumbnail .ui-display-thumbnail__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 1;
}


/* fulgore: ui/empty_state.css */
.ui-empty-state {
  text-align: center;
  padding: var(--space-12) var(--space-8);
  color: var(--color-text-subtle);

  .empty-state-icon {
    margin-bottom: var(--space-3);

    .svg {
      width: var(--space-10);
      height: var(--space-10);
      fill: currentColor;
      opacity: 0.4;
      /* Consumer resets may force `svg { display: block }`, which escapes
         the text-align: center of the root — margin-inline keeps a block
         svg centered and is a no-op on an inline one. */
      margin-inline: auto;
    }
  }

  .empty-state-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-medium);
    margin: 0 0 var(--space-2) 0;
  }

  .empty-state-description {
    font-size: var(--font-size-base);
    margin: 0;
  }

  .empty-state-cta {
    margin-top: var(--space-5);
  }
}


/* fulgore: ui/gauge.css */
.ui-gauge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-3);
  background-color: var(--color-brand-surface);
  border: 1px solid var(--color-brand-a10);
  border-radius: var(--radius-lg);
  text-align: center;
}

.ui-gauge__icon {
  font-size: var(--font-size-2xl);
  line-height: 1;
}

.ui-gauge__label {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-brand);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.ui-gauge .ui-bases-progress-bar {
  width: 100%;
}

.ui-gauge .ui-bases-progress-bar__track {
  flex-direction: column;
  gap: var(--space-2);
}

.ui-gauge .ui-bases-progress-bar__bar {
  flex: none;
  width: 100%;
  height: var(--space-1);
}

.ui-gauge .ui-bases-progress-bar__percentage {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
  color: var(--color-brand);
  text-align: center;
  min-width: unset;
}


/* fulgore: ui/ghost_row.css */
.ui-ghost-row {
  
  & .ui-ghost-row__cell {
    
    border: 3px dashed var(--color-brand);
    background-color: var(--color-brand-a20);
    padding-block: var(--space-1);
  }
}


/* fulgore: ui/help_tooltip.css */
.ui-help-tooltip {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.ui-help-tooltip__trigger {
  position: relative;
  width: 1.1rem;
  height: 1.1rem;
  background: var(--color-surface-raised);
  color: var(--color-text-subtle);
  font-size: var(--font-size-xs);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  cursor: pointer;
  line-height: 1;
  padding: 0;
}

/* Le rond visible fait 17,6 px (1.1rem, bordure comprise) ; le minimum
   WCAG 2.5.8 (AA) est 24 px. On étend la zone touchable AUTOUR du rond au lieu
   de grossir le rond : l'aspect ne bouge dans aucun consumer, et la cible passe
   la norme.
   ⚠️ Le débord se choisit à la mesure, pas au calcul : 3 px donnent 23,6 px,
   sous la barre. Mesuré au navigateur (WebKit ET Chromium, 390×844, sonde
   elementFromPoint), 0.25rem rend 24,4 px — ça passe, mais 0,4 px de marge se
   perd au premier arrondi d'appareil. 0.3rem rend 26 px. */
.ui-help-tooltip__trigger::before {
  content: "";
  position: absolute;
  inset: -0.3rem;
  border-radius: var(--radius-full);
}

.ui-help-tooltip__trigger:hover {
  background: var(--color-surface);
  color: var(--color-text);
}

.ui-help-tooltip__trigger:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.ui-help-tooltip__panel {
  --ui-tooltip-shift: 0;

  position: absolute;
  top: 50%;
  right: calc(100% + var(--space-2));
  transform: translateY(-50%);
  /* Rattrapage horizontal posé par tooltip_controller quand la bulle dépasse
     encore un bord après bascule. `translate` est une propriété distincte de
     `transform` : elle se compose avec le centrage ci-dessus ET avec les
     `transform: none` que certains consumers posent en repositionnant. */
  translate: var(--ui-tooltip-shift);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--font-size-sm);
  color: var(--color-text);
  box-shadow: var(--shadow-lg);
  min-width: 220px;
  max-width: 320px;
  z-index: var(--z-dropdown);
  white-space: normal;
}

/* Bascule posée par tooltip_controller quand la bulle sortirait du bord
   gauche du viewport : elle s'ouvre alors à droite du déclencheur. */
.ui-help-tooltip__panel[data-flipped] {
  right: auto;
  left: calc(100% + var(--space-2));
}


/* fulgore: ui/icon.css */
.svg {
  width: var(--icon-size-md);
  height: var(--icon-size-md);
  flex-shrink: 0;
  fill: currentColor;
}


/* fulgore: ui/icon_label.css */
.ui-icon-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.ui-icon-label__icon {
  flex-shrink: 0;
  font-size: var(--font-size-base);
  line-height: 1;
}

.ui-icon-label__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}


/* fulgore: ui/inputs/checkbox.css */
.ui-input--checkbox {
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-3);

  label {
    cursor: pointer;
  }

  input[type="checkbox"] {
    width: 1.125rem;
    height: 1.125rem;
    accent-color: var(--color-brand);
    cursor: pointer;
  }

  input[type="hidden"] {
    display: none;
  }
}


/* fulgore: ui/inputs/checkbox_card.css */
.ui-inputs-checkbox-card {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--easing-default),
    background var(--duration-fast) var(--easing-default);

  &:hover {
    border-color: var(--color-brand);
    background: var(--color-brand-a10);
  }

  &.is-checked {
    border-color: var(--color-brand);
    background: var(--color-brand-a10);
  }
}

.ui-inputs-checkbox-card__checkbox {
  width: 1.25rem;
  height: 1.25rem;
  accent-color: var(--color-brand);
  cursor: pointer;
  transition: transform var(--duration-fast) var(--easing-bounce, cubic-bezier(0.34, 1.56, 0.64, 1));

  .no-transition & {
    transition: none;
  }
}

.ui-inputs-checkbox-card.is-checked .ui-inputs-checkbox-card__checkbox {
  animation: checkbox-pop var(--duration-normal, 250ms) var(--easing-bounce, cubic-bezier(0.34, 1.56, 0.64, 1));
}

.ui-inputs-checkbox-card.no-transition .ui-inputs-checkbox-card__checkbox {
  animation: none;
}

@keyframes checkbox-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.35); }
  100% { transform: scale(1); }
}

.ui-inputs-checkbox-card__text {
  position: relative;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

.ui-inputs-checkbox-card__label {
  display: block;
  transition: opacity var(--duration-fast) var(--easing-default);
}

.ui-inputs-checkbox-card__label--unchecked {
  opacity: 1;
}

.ui-inputs-checkbox-card__label--checked {
  position: absolute;
  inset: 0;
  opacity: 0;
}

.ui-inputs-checkbox-card.is-checked .ui-inputs-checkbox-card__label--unchecked {
  opacity: 0;
}

.ui-inputs-checkbox-card.is-checked .ui-inputs-checkbox-card__label--checked {
  opacity: 1;
}


/* fulgore: ui/inputs/checkbox_select.css */
.ui-input {
  .ui-checkbox-select {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
  }

  .ui-checkbox-select__option {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: var(--space-2);
    cursor: pointer;
    font-size: var(--font-size-sm);
    color: var(--color-text);

    input[type="checkbox"] {
      width: auto;
      flex: none;
      accent-color: var(--color-brand);
      cursor: pointer;
    }
  }
}


/* fulgore: ui/inputs/color.css */
.ui-input {
  [data-controller="color-picker"] {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
  }

  [data-color-picker-target="swatch"] {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    padding: var(--space-1);
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    cursor: pointer;
    transition:
      border-color var(--duration-fast) var(--easing-default),
      box-shadow var(--duration-fast) var(--easing-default);

    &::-webkit-color-swatch-wrapper {
      padding: 0;
    }

    &::-webkit-color-swatch {
      border: none;
      border-radius: var(--radius-sm);
    }

    &::-moz-color-swatch {
      border: none;
      border-radius: var(--radius-sm);
    }

    &:focus {
      border-color: var(--color-brand);
      box-shadow: var(--focus-ring);
    }
  }

  [data-color-picker-target="hex"] {
    flex: 1;
    width: auto;
    font-family: var(--font-family-mono);
  }

  &.ui-input--error {
    [data-color-picker-target="swatch"] {
      border-color: var(--color-danger);

      &:focus {
        box-shadow: 0 0 0 3px var(--color-danger-a10);
      }
    }
  }
}


/* fulgore: ui/inputs/date_range.css */
.filter-field--date-range {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.filter-date-range__field {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.filter-date-range__label {
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
}

.filter-field--date-range input[type="date"] {
  padding: var(--space-1) var(--space-2);
  font-size: var(--font-size-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
}


/* fulgore: ui/inputs/file_dropzone.css */
.ui-inputs-file-dropzone__zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-4);
  border: 2px dashed var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease;
}

.ui-inputs-file-dropzone__zone:hover {
  border-color: var(--color-brand);
  background-color: var(--color-brand-surface);
}

.ui-inputs-file-dropzone__zone.is-dragover {
  border-color: var(--color-brand);
  background-color: var(--color-brand-surface);
}

.ui-inputs-file-dropzone__icon {
  font-size: var(--font-size-2xl);
}

.ui-inputs-file-dropzone__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

.ui-inputs-file-dropzone__hint {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
}

.ui-inputs-file-dropzone__zone.is-uploading {
  border-color: var(--color-brand);
  background-color: var(--color-brand-surface);
  pointer-events: none;
  cursor: default;
}

.ui-inputs-file-dropzone__zone.is-uploading .ui-inputs-file-dropzone__icon,
.ui-inputs-file-dropzone__zone.is-uploading .ui-inputs-file-dropzone__label,
.ui-inputs-file-dropzone__zone.is-uploading .ui-inputs-file-dropzone__hint {
  display: none;
}

.ui-inputs-file-dropzone__zone.is-uploading::after {
  content: "Envoi en cours…";
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-brand);
}

.ui-inputs-file-dropzone__zone.is-uploading::before {
  content: "";
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--color-brand);
  border-right-color: transparent;
  border-radius: var(--radius-full);
  animation: dropzone-spin 600ms linear infinite;
}

@keyframes dropzone-spin {
  to { transform: rotate(360deg); }
}

.ui-inputs-file-dropzone__input {
  display: none;
}


/* fulgore: ui/inputs/file_zone.css */
.ui-inputs-file-zone__zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-4);
  border: 2px dashed var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  cursor: pointer;
  transition: border-color var(--duration-normal) var(--easing-default),
    background-color var(--duration-normal) var(--easing-default);
}

.ui-inputs-file-zone__zone:hover {
  border-color: var(--color-brand);
  background-color: var(--color-brand-surface);
}

.ui-inputs-file-zone__zone.is-dragover {
  border-color: var(--color-brand);
  background-color: var(--color-brand-surface);
}

.ui-inputs-file-zone__current {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  margin-bottom: var(--space-2);
}

.ui-inputs-file-zone__current-thumb {
  max-height: 7.5rem;
  border-radius: var(--radius-md);
  object-fit: contain;
}

.ui-inputs-file-zone__current-name {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.ui-inputs-file-zone__replace {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
}

.ui-inputs-file-zone__zone.has-file .ui-inputs-file-zone__current {
  display: none !important;
}

.ui-inputs-file-zone__preview {
  max-height: 7.5rem;
  margin-bottom: var(--space-2);
  border-radius: var(--radius-md);
  object-fit: contain;
}

.ui-inputs-file-zone__preview[hidden] {
  display: none !important;
}

.ui-inputs-file-zone__icon {
  font-size: var(--font-size-2xl);
}

.ui-inputs-file-zone__invite {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}

.ui-inputs-file-zone__filename {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.ui-inputs-file-zone__filename[hidden] {
  display: none !important;
}

.ui-inputs-file-zone__formats {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
}

.ui-inputs-file-zone__zone.has-file .ui-inputs-file-zone__invite {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-normal);
  color: var(--color-text-subtle);
}


/* fulgore: ui/inputs/hidden.css */
/* Le conteneur d'un champ caché ne prend aucune place dans le formulaire. */
.ui-input--hidden {
  display: none;
}


/* fulgore: ui/inputs/money.css */
.ui-inputs-money {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  width: 100%;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition:
    border-color var(--duration-fast) var(--easing-default),
    box-shadow var(--duration-fast) var(--easing-default);
}

.ui-inputs-money:focus-within {
  border-color: var(--color-brand);
  box-shadow: var(--focus-ring);
}

.ui-inputs-money input[type="text"] {
  flex: 1;
  border: none;
  border-radius: 0;
  box-shadow: none;
}

.ui-inputs-money input[type="text"]:focus {
  border-color: transparent;
  box-shadow: none;
}

.ui-inputs-money__currency {
  display: flex;
  align-items: center;
  padding: 0 var(--space-3);
  border-left: 1px solid var(--color-border);
  background: var(--color-surface-subtle);
  color: var(--color-text-subtle);
  font-size: var(--font-size-sm);
  white-space: nowrap;
}

.ui-input--error .ui-inputs-money {
  border-color: var(--color-danger);
}

.ui-input--error .ui-inputs-money:focus-within {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px var(--color-danger-a10);
}


/* fulgore: ui/inputs/password.css */
.ui-input {
  .password-wrapper {
    position: relative;
  }

  .password-wrapper input {
    padding-right: var(--space-10);
  }

  /* LA ZONE TACTILE, PAS L'ICÔNE. La pastille mesurait 16×16 — la taille de son
     icône, avec `padding: 0` autour. Le minimum WCAG 2.5.8 est 24×24 et Apple
     recommande 44 : sur un téléphone, 16px se rate. On agrandit la ZONE et on
     centre l'icône dedans, qui reste à 1rem : l'apparence ne change pas, la
     cible oui. `right` passe à `--space-1` pour que le carré de 44px reste dans
     le champ, qui fait 45px de haut.
     Mesuré au navigateur sur les écrans d'accès de FBordes, le 2026-08-03.
     ⚠️ CE SIDECAR EST LA COPIE SERVIE. `app/assets/stylesheets/fulgore/
     input.css` porte une seconde définition de `.password-toggle` qui n'est
     chargée nulle part chez les consumers — corriger celle-là seule ne change
     rien à l'écran, contre-épreuve faite le 2026-08-03. Les deux sont tenues
     alignées en attendant qu'on tranche laquelle disparaît. */
  .password-toggle {
    position: absolute;
    right: var(--space-1);
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    width: 44px;
    height: 44px;
    padding: 0;
    cursor: pointer;
    color: var(--color-text-subtle);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color var(--duration-fast) var(--easing-default);

    &:hover { color: var(--color-text); }

    .svg {
      display: block;
      width: 1rem;
      height: 1rem;
    }
  }
}


/* fulgore: ui/inputs/percentage.css */
.ui-inputs-percentage {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  width: 100%;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition:
    border-color var(--duration-fast) var(--easing-default),
    box-shadow var(--duration-fast) var(--easing-default);
}

.ui-inputs-percentage:focus-within {
  border-color: var(--color-brand);
  box-shadow: var(--focus-ring);
}

.ui-inputs-percentage input[type="number"] {
  flex: 1;
  border: none;
  border-radius: 0;
  box-shadow: none;
}

.ui-inputs-percentage input[type="number"]:focus {
  border-color: transparent;
  box-shadow: none;
}

.ui-inputs-percentage__suffix {
  display: flex;
  align-items: center;
  padding: 0 var(--space-3);
  border-left: 1px solid var(--color-border);
  background: var(--color-surface-subtle);
  color: var(--color-text-subtle);
  font-size: var(--font-size-sm);
  white-space: nowrap;
}

.ui-input--error .ui-inputs-percentage {
  border-color: var(--color-danger);
}

.ui-input--error .ui-inputs-percentage:focus-within {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px var(--color-danger-a10);
}


/* fulgore: ui/inputs/pill_select.css */
.pill-select {
  position: relative;
  display: inline-block;
  width: 100%;
}

.pill-select__trigger {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-1) var(--space-2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
}

.pill-select__caret {
  margin-left: auto;
  color: var(--color-text-subtle);
  font-size: var(--font-size-xs);
}

.pill-select__dropdown {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  z-index: var(--z-dropdown);
  min-width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.pill-select__dropdown[hidden] {
  display: none;
}

.pill-select__option {
  display: flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  width: 100%;
  text-align: left;
}

.pill-select__option:hover {
  background: var(--color-surface-subtle);
}


/* fulgore: ui/inputs/range_slider.css */
.filter-field--range-slider {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
  min-width: 180px;
}

.filter-range-slider__labels {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-subtle);
  min-height: 1.2em;
  word-break: break-word;
}

.filter-range-slider__label {
  font-weight: var(--font-weight-semibold);
  color: var(--color-brand-dark);
}

.filter-range-slider__separator {
  color: var(--color-text-subtle);
  flex-shrink: 0;
}

.filter-range-slider__track {
  position: relative;
  height: 28px;
  display: flex;
  align-items: center;
}

.filter-range-slider__track::before {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 4px;
  margin-top: -2px;
  background: var(--color-border);
  border-radius: var(--radius-full);
  pointer-events: none;
}

/* Les deux `input[type=range]` sont superposés en plein cadre et transparents :
   seules leurs poignées reçoivent le pointeur, ce qui laisse les deux
   attrapables sur toute la longueur de la piste. */
.filter-range-slider__thumb {
  position: absolute;
  inset: 0 0 0 0;
  width: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}

.filter-range-slider__thumb:focus-visible {
  outline: none;
}

.filter-range-slider__thumb::-webkit-slider-runnable-track {
  background: transparent;
  height: 28px;
  border: none;
}

.filter-range-slider__thumb::-moz-range-track {
  background: transparent;
  height: 28px;
  border: none;
}

.filter-range-slider__thumb::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  pointer-events: all;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  background: var(--color-brand);
  border: 2px solid var(--color-surface);
  box-shadow: 0 0 0 1px var(--color-brand-dark);
  cursor: grab;
  transition: transform 100ms ease;
}

.filter-range-slider__thumb::-webkit-slider-thumb:active {
  cursor: grabbing;
  transform: scale(1.1);
}

.filter-range-slider__thumb::-moz-range-thumb {
  pointer-events: all;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  background: var(--color-brand);
  border: 2px solid var(--color-surface);
  box-shadow: 0 0 0 1px var(--color-brand-dark);
  cursor: grab;
  transition: transform 100ms ease;
}

.filter-range-slider__thumb::-moz-range-thumb:active {
  cursor: grabbing;
  transform: scale(1.1);
}

.filter-range-slider__thumb:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 3px var(--color-brand-surface);
}

.filter-range-slider__thumb:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 3px var(--color-brand-surface);
}

.filter-range-slider__thumb--min {
  z-index: 1;
}

.filter-range-slider__thumb--max {
  z-index: 2;
}


/* fulgore: ui/inputs/rich_text.css */
.ui-input__rich-text {
  min-height: 200px;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--font-size-base);
  line-height: 1.5;
  background-color: var(--color-surface);
}

.ui-input__rich-text:focus {
  outline: none;
  border-color: var(--color-brand);
  box-shadow: var(--focus-ring);
}

.ui-input__rich-text:disabled {
  background-color: var(--color-surface-subtle);
  color: var(--color-text-disabled);
  cursor: not-allowed;
}


/* fulgore: ui/inputs/select.css */
.ui-select {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  cursor: pointer;
}

/* ============================================================
   Mode recherche (UI::Inputs::Select searchable: true)
   Le <select> natif garde .ui-select ci-dessus et reste la valeur
   soumise ; ce bloc n'habille que le déclencheur et le panneau que
   search-select_controller révèle par-dessus lui. `.is-open` est
   posé par dropdown_controller sur la racine .ui-search-select,
   jamais sur le panneau — même convention que row_actions_menu.css
   / directions_dropdown.css (racine.is-open racine__menu).
   ============================================================ */

.ui-search-select {
  position: relative;
  display: block;
  width: 100%;
}

/* Doit rendre comme .ui-select ci-dessus (même bordure, rayon,
   fond, taille de texte) pour qu'un formulaire mixant les deux
   modes reste homogène visuellement. */
.ui-search-select__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;

  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);

  font-size: var(--font-size-sm);
  text-align: left;
  color: var(--color-text);

  background-color: var(--color-surface);

  cursor: pointer;

  /* Le libellé peut déborder (valeur longue) : il se coupe
     proprement, jamais le chevron qui reste visible à droite. */
  span {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    min-width: 0;
  }

  &::after {
    content: "▾";
    flex-shrink: 0;
    font-size: 0.75em; /* pas de token pour une taille relative au glyphe — même valeur que directions_dropdown.css */
    color: var(--color-text-subtle);
  }

  &:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }
}

.ui-search-select__panel {
  display: none;
  flex-direction: column;
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  z-index: var(--z-dropdown);

  /* Pas de token de hauteur dédié : borne dérivée de l'espacement
     (~15rem) pour garder ~6-7 options visibles avant de défiler. */
  max-height: calc(var(--space-10) * 6);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;

  /* L'écart intérieur est porté PAR LE PANNEAU, et aucun de ses deux enfants
     ne porte de marge horizontale. C'est délibéré : un enfant de conteneur
     flex étiré prend la largeur du contenu du parent SANS en déduire sa
     propre marge — mesuré ici à 9px à gauche et −7px à droite, un débordement
     que le `overflow: hidden` ci-dessus rogne, donc invisible à l'œil et
     visible seulement à la mesure. Reprendre l'écart en marge sur le champ
     réintroduirait exactement ce défaut. */
  padding: var(--space-2);

  background: var(--color-surface);
  box-shadow: var(--shadow-md);
}

.ui-search-select.is-open .ui-search-select__panel {
  display: flex;
}

.ui-search-select__filter {
  flex-shrink: 0;
  box-sizing: border-box;
  /* Aucune marge horizontale : l'écart vient du padding du panneau (cf. son
     commentaire). Seul l'écart SOUS le champ lui appartient. */
  margin: 0 0 var(--space-2);
  padding: var(--space-2) var(--space-3);

  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);

  font-size: var(--font-size-sm);
  color: var(--color-text);

  background: var(--color-surface);

  &:focus {
    outline: none;
    border-color: var(--color-brand);
    box-shadow: var(--focus-ring);
  }
}

/* Liste bornée + défilante : c'est tout l'intérêt du panneau
   recherche. Le champ de filtre ci-dessus reste fixe (flex-shrink: 0)
   pendant que la liste défile dans l'espace restant. */
.ui-search-select__list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;

  margin: 0;
  padding: var(--space-1) 0;
  list-style: none;
}

.ui-search-select__option {
  padding: var(--space-2) var(--space-3);

  font-size: var(--font-size-sm);
  color: var(--color-text);

  cursor: pointer;

  /* Survol souris et .is-active (option courante au clavier)
     doivent rester visuellement distincts : les deux peuvent être
     vrais en même temps sur deux lignes différentes. */
  &:hover {
    background: var(--color-surface-alt);
  }

  &.is-active {
    background: var(--color-brand-a10);
    color: var(--color-brand-dark);
  }
}

.ui-search-select__empty {
  margin: 0;
  padding: var(--space-4);

  font-size: var(--font-size-sm);
  text-align: center;
  color: var(--color-text-subtle);
}


/* fulgore: ui/inputs/vat_breakdown.css */
.ui-inputs-vat-breakdown {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}


/* fulgore: ui/inputs/verification_code.css */
.ui-verification-code__boxes {
  display: flex;
  flex-direction: row;
  gap: var(--space-2);
}

.ui-verification-code__box {
  width: 3rem;
  height: 3.5rem;
  text-align: center;
  font-family: var(--font-family-mono);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  color: var(--color-text);
  transition: border-color var(--duration-fast) var(--easing-default),
              box-shadow var(--duration-fast) var(--easing-default);
  appearance: none;
  -moz-appearance: textfield;
}

.ui-verification-code__box::-webkit-outer-spin-button,
.ui-verification-code__box::-webkit-inner-spin-button {
  appearance: none;
}

.ui-verification-code__box:focus {
  outline: none;
  border-color: var(--color-brand);
  box-shadow: var(--focus-ring);
}

.ui-input--error .ui-verification-code__box {
  border-color: var(--color-danger);
}

.ui-input--error .ui-verification-code__box:focus {
  box-shadow: 0 0 0 3px var(--color-danger-a10);
}

.ui-verification-code__box:disabled {
  background-color: var(--color-surface-raised);
  color: var(--color-text-disabled);
  cursor: not-allowed;
}


/* fulgore: ui/label_with_tooltip.css */
.ui-label-with-tooltip {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex: 1;
  min-width: 0;
}

.ui-label-with-tooltip__text {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}


/* fulgore: ui/links/back.css */
.ui-links-back {
  display: flex;
  align-items: center;
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  margin-block: var(--space-6);
}

.ui-links-back a {
  color: inherit;
  text-decoration: none;
  transition: color var(--duration-fast) var(--easing-default);

  &:hover {
    color: var(--color-brand);
  }
}


/* fulgore: ui/links/edit.css */
.ui-button--sm .svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}


/* fulgore: ui/links/plain.css */
.ui-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: opacity var(--duration-fast) var(--easing-default);

  &:hover {
    opacity: 0.7;
  }

  &:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
    border-radius: var(--radius-sm);
  }
}


/* fulgore: ui/locale_flag_switch.css */
/* Drapeau SVG du switch de langue. PAS de règle `fill` : les couleurs
   viennent du fichier SVG (contrairement à .svg de UI::Icon qui force
   currentColor). Ratio 4:3 (viewBox 640x480), hauteur fixe pour aligner. */
.ui-locale-flag {
  display: block;
  height: 1.25rem;
  width: auto;
  border-radius: var(--radius-sm);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
}


/* fulgore: ui/locale_switch.css */
.ui-locale-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.ui-locale-switch__link {
  text-transform: uppercase;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
}

/* Sous `include_current`, la langue courante est affichée à côté des autres.
   Sans marque visuelle, deux drapeaux côte à côte ne disent pas lequel est
   actif — le sélecteur redevient muet, ce que l'option cherchait à corriger.
   Ce sont donc les AUTRES qui s'effacent, et le `:has()` limite la règle aux
   switchers qui affichent réellement la langue courante : un switcher sans
   `--current` (le régime par défaut) garde ses liens à pleine opacité. */
.ui-locale-switch:has(.ui-locale-switch__link--current)
  .ui-locale-switch__link:not(.ui-locale-switch__link--current) {
  opacity: 0.55;
}

/* Le survol doit ANNULER l'estompage, pas le retour au survol de `.ui-link`
   (`opacity: 0.7`, plain.css). Un simple `.ui-locale-switch__link:hover` a la
   même spécificité que lui et passe après dans le bundle : il l'aurait écrasé
   partout, y compris sur les switchers qui n'utilisent pas `include_current`.
   Le sélecteur reste donc calqué sur celui de l'estompage.
   La valeur est `1` et non `0.7` : depuis un repos à 0.55, un survol à 0.7 ne
   laisserait que 0.15 d'écart, un signal qu'on ne voit plus. Annuler pour de
   bon est aussi ce que le premier mot de ce commentaire promet. */
.ui-locale-switch:has(.ui-locale-switch__link--current)
  .ui-locale-switch__link:not(.ui-locale-switch__link--current):hover {
  opacity: 1;
}


/* fulgore: ui/map.css */
.ui-map {
  width: 100%;
  height: 20rem;
  border-radius: var(--radius-md);
  overflow: hidden;
  z-index: 0;
}


/* fulgore: ui/menu_toggle.css */
.ui-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: none;
  color: var(--color-text);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--easing-default),
              background-color var(--duration-fast) var(--easing-default);
}

.ui-menu-toggle:hover {
  border-color: var(--color-text-soft);
  background-color: var(--color-surface-alt);
}

.ui-menu-toggle:focus-visible {
  outline: none;
  border-color: var(--color-text-soft);
  box-shadow: var(--focus-ring);
}


/* fulgore: ui/metric_card.css */
.ui-metric-card {
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.ui-metric-card__label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  font-weight: var(--font-weight-medium);
  margin-bottom: var(--space-1);
  position: relative;
}

.ui-metric-card__value {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* ── Tooltip repositioning inside card ── */

.ui-metric-card .ui-help-tooltip__panel {
  top: calc(100% + var(--space-1));
  right: auto;
  left: 0;
  transform: none;
  min-width: 12rem;
}

/* ── Comparison delta (M/M-1, etc.) ── */

.ui-metric-card__comparison {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-top: var(--space-1);
  font-size: var(--font-size-xs);
}

.ui-metric-card__delta-value {
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}

.ui-metric-card__delta-label {
  color: var(--color-text-subtle);
}

.ui-metric-card__comparison--positive .ui-metric-card__delta-value {
  color: var(--color-success);
}

.ui-metric-card__comparison--negative .ui-metric-card__delta-value {
  color: var(--color-danger);
}

.ui-metric-card__comparison--neutral .ui-metric-card__delta-value {
  color: var(--color-text-subtle);
}


/* fulgore: ui/notification/badge.css */
.ui-notification-badge {
  display: inline-block;
  min-width: 1.25rem;
  height: 1.25rem;
  line-height: 1.25rem;
  padding-inline: 5px;
  border-radius: var(--radius-full);
  background: var(--color-danger);
  color: var(--color-text-inverted);
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.6875rem;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-sizing: border-box;
}


/* fulgore: ui/notification/bell.css */
.ui-notification-bell {
  position: relative;
}

.ui-notification-bell__button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-inverted);
  cursor: pointer;
  position: relative;
  transition: background var(--duration-fast) var(--easing-default);

  .svg {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
  }

  &:hover {
    background: rgba(255, 255, 255, 0.15);
  }

  &:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }
}

.ui-notification-bell__badge {
  position: absolute;
  top: 2px;
  right: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 1rem;
  height: 1rem;
  padding: 0 3px;
  border-radius: var(--radius-full);
  background: var(--color-danger);
  color: var(--color-text-inverted);
  font-size: 0.625rem;
  font-weight: var(--font-weight-semibold);
  line-height: 1;
}

.ui-notification-bell__badge--hidden {
  display: none;
}

.ui-notification-bell__dropdown {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: var(--space-2);
  width: 22rem;
  max-width: calc(100vw - 2rem);
  max-height: 28rem;
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  z-index: var(--z-dropdown);

  &.is-open {
    display: block;
  }
}

.ui-notification-bell__dropdown-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.ui-notification-bell__dropdown-title {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.ui-notification-bell__mark-all {
  border: none;
  background: none;
  padding: 0;
  font-size: var(--font-size-xs);
  color: var(--color-brand);
  cursor: pointer;

  &:hover {
    text-decoration: underline;
  }
}

.ui-notification-bell__list {
  display: flex;
  flex-direction: column;
}

.ui-notification-bell__empty {
  padding: var(--space-6);
  text-align: center;
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  margin: 0;
}


/* fulgore: ui/notification/item.css */
.ui-notification-item {
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  gap: var(--space-2);
  align-items: start;
  padding: var(--space-2) var(--space-4);
  text-decoration: none;
  color: var(--color-text);

  &:not(:last-child) {
    border-bottom: 1px solid var(--color-border);
  }

  &:hover {
    background: var(--color-surface-raised);
  }

  &--unread {
    background: var(--color-brand-surface);

    &:hover {
      background: var(--color-brand-a10);
    }
  }
}

.ui-notification-item__avatar {
  flex-shrink: 0;

  .ui-user-badge {
    gap: 0;
  }

  .ui-user-badge__text {
    display: none;
  }

  .ui-user-badge__circle {
    width: 1.75rem !important;
    height: 1.75rem !important;
    font-size: 0.625rem !important;
  }
}

.ui-notification-item__content {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ui-notification-item__title-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1);
}

.ui-notification-item__actor-name {
  font-size: var(--font-size-xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ui-notification-item .ui-pill {
  font-size: 0.5625rem;
  padding: 0 4px;
  line-height: 1.125rem;
  flex-shrink: 0;
}

.ui-notification-item__body {
  margin: 0;
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-notification-item__meta {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: 1px;
}

.ui-notification-item__time,
.ui-notification-item__context {
  font-size: 0.625rem;
  color: var(--color-text-disabled);
}


/* fulgore: ui/pagination.css */
.ui-pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
}

.ui-pagination__arrow,
.ui-pagination__page,
.ui-pagination__gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--space-8);
  height: var(--space-8);
  padding: 0 var(--space-2);
  border-radius: var(--radius-md);
  font-size: var(--font-size-sm);
  text-decoration: none;
}

.ui-pagination__arrow {
  color: var(--color-text-subtle);

  &:hover {
    background: var(--color-surface-subtle);
    color: var(--color-text);
  }
}

.ui-pagination__arrow--disabled {
  color: var(--color-text-disabled);
  pointer-events: none;
}

.ui-pagination__page {
  color: var(--color-text-subtle);

  &:hover {
    background: var(--color-surface-subtle);
    color: var(--color-text);
  }
}

.ui-pagination__page--current {
  background: var(--color-brand);
  color: var(--color-text-inverted);
  border: 1px solid var(--color-brand);
  font-weight: var(--font-weight-medium);
  pointer-events: none;
}

.ui-pagination__gap {
  color: var(--color-text-disabled);
  pointer-events: none;
}


/* fulgore: ui/pill.css */
.ui-pill {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-3);
  border-radius: 999px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

.ui-pill--brand {
  background: var(--color-violet-100);
  color: var(--color-violet-700);
}

.ui-pill--info {
  background: var(--color-blue-100);
  color: var(--color-blue-700);
}

.ui-pill--success {
  background: var(--color-green-100);
  color: var(--color-green-700);
}

.ui-pill--danger {
  background: var(--color-red-100);
  color: var(--color-red-700);
}

.ui-pill--warning {
  background: var(--color-amber-100);
  color: var(--color-amber-700);
}

.ui-pill--neutral {
  background: var(--color-neutral-100);
  color: var(--color-neutral-700);
}

/* Teintes nommées — la couleur est choisie par l'utilisateur d'un consumer,
   le nom ne porte donc aucun sens métier. Les cinq premières doublent
   volontairement une variante sémantique (brand/info/success/danger/warning) :
   « ce que ça veut dire » et « de quelle couleur c'est » sont deux vocabulaires
   distincts, et seul le second est configurable. */
.ui-pill--violet { background: var(--color-violet-100); color: var(--color-violet-700); }
.ui-pill--blue   { background: var(--color-blue-100);   color: var(--color-blue-700); }
.ui-pill--green  { background: var(--color-green-100);  color: var(--color-green-700); }
.ui-pill--red    { background: var(--color-red-100);    color: var(--color-red-700); }
.ui-pill--amber  { background: var(--color-amber-100);  color: var(--color-amber-700); }
.ui-pill--indigo { background: var(--color-indigo-100); color: var(--color-indigo-700); }
.ui-pill--teal   { background: var(--color-teal-100);   color: var(--color-teal-700); }
.ui-pill--lime   { background: var(--color-lime-100);   color: var(--color-lime-700); }
.ui-pill--orange { background: var(--color-orange-100); color: var(--color-orange-700); }
.ui-pill--pink   { background: var(--color-pink-100);   color: var(--color-pink-700); }
.ui-pill--brown  { background: var(--color-brown-100);  color: var(--color-brown-700); }

.ui-pill--draft {
  background: var(--color-surface-raised);
  color: var(--color-text-subtle);
}

.ui-pill--in_progress {
  background: var(--color-success-surface);
  color: var(--color-success);
}

.ui-pill--review {
  background: var(--color-warning-surface);
  color: var(--color-warning);
}

.ui-pill--completed {
  background: var(--color-info-surface);
  color: var(--color-info);
}

.ui-pill--archived {
  background: var(--color-surface-raised);
  color: var(--color-text-subtle);
}

.ui-pill--admin {
  background: var(--color-violet-100);
  color: var(--color-violet-700);
}

.ui-pill--accountant {
  background: var(--color-blue-100);
  color: var(--color-blue-700);
}

.ui-pill--active {
  background: var(--color-success-surface);
  color: var(--color-success);
}

.ui-pill--suspended {
  background: var(--color-red-100);
  color: var(--color-red-700);
}

.ui-pill--pending {
  background: var(--color-warning-surface);
  color: var(--color-warning);
}

.ui-pill--read {
  background: var(--color-blue-100);
  color: var(--color-blue-700);
}

.ui-pill--lmnp {
  background: var(--color-brand-surface);
  color: var(--color-brand);
}

.ui-pill--lmnp_vat {
  background: var(--color-info-surface);
  color: var(--color-info);
}

.ui-pill--lg {
  padding: var(--space-2) var(--space-4);
  font-size: var(--font-size-sm);
}

.ui-pill--strong {
  padding: var(--space-1) var(--space-3);
  font-weight: var(--font-weight-bold);
  box-shadow: var(--shadow-pill-strong);
}

.ui-pill--strong.ui-pill--brand   { background: var(--color-violet-600); color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--info    { background: var(--color-blue-700);   color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--success { background: var(--color-green-500);  color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--warning { background: var(--color-amber-500);  color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--danger  { background: var(--color-red-500);    color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--neutral { background: var(--color-neutral-700); color: var(--color-neutral-0); }

.ui-pill--strong.ui-pill--violet { background: var(--color-violet-600); color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--blue   { background: var(--color-blue-700);   color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--green  { background: var(--color-green-500);  color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--red    { background: var(--color-red-500);    color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--amber  { background: var(--color-amber-500);  color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--indigo { background: var(--color-indigo-700); color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--teal   { background: var(--color-teal-700);   color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--lime   { background: var(--color-lime-700);   color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--orange { background: var(--color-orange-700); color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--pink   { background: var(--color-pink-700);   color: var(--color-neutral-0); }
.ui-pill--strong.ui-pill--brown  { background: var(--color-brown-700);  color: var(--color-neutral-0); }


/* fulgore: ui/progress_ring.css */
.ui-progress-ring {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-8);
  background-color: var(--color-brand-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.ui-progress-ring__ring {
  flex-shrink: 0;
  width: 5rem;
  height: 5rem;
}

.ui-progress-ring__svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.ui-progress-ring__track {
  fill: none;
  stroke: var(--color-border);
  stroke-width: 8;
}

.ui-progress-ring__fill {
  fill: none;
  stroke: var(--color-brand);
  stroke-width: 8;
  stroke-linecap: round;
  transition: stroke-dashoffset 1.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.ui-progress-ring__ratio {
  transform: rotate(90deg);
  transform-origin: 60px 60px;
  text-anchor: middle;
  dominant-baseline: central;
  font-family: var(--font-family-display);
  font-size: 1.25rem;
  font-weight: var(--font-weight-bold);
  fill: var(--color-text);
}

.ui-progress-ring__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.ui-progress-ring__title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
}

.ui-progress-ring__subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  margin: 0;
}


/* fulgore: ui/row_actions_menu.css */
/* RowActionsMenu — kebab (⋮) dropdown wrapping already-rendered action
   components (UI::Links::* / UI::Buttons::*) as flat, full-width menu rows.
   Stimulus `dropdown` toggles .is-open on this root element, not the menu
   (cf. directions_dropdown.css / dropdown_controller). */

.ui-row-actions-menu {
  position: relative;
  display: inline-block;
}

.ui-row-actions-menu__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;

  width: 2rem;
  height: 2rem;
  padding: 0;
  border: none;
  border-radius: var(--radius-md);

  color: var(--color-text-subtle);
  background: transparent;

  cursor: pointer;
  transition: background var(--duration-fast) var(--easing-default),
    color var(--duration-fast) var(--easing-default);

  .svg {
    width: 1.25rem;
    height: 1.25rem;
  }

  &:hover:not(:disabled):not(.ui-row-actions-menu__toggle--disabled) {
    background: var(--color-surface-subtle);
    color: var(--color-text);
  }

  &:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }
}

.ui-row-actions-menu__menu {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: var(--z-dropdown);
  min-width: 12rem;

  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;

  background: var(--color-surface);
  box-shadow: var(--shadow-md);
}

.ui-row-actions-menu.is-open .ui-row-actions-menu__menu {
  display: block;
}

.ui-row-actions-menu__item {
  display: block;
}

/* Neutralize the wrapped action components (ui-link, ui-button — primary/
   secondary/danger, all sizes) back into flat, full-width text menu rows.
   Targets the real classes emitted by UI::Links::Show/Edit/New (<a
   class="ui-button ui-button--{primary,secondary} ui-button--sm">) and
   UI::Buttons::Destroy (<form> root wrapping <button class="ui-button
   ui-button--danger ui-button--sm">). */
.ui-row-actions-menu__item a,
.ui-row-actions-menu__item button,
.ui-row-actions-menu__item form {
  display: block;
  width: 100%;
  box-sizing: border-box;

  margin: 0;
  padding: var(--space-2) var(--space-4);
  border: none;
  border-radius: 0;

  font-size: var(--font-size-sm);
  text-align: left;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;

  background: transparent;
  box-shadow: none;

  cursor: pointer;
}

.ui-row-actions-menu__item a:hover,
.ui-row-actions-menu__item button:hover,
.ui-row-actions-menu__item form:hover {
  background: var(--color-surface-alt);
}

.ui-row-actions-menu__item a:focus-visible,
.ui-row-actions-menu__item button:focus-visible {
  outline: none;
  box-shadow: none;
  background: var(--color-surface-alt);
}

/* The base variant rules (.ui-button.ui-button--primary/secondary/danger,
   specificity 0,2,0) outrank the plain-element resets above (0,1,1) and
   win regardless of concat order — so background/color/hover-background
   from the wrapped button chrome survive unless matched at equal-or-higher
   specificity here. Re-neutralize per variant explicitly. */
.ui-row-actions-menu__item .ui-button--primary,
.ui-row-actions-menu__item .ui-button--secondary,
.ui-row-actions-menu__item .ui-button--danger {
  color: var(--color-text);
  background: transparent;
  border-color: transparent;
}

.ui-row-actions-menu__item .ui-button--primary:hover,
.ui-row-actions-menu__item .ui-button--secondary:hover,
.ui-row-actions-menu__item .ui-button--danger:hover {
  background: var(--color-surface-alt);
  border-color: transparent;
}

/* The wrapped icon (pen-to-square, plus…) rides along the text baseline
   instead of the button's centered flex layout. `display: inline-block`
   defends against a consumer global reset (`svg { display: block }`) that
   would otherwise stack the icon above its label. */
.ui-row-actions-menu__item .svg {
  display: inline-block;
  width: var(--font-size-sm);
  height: var(--font-size-sm);
  margin-right: var(--space-2);
  vertical-align: -0.15em;
}

/* Destroy's <form> is the item's direct child and must not add its own
   padding on top of the <button> it wraps, or add block spacing. */
.ui-row-actions-menu__item form {
  padding: 0;
}

.ui-row-actions-menu__item form button {
  width: 100%;
}

/* Danger row (UI::Buttons::Destroy → .ui-button--danger) keeps a red
   label, overriding the neutral text-color reset above. Source order
   (after the variant reset block) settles the equal-specificity (0,2,0)
   tie in its favor — hover background already comes from the reset
   block above, so only color needs restating here. */
.ui-row-actions-menu__item .ui-button--danger {
  color: var(--color-danger);
}

@media (prefers-reduced-motion: reduce) {
  .ui-row-actions-menu__toggle {
    transition: none;
  }
}


/* fulgore: ui/section.css */
.ui-section {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
}

/* ── Header ── */

.ui-section__header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-4);
}

.ui-section__header[data-action] {
  cursor: pointer;
  user-select: none;
}

.ui-section__icon {
  flex-shrink: 0;
  font-size: var(--font-size-lg);
  line-height: 1;
}

.ui-section__title {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
}

.ui-section__counter {
  font-weight: var(--font-weight-normal);
  color: var(--color-text-subtle);
}

.ui-section__action {
  margin-left: auto;
  flex-shrink: 0;
}

.ui-section__toggle {
  margin-left: auto;
  background: none;
  border: none;
  padding: var(--space-1);
  cursor: pointer;
  color: var(--color-text-subtle);
  font-size: var(--font-size-sm);
  transition: transform var(--duration-fast);
}

.ui-section__action + .ui-section__toggle {
  margin-left: 0;
}

/* ── Body ── */

.ui-section__body {
  min-height: 0;
}

/* ── Footer ── */

.ui-section__footer {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-4);
}


/* fulgore: ui/section_header.css */
.ui-section-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-4);
}

.ui-section-header__icon {
  flex-shrink: 0;
  font-size: var(--font-size-lg);
  line-height: 1;
}

.ui-section-header__title {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
}

.ui-section-header__action {
  margin-left: auto;
  flex-shrink: 0;
}


/* fulgore: ui/shell/navbar.css */
.ui-shell-navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  height: var(--navbar-height);
  padding: var(--space-1) var(--space-4);
  box-sizing: border-box;
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--shell-navbar-bg);
  color: var(--shell-navbar-fg);

  .navbar-hamburger { display: none; }
}
@media (max-width: 1023px) {
  .ui-shell-navbar .navbar-hamburger { display: flex; }
}
.navbar-sidebar-toggle {
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: none;
  border-radius: var(--radius-md);
  color: inherit;
  background: transparent;
  cursor: pointer;
  transition: background var(--duration-fast) var(--easing-default);
  .svg {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
    transition: transform var(--duration-fast) var(--easing-default);
  }
  &[aria-expanded="false"] .svg { transform: rotate(180deg); }
  &:hover { background: rgba(255, 255, 255, 0.15); }
  &:focus-visible { outline: none; box-shadow: var(--focus-ring); }
}
.ui-shell-navbar .navbar-sidebar-toggle { display: flex; }
@media (max-width: 1023px) {
  .ui-shell-navbar .navbar-sidebar-toggle { display: none; }
}
.ui-shell-navbar__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: inherit;
}
.ui-shell-navbar__brand-logo { height: 28px; width: auto; }
.ui-shell-navbar__brand-name {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}
.navbar-session-email {
  font-size: var(--font-size-sm);
  color: color-mix(in srgb, var(--shell-navbar-fg) 85%, transparent);
  white-space: nowrap;
}
@media (max-width: 1023px) {
  .navbar-session-email { display: none; }
}
.navbar-logout { margin: 0; }
.ui-shell-navbar .navbar-logout .ui-button {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border: 1px solid color-mix(in srgb, var(--shell-navbar-fg) 30%, transparent);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--font-size-sm);
  font-weight: inherit;
  color: var(--shell-navbar-fg);
  background: transparent;
  box-shadow: none;
  &:hover:not(:disabled) {
    background: color-mix(in srgb, var(--shell-navbar-fg) 15%, transparent);
    color: var(--shell-navbar-fg);
  }
  &:focus-visible { outline: none; box-shadow: var(--focus-ring); }
}


/* fulgore: ui/shell/sidebar.css */
.ui-shell-sidebar {
  position: fixed;
  top: var(--navbar-height);
  left: 0;
  bottom: 0;
  z-index: var(--z-raised);
  width: var(--sidebar-width);
  max-width: 80vw;
  box-sizing: border-box;
  overflow-x: hidden;
  overflow-y: auto;
  padding: var(--space-6) var(--space-4);
  border-right: 1px solid var(--color-border);
  box-shadow: var(--shadow-lg);
  background: var(--color-surface-subtle);
  transform: translateX(-100%);
  transition: transform var(--duration-slow) var(--easing-out);
  nav { display: flex; flex-direction: column; gap: var(--space-2); }
  &.is-compact, &.is-expanded { transform: translateX(0); }
}
@media (min-width: 1024px) {
  .ui-shell-sidebar {
    position: sticky;
    top: var(--navbar-height);
    left: auto;
    bottom: auto;
    height: calc(100dvh - var(--navbar-height));
    max-width: none;
    width: var(--sidebar-width);
    flex-shrink: 0;
    align-self: flex-start;
    box-shadow: none;
    transform: none;
    transition: width var(--duration-slow) var(--easing-out);
  }
  .ui-shell-sidebar.is-compact {
    width: var(--sidebar-compact-width);
    padding: var(--space-6) var(--space-3);
  }
  .ui-shell-sidebar.is-expanded { width: var(--sidebar-width); }
  .ui-shell-sidebar.is-compact .ui-shell-sidebar__link {
    justify-content: center;
    padding: var(--space-3);
  }
  .ui-shell-sidebar.is-compact .sidebar-link__label { display: none; }
  .ui-shell-sidebar.is-compact .sidebar-section__heading { display: none; }
  .ui-shell-sidebar.is-compact .sidebar-section.is-collapsed .sidebar-section__items { display: flex; }
}
@media (prefers-reduced-motion: reduce) {
  .ui-shell-sidebar,
  .ui-shell-sidebar .sidebar-section__toggle .svg { transition: none; }
}
.sidebar-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-top: var(--space-4);
}
.sidebar-section:first-of-type { padding-top: var(--space-2); }
.sidebar-section__heading { margin: 0; }
.sidebar-section__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-1) var(--space-3);
  border: none;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-subtle);
  background: transparent;
  cursor: pointer;
  transition: color var(--duration-fast) var(--easing-default);
  .svg {
    width: var(--icon-size-sm);
    height: var(--icon-size-sm);
    flex-shrink: 0;
    transition: transform var(--duration-fast) var(--easing-default);
  }
  &:hover { color: var(--color-text); }
  &:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
}
.sidebar-section.is-collapsed .sidebar-section__toggle .svg { transform: rotate(-90deg); }
.sidebar-section__items { display: flex; flex-direction: column; gap: var(--space-2); }
.sidebar-section.is-collapsed .sidebar-section__items { display: none; }
.ui-shell-sidebar__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  text-decoration: none;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-subtle);
  transition:
    background var(--duration-fast) var(--easing-default),
    color var(--duration-fast) var(--easing-default);
  .svg { width: var(--icon-size-sm); height: var(--icon-size-sm); flex-shrink: 0; }
  &:hover:not(.ui-shell-sidebar__link--active) {
    background: var(--color-surface-raised);
    color: var(--color-text);
  }
  &:focus-visible { outline: none; box-shadow: var(--focus-ring); }
}
.ui-shell-sidebar__link--active {
  background: var(--color-brand-surface);
  color: var(--color-brand);
  font-weight: var(--font-weight-semibold);
}
.sidebar-link__label { display: inline; }


/* fulgore: ui/skeleton_block.css */
@keyframes skeleton-shimmer {
  0%   { background-position: 200% center; }
  100% { background-position: -200% center; }
}

.ui-skeleton-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.ui-skeleton-block--card {
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  gap: var(--space-3);
}

.ui-skeleton-block__title {
  height: 0.875rem;
  width: 45%;
  border-radius: var(--radius-sm);
  background: linear-gradient(
    90deg,
    var(--color-surface-raised) 25%,
    var(--color-surface-subtle) 50%,
    var(--color-surface-raised) 75%
  );
  background-size: 200%;
  animation: skeleton-shimmer 1.5s infinite;
  margin-bottom: var(--space-1);
}

.ui-skeleton-block__row {
  display: flex;
  flex-direction: row;
  gap: var(--space-3);
  height: 2rem;
  border-radius: var(--radius-sm);
  background: linear-gradient(
    90deg,
    var(--color-surface-raised) 25%,
    var(--color-surface-subtle) 50%,
    var(--color-surface-raised) 75%
  );
  background-size: 200%;
  animation: skeleton-shimmer 1.5s infinite;
}

.ui-skeleton-block--card .ui-skeleton-block__row {
  height: 1.25rem;
}

.ui-skeleton-block__cell--wide {
  flex: 3;
}

.ui-skeleton-block__cell--narrow {
  flex: 1;
}


/* fulgore: ui/spinner.css */
.ui-spinner {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.ui-spinner::before {
  content: "";
  display: block;
  width: 1em;
  height: 1em;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-brand);
  border-radius: var(--radius-full);
  animation: spinner-spin var(--duration-slow) linear infinite;
}

@keyframes spinner-spin {
  to { transform: rotate(360deg); }
}

.spinner-label {
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
}


/* fulgore: ui/stat_grid.css */
/* ── Stat grid: reusable dt/dd key-value layout ──
 *
 * PAS un sidecar orphelin : aucun stat_grid.rb n'existe et c'est voulu.
 * `.ui-stat-grid` est une layout utilitaire cross-composant, émise par
 * UI::Bases::StatCard (qui a par ailleurs son propre sidecar
 * bases/stat_card.css) et écrite en dur chez des consumers (Fatima
 * admin/orders/*_section, FBordes manage/dashboard). La purger ou la
 * renommer casse leur rendu sans erreur Ruby. */

.ui-stat-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin: 0;
}

.ui-stat-grid__label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-subtle);
  font-weight: var(--font-weight-medium);
  position: relative;
}

.ui-stat-grid__icon {
  font-size: var(--font-size-base);
}

.ui-stat-grid__value {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0;
  text-align: right;
}

/* ── Tooltip repositioning ── */

.ui-stat-grid .ui-help-tooltip__panel {
  top: calc(100% + var(--space-1));
  right: auto;
  left: 0;
  transform: none;
}


/* fulgore: ui/status_icon.css */
.ui-status-icon {
  font-size: var(--font-size-base);
  flex-shrink: 0;
  line-height: 1;
}


/* fulgore: ui/summary_row.css */
.ui-summary-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  text-decoration: none;
  color: inherit;
}

.ui-summary-row--clickable {
  border-radius: var(--radius-md);
  transition: background var(--duration-fast) var(--easing-default);
}

.ui-summary-row--clickable:hover {
  background: var(--color-surface-subtle);
}

.ui-summary-row__icon {
  font-size: var(--font-size-base);
  flex-shrink: 0;
  line-height: 1;
}

.ui-summary-row__label {
  flex: 1;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-summary-row__dots {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-shrink: 0;
}

.ui-summary-row__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-full);
}

.ui-summary-row__dot--validated {
  background: var(--color-success);
}

.ui-summary-row__dot--pending {
  background: var(--color-warning);
}

.ui-summary-row__dot--rejected {
  background: var(--color-danger);
}

.ui-summary-row__dot--missing {
  background: var(--color-neutral-300);
}

.ui-summary-row__count {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}


/* fulgore: ui/tabs.css */
.ui-tabs__list {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-4);
  scrollbar-width: none;
}

.ui-tabs__list::-webkit-scrollbar {
  display: none;
}

.ui-tabs__tab {
  flex-shrink: 0;
  padding: var(--space-2) var(--space-4);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--color-text-subtle);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--duration-fast) var(--easing-default),
              border-color var(--duration-fast) var(--easing-default);
}

.ui-tabs__tab:hover {
  color: var(--color-text);
}

.ui-tabs__tab--active {
  color: var(--color-brand);
  border-bottom-color: var(--color-brand);
}

.ui-tabs__panel[hidden] {
  display: none;
}


/* fulgore: ui/timeline.css */
.ui-timeline {
  padding: var(--space-4) 0;
}

/* ── Track ── */

.ui-timeline__track {
  position: relative;
  height: 2rem;
  margin: 0 var(--space-6);
}

.ui-timeline__line {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--color-border-strong);
  transform: translateY(-50%);
}

.ui-timeline__dot {
  position: absolute;
  top: 50%;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: var(--radius-full);
  background: var(--color-neutral-400);
  border: 2px solid var(--color-surface);
  transform: translate(-50%, -50%);
  z-index: 1;
}

.ui-timeline__dot--past {
  background: var(--color-brand);
}

.ui-timeline__today {
  position: absolute;
  top: 50%;
  width: 0.5rem;
  height: 1.25rem;
  background: var(--color-danger);
  border-radius: var(--radius-sm);
  transform: translate(-50%, -50%);
  z-index: 2;
}

/* ── Labels ── */

.ui-timeline__labels {
  position: relative;
  margin: var(--space-2) var(--space-6) 0;
  height: 3.5rem;
}

.ui-timeline__label {
  position: absolute;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  white-space: nowrap;
}

.ui-timeline__label-text {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
}

.ui-timeline__label-date {
  font-size: var(--font-size-xs);
  color: var(--color-text-subtle);
}

.ui-timeline__delay {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-subtle);
  margin-top: var(--space-1);
}

.ui-timeline__delay--urgent {
  color: var(--color-danger);
  font-weight: var(--font-weight-semibold);
}


/* fulgore: ui/user_badge.css */
.ui-user-badge {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.ui-user-badge__circle {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  overflow: hidden;
  color: var(--color-neutral-0);
  font-weight: var(--font-weight-semibold);
  flex-shrink: 0;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.ui-user-badge__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.ui-user-badge__name {
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ui-user-badge__email {
  color: var(--color-text-subtle);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ui-user-badge__avatar {
  width: 100%;
  height: 100%;
  border-radius: var(--radius-full);
  object-fit: cover;
}

.ui-user-badge__you {
  color: var(--color-text-subtle);
  font-style: italic;
  font-size: var(--font-size-xs);
}

/* --- Tailles --- */

.ui-user-badge--sm .ui-user-badge__circle {
  width: 1.5rem;
  height: 1.5rem;
  font-size: var(--font-size-xs);
}

.ui-user-badge--sm .ui-user-badge__name {
  font-size: 0.8125rem;
}

.ui-user-badge--sm .ui-user-badge__email {
  font-size: var(--font-size-xs);
}

.ui-user-badge--md .ui-user-badge__circle {
  width: 2rem;
  height: 2rem;
  font-size: 0.8125rem;
}

.ui-user-badge--md .ui-user-badge__name {
  font-size: var(--font-size-sm);
}

.ui-user-badge--md .ui-user-badge__email {
  font-size: var(--font-size-xs);
}

.ui-user-badge--lg .ui-user-badge__circle {
  width: 2.5rem;
  height: 2.5rem;
  font-size: var(--font-size-base);
}

.ui-user-badge--lg .ui-user-badge__name {
  font-size: var(--font-size-base);
}

.ui-user-badge--lg .ui-user-badge__email {
  font-size: var(--font-size-sm);
}


/* fulgore: ui/widgets/grid.css */
.ui-widgets-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: var(--space-6);
  align-items: start;
}


/* auth/login_form.css */
.auth-login-form {
  max-width: 28rem;
  margin: var(--space-16) auto;
  display: grid;
  gap: var(--space-6);

  h2 {
    margin: 0;
  }

  form {
    display: grid;
    gap: var(--space-5);
  }

  .alert {
    color: var(--color-danger);
  }
}


/* auth/password_reset_form.css */
/* L'ÉCRAN « NOUVEAU MOT DE PASSE » — celui qu'on atteint depuis le lien reçu par
   mail, et le seul des trois qu'on ne peut pas rendre sans un jeton valide. Il
   n'avait aucun gabarit non plus, pour la même raison que son frère
   `password_reset_request_form.css`.

   Il porte DEUX champs (mot de passe + confirmation) là où son frère n'en a
   qu'un, d'où le même espacement interne. Largeur et centrage sont repris de
   `login_form.css` : un consumer fraîchement généré n'a pas de cadre d'écrans
   d'accès à qui les déléguer. */
.auth-password-reset-form {
  max-width: 28rem;
  margin: var(--space-16) auto;
  display: grid;
  gap: var(--space-6);

  h2 {
    margin: 0;
  }

  form {
    display: grid;
    gap: var(--space-5);
  }
}


/* auth/password_reset_request_form.css */
/* L'ÉCRAN « MOT DE PASSE OUBLIÉ ». Ce gabarit n'existait pas : le générateur ne
   copiait que `login_form.css`, et la mise en forme des écrans d'accès s'arrêtait
   donc net au premier des trois. Mesuré sur FBordes en production le 2026-08-03,
   à 1280×800 : titre, libellé et champ faisaient 1280px de large, collés aux deux
   bords de la fenêtre.

   Largeur et centrage sont repris de `login_form.css` plutôt que délégués à un
   cadre : un consumer fraîchement généré n'en a aucun. Le site qui se donne un
   cadre d'écrans d'accès (`body.auth-page` & co) écrase ces deux lignes chez lui
   et ne garde ici que l'espacement interne. */
.auth-password-reset-request-form {
  max-width: 28rem;
  margin: var(--space-16) auto;
  display: grid;
  gap: var(--space-6);

  h2 {
    margin: 0;
  }

  form {
    display: grid;
    gap: var(--space-5);
  }
}


/* manage/dashboard/calendar.css */
.manage-dashboard-calendar__events {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.manage-dashboard-calendar__item {
  min-width: 0;
}

.manage-dashboard-calendar__event {
  display: block;
  overflow: hidden;
  padding: 0 var(--space-1);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs);
  line-height: 1.4;
  color: var(--color-brand-dark);
  background: var(--color-brand-a10);
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.manage-dashboard-calendar__event:hover {
  background: var(--color-brand-a20);
}

.manage-dashboard-calendar__event:focus-visible {
  outline: 2px solid var(--color-brand);
}


/* manage/navigation/shell.css */
/* Back-office shell — consumer glue styles.
   The shell layout & styling live in the gem (UI::Shell::Navbar / Sidebar).
   This sidecar only carries this site's identity + the layout scaffolding. */

.manage-shell {
  /* Uncomment to give this site its own top-bar colour (defaults to the brand). */
  /* --shell-navbar-bg: var(--color-brand); */
  /* --shell-navbar-fg: var(--color-text-inverted); */

  /* Le layout manage n'a pas de police : sans elle, le navigateur sert Times. */
  font-family: var(--font-family-base);
}

.manage-shell__body {
  display: flex;
  min-height: calc(100vh - var(--navbar-height));
}

.manage-shell__main {
  flex: 1;
  min-width: 0; /* let the main column shrink instead of overflowing the flex row */
  padding: var(--space-6);
}
