    /* ─────────────────────────────────────────────────────────────────────────
       Écran de badgeage FIGÉ : la page index occupe exactement la hauteur
       visible et ne défile JAMAIS (ni vers le haut, ni vers le bas).
       index-page.css n'étant chargé que par public/index.php, ces règles
       html/body/.badgeuse-wrap restent confinées à cette page — admin,
       history, planning et marketing conservent leur défilement normal.
       Paddings resserrés pour que PIN + dernier pointage + boutons tiennent
       dans une seule vue sans coupe.
       ------------------------------------------------------------------------- */
    html,
    body {
      height: 100%;
      overflow: hidden;
      overscroll-behavior: none;
    }

    .badgeuse-wrap.uk-height-viewport {
      /* 100dvh = hauteur visible réelle (gère la barre d'URL mobile dynamique).
         Remplace le min-height:100vh d'UIkit par une hauteur FIXE : le contenu
         ne peut plus pousser la page au-delà de l'écran. */
      height: 100vh;
      height: 100dvh;
      min-height: 0;
      padding-top: 84px;
      padding-bottom: 12px;
      overflow: hidden;
    }

    /* Marges auto sur la colonne centrale : tant que le contenu tient, il reste
       centré verticalement (rendu desktop inchangé). Dès qu'il dépasse la
       hauteur visible, les marges auto se résolvent à 0 et le contenu se cale
       EN HAUT (flex-start) — le PIN et les boutons Entrer/Sortir ne passent
       donc JAMAIS sous la navbar ; seul le bas décoratif (footer scellé) sort
       du cadre sur les écrans courts. */
    .badgeuse-wrap.uk-height-viewport > .badgeuse-main-column {
      margin-top: auto;
      margin-bottom: auto;
    }

    @media (max-width: 640px) and (pointer: coarse) {
      .badgeuse-wrap.uk-height-viewport {
        padding-top: 88px;
      }
    }

    .navbar-title-link {
      padding: 0 8px !important;
    }

    .navbar-title {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 520px;
      max-width: calc(100vw - 48px);
      height: 70px;
      overflow: hidden;
      line-height: 0;
    }

    .navbar-title-image {
      width: 100%;
      height: 100%;
      display: block;
      object-fit: contain;
      object-position: center;
      transform: translateY(-1px) scale(1.08);
      transform-origin: center center;
    }

    @media (max-width: 640px) {
      .navbar-title-link {
        padding: 0 4px !important;
      }

      .navbar-title {
        width: 360px;
        max-width: calc(100vw - 24px);
        height: 58px;
      }

      .navbar-title-image {
        transform: translateY(-1px) scale(1.06);
      }
    }

    /* ─── Cloche notifications (haut DROIT de la navbar) ──────────────────────
       Styles UNIFIÉS dans badgeuse-app.css (.app-navbar-notif-bell) — plus de
       copie locale à resynchroniser. Révélée par index-page.js quand le PIN
       désigne un admin ([hidden] par défaut). */

    /* Pop-up « Notifications » ouvert par la cloche. Le corps réutilise les
       lignes .ba-notif-pref (badgeuse-app.css) ; ici seul le cadre/entête. */
    .index-notif-modal__dialog {
      max-width: 460px;
    }

    .index-notif-modal__header {
      margin-bottom: var(--ba-space-3);
    }

    .index-notif-modal__title {
      margin: 4px 0 6px;
    }

    .index-notif-modal__subtitle {
      margin: 0;
      font-size: .92rem;
      line-height: 1.4;
      color: #5b6b7a;
    }

    .index-notif-modal__device {
      margin-bottom: 12px;
    }

    /* Pop-up post-activation passkey (#indexPushEnrollModal) : paire d'actions
       « Plus tard » / « Activer », même gabarit que module-manager-modal__actions. */
    .index-notif-modal__actions {
      display: flex;
      justify-content: flex-end;
      gap: var(--ba-space-2);
      margin-top: var(--ba-space-3);
    }

    .index-notif-modal__actions .uk-button[disabled] {
      opacity: 0.55;
      pointer-events: none;
    }

    .uk-notification.uk-notification-top-center {
      top: var(--badgeuse-notification-top, calc(env(safe-area-inset-top) + 88px));
    }

    .uk-notification-top-center .uk-notification-message {
      animation: badgeuseToastSlideDown 0.24s cubic-bezier(0.22, 1, 0.36, 1);
      will-change: opacity, transform;
    }

    @keyframes badgeuseToastSlideDown {
      from {
        opacity: 0;
        transform: translateY(-12px);
      }

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

    @media (prefers-reduced-motion: reduce) {
      .uk-notification-top-center .uk-notification-message {
        animation: none;
        will-change: auto;
      }
    }

    /* Carte principale autour du PIN + boutons */
    .badgeuse-card {
      border-radius: 10px;
      padding: 18px 16px;
    }

    .badgeuse-main-column {
      box-sizing: border-box;
    }

    /* PIN plus gros, centré */
    .pin-input {
      font-size: 34px;
      height: 64px;
      text-align: center;
      letter-spacing: 0.18em;
    }

    /* Écran de badgeage = surtout mobile : PIN encore plus grand, pleine largeur */
    @media (max-width: 640px) {
      .pin-input {
        font-size: 42px;
        height: 72px;
      }
    }

    .pin-remember-control {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      width: 100%;
      margin-top: var(--ba-space-2);
      color: #52606d;
      font-size: var(--ba-font-base);
      line-height: 1.3;
      user-select: none;
    }

    .pin-remember-control__input {
      width: 16px;
      height: 16px;
      margin: 0;
      accent-color: var(--ba-primary);
    }

    /* Boutons plus gros, pleine largeur sur mobile */
    .badgeuse-btn-large {
      font-size: var(--ba-font-2xl);
      padding: 14px 20px;
      border-radius: 8px;
      font-weight: 400;
      letter-spacing: 0.01em;
    }

    .badgeuse-btn-icon-wrap {
      display: inline-flex;
      align-items: center;
      vertical-align: middle;
      margin-right: var(--ba-space-1);
    }

        .badgeuse-btn-label-mobile {
      display: inline;
    }

    #btnEnroll .badgeuse-btn-icon-wrap,
    #btnAdmin .badgeuse-btn-icon-wrap,
    #btnPlanningAdmin .badgeuse-btn-icon-wrap,
    #btnTasksAdmin .badgeuse-btn-icon-wrap {
      margin-right: 0;
    }

    #btnEnroll,
    #btnAdmin,
    #btnPlanningAdmin,
    #btnTasksAdmin {
      min-height: 70px;
      padding: 10px 20px;
      color: var(--ba-primary);
    }

    #btnEnroll:hover,
    #btnEnroll:focus-visible,
    #btnAdmin:hover,
    #btnAdmin:focus-visible,
    #btnPlanningAdmin:hover,
    #btnPlanningAdmin:focus-visible,
    #btnTasksAdmin:hover,
    #btnTasksAdmin:focus-visible {
      color: var(--ba-primary-deep);
    }

    .passkey-enroll-lock,
    .admin-access-gear {
      width: 58px;
      height: 58px;
      display: block;
      color: currentColor;
      filter: drop-shadow(0 8px 16px rgba(16, 80, 123, 0.14));
      transition: transform 0.16s ease, filter 0.16s ease;
    }

    #btnEnroll:hover .passkey-enroll-lock,
    #btnEnroll:focus-visible .passkey-enroll-lock,
    #btnAdmin:hover .admin-access-gear,
    #btnAdmin:focus-visible .admin-access-gear {
      transform: translateY(-1px) scale(1.03);
      filter: drop-shadow(0 10px 18px rgba(16, 80, 123, 0.18));
    }

    .passkey-enroll-lock__body {
      fill: var(--ba-bg-white);
      stroke: currentColor;
      stroke-width: 5;
      stroke-linejoin: round;
    }

    .passkey-enroll-lock__shackle,
    .passkey-enroll-lock__keyhole {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .passkey-enroll-lock__keyhole {
      stroke-width: 4;
    }

    .admin-access-gear__ring,
    .admin-access-gear__teeth {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .punch-action-icon {
      width: 42px;
      height: 42px;
      display: block;
      color: currentColor;
      filter: drop-shadow(0 7px 14px rgba(16, 80, 123, 0.12));
      transition: transform 0.16s ease, filter 0.16s ease;
    }

    #btnEnter:hover .punch-action-icon,
    #btnEnter:focus-visible .punch-action-icon,
    #btnExit:hover .punch-action-icon,
    #btnExit:focus-visible .punch-action-icon {
      transform: translateY(-1px) scale(1.03);
      filter: drop-shadow(0 9px 16px rgba(16, 80, 123, 0.16));
    }

    .punch-action-icon__door,
    .punch-action-icon__threshold,
    .punch-action-icon__arrow,
    .punch-action-icon__handle {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .punch-action-icon__door {
      transform-box: fill-box;
    }

    #btnEnter.is-punch-cinematic,
    #btnExit.is-punch-cinematic {
      opacity: 1;
      pointer-events: none;
      transform: translateY(-1px) scale(1.015);
      box-shadow: 0 10px 22px rgba(16, 80, 123, 0.18);
    }

    #btnEnter.is-punch-cinematic[disabled],
    #btnExit.is-punch-cinematic[disabled] {
      opacity: 1;
    }

    #btnEnter.is-punch-cinematic .punch-action-icon,
    #btnExit.is-punch-cinematic .punch-action-icon {
      animation: punchAcceptedIconPulse 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
      filter: drop-shadow(0 10px 18px rgba(16, 80, 123, 0.2));
    }

    #btnEnter.is-punch-cinematic .punch-action-icon__arrow {
      animation: punchEnterArrow 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    #btnEnter.is-punch-cinematic .punch-action-icon__door {
      transform-origin: right center;
      animation: punchEnterDoor 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    #btnExit.is-punch-cinematic .punch-action-icon__arrow {
      animation: punchExitArrow 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    #btnExit.is-punch-cinematic .punch-action-icon__door {
      transform-origin: left center;
      animation: punchExitDoor 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    @keyframes punchAcceptedIconPulse {
      0% {
        transform: scale(1);
      }
      42% {
        transform: scale(1.08);
      }
      100% {
        transform: scale(1);
      }
    }

    @keyframes punchEnterArrow {
      0% {
        transform: translateX(-5px);
        opacity: 0.72;
      }
      62% {
        transform: translateX(10px);
        opacity: 1;
      }
      100% {
        transform: translateX(6px);
        opacity: 1;
      }
    }

    @keyframes punchExitArrow {
      0% {
        transform: translateX(-2px);
        opacity: 0.72;
      }
      62% {
        transform: translateX(13px);
        opacity: 1;
      }
      100% {
        transform: translateX(8px);
        opacity: 1;
      }
    }

    @keyframes punchEnterDoor {
      0%,
      28% {
        transform: translateX(0) scaleX(1);
      }
      70% {
        transform: translateX(3px) scaleX(0.9);
      }
      100% {
        transform: translateX(0) scaleX(1);
      }
    }

    @keyframes punchExitDoor {
      0%,
      28% {
        transform: translateX(0) scaleX(1);
      }
      70% {
        transform: translateX(-3px) scaleX(0.9);
      }
      100% {
        transform: translateX(0) scaleX(1);
      }
    }

    .admin-access-cinematic {
      grid-column: 1 / -1;
      grid-row: 1;
      min-height: 68px;
      display: grid;
      place-items: center;
      pointer-events: none;
      opacity: 0;
      visibility: hidden;
      transition: opacity 0.18s ease, visibility 0s linear 0.18s;
    }

    .admin-access-cinematic[hidden] {
      display: none !important;
    }

    .admin-access-cinematic.is-running {
      opacity: 1;
      visibility: visible;
      transition-delay: 0s;
    }

    .admin-access-cinematic__stage {
      position: relative;
      width: 118px;
      height: 72px;
      display: grid;
      place-items: center;
      /* Décalage posé par le JS pour aligner la cinématique sur le pictogramme
         du bouton cliqué. Horizontal : roue à gauche / calendrier à droite en
         mode duo. Vertical : les pictos Planning/Tâches vivent dans le bloc
         « dernier pointage » situé au-dessus de .badgeuse-actions → sans ce
         décalage la cinématique démarrait plus bas que le picto statique.
         0 par défaut → centré, comportement hors duo inchangé. */
      transform: translate(var(--cinematic-origin-x, 0px), var(--cinematic-origin-y, 0px));
    }

    .admin-access-cinematic__gear {
      width: 68px;
      height: 68px;
      color: var(--ba-primary);
      filter: drop-shadow(0 9px 18px rgba(16, 80, 123, 0.18));
      opacity: 0;
      transform-origin: center;
    }

    .admin-access-cinematic.is-running .admin-access-cinematic__gear {
      animation:
        adminAccessGearAppear 0.18s ease forwards,
        adminAccessGearSpin 0.4s cubic-bezier(0.45, 0, 0.2, 1) 0.08s 1;
    }

    @keyframes adminAccessGearAppear {
      from {
        opacity: 0;
        transform: scale(0.78);
      }
      to {
        opacity: 1;
        transform: scale(1);
      }
    }

    @keyframes adminAccessGearSpin {
      from {
        transform: rotate(0deg) scale(1);
      }
      to {
        transform: rotate(360deg) scale(1);
      }
    }

    /* Variante Planning de l'overlay d'accès : le calendrier apparaît puis
       ses lignes se dessinent (pas de rotation — réservée à la roue). */
    .planning-access-cinematic__icon {
      width: 68px;
      height: 68px;
      color: var(--ba-primary);
      filter: drop-shadow(0 9px 18px rgba(16, 80, 123, 0.18));
      opacity: 0;
      transform-origin: center;
    }

    .planning-access-cinematic__frame,
    .planning-access-cinematic__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .admin-access-cinematic.is-running .planning-access-cinematic__icon {
      animation: adminAccessGearAppear 0.18s ease forwards;
    }

    .admin-access-cinematic.is-running .planning-access-cinematic__line {
      stroke-dasharray: 14;
      stroke-dashoffset: 14;
      animation: planningLineReveal 0.4s ease forwards;
    }

    .admin-access-cinematic.is-running .planning-access-cinematic__line--one { animation-delay: 0.16s; }
    .admin-access-cinematic.is-running .planning-access-cinematic__line--two { animation-delay: 0.30s; }
    .admin-access-cinematic.is-running .planning-access-cinematic__line--three { animation-delay: 0.44s; }

    /* Variante Tâches de l'overlay d'accès : la check-list apparaît puis ses
       coches se tracent (mêmes keyframes que le Planning, pas de rotation). */
    .tasks-access-cinematic__icon {
      width: 68px;
      height: 68px;
      color: var(--ba-primary);
      filter: drop-shadow(0 9px 18px rgba(16, 80, 123, 0.18));
      opacity: 0;
      transform-origin: center;
    }

    .tasks-access-cinematic__frame,
    .tasks-access-cinematic__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .admin-access-cinematic.is-running .tasks-access-cinematic__icon {
      animation: adminAccessGearAppear 0.18s ease forwards;
    }

    .admin-access-cinematic.is-running .tasks-access-cinematic__line {
      stroke-dasharray: 26;
      stroke-dashoffset: 26;
      animation: planningLineReveal 0.4s ease forwards;
    }

    .admin-access-cinematic.is-running .tasks-access-cinematic__line--one { animation-delay: 0.18s; }
    .admin-access-cinematic.is-running .tasks-access-cinematic__line--two { animation-delay: 0.34s; }

    .history-route-icon,
    .support-route-icon {
      color: currentColor;
      transform-origin: center;
    }

    .history-route-icon__cover,
    .history-route-icon__page,
    .history-route-icon__spine,
    .history-route-icon__line,
    .support-route-icon__body,
    .support-route-icon__band,
    .support-route-icon__tip,
    .support-route-icon__trace {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .history-route-icon__page {
      transform-box: fill-box;
      transform-origin: left center;
      transform: translateX(0) scaleX(1);
    }

    .history-route-icon__line {
      stroke-dasharray: 24;
      stroke-dashoffset: 0;
    }

    .support-route-icon__trace {
      stroke-dasharray: 80;
      stroke-dashoffset: 0;
    }

    .support-route-icon__body {
      fill: var(--ba-bg-white);
    }

    .last-punch-history-btn.is-route-cinematic .history-route-icon {
      animation: routeIconAppear 0.22s ease forwards;
    }

    .last-punch-history-btn.is-route-cinematic .history-route-icon__page {
      transform: translateX(-6px) scaleX(0.72);
      animation: historyPageOpen 0.76s cubic-bezier(0.22, 1, 0.36, 1) 0.16s forwards;
    }

    .last-punch-history-btn.is-route-cinematic .history-route-icon__line {
      stroke-dashoffset: 24;
      animation: historyLineReveal 0.42s ease forwards;
    }

    .last-punch-history-btn.is-route-cinematic .history-route-icon__line--one { animation-delay: 0.34s; }
    .last-punch-history-btn.is-route-cinematic .history-route-icon__line--two { animation-delay: 0.42s; }
    .last-punch-history-btn.is-route-cinematic .history-route-icon__line--three { animation-delay: 0.50s; }
    .last-punch-history-btn.is-route-cinematic .history-route-icon__line--four { animation-delay: 0.58s; }
    .last-punch-history-btn.is-route-cinematic .history-route-icon__line--five { animation-delay: 0.66s; }

    .last-punch-manual-btn.is-route-cinematic .support-route-icon {
      animation:
        routeIconAppear 0.2s ease forwards,
        supportPencilMove 0.84s cubic-bezier(0.22, 1, 0.36, 1) 0.2s forwards;
    }

    .last-punch-manual-btn.is-route-cinematic .support-route-icon__trace {
      stroke-dashoffset: 80;
      animation: supportTraceDraw 0.72s ease 0.38s forwards;
    }

    @keyframes routeIconAppear {
      from {
        opacity: 0;
        transform: translateY(6px) scale(0.82);
      }
      to {
        opacity: 1;
        transform: translateY(0) scale(1);
      }
    }

    @keyframes historyPageOpen {
      0% {
        transform: translateX(-6px) scaleX(0.72);
      }
      100% {
        transform: translateX(0) scaleX(1);
      }
    }

    @keyframes historyLineReveal {
      from {
        stroke-dashoffset: 24;
      }
      to {
        stroke-dashoffset: 0;
      }
    }

    @keyframes supportPencilMove {
      0% {
        transform: translate(-7px, 5px) rotate(-6deg) scale(1);
      }
      70% {
        transform: translate(4px, -2px) rotate(2deg) scale(1.03);
      }
      100% {
        transform: translate(0, 0) rotate(0deg) scale(1);
      }
    }

    @keyframes supportTraceDraw {
      from {
        stroke-dashoffset: 80;
      }
      to {
        stroke-dashoffset: 0;
      }
    }

    .badgeuse-btn-large[disabled] {
      opacity: 0.45;
      cursor: not-allowed;
      box-shadow: none;
    }

    /* Paire volontairement CHEVAUCHANTE à exactement 640px (min-640 + max-640) :
       le sélecteur .mobile-icon-only.badgeuse-btn-large du bloc mobile est plus
       spécifique et gagne. Ne pas « corriger » en min-641 (Galaxy S5 landscape = 640). */
    @media (min-width: 640px) {
      .badgeuse-btn-large {
        min-width: 220px;
      }
    }

    @media (max-width: 640px) {
      .mobile-icon-only.badgeuse-btn-large {
        width: auto !important;
        min-width: 132px;
        padding: 14px 18px;
      }
    }

    @media (max-width: 430px) {
      .mobile-icon-only .badgeuse-btn-label-mobile {
        display: none;
      }

      .mobile-icon-only.badgeuse-btn-large {
        min-width: 84px;
        padding: 14px 22px;
      }

      .mobile-icon-only .badgeuse-btn-icon-wrap {
        margin-right: 0;
      }

      #btnEnroll .badgeuse-btn-label-mobile {
        display: inline;
      }

      #btnEnroll.badgeuse-btn-large {
        min-width: 84px;
        padding: 14px 22px;
      }

      #btnEnroll .badgeuse-btn-icon-wrap {
        margin-right: 0;
      }
    }

    /* ── Entrer / Sortir sur mobile : picto agrandi + libellé EMPILÉ dessous ──
       Les équipes ne repéraient pas « où badger ». Sur mobile, on passe les deux
       boutons en colonne (grande porte au-dessus, mot dessous TOUJOURS visible,
       même < 430px où il était masqué) au lieu de l'icône seule. Desktop (≥640px)
       inchangé : icône + libellé en ligne. Ciblage par #id pour ne pas toucher au
       trio admin ni au bouton d'enrôlement. */
    @media (max-width: 640px) {
      #btnEnter.badgeuse-btn-large,
      #btnExit.badgeuse-btn-large {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 8px;
        /* width:100% !important neutralise le width:auto !important hérité de
           .mobile-icon-only.badgeuse-btn-large : sinon les boutons restent
           dimensionnés au contenu (étroits) au lieu de remplir leur colonne.
           Couplé au full-bleed de .badgeuse-actions → boutons larges bord à bord. */
        width: 100% !important;
        min-width: 0;
        padding: 16px 10px;
      }

      #btnEnter .badgeuse-btn-icon-wrap,
      #btnExit .badgeuse-btn-icon-wrap {
        margin-right: 0;
      }

      #btnEnter .punch-action-icon,
      #btnExit .punch-action-icon {
        width: 60px;
        height: 60px;
      }

      #btnEnter .badgeuse-btn-label-mobile,
      #btnExit .badgeuse-btn-label-mobile {
        display: block;
        font-size: var(--ba-font-2xl);
        font-weight: 500;
        line-height: 1;
        letter-spacing: 0.01em;
      }
    }

    /* Trio admin (roue + calendrier + check-list) sur mobile : mobile-icon-only
       force width:auto + min-width:132/84px, ce qui ferait déborder 3 pictos.
       On neutralise (spécificité + !important) pour que les 3 boutons se
       partagent la rangée, et on resserre gap/padding en descendant. */
    @media (max-width: 640px) {
      .badgeuse-actions--admin-trio .mobile-icon-only.badgeuse-btn-large {
        width: 100% !important;
        min-width: 0;
        padding-left: var(--ba-space-2);
        padding-right: var(--ba-space-2);
      }

      .badgeuse-actions--admin-trio {
        gap: 8px;
      }
    }

    @media (max-width: 430px) {
      .badgeuse-actions--admin-trio .mobile-icon-only.badgeuse-btn-large {
        min-width: 0;
        padding-left: var(--ba-space-1);
        padding-right: var(--ba-space-1);
      }

      .badgeuse-actions--admin-trio {
        gap: var(--ba-space-1);
      }
    }

    /* Très petits écrans (iPhone SE / Android compacts ~320-360px) : filet de
       sécurité, on réduit les 3 pictos de 58→50px pour garantir la tenue sur
       une ligne. Breakpoint 360px hors échelle standard (exception documentée). */
    @media (max-width: 360px) {
      .badgeuse-actions--admin-trio .admin-access-gear,
      .badgeuse-actions--admin-trio .planning-admin-icon,
      .badgeuse-actions--admin-trio .tasks-admin-icon {
        width: 50px;
        height: 50px;
      }
    }

    /* Encadré pour le dernier pointage */
    .last-punch-wrapper {
      height: 116px;
      margin-top: var(--ba-space-2);
    }

    /* Le bloc garde une empreinte fixe dans la carte, masqué ou visible */
    #lastPunchBox {
      margin: 0;
      padding: 0 18px;
      border-radius: 8px;
      border: 1px solid var(--ba-border-light);
      background: var(--ba-bg-subtle);
      height: 100%;
      width: 100%;
      box-sizing: border-box;
      display: grid;
      place-items: center;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transition:
        opacity 0.35s ease,
        background-color 0.28s ease,
        border-color 0.28s ease,
        visibility 0s linear 0.35s;
    }

    #lastPunchBox.last-punch-visible {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transition-delay: 0s;
    }

    #lastPunchBox.last-punch-hidden {
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
    }

    #lastPunchBox.last-punch-route-cinematic {
      background: transparent;
      border-color: transparent;
      pointer-events: none;
    }

    .last-punch-row {
      display: grid;
      grid-template-columns: 72px minmax(0, 1fr) 72px;
      align-items: center;
      gap: 8px;
      width: 100%;
      max-width: 100%;
      justify-items: center;
    }

    .last-punch-manual-btn,
    .last-punch-history-btn {
      width: 72px;
      height: 72px;
      border: 1px solid #d4dce6;
      border-radius: var(--ba-radius-pill);
      background: var(--ba-bg-white);
      color: var(--ba-primary-dark);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      transition: transform .15s ease, box-shadow .15s ease;
      box-shadow: 0 2px 8px rgba(16, 80, 123, 0.08);
    }

    .last-punch-manual-btn {
      grid-column: 1;
    }

    .last-punch-history-btn {
      grid-column: 3;
    }

    /* Pictogrammes centraux (salarié) : Le Planning + Les Tâches côte à côte.
       Conteneur = unique enfant de grille de .last-punch-content (grid-area 1/1,
       empilé sur texte/œil) ; les deux pictos y sont posés en flex row. Le
       conteneur ne capture jamais le clic : seuls les pictos révélés (mode
       --planning) réactivent pointer-events. */
    .last-punch-pictos {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--ba-space-4);
      pointer-events: none;
    }

    /* Picto Tâches : pictogramme CENTRAL à droite du Planning. Même gabarit et
       même mécanique de révélation (opacité/visibilité) que le picto Planning. */
    .last-punch-tasks-btn {
      position: relative; /* ancre la pastille « tâches non vues » */
      width: 64px;
      height: 64px;
      border: 0;
      border-radius: var(--ba-radius-pill);
      background: transparent;
      color: var(--ba-primary);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      text-decoration: none;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transform: translateY(4px);
      transition:
        opacity 0.25s ease,
        transform 0.25s ease,
        color 0.16s ease,
        visibility 0s linear 0.25s;
    }

    .last-punch-content--planning .last-punch-tasks-btn {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transform: translateY(0);
      transition-delay: 0s;
    }

    .last-punch-tasks-btn:hover,
    .last-punch-tasks-btn:focus-visible {
      color: var(--ba-primary-deep);
      transform: translateY(0) scale(1.04);
      outline: none;
    }

    .tasks-route-icon {
      width: 52px;
      height: 52px;
      display: block;
      filter: drop-shadow(0 8px 16px rgba(16, 80, 123, 0.12));
    }
    .tasks-route-icon__frame,
    .tasks-route-icon__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    /* Pastille « tâches non vues » : disque rouge en haut-droite du picto. */
    .last-punch-tasks-dot {
      position: absolute;
      top: 6px;
      right: 6px;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background: var(--ba-danger-text);
      border: 2px solid var(--ba-surface, #fff);
      box-shadow: 0 1px 3px rgba(156, 34, 54, 0.4);
      pointer-events: none;
    }
    .last-punch-tasks-dot[hidden] {
      display: none;
    }

    /* Le Planning : pictogramme CENTRAL de la rangée dernier pointage.
       Empilé dans .last-punch-content (grid-area 1/1) avec le texte et l'œil ;
       révélé par le mode .last-punch-content--planning (posé par le JS quand
       le module est actif), exactement comme --message / --reveal. */
    .last-punch-planning-btn {
      position: relative; /* ancre la pastille « planning modifié » */
      width: 64px;
      height: 64px;
      border: 0;
      border-radius: var(--ba-radius-pill);
      background: transparent;
      color: var(--ba-primary);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      text-decoration: none;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transform: translateY(4px);
      transition:
        opacity 0.25s ease,
        transform 0.25s ease,
        color 0.16s ease,
        visibility 0s linear 0.25s;
    }

    .last-punch-content--planning .last-punch-planning-btn {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transform: translateY(0);
      transition-delay: 0s;
    }

    .last-punch-planning-btn:hover,
    .last-punch-planning-btn:focus-visible {
      color: var(--ba-primary-deep);
      transform: translateY(0) scale(1.04);
      outline: none;
    }

    .planning-route-icon {
      width: 52px;
      height: 52px;
      display: block;
      filter: drop-shadow(0 8px 16px rgba(16, 80, 123, 0.12));
    }

    .planning-route-icon__frame,
    .planning-route-icon__header,
    .planning-route-icon__post,
    .planning-route-icon__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    /* Pastille « planning modifié » : petit disque rouge en haut-droite du
       pictogramme agenda. Masquée par défaut ([hidden]) ; le JS la révèle quand
       /api/pin_status.php renvoie planning_unseen_change = true pour le salarié. */
    .last-punch-planning-dot {
      position: absolute;
      top: 8px;
      right: 8px;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background: var(--ba-danger-text);
      border: 2px solid var(--ba-surface, #fff);
      box-shadow: 0 1px 3px rgba(156, 34, 54, 0.4);
      pointer-events: none;
    }

    .last-punch-planning-dot[hidden] {
      display: none;
    }

    /* Le clic sur le pictogramme Planning du salarié joue l'overlay d'accès
       (calendrier centré, .planning-access-cinematic) — identique à la session
       admin — au lieu d'une cinématique de route en place. */
    @keyframes planningLineReveal {
      to { stroke-dashoffset: 0; }
    }

    /* Icône du bouton "Planning admin" (à côté de la roue) : mêmes traits et
       même taille que la roue dentée admin (.admin-access-gear, 58px) pour que
       le couple roue + calendrier soit visuellement homogène en session admin. */
    .planning-admin-icon {
      width: 58px;
      height: 58px;
      display: block;
    }

    .planning-admin-icon__frame,
    .planning-admin-icon__header,
    .planning-admin-icon__post,
    .planning-admin-icon__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    /* Icône du bouton "Tâches admin" (3e picto de la rangée) : même gabarit
       58px et mêmes traits que la roue et le calendrier pour un trio homogène. */
    .tasks-admin-icon {
      width: 58px;
      height: 58px;
      display: block;
    }

    .tasks-admin-icon__frame,
    .tasks-admin-icon__line {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .last-punch-manual-btn .badgeuse-btn-icon-wrap {
      margin-right: 0;
    }

    .last-punch-content {
      grid-column: 2;
      min-height: 68px;
      display: grid;
      place-items: center;
      width: 100%;
      opacity: 1;
      visibility: visible;
      transform: scale(1);
      transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s linear 0s;
    }

    #lastPunchBox.last-punch-route-cinematic .last-punch-content {
      opacity: 0;
      visibility: hidden;
      transform: scale(0.98);
      transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s linear 0.22s;
    }

    .last-punch-content > * {
      grid-area: 1 / 1;
    }

    #lastPunchText {
      font-size: var(--ba-font-xl);
      font-weight: 400;
      line-height: 1.35;
      margin: 0;
      text-align: center;
      min-height: calc(1.35em * 3);
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      opacity: 0;
      visibility: hidden;
      transform: translateY(4px);
      transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0.25s;
    }

    /* Salutation et statut empilés sur deux lignes ("Bonjour Léo" /
       "vous êtes sorti."). Le span unique est un flex-item de #lastPunchText
       et s'organise lui-même en colonne centrée. */
    .last-punch-status {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 2px;
    }

    .last-punch-reveal-btn {
      width: 64px;
      height: 64px;
      border: 0;
      border-radius: var(--ba-radius-pill);
      background: transparent;
      color: var(--ba-primary);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      cursor: pointer;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transform: translateY(4px);
      transition:
        opacity 0.25s ease,
        transform 0.25s ease,
        color 0.16s ease,
        visibility 0s linear 0.25s;
    }

    .last-punch-reveal-btn:hover,
    .last-punch-reveal-btn:focus-visible {
      color: var(--ba-primary-deep);
      transform: translateY(0) scale(1.04);
      outline: none;
    }

    .last-punch-reveal-icon {
      width: 56px;
      height: 56px;
      display: block;
      filter: drop-shadow(0 8px 16px rgba(16, 80, 123, 0.12));
    }

    .last-punch-reveal-icon__open,
    .last-punch-reveal-icon__iris,
    .last-punch-reveal-icon__lid,
    .last-punch-reveal-icon__lash,
    .last-punch-reveal-icon__bar,
    .last-punch-reveal-icon__accent {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .last-punch-reveal-icon__open,
    .last-punch-reveal-icon__iris {
      opacity: 0;
      transform: scaleY(0.24);
      transform-box: fill-box;
      transform-origin: center;
    }

    .last-punch-reveal-icon__iris {
      fill: currentColor;
      stroke: none;
      opacity: 0;
      transform: scaleY(0.34);
    }

    .last-punch-reveal-icon__accent {
      stroke: currentColor;
      opacity: 0.58;
    }

    .last-punch-reveal-icon__lash {
      opacity: 0.62;
      stroke-width: 2.2;
    }

    .last-punch-reveal-icon__bar {
      opacity: 0.92;
      stroke-width: 5.2;
      stroke-dasharray: 76;
      stroke-dashoffset: 0;
      transform-box: fill-box;
      transform-origin: center;
    }

    .last-punch-reveal-btn.is-eye-opening {
      pointer-events: none;
      color: var(--ba-primary);
    }

    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon {
      animation: revealEyePulse 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__open,
    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__iris {
      animation: revealEyeOpen 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__bar {
      animation: revealEyeBarClear 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__lid,
    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__lash,
    .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__accent {
      animation: revealEyeClosedFade 0.36s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    @keyframes revealEyePulse {
      0% {
        transform: scale(1);
      }
      52% {
        transform: scale(1.1);
      }
      100% {
        transform: scale(1.02);
      }
    }

    @keyframes revealEyeOpen {
      0% {
        opacity: 0;
        transform: scaleY(0.24);
      }
      28% {
        opacity: 0;
        transform: scaleY(0.24);
      }
      58% {
        opacity: 0.78;
        transform: scaleY(0.52);
      }
      78%,
      100% {
        opacity: 1;
        transform: scaleY(1);
      }
    }

    @keyframes revealEyeBarClear {
      0% {
        opacity: 0.92;
        stroke-dashoffset: 0;
        transform: translate(0, 0);
      }
      46% {
        opacity: 0.92;
        stroke-dashoffset: 76;
        transform: translate(4px, -4px);
      }
      100% {
        opacity: 0;
        stroke-dashoffset: 76;
        transform: translate(6px, -6px);
      }
    }

    @keyframes revealEyeClosedFade {
      0%,
      34% {
        opacity: 1;
        transform: translateY(0);
      }
      100% {
        opacity: 0;
        transform: translateY(-4px);
      }
    }

    .last-punch-content--message #lastPunchText {
      opacity: 1;
      visibility: visible;
      transform: translateY(0);
      transition-delay: 0s;
    }

    .last-punch-content--reveal .last-punch-reveal-btn {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transform: translateY(0);
      transition-delay: 0s;
    }

    /* Rangée d'actions : grille 2 colonnes. TOUS les boutons partagent
       grid-row 1 — ils se superposent, seul le visible a opacity 1. Comme
       les boutons masqués gardent leur cellule (opacity 0, PAS display none),
       le placement explicite par grid-column garde le centrage correct
       quel que soit le bouton affiché. */
    .badgeuse-actions {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--ba-space-2);
      width: 100%;
      max-width: 460px;
      margin: 16px auto 0;
      align-items: stretch;
      min-height: 60px;
    }

    .badgeuse-actions .badgeuse-btn-large {
      width: 100%;
      min-width: 0;
      grid-row: 1;
    }

    /* ── Entrer / Sortir sur mobile : élargis DANS la carte ─────────────────────
       Les boutons restent en flux normal À L'INTÉRIEUR de .badgeuse-card (aucun
       débordement possible). Pour les élargir on resserre le padding horizontal
       de la carte sur mobile (16px → 12px, cf. règle .badgeuse-card ci-dessous) :
       comme la rangée d'actions est en width:100%, elle gagne cette largeur. Une
       bordure libre demeure (gutter .uk-container 15px + padding carte 12px ≈
       27px de chaque côté). PAS de full-bleed 100vw (faisait sortir les boutons
       hors de la carte → « débordement » visuel). */
    @media (max-width: 640px) {
      .badgeuse-card {
        padding-left: 12px;
        padding-right: 12px;
      }
    }

    .passkey-unlock-cinematic {
      grid-column: 1 / -1;
      grid-row: 1;
      min-height: 68px;
      display: grid;
      place-items: center;
      pointer-events: none;
      opacity: 0;
      visibility: hidden;
      transition: opacity 0.18s ease, visibility 0s linear 0.18s;
    }

    .passkey-unlock-cinematic[hidden] {
      display: none !important;
    }

    .passkey-unlock-cinematic.is-running {
      opacity: 1;
      visibility: visible;
      transition-delay: 0s;
    }

    .passkey-unlock-cinematic__stage {
      position: relative;
      width: 118px;
      height: 72px;
      display: grid;
      place-items: center;
    }

    .passkey-unlock-cinematic__lock {
      width: 68px;
      height: 68px;
      color: var(--ba-primary);
      filter: drop-shadow(0 9px 18px rgba(16, 80, 123, 0.18));
      opacity: 0;
      transform: translateY(8px) scale(0.84);
    }

    .passkey-unlock-cinematic__body {
      fill: var(--ba-bg-white);
      stroke: currentColor;
      stroke-width: 5;
      stroke-linejoin: round;
    }

    .passkey-unlock-cinematic__shackle,
    .passkey-unlock-cinematic__keyhole {
      fill: none;
      stroke: currentColor;
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .passkey-unlock-cinematic__keyhole {
      stroke-width: 4;
    }

    .passkey-unlock-cinematic__particle {
      --burst-x: 0px;
      --burst-y: 0px;
      --burst-size: 7px;
      --burst-color: var(--ba-primary);
      position: absolute;
      left: 50%;
      top: 52%;
      width: var(--burst-size);
      height: var(--burst-size);
      border-radius: var(--ba-radius-pill);
      background: var(--burst-color);
      box-shadow: 0 0 14px rgba(16, 80, 123, 0.16);
      opacity: 0;
      transform: translate(-50%, -50%) scale(0.25);
    }

    .passkey-unlock-cinematic__particle:nth-of-type(1) { --burst-x: -52px; --burst-y: -26px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(2) { --burst-x: -34px; --burst-y: -44px; --burst-size: 5px; --burst-color: var(--ba-success-text); }
    .passkey-unlock-cinematic__particle:nth-of-type(3) { --burst-x: -10px; --burst-y: -54px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(4) { --burst-x: 22px; --burst-y: -46px; --burst-size: 6px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(5) { --burst-x: 48px; --burst-y: -25px; --burst-color: var(--ba-success-text); }
    .passkey-unlock-cinematic__particle:nth-of-type(6) { --burst-x: 56px; --burst-y: 6px; --burst-size: 5px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(7) { --burst-x: 36px; --burst-y: 34px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(8) { --burst-x: 8px; --burst-y: 46px; --burst-size: 5px; --burst-color: var(--ba-success-text); }
    .passkey-unlock-cinematic__particle:nth-of-type(9) { --burst-x: -22px; --burst-y: 42px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(10) { --burst-x: -48px; --burst-y: 18px; --burst-size: 6px; --burst-color: var(--ba-primary); }
    .passkey-unlock-cinematic__particle:nth-of-type(11) { --burst-x: -60px; --burst-y: 2px; --burst-size: 5px; --burst-color: var(--ba-success-text); }
    .passkey-unlock-cinematic__particle:nth-of-type(12) { --burst-x: 58px; --burst-y: 24px; --burst-color: var(--ba-primary); }

    .passkey-unlock-cinematic.is-running .passkey-unlock-cinematic__lock {
      animation: passkeyUnlockFade 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }

    .passkey-unlock-cinematic.is-running .passkey-unlock-cinematic__shackle {
      animation: passkeyUnlockShackle 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
      transform-box: fill-box;
      transform-origin: 34px 43px;
    }

    .passkey-unlock-cinematic.is-running .passkey-unlock-cinematic__particle {
      animation: passkeyUnlockBurst 0.32s cubic-bezier(0.16, 1, 0.3, 1) 0.36s forwards;
    }

    @keyframes passkeyUnlockFade {
      0% {
        opacity: 0;
        transform: translateY(8px) scale(0.84);
      }
      22% {
        opacity: 1;
        transform: translateY(0) scale(1);
      }
      52% {
        opacity: 1;
        transform: translateY(0) scale(1);
      }
      72% {
        opacity: 1;
        transform: translateY(0) scale(0.96);
      }
      100% {
        opacity: 0;
        transform: translateY(0) scale(0.36);
      }
    }

    @keyframes passkeyUnlockShackle {
      0%,
      34% {
        transform: rotate(0deg) translate(0, 0);
      }
      58%,
      100% {
        transform: rotate(-14deg) translate(-2px, -2px);
      }
    }

    @keyframes passkeyUnlockBurst {
      0% {
        opacity: 0;
        transform: translate(-50%, -50%) scale(0.18);
      }
      10% {
        opacity: 1;
      }
      100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--burst-x)), calc(-50% + var(--burst-y))) scale(0.72);
      }
    }

    /* Bouton d'accès SEUL (passkey OU roue admin sans Planning) : occupe les
       deux colonnes et se centre, largeur plafonnée. */
    #btnEnroll,
    #btnAdmin {
      grid-column: 1 / -1;
      justify-self: center;
      width: min(100%, 260px);
    }

    /* Calendrier (Planning) et check-list (Tâches) vivent en colonne droite par
       défaut → jamais affichés seuls, et n'ajoutent pas de 3e colonne implicite
       tant que la grille reste à 2 colonnes (ils se superposent, masqués). */
    #btnPlanningAdmin,
    #btnTasksAdmin {
      grid-column: 2;
      justify-self: start;
    }

    /* Roue + 1 picto secondaire (Planning OU Tâches) : la roue passe en colonne
       gauche → paire symétrique autour du centre. */
    .badgeuse-actions--admin-duo #btnAdmin {
      grid-column: 1;
      justify-self: end;
      width: 100%;
    }

    /* Trio roue + calendrier + check-list (PIN admin + Planning ET Tâches
       actifs) : grille à 3 colonnes égales, chaque picto centré dans la sienne.
       min-width:0 + width:100% pour que les 3 boutons se partagent la largeur
       sans déborder (l'override mobile ci-dessous neutralise le width:auto de
       mobile-icon-only). */
    .badgeuse-actions--admin-trio {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .badgeuse-actions--admin-trio #btnAdmin,
    .badgeuse-actions--admin-trio #btnPlanningAdmin,
    .badgeuse-actions--admin-trio #btnTasksAdmin {
      min-width: 0;
      width: 100%;
      justify-self: center;
    }

    .badgeuse-actions--admin-trio #btnAdmin { grid-column: 1; }
    .badgeuse-actions--admin-trio #btnPlanningAdmin { grid-column: 2; }
    .badgeuse-actions--admin-trio #btnTasksAdmin { grid-column: 3; }

    /* justify-self end/start : sans effet sur desktop (les boutons remplissent
       leur colonne en largeur 100 %), mais sur mobile — où mobile-icon-only
       force width:auto — ça colle chaque bouton vers le centre, donc la paire
       reste centrée au lieu de se caler à gauche de chaque colonne. */
    #btnEnter {
      grid-column: 1;
      justify-self: end;
    }

    #btnExit {
      grid-column: 2;
      justify-self: start;
    }

    #btnEnter.is-suggested,
    #btnExit.is-suggested {
      background: var(--ba-primary);
      border-color: var(--ba-primary);
      color: var(--ba-bg-white);
      box-shadow: 0 8px 18px rgba(16, 80, 123, 0.18);
    }

    #btnEnter.is-suggested:hover,
    #btnEnter.is-suggested:focus-visible,
    #btnExit.is-suggested:hover,
    #btnExit.is-suggested:focus-visible {
      background: var(--ba-primary-deep);
      border-color: var(--ba-primary-deep);
      color: var(--ba-bg-white);
    }

    #btnEnter.is-secondary,
    #btnExit.is-secondary {
      background: var(--ba-bg-white);
      border-color: var(--ba-border);
      color: var(--ba-primary);
      box-shadow: none;
    }

    #btnEnter.is-secondary:hover,
    #btnEnter.is-secondary:focus-visible,
    #btnExit.is-secondary:hover,
    #btnExit.is-secondary:focus-visible {
      background: var(--ba-surface-subtle);
      border-color: #bfd0de;
      color: var(--ba-primary-deep);
    }

    #btnEnter.is-suggested .punch-action-icon,
    #btnExit.is-suggested .punch-action-icon {
      filter: drop-shadow(0 7px 14px rgba(255, 255, 255, 0.16));
    }

    .badgeuse-action-button {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transform: translateY(0);
      transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0s;
    }

    .badgeuse-action-button--hidden {
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transform: translateY(2px);
      transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
    }

    @media (max-width: 640px) {
      .last-punch-wrapper,
      #lastPunchBox {
        height: 116px;
      }

      .last-punch-row {
        grid-template-columns: 72px minmax(0, 1fr) 72px;
        gap: 0;
      }

      #lastPunchBox {
        padding: 0 14px;
      }

      .last-punch-content {
        justify-self: center;
      }

      .last-punch-reveal-btn {
        margin: 0 auto;
      }

      .passkey-unlock-cinematic {
        min-height: 64px;
      }

      .admin-access-cinematic {
        min-height: 64px;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .passkey-unlock-cinematic,
      .admin-access-cinematic,
      .passkey-unlock-cinematic__lock,
      .passkey-unlock-cinematic__shackle,
      .passkey-unlock-cinematic__particle,
      .admin-access-cinematic__gear,
      .planning-access-cinematic__icon,
      .planning-access-cinematic__line,
      .tasks-access-cinematic__icon,
      .tasks-access-cinematic__line,
      .history-route-icon,
      .history-route-icon__page,
      .history-route-icon__line,
      .support-route-icon,
      .support-route-icon__trace,
      .punch-action-icon,
      .punch-action-icon__arrow,
      .punch-action-icon__door,
      .last-punch-reveal-icon,
      .last-punch-reveal-icon__open,
      .last-punch-reveal-icon__iris,
      .last-punch-reveal-icon__lid,
      .last-punch-reveal-icon__lash,
      .last-punch-reveal-icon__bar,
      .last-punch-reveal-icon__accent {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
      }

      .passkey-unlock-cinematic.is-running .passkey-unlock-cinematic__lock {
        opacity: 1;
        transform: translateY(0) scale(1);
      }

      .passkey-unlock-cinematic__particle {
        display: none;
      }

      .admin-access-cinematic.is-running .admin-access-cinematic__gear,
      .admin-access-cinematic.is-running .planning-access-cinematic__icon,
      .admin-access-cinematic.is-running .tasks-access-cinematic__icon {
        opacity: 1;
        transform: scale(1);
      }

      .tasks-access-cinematic__line {
        stroke-dashoffset: 0;
      }

      .last-punch-history-btn.is-route-cinematic .history-route-icon,
      .last-punch-manual-btn.is-route-cinematic .support-route-icon {
        opacity: 1;
        transform: scale(1);
      }

      .history-route-icon__line,
      .support-route-icon__trace {
        stroke-dashoffset: 0;
      }

      .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__open,
      .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__iris {
        opacity: 1;
        transform: scaleY(1);
      }

      .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__bar {
        opacity: 0;
        stroke-dashoffset: 76;
        transform: translate(6px, -6px);
      }

      .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__lid,
      .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__lash,
      .last-punch-reveal-btn.is-eye-opening .last-punch-reveal-icon__accent {
        opacity: 0;
      }
    }

    .last-punch-manual-btn:hover,
    .last-punch-history-btn:hover {
      transform: translateY(-1px);
      box-shadow: 0 6px 14px rgba(16, 80, 123, 0.12);
    }

    .last-punch-manual-btn svg,
    .last-punch-history-btn svg {
      width: 58px;
      height: 58px;
    }

    .last-punch-manual-btn.is-route-cinematic,
    .last-punch-history-btn.is-route-cinematic {
      width: 78px;
      height: 78px;
      color: var(--ba-primary);
      border-color: #d4dce6;
      background: var(--ba-bg-white);
      box-shadow: 0 12px 26px rgba(16, 80, 123, 0.18);
      pointer-events: none;
      position: relative;
      z-index: var(--ba-z-raised);
      transform: translateY(-17px);
    }

    .last-punch-manual-btn.is-route-cinematic svg,
    .last-punch-history-btn.is-route-cinematic svg {
      width: 68px;
      height: 68px;
      filter: drop-shadow(0 9px 18px rgba(16, 80, 123, 0.16));
    }

    .support-disclosure {
      box-sizing: border-box;
      border-radius: 10px;
      padding: 0;
      overflow: hidden;
    }

    .support-disclosure__summary {
      list-style: none;
      display: grid;
      grid-template-columns: 10px minmax(0, 1fr) 10px;
      align-items: center;
      justify-content: center;
      gap: 12px;
      padding: 14px 16px;
      cursor: pointer;
      font-weight: 500;
    }

    .support-disclosure__title {
      grid-column: 2;
      text-align: center;
    }

    .support-disclosure__arrow {
      grid-column: 3;
    }

    .support-disclosure__content {
      padding: 0 16px 16px;
    }

    .support-disclosure__notice {
      text-align: justify;
      text-align-last: left;
    }

    .support-disclosure__content p:last-child {
      margin-bottom: 0;
    }

    /* La barre « Informations et support » ouvre désormais un pop-up : le
       déclencheur est un <button> qui doit ressembler à l'ancien <summary>. */
    .support-disclosure__trigger {
      width: 100%;
      margin: 0;
      border: 0;
      background: transparent;
      color: inherit;
      font: inherit;
    }

    /* Pop-up scrollable, même couleur que la barre. uk-alert-primary porte la
       couleur de texte (#1e87f0) ; le fond doit être réaffirmé car
       .uk-modal-dialog{background:var(--ba-surface)} est déclaré APRÈS .uk-alert-primary
       dans UIkit. L'overflow/scroll est géré par UIkit. */
    .support-modal__dialog {
      background: #d8eafc;
      border-radius: 10px;
    }

    .support-modal__title {
      color: inherit;
      font-size: var(--ba-font-2xl);
      /* La croix flottante (sticky) occupe le coin haut-droit. */
      padding-right: 44px;
    }

    .support-modal .support-disclosure__content {
      padding: 0;
    }

    .support-modal__content p:first-child {
      margin-top: 0;
    }

    /* Bulle onboarding 1re visite — affichee une seule fois (flag localStorage
       badgeuse_onboarded_v1). JS gere l'apparition et le dismiss. */
    .badgeuse-onboarding-hint {
      position: relative;
      margin: 0 0 14px;
      padding: 10px 40px 10px 14px;
      border: 1px solid var(--ba-border-light);
      border-left: 3px solid var(--ba-primary);
      border-radius: 10px;
      background: var(--ba-surface-subtle);
      color: var(--ba-text-strong);
      font-size: var(--ba-font-sm);
      line-height: 1.4;
    }

    .badgeuse-onboarding-hint[hidden] {
      display: none;
    }

    .badgeuse-onboarding-hint__text {
      margin: 0;
    }

    .badgeuse-onboarding-hint__close {
      position: absolute;
      top: 4px;
      right: 4px;
      width: 32px;
      height: 32px;
      border: 0;
      border-radius: var(--ba-radius-pill);
      background: transparent;
      color: var(--ba-text-muted);
      font-size: var(--ba-font-3xl);
      line-height: 1;
      cursor: pointer;
      transition: background-color 0.15s ease, color 0.15s ease;
    }

    .badgeuse-onboarding-hint__close:hover,
    .badgeuse-onboarding-hint__close:focus-visible {
      background: var(--ba-bg-white);
      color: var(--ba-text-strong);
      outline: none;
    }

    @media (prefers-reduced-motion: no-preference) {
      .badgeuse-onboarding-hint:not([hidden]) {
        animation: badgeuseOnboardingFadeIn 0.24s ease-out;
      }
    }

    @keyframes badgeuseOnboardingFadeIn {
      from { opacity: 0; transform: translateY(-4px); }
      to   { opacity: 1; transform: translateY(0); }
    }

/* ── Récupération admin contextuelle (révélée après plusieurs PIN inconnus) ──── */
.badgeuse-admin-recovery__lead {
  display: block;
  color: var(--ba-text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  .badgeuse-admin-recovery:not([hidden]) {
    animation: badgeuseOnboardingFadeIn 0.24s ease-out;
  }
}

/* ── Tactile : pas de grossissement au tap (les :hover restent colles) ──────── */
@media (hover: none), (pointer: coarse) {
  #btnEnroll:hover .passkey-enroll-lock,
  #btnEnroll:focus-visible .passkey-enroll-lock,
  #btnAdmin:hover .admin-access-gear,
  #btnAdmin:focus-visible .admin-access-gear,
  #btnEnter:hover .punch-action-icon,
  #btnEnter:focus-visible .punch-action-icon,
  #btnExit:hover .punch-action-icon,
  #btnExit:focus-visible .punch-action-icon,
  .last-punch-manual-btn:hover,
  .last-punch-manual-btn:focus-visible {
    transform: none;
  }

  /* ces boutons ont une base translateY(0) (etat revele) : on garde la position */
  .last-punch-planning-btn:hover,
  .last-punch-planning-btn:focus-visible,
  .last-punch-reveal-btn:hover,
  .last-punch-reveal-btn:focus-visible {
    transform: translateY(0);
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   Gestion des modules depuis la badgeuse (index.php) — admin uniquement.
   • Picto « + » flottant (ajout de modules) à côté de la roue admin.
   • Croix de retrait façon widget iOS sur les pictos Planning / Tâches
     (révélée par appui long mobile ou clic droit desktop).
   • Menu contextuel « Supprimer » (clic droit desktop).
   • Pop-up d'ajout de modules.
   Placement « + » : coin haut-droit de la rangée d'actions, hors grille
   duo/trio (position:absolute → n'altère pas le calcul de colonnes).
   ------------------------------------------------------------------------- */
.badgeuse-actions {
  position: relative;
}

.module-manager-add {
  position: absolute;
  top: -12px;
  right: 0;
  z-index: var(--ba-z-dropdown);
  width: 32px;
  height: 32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--ba-radius-pill);
  background: var(--ba-primary);
  color: var(--ba-bg-white);
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(16, 80, 123, 0.28), 0 0 0 3px var(--ba-bg-white);
  transition: transform 0.15s ease, background 0.15s ease, opacity 0.18s ease;
}

.module-manager-add:hover,
.module-manager-add:focus-visible {
  background: var(--ba-primary-dark);
  transform: scale(1.08);
  outline: none;
}

.module-manager-add:active {
  transform: scale(0.94);
}

.module-manager-add svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
}

/* Ancre des croix de retrait sur les pictos secondaires. */
#btnPlanningAdmin,
#btnTasksAdmin {
  position: relative;
}

.module-remove-badge {
  position: absolute;
  top: -8px;
  left: -8px;
  z-index: 3;
  width: 24px;
  height: 24px;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: var(--ba-radius-pill);
  background: var(--ba-danger-text);
  color: var(--ba-bg-white);
  box-shadow: 0 2px 8px rgba(156, 34, 54, 0.4), 0 0 0 2px var(--ba-bg-white);
  cursor: pointer;
}

.module-remove-badge svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
}

/* Mode édition (appui long / clic droit) : croix visible + léger tremblement
   « widget iOS ». Le picto reste cliquable seulement via la croix. */
.module-picto.is-editing .module-remove-badge {
  display: inline-flex;
}

.module-picto.is-editing {
  animation: moduleJiggle 0.32s ease-in-out infinite;
}

@keyframes moduleJiggle {
  0%   { transform: rotate(-1.4deg); }
  50%  { transform: rotate(1.4deg); }
  100% { transform: rotate(-1.4deg); }
}

/* Menu contextuel desktop (clic droit) : un seul item « Supprimer ». */
.module-picto-menu {
  position: fixed;
  z-index: var(--ba-z-popover);
  min-width: 148px;
  padding: var(--ba-space-1);
  border-radius: var(--ba-radius-control);
  background: var(--ba-bg-white);
  border: 1px solid var(--ba-border);
  box-shadow: var(--ba-shadow-card);
}

.module-picto-menu__item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: none;
  border-radius: var(--ba-radius-control);
  background: transparent;
  color: var(--ba-danger-text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}

.module-picto-menu__item:hover,
.module-picto-menu__item:focus-visible {
  background: var(--ba-danger-bg);
  outline: none;
}

.module-picto-menu__item svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
}

/* ── Pop-up d'ajout de modules ─────────────────────────────────────────── */
.module-manager-modal {
  position: fixed;
  inset: 0;
  z-index: var(--ba-z-modal-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--ba-space-4);
}

.module-manager-modal[hidden] {
  display: none !important;
}

.module-manager-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.42);
  backdrop-filter: blur(2px);
}

.module-manager-modal__panel {
  position: relative;
  z-index: var(--ba-z-modal-panel);
  width: min(100%, 440px);
  max-height: calc(100vh - 36px);
  overflow-y: auto;
  padding: 22px;
  border-radius: var(--ba-radius-card);
  background: var(--ba-bg-white);
  box-shadow: var(--ba-shadow-card);
  animation: moduleModalPop 0.18s ease;
}

@keyframes moduleModalPop {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.module-manager-modal__title {
  margin: 0 0 6px;
  font-size: 1.2rem;
  color: var(--ba-text-strong);
}

.module-manager-modal__intro {
  margin: 0 0 16px;
  font-size: 0.9rem;
  color: var(--ba-text-muted);
}

.module-manager-modal__list {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  display: grid;
  gap: var(--ba-space-2);
}

.module-manager-option__label {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--ba-border);
  border-radius: var(--ba-radius-panel);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.module-manager-option__label:hover {
  border-color: var(--ba-primary);
  background: var(--ba-surface-subtle);
}

.module-manager-option__checkbox {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  accent-color: var(--ba-primary);
}

.module-manager-option__icon {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--ba-radius-control);
  background: var(--ba-surface-subtle);
  color: var(--ba-primary);
}

.module-manager-option__icon svg {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: currentColor;
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.module-manager-option__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.module-manager-option__text strong {
  color: var(--ba-text-strong);
  font-size: 0.98rem;
}

.module-manager-option__desc {
  font-size: 0.8rem;
  color: var(--ba-text-muted);
}

.module-manager-option__state {
  margin-left: auto;
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: var(--ba-radius-pill);
}

/* Module déjà actif : rappel non modifiable (le pop-up est « ajout uniquement »). */
.module-manager-option.is-active .module-manager-option__state {
  background: var(--ba-success-bg);
  color: var(--ba-success-text);
}

.module-manager-option.is-active .module-manager-option__label {
  cursor: default;
  opacity: 0.72;
}

.module-manager-option.is-active .module-manager-option__label:hover {
  border-color: var(--ba-border);
  background: transparent;
}

.module-manager-modal__hint {
  margin: 0 0 18px;
  font-size: 0.78rem;
  color: var(--ba-text-muted);
}

.module-manager-modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--ba-space-2);
}

.module-manager-modal__confirm[disabled] {
  opacity: 0.55;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .module-picto.is-editing {
    animation: none;
  }
  .module-manager-modal__panel {
    animation: none;
  }
}
