    /* Toast animations */
    @keyframes slide-up {
      from {
        transform: translateY(100%);
        opacity: 0;
      }

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

    @keyframes slide-down {
      from {
        transform: translateY(0);
        opacity: 1;
      }

      to {
        transform: translateY(100%);
        opacity: 0;
      }
    }

    .animate-slide-up {
      animation: slide-up 0.3s ease-out forwards;
    }

    .animate-slide-down {
      animation: slide-down 0.3s ease-out forwards;
    }

    /* Actor tooltip card: reveal + gloss sweep on hover */
    @keyframes card-reveal {
      from { transform: scale(0.94); opacity: 0; }
      to   { transform: scale(1);    opacity: 1; }
    }
    @keyframes card-shine {
      0%   { transform: translateX(-120%) skewX(-20deg); opacity: 0; }
      15%  { opacity: 0.55; }
      100% { transform: translateX(220%)  skewX(-20deg); opacity: 0; }
    }
    .actor-card-tooltip {
      position: relative;
      overflow: hidden;
      animation: card-reveal 0.28s cubic-bezier(0.16, 1, 0.3, 1) forwards;
    }
    .actor-card-tooltip::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 40%;
      height: 100%;
      background: linear-gradient(
        100deg,
        transparent 0%,
        rgba(255,255,255,0.0) 30%,
        rgba(255,255,255,0.65) 50%,
        rgba(255,255,255,0.0) 70%,
        transparent 100%
      );
      pointer-events: none;
      animation: card-shine 1.1s ease-out 0.15s forwards;
    }

    /* Top-center toast: drops in from above, lifts back out. Centering is done with
       auto margins (not transform) so it doesn't clash with these translateY frames. */
    @keyframes toast-drop-in {
      from { transform: translateY(-130%); opacity: 0; }
      to   { transform: translateY(0); opacity: 1; }
    }
    @keyframes toast-lift-out {
      from { transform: translateY(0); opacity: 1; }
      to   { transform: translateY(-130%); opacity: 0; }
    }
    .animate-toast-in { animation: toast-drop-in 0.3s ease-out forwards; }
    .animate-toast-out { animation: toast-lift-out 0.3s ease-out forwards; }

    /* ── File preview (renderDocPreviewModal, 09c_documents.js) ──────────────
       Word / uploaded-HTML and Excel previews arrive as bare, server-sanitised
       markup (utils/documentPreview.js), so the document's own look has to come
       from here. Tailwind's preflight strips every heading and list back to
       inherit, so without these rules a converted contract renders as one
       undifferentiated blob of 14px text. Scoped to the two preview containers —
       never global, or it restyles the SPA. */
    .cf-doc-preview h1 { font-size: 25px; font-weight: 700; margin: 0 0 14px; line-height: 1.25; }
    .cf-doc-preview h2 { font-size: 20px; font-weight: 700; margin: 22px 0 10px; line-height: 1.3; }
    .cf-doc-preview h3 { font-size: 17px; font-weight: 700; margin: 18px 0 8px; }
    .cf-doc-preview h4, .cf-doc-preview h5, .cf-doc-preview h6 { font-size: 15px; font-weight: 700; margin: 16px 0 6px; }
    .cf-doc-preview p { margin: 0 0 11px; }
    .cf-doc-preview ul, .cf-doc-preview ol { margin: 0 0 12px; padding-left: 26px; list-style: revert; }
    .cf-doc-preview li { margin: 3px 0; }
    .cf-doc-preview strong, .cf-doc-preview b { font-weight: 700; }
    .cf-doc-preview em, .cf-doc-preview i { font-style: italic; }
    .cf-doc-preview u { text-decoration: underline; }
    .cf-doc-preview s, .cf-doc-preview del, .cf-doc-preview strike { text-decoration: line-through; }
    .cf-doc-preview a { color: #006a85; text-decoration: underline; }
    .cf-doc-preview blockquote { margin: 0 0 12px; padding: 4px 0 4px 15px; border-left: 3px solid #e5e8ed; color: #637382; }
    .cf-doc-preview pre { margin: 0 0 12px; padding: 12px 14px; background: #f7f7fa; border-radius: 8px; overflow-x: auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
    .cf-doc-preview code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
    .cf-doc-preview hr { margin: 18px 0; border: 0; border-top: 1px solid #e5e8ed; }
    /* A .docx picture is a base64 data: URI inlined by mammoth — cap it so a
       full-page scan does not blow the modal out horizontally. */
    .cf-doc-preview img { max-width: 100%; height: auto; border-radius: 6px; margin: 6px 0; }
    .cf-doc-preview table, .cf-sheet-preview table { border-collapse: collapse; width: 100%; font-size: 13px; }
    .cf-doc-preview th, .cf-doc-preview td,
    .cf-sheet-preview th, .cf-sheet-preview td {
      border: 1px solid #e5e8ed; padding: 7px 10px; text-align: left; vertical-align: top;
    }
    .cf-doc-preview th, .cf-sheet-preview th {
      background: #fbfcfd; font-weight: 700; position: sticky; top: 0; z-index: 1;
    }
    .cf-sheet-preview td { white-space: pre-wrap; word-break: break-word; }
    .cf-sheet-preview tbody tr:nth-child(even) { background: #fcfcfd; }

    /* Context menu — light theme, matches the Projets kanban right-click menu */
    .context-menu {
      position: fixed;
      background: #ffffff;
      border: 1px solid #e5e7eb;
      border-radius: 10px;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
      z-index: 100;
      min-width: 182px;
      padding: 4px;
    }

    .context-menu button {
      width: 100%;
      padding: 9px 12px;
      text-align: left;
      color: #374151;
      display: flex;
      align-items: center;
      gap: 9px;
      border-radius: 6px;
      transition: background 0.15s;
    }

    .context-menu button:hover {
      background: #f3f4f6;
    }

    .context-menu button.danger {
      color: #dc2626;
    }

    .context-menu button.danger:hover {
      background: #fef2f2;
    }

    .floating-nav-arrow {
      position: fixed;
      bottom: 1.5rem;
      /* CFT-1596: was 40, tied with .sidebar-main (09a_ui_core.js), which fell
         back to DOM order and let this button paint over the ENTIRE sidebar
         (including its .cf-rail-tip tooltips, z-index:60 — a child's z-index
         never escapes its own stacking-context parent, so the tip's 60 could
         never win that tie no matter how high it went). Lowered to 39, just
         below the sidebar, rather than raising the sidebar above 40: the
         sidebar is also compared at that SAME level against several other
         fixed, full-viewport click-catchers this app owns (the wizard's own
         composer/mode-modal/approval-menu backdrops, z-index 40 and 42 in
         07_casting_import_dates.js), which rely on sitting ABOVE the sidebar to
         catch a click anywhere, including over it — raising the sidebar past 40
         would have fixed this tooltip and broken those. See
         docs/frontend/UI_RULES.md → "A higher z-index only wins INSIDE its own
         stacking context". */
      z-index: 39;
      display: inline-flex;
      align-items: center;
      gap: 0.5rem;
      height: 2.5rem;
      padding: 0 1.125rem;
      border-radius: 10px;
      font-size: 0.875rem;
      font-weight: 600;
      color: white;
      transition: all 0.2s ease;
      cursor: pointer;
      border: none;
      outline: none;
      box-shadow: 0 2px 6px rgba(0,0,0,0.12);
    }

    .floating-nav-arrow.left {
      left: 6rem;
      background: #ffffff;
      color: #374151;
      border: 1px solid #d1d5db;
    }

    .floating-nav-arrow.right {
      right: 4rem;
      background: #006a85;
    }

    .floating-nav-arrow.left:hover {
      background: #f3f4f6;
    }

    .floating-nav-arrow.right:hover {
      background: #005266;
      box-shadow: 0 3px 10px rgba(0, 106, 133, 0.35);
    }

    .floating-nav-arrow:disabled {
      background: #9ca3af !important;
      color: #f3f4f6 !important;
      opacity: 1;
      cursor: wait;
      box-shadow: none !important;
      transform: none !important;
    }

    /* Secondary wizard action ("Mettre en révision") — clean white/outline pill,
       sits to the left of the primary Send button. Its own hover (NOT the teal
       .right:hover) so it stays white. */
    .floating-nav-secondary {
      right: 17rem;
      background: #ffffff;
      color: #374151;
      border: 1px solid #e5e7eb;
      /* Narrower than the primary buttons — small floppy icon + short label. */
      padding: 0 0.75rem;
      gap: 0.375rem;
    }
    .floating-nav-secondary:hover {
      background: #f9fafb;
      border-color: #d1d5db;
      box-shadow: 0 3px 10px rgba(0,0,0,0.10);
    }
    .floating-nav-secondary--alone { right: 1.5rem; }
    @media (max-width: 767px) {
      .floating-nav-secondary { right: 4rem; }
      .floating-nav-secondary--alone { right: 0.75rem; }
    }

    /* Wizard Express / breakdown drawer: when the full-height right drawer is open,
       shift the wizard content (inside #mainContent) and the fixed floating-nav
       buttons left by the drawer width so nothing hides behind it. Desktop only —
       on narrow screens the drawer overlays and the user collapses it.
       The breakpoint moved 1024 → 1280 when the drawer went from 380 to 570: at
       1024 the shift left the wizard 238px of column between a 216px rail and the
       drawer, which is narrower than the form it has to draw. Below 1280 the
       drawer overlays, which is what it already did on a phone. */
    :root { --cf-drawer-w: 570px; }  /* le tiroir Breakdown — 380 × 1,5, cf. renderExpressSidebar */
    @media (min-width: 1280px) {
      body.cf-drawer-open #mainContent { padding-right: var(--cf-drawer-w); transition: padding-right .15s ease; }
      body.cf-drawer-open .floating-nav-arrow.right { right: calc(4rem + var(--cf-drawer-w)); }
      body.cf-drawer-open .floating-nav-secondary { right: calc(17rem + var(--cf-drawer-w)); }
      body.cf-drawer-open .floating-nav-secondary--alone { right: calc(1.5rem + var(--cf-drawer-w)); }
      /* The top bar's popovers (the bell's panel, the feedback thumbs' panel) take
         the top bar's shift too. Without it they opened at the viewport's edge,
         behind the drawer, and the bell looked dead (CFT-1489). */
      body.cf-drawer-open #notifications-modal { padding-right: calc(1rem + var(--cf-drawer-w)); }
      body.cf-drawer-open #cf-fb-panel { right: calc(16px + var(--cf-drawer-w)) !important; }
    }

    /* Actor circle avatars: shift the crop up so the eyes (top vertical third of
       a portrait) stay inside the circle instead of being centered on the nose. */
    img.rounded-full.object-cover { object-position: 50% 22%; }

    .floating-nav-arrow:hover .nav-arrow-icon {
      transform: scale(1.1);
    }

    @media (max-width: 767px) {
      .floating-nav-arrow {
        height: 2.375rem;
        padding: 0 1rem;
        font-size: 0.8125rem;
        bottom: 1rem;
      }
      .floating-nav-arrow.left {
        left: 0.75rem;
      }
      .floating-nav-arrow.right {
        right: 0.75rem;
      }
    }

