/* ═══════════════════════════════════════════════════════════════════
   Scope — thème du panel (tokens + règles globales)

   Chargé sur toutes les pages du panel via le renderHook HEAD_END de
   AdminPanelProvider (cache-bust par filemtime — aucun build step).

   DOCTRINE COULEURS
   -----------------
   Aucune couleur en dur dans les blades du panel : toute couleur passe
   par un token sémantique `var(--sc-…)`. Les valeurs light reproduisent
   exactement la palette historique (gris Tailwind) — le light mode est
   iso-pixel avec l'ancien rendu. Le bloc `.dark` cale les surfaces sur
   la palette zinc que Filament 5 utilise en thème sombre (cartes
   zinc-900, bordures blanc translucide) pour que nos cartes custom se
   fondent dans le chrome Filament.

   Choisir un token par RÔLE, pas par valeur : le même gris clair est
   `--sc-surface-muted` en fond de puce mais `--sc-border-soft` en
   séparateur de lignes — en dark les deux divergent.

   Les couleurs de SÉRIES de graphiques (barres, sparklines) restent des
   teintes saturées lisibles sur les deux thèmes : tokens `--sc-chart-*`.

   Hors périmètre : les vues publiques (signature de devis, courriels)
   ont leur propre layout clair permanent et n'utilisent pas ces tokens.
   ═══════════════════════════════════════════════════════════════════ */

:root {
    /* Surfaces (fonds) */
    --sc-surface: #ffffff;                 /* cartes, tableaux */
    --sc-surface-alt: rgb(249 250 251);    /* gray-50 : en-têtes de table, hover de ligne */
    --sc-surface-muted: rgb(243 244 246);  /* gray-100 : puces, wells, zones neutres */
    --sc-surface-inset: rgb(229 231 235);  /* gray-200 : pistes de progress bar, creux */

    /* Bordures */
    --sc-border: rgb(229 231 235);         /* gray-200 : bordure par défaut des cartes */
    --sc-border-strong: rgb(209 213 219);  /* gray-300 : inputs, bordures appuyées */
    --sc-border-soft: rgb(243 244 246);    /* gray-100 : séparateurs de lignes */

    /* Texte */
    --sc-text: rgb(17 24 39);              /* gray-900 : titres, montants */
    --sc-text-secondary: rgb(55 65 81);    /* gray-700 : corps de texte */
    --sc-text-muted: rgb(107 114 128);     /* gray-500 : libellés, méta */
    --sc-text-faint: rgb(156 163 175);     /* gray-400 : placeholders, icônes discrètes */
    --sc-text-inverse: #ffffff;            /* texte sur fond plein coloré */

    /* Marque */
    --sc-primary: #2998ea;
    --sc-primary-strong: #1c7ec3;          /* hover / actif */
    --sc-primary-bg: rgb(239 246 255);     /* blue-50 : sélection, well informatif marque */

    /* Statuts — fg = texte, bg = fond teinté, border = liseré, solid = aplat */
    --sc-info-fg: rgb(30 64 175);
    --sc-info-bg: rgb(219 234 254);
    --sc-info-border: rgb(191 219 254);
    --sc-info-solid: rgb(37 99 235);

    --sc-success-fg: rgb(22 101 52);
    --sc-success-bg: rgb(220 252 231);
    --sc-success-border: rgb(187 247 208);
    --sc-success-solid: rgb(22 163 74);

    --sc-warning-fg: rgb(120 53 15);
    --sc-warning-bg: rgb(254 243 199);
    --sc-warning-border: rgb(253 230 138);
    --sc-warning-solid: rgb(217 119 6);

    --sc-danger-fg: rgb(153 27 27);
    --sc-danger-bg: rgb(254 226 226);
    --sc-danger-border: rgb(254 202 202);
    --sc-danger-solid: rgb(220 38 38);

    /* Accent secondaire (indigo/violet — abonnements, séries « autres ») */
    --sc-accent-fg: rgb(55 48 163);
    --sc-accent-bg: rgb(238 242 255);
    --sc-accent-border: rgb(199 210 254);
    --sc-accent-solid: #6366f1;

    /* Divers */
    --sc-overlay: rgb(0 0 0 / 0.5);        /* backdrop des modales custom */

    /* Séries de graphiques — saturées, lisibles sur les deux thèmes */
    --sc-chart-blue: #2998ea;
    --sc-chart-indigo: #6366f1;
    --sc-chart-green: #22c55e;
    --sc-chart-amber: #f59e0b;
    --sc-chart-amber-soft: #fcd34d;
    --sc-chart-red: #ef4444;
    --sc-chart-violet: #8b5cf6;
}

/* Thème sombre — surfaces calées sur la palette zinc de Filament 5
   (cartes dark:bg-gray-900 où gray = zinc), bordures en blanc
   translucide comme le chrome Filament, statuts en teinte claire sur
   fond translucide de la même teinte. */
.dark {
    --sc-surface: #18181b;                     /* zinc-900 */
    --sc-surface-alt: rgb(255 255 255 / 0.04);
    --sc-surface-muted: rgb(255 255 255 / 0.08);
    --sc-surface-inset: rgb(255 255 255 / 0.12);

    --sc-border: rgb(255 255 255 / 0.10);
    --sc-border-strong: rgb(255 255 255 / 0.20);
    --sc-border-soft: rgb(255 255 255 / 0.06);

    --sc-text: #f4f4f5;                        /* zinc-100 */
    --sc-text-secondary: #d4d4d8;              /* zinc-300 */
    --sc-text-muted: #a1a1aa;                  /* zinc-400 */
    --sc-text-faint: #71717a;                  /* zinc-500 */
    --sc-text-inverse: #ffffff;

    --sc-primary: #2998ea;
    --sc-primary-strong: #1c7ec3;
    --sc-primary-bg: rgb(41 152 234 / 0.15);

    --sc-info-fg: #93c5fd;
    --sc-info-bg: rgb(59 130 246 / 0.15);
    --sc-info-border: rgb(59 130 246 / 0.35);
    --sc-info-solid: #60a5fa;

    --sc-success-fg: #4ade80;
    --sc-success-bg: rgb(34 197 94 / 0.15);
    --sc-success-border: rgb(34 197 94 / 0.35);
    --sc-success-solid: #22c55e;

    --sc-warning-fg: #fcd34d;
    --sc-warning-bg: rgb(245 158 11 / 0.15);
    --sc-warning-border: rgb(245 158 11 / 0.35);
    --sc-warning-solid: #f59e0b;

    --sc-danger-fg: #f87171;
    --sc-danger-bg: rgb(239 68 68 / 0.15);
    --sc-danger-border: rgb(239 68 68 / 0.35);
    --sc-danger-solid: #ef4444;

    --sc-accent-fg: #a5b4fc;
    --sc-accent-bg: rgb(99 102 241 / 0.15);
    --sc-accent-border: rgb(99 102 241 / 0.35);
    --sc-accent-solid: #818cf8;

    --sc-overlay: rgb(0 0 0 / 0.6);
}

/* ═══════════════════════════════════════════════════════════════════
   Règles globales du panel (ex-renderHook de AdminPanelProvider)
   ═══════════════════════════════════════════════════════════════════ */

/* Primary-button overrides :
   1. Force white text — Filament's auto-contrast helper would
      otherwise pick dark text on #2998ea (WCAG ratio < 4.5).
   2. Hover state — darken the background to primary-700 with a smooth
      transition so the button feels responsive on pointer-over.
      Filament's default hover would lighten the colour, which clashes
      with the brand intent here. */
.fi-btn.fi-color-primary,
.fi-btn.fi-btn-color-primary,
.fi-btn.fi-color-primary *,
.fi-btn.fi-btn-color-primary *,
.fi-ac-btn-action.fi-color-primary,
.fi-ac-btn-action.fi-color-primary * {
    color: var(--sc-text-inverse) !important;
}

.fi-btn.fi-color-primary,
.fi-btn.fi-btn-color-primary {
    transition: background-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.fi-btn.fi-color-primary:hover,
.fi-btn.fi-btn-color-primary:hover,
.fi-btn.fi-color-primary:focus-visible,
.fi-btn.fi-btn-color-primary:focus-visible {
    background-color: var(--sc-primary-strong) !important;
}

.fi-btn.fi-color-primary:active,
.fi-btn.fi-btn-color-primary:active {
    background-color: #155d96 !important;
}

/* Toast notifications must ALWAYS sit above every modal. Filament's
   toast container (.fi-no) ships at z-index:50, but our custom modal
   backdrops sit at 50–80, so success/error toasts got hidden behind
   the dark overlay. Pin the container to the top of the stack,
   app-wide. (.fi-no keeps pointer-events:none from the theme, so
   clicks still pass through to whatever is behind it ; only the
   toasts themselves capture clicks.) */
.fi-no {
    z-index: 2147483647 !important;
}

/* Full-width tabs as the app-wide default for any <x-filament::tabs>
   instance. The :not() guard preserves Filament's own page
   sub-navigation tabs (which can carry many items and need to keep
   their natural sizing). */
.fi-tabs:not(.fi-page-sub-navigation-tabs) {
    display: flex !important;
    width: 100% !important;
}
.fi-tabs:not(.fi-page-sub-navigation-tabs) .fi-tabs-item {
    flex: 1 1 0 !important;
    justify-content: center !important;
}

/* Indent sub-items in the sidebar nested navigation (e.g. Historique
   des prix under Ajustements des prix). The real Filament 5 class is
   .fi-sidebar-item-btn (with the trailing dot indicator rendered via
   .fi-sidebar-item-grouped-border). We push the whole button right so
   the hierarchy reads at a glance. */
.fi-sidebar-sub-group-items .fi-sidebar-item-btn {
    padding-left: 2.5rem !important;
}

/* Navigation group labels (Administration, Commissions, etc.) in
   uppercase with a touch of letter-spacing so they read as section
   headers, visually distinct from menu items. */
.fi-sidebar-group-label {
    text-transform: uppercase !important;
    letter-spacing: 0.06em !important;
    font-size: 0.7rem !important;
}

/* Design decision : page headers show the TITLE only — no description
   subheading. Filament renders the subheading (from getSubheading() /
   $subheading) as <p class="fi-header-subheading"> in the shared
   header component, so this single rule hides it on EVERY page,
   resource and sub-page — current and future — without touching each
   page class. The getSubheading() strings are harmless if left in
   place ; flip this rule off to bring descriptions back. */
.fi-header-subheading {
    display: none !important;
}

/* Uniform appearance for custom Blade data tables. Drop the
   .data-table class on the wrapping div of a table and it adopts the
   same look as the Clients/Produits pages : carte sur --sc-surface,
   ligne d'en-tête en majuscules sur --sc-surface-alt, hover doux.
   Avoids per-page styling drift — et suit le thème sombre via les
   tokens. */
.data-table {
    background-color: var(--sc-surface);
    border: 1px solid var(--sc-border);
    border-radius: 0.75rem;
    overflow: hidden;
}
.data-table-header {
    background-color: var(--sc-surface-alt);
    border-bottom: 1px solid var(--sc-border);
    padding: 0.625rem 1.125rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--sc-text-muted);
}
.data-table-row {
    padding: 0.75rem 1.125rem;
    border-bottom: 1px solid var(--sc-border-soft);
    align-items: center;
    transition: background-color 0.1s;
}
.data-table-row:last-child {
    border-bottom: none;
}
.data-table-row:hover {
    background-color: var(--sc-surface-alt);
}

/* Hide Filament Tables' built-in compact search field — we render
   <x-search-bar> above each table instead, bound to the same
   $tableSearch Livewire property. Targets the wrapper class
   Filament 5 emits (`.fi-ta-search-field`). */
.fi-ta-search-field {
    display: none !important;
}

/* Unify Filament Tables' header row with the .data-table-header look
   used by hand-rolled tables (Clients, Abonnements). Filament 5 wraps
   sortable column labels in a <button> but non-sortable ones in a
   plain <span> / text node — earlier override caught only sortable
   columns. We target the th itself AND every descendant (except SVG
   paths so sort arrows keep their geometry) so every label, sortable
   or not, gets the same look. Pages affected : Suivi des paiements,
   Historique des paiements, Représentants. */
.fi-ta-header-cell {
    background-color: var(--sc-surface-alt) !important;
    font-size: 0.7rem !important;
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.05em !important;
    color: var(--sc-text-muted) !important;
}
.fi-ta-header-cell *:not(svg):not(path):not(circle):not(rect) {
    font-size: inherit !important;
    font-weight: inherit !important;
    text-transform: inherit !important;
    letter-spacing: inherit !important;
    color: inherit !important;
}

/* The selection (checkbox) and per-row actions columns carry their OWN
   header-cell classes (fi-ta-selection-cell / fi-ta-actions-header-cell),
   not .fi-ta-header-cell — so they missed the header surface above and read
   as a lighter, mismatched band at the two ends of the header row. Give
   them the same background. fi-ta-selection-cell is shared with the body
   checkbox cells, so scope that one to the header (thead) to avoid tinting
   every row's checkbox cell. */
thead .fi-ta-selection-cell,
.fi-ta-actions-header-cell {
    background-color: var(--sc-surface-alt) !important;
}

/* Hide the built-in filter funnel button and the column-manager
   toggle button in the table toolbar. We don't use either feature on
   any current page, and they cluttered tables with ad-hoc icons.
   Filament 5 emits different classes depending on whether the filters
   are configured at all and whether they render as a dropdown vs
   modal vs collapsible-above-content. We cover all variants. */
/* Filter trigger : above-content / before-content variant */
.fi-ta-filters-trigger-action-ctn,
/* Filter trigger : default dropdown variant (kicks in when
   ->filters([...]) is non-empty, e.g. Représentants TernaryFilter) */
.fi-ta-filters-dropdown,
/* Filter trigger : modal variant */
.fi-ta-filters-modal,
/* Column manager : dropdown + modal variants */
.fi-ta-col-manager-dropdown,
.fi-ta-col-manager-modal {
    display: none !important;
}

/* With the built-in search, filters and column manager all hidden
   above, the table header toolbar is usually an EMPTY 25px strip that
   reads as a stray horizontal bar above the column headers. Hide it by
   default — BUT the toolbar is ALSO where bulk actions surface once the
   operator selects rows (« Marquer payé » on Suivi, delete on
   Utilisateurs/Représentants). A blanket display:none swallowed every
   table's bulk actions (issue #1). So hide it only while empty, and
   reveal it the instant a bulk action becomes visible.

   The bulk actions live in .fi-ta-actions and are Alpine x-show'd —
   hidden with an inline `display: none` until rows are selected, and
   cloaked (x-cloak) until Alpine boots. The :has() below matches a
   booted, currently-visible action, so the toolbar reappears exactly
   when it has something to show (bare button OR ⋮ dropdown trigger). */
.fi-ta-header-toolbar {
    display: none !important;
}
.fi-ta-header-toolbar:has(.fi-ta-actions [x-show]:not([x-cloak]):not([style*="display: none"])) {
    display: flex !important;
}

/* …and with the toolbar gone, the thead became the card's first
   element : its square gray band painted over the container's rounded
   top corners and sat directly on Filament's very subtle ring
   (gray-950/5), which reads as a MISSING top border. Give the content
   container an explicit top edge — same 1px var(--sc-border) line as
   the hand-rolled .data-table cards — and round its top corners so the
   header band stays inside the card silhouette (it clips through its
   own overflow). */
.fi-ta-ctn-with-header .fi-ta-content-ctn {
    border-top: 1px solid var(--sc-border);
    border-top-left-radius: 0.75rem;
    border-top-right-radius: 0.75rem;
}

/* …but when the toolbar DOES reveal itself (a bulk action became visible),
   it already carries its own bottom border : the compensating top edge
   above would then double up and round the content mid-card. Drop it while
   the toolbar is shown — same :has() condition that reveals the toolbar. */
.fi-ta-ctn-with-header:has(.fi-ta-header-toolbar .fi-ta-actions [x-show]:not([x-cloak]):not([style*="display: none"])) .fi-ta-content-ctn {
    border-top: 0;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

/* ════════════════════════════════════════════════
   Global skeleton / loading shimmer.

   Drop `.is-loading` on any container to overlay a sliding-gradient
   shimmer. Typical usage with Livewire :

     <div wire:loading.class="is-loading" wire:target="someAction">
         ...content...
     </div>

   Active during the Livewire roundtrip ; removed automatically on
   response. Works with Alpine (`:class="loading && 'is-loading'"`)
   and plain JS too. Scoped to the `.is-loading` class so it never
   bleeds into normal page styles.
   ════════════════════════════════════════════════ */
.is-loading {
    position: relative;
    overflow: hidden;
}
/* Sweeping highlight band. On the light theme this is a translucent
   SLATE band (not white) — a white shimmer over a white card is
   invisible, which is the #1 reason a skeleton "doesn't show". The
   grey streak reads clearly as it crosses white content. */
.is-loading::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        rgba(148, 163, 184, 0) 0%,
        rgba(148, 163, 184, 0.18) 45%,
        rgba(148, 163, 184, 0.28) 50%,
        rgba(148, 163, 184, 0.18) 55%,
        rgba(148, 163, 184, 0) 100%
    );
    background-size: 250% 100%;
    background-repeat: no-repeat;
    animation: skel-shimmer 1.3s ease-in-out infinite;
    pointer-events: none;
    z-index: 5;
}
@keyframes skel-shimmer {
    0% { background-position: 250% 0; }
    100% { background-position: -150% 0; }
}
/* The container is busy : fade the content so the region reads as
   inactive even between shimmer passes, and block clicks so operators
   don't fire the same action twice while the server processes. */
.is-loading > * {
    opacity: 0.55;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

/* Dark-mode tweak : a muted-white band reads better than slate on
   dark backgrounds. */
.dark .is-loading::after {
    background: linear-gradient(90deg,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.10) 45%,
        rgba(255, 255, 255, 0.18) 50%,
        rgba(255, 255, 255, 0.10) 55%,
        rgba(255, 255, 255, 0) 100%
    );
    background-size: 250% 100%;
    background-repeat: no-repeat;
}
.dark .is-loading > * {
    opacity: 0.65;
}

/* Accessibility : honour a reduced-motion preference. Drop the
   infinite sweep animation but KEEP the dimmed/non-interactive state
   so the region still reads as busy (and the double-submit guard
   still holds) — just without the moving band. */
@media (prefers-reduced-motion: reduce) {
    .is-loading::after {
        animation: none;
        /* A faint static veil instead of a sweep. */
        background: rgba(148, 163, 184, 0.12);
    }
    .dark .is-loading::after {
        background: rgba(255, 255, 255, 0.08);
    }
}

/* ════════════════════════════════════════════════
   Reusable skeleton placeholder primitive.

   Drop `.skel` on any element and set its width/height inline — a
   crisp WHITE glint sweeps across a solid grey base (the
   react-loading-skeleton technique). A fixed-px streak reads as
   obvious motion ; the earlier low-contrast grey-on-grey gradient
   animated but was nearly imperceptible. Used by the dashboard shell
   AND the list-page skeletons (Clients / Factures / Abonnements).
   Distinct from `.is-loading`, which overlays a sweep on REAL content
   during an action roundtrip.
   ════════════════════════════════════════════════ */
.skel {
    position: relative;
    display: block;
    overflow: hidden;
    border-radius: 0.375rem;
    /* Solid grey base, clearly distinct from a white card so the bar
       reads on its own. */
    background-color: rgb(224 228 234);
}
/* The travelling glint as a TRANSFORM-animated overlay (GPU,
   universally reliable) rather than a calc() background-position —
   the latter can fail to interpolate and leave the streak parked
   off-screen (looks static). The band is the full bar width ;
   translating it -100% → 100% sweeps the bright centre across. */
.skel::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.85) 50%,
        rgba(255, 255, 255, 0) 100%);
    animation: skel-sheen 1.3s ease-in-out infinite;
}
@keyframes skel-sheen {
    100% { transform: translateX(100%); }
}
.dark .skel { background-color: rgb(51 60 74); }
.dark .skel::after {
    background: linear-gradient(90deg,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.16) 50%,
        rgba(255, 255, 255, 0) 100%);
}
/* Reduced-motion : drop the spatial sweep (no translation —
   vestibular-safe) but keep a gentle opacity pulse so the skeleton
   still reads as « loading », never frozen. */
@media (prefers-reduced-motion: reduce) {
    .skel::after { display: none; }
    .skel { animation: skel-pulse 1.6s ease-in-out infinite; }
}
@keyframes skel-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.5; }
}
