/* public/css/ui.css - Shared foundations injected into every HTML page (see server.js):
   design tokens, one font stack, visible keyboard focus, reduced motion, and the
   toast/dialog styles used by public/js/ui.js. */

:root {
    /* Motion (see memory: animation principles). Enter/exit: ease-out, fast start, soft landing.
       Something already on screen that moves: ease-in-out. Nothing bounces: this is a work tool. */
    --ui-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --ui-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
    --ui-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --ui-text: #111827;
    --ui-text-muted: #4b5563;
    --ui-surface: #ffffff;
    --ui-surface-inverse: #041a3e; /* brand navy */
    --ui-border: #e5e7eb;
    --ui-accent: #c25407; /* brand orange, 4.6:1 with white */
    --ui-accent-hover: #b24d06;
    --ui-danger: #dc2626;
    --ui-danger-hover: #b91c1c;
    --ui-success: #15803d;
    --ui-radius: 10px;
    --ui-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}

body { font-family: var(--ui-font); }

/* Keyboard focus is always visible, whatever a page's own `outline: none` says.
   Text fields are left to their own focus border (plus the caret) to avoid a double ring. */
:focus-visible:not(input):not(textarea):not(select) {
    outline: 2px solid #ed6608 !important;
    outline-offset: 2px !important;
}
[onclick]:not(button):not(a) { cursor: pointer; }

/* Respect the OS "reduce motion" setting; loading spinners keep turning (they carry meaning). */
@media (prefers-reduced-motion: reduce) {
    *:not(.animate-spin):not(.fa-spin),
    *:not(.animate-spin):not(.fa-spin)::before,
    *:not(.animate-spin):not(.fa-spin)::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    @view-transition { navigation: none; }
}

/* Toasts */
.ui-toasts {
    position: fixed; z-index: 10000; bottom: 16px; left: 50%; transform: translateX(-50%);
    display: flex; flex-direction: column; gap: 8px; align-items: center;
    width: min(480px, calc(100vw - 32px)); pointer-events: none;
}
.ui-toast {
    pointer-events: auto; display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 12px 12px 12px 16px; border-radius: var(--ui-radius);
    background: var(--ui-surface-inverse); color: #f9fafb; box-shadow: var(--ui-shadow);
    font: 500 14px/1.4 var(--ui-font);
    animation: ui-toast-in 0.18s var(--ui-ease-out);
}
.ui-toast > span { flex: 1; white-space: pre-line; }
.ui-toast-error { background: var(--ui-danger); }
.ui-toast-action {
    background: none; border: 0; color: #f6b284; font: 600 14px var(--ui-font);
    padding: 6px 8px; border-radius: 6px; cursor: pointer;
}
.ui-toast-error .ui-toast-action { color: #fff; text-decoration: underline; }
.ui-toast-close {
    background: none; border: 0; color: inherit; opacity: 0.7; font-size: 20px; line-height: 1;
    width: 32px; height: 32px; border-radius: 6px; cursor: pointer;
}
.ui-toast-close:hover, .ui-toast-action:hover { background: rgba(255, 255, 255, 0.12); opacity: 1; }
@keyframes ui-toast-in { from { opacity: 0; transform: translateY(8px); } }
/* Leaving is quicker than arriving, and only fades: it is not news any more. */
.ui-toast-out { animation: ui-fade-out 0.12s var(--ui-ease-out) forwards; }
@keyframes ui-fade-out { to { opacity: 0; } }

/* Dialogs (confirm / prompt) */
.ui-dialog {
    border: 0; border-radius: 14px; padding: 24px; width: min(420px, calc(100vw - 32px));
    box-shadow: var(--ui-shadow); color: var(--ui-text); font-family: var(--ui-font);
}
.ui-dialog::backdrop { background: rgba(17, 24, 39, 0.5); }
/* A dialog says "something opened on top of the page": a short rise from 97 %, no bounce.
   It opens on a click, rarely enough for the motion to teach rather than slow down. */
.ui-dialog[open] { animation: ui-dialog-in 0.16s var(--ui-ease-out); }
.ui-dialog[open]::backdrop { animation: ui-backdrop-in 0.16s var(--ui-ease-out); }
@keyframes ui-dialog-in { from { opacity: 0; transform: scale(0.97); } }
@keyframes ui-backdrop-in { from { opacity: 0; } }
.ui-dialog-message { margin: 0 0 20px; font-size: 15px; line-height: 1.5; white-space: pre-line; }
.ui-dialog-input {
    width: 100%; box-sizing: border-box; margin: -8px 0 20px; padding: 10px 12px; font-size: 15px;
    border: 1px solid var(--ui-border); border-radius: 8px;
}
.ui-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }
.ui-btn {
    min-height: 40px; padding: 0 16px; border-radius: 8px; border: 1px solid var(--ui-border);
    background: var(--ui-surface); color: var(--ui-text); font: 600 14px var(--ui-font); cursor: pointer;
}
.ui-btn:hover { background: #f3f4f6; }
.ui-btn-primary { background: var(--ui-accent); border-color: var(--ui-accent); color: #fff; }
.ui-btn-primary:hover { background: var(--ui-accent-hover); }
.ui-btn-danger { background: var(--ui-danger); border-color: var(--ui-danger); }
.ui-btn-danger:hover { background: var(--ui-danger-hover); }

/* The hidden attribute always wins over utility display classes like .flex. */
[hidden] { display: none !important; }

/* Loading placeholders (ui.skeletonRows / ui.skeleton): the shape of the rows to come, gently
   pulsing, instead of "Chargement…" then a jump. Reduced motion stops the pulse (rule above). */
.ui-skel { display: block; height: 10px; border-radius: 4px; background: #e9ecf0; animation: ui-skel 1.2s ease-in-out infinite; }
.ui-skel-row td { padding: 14px 12px; }
@keyframes ui-skel { 50% { opacity: .45; } }

/* Interventions tables on phones: each row becomes a card instead of a 7-column table that
   scrolls sideways. Columns: N°, title, address, price, status, date / technician, ⋯. */
@media (max-width: 767px) {
    .ui-cards-sm thead { display: none; }
    .ui-cards-sm tbody tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "num menu" "title title" "addr addr" "status date"; row-gap: 4px; padding: 10px 4px; }
    .ui-cards-sm tbody td { display: block; padding: 0 8px !important; max-width: none !important; }
    .ui-cards-sm tbody td:nth-child(1) { grid-area: num; align-self: center; font-size: 12px; color: #4b5563; }
    .ui-cards-sm tbody td:nth-child(2) { grid-area: title; }
    .ui-cards-sm tbody td:nth-child(3) { grid-area: addr; font-size: 12px; color: #4b5563; }
    .ui-cards-sm tbody td:nth-child(4) { display: none; }
    .ui-cards-sm tbody td:nth-child(5) { grid-area: status; justify-self: start; }
    .ui-cards-sm tbody td:nth-child(6) { grid-area: date; text-align: right; }
    .ui-cards-sm tbody td:nth-child(7) { grid-area: menu; justify-self: end; }
    .ui-cards-sm tbody tr:has(> td[colspan]) { display: table-row; } /* empty / error message row */
    .ui-cards-sm tbody td[colspan] { padding: 24px 8px !important; }
    .ui-cards-sm tbody tr.ui-skel-row td:nth-child(n+3) { display: none; }
    .ui-cards-sm tbody td.addr-empty { display: none; } /* no address: no lone dash on the card */
}

/* Columns hidden from the Interventions list (Colonnes picker), from tablet width up: on phones
   the rows are cards and every field keeps its place. */
@media (min-width: 768px) {
    .hide-c3 tr > :nth-child(3), .hide-c4 tr > :nth-child(4), .hide-c5 tr > :nth-child(5), .hide-c6 tr > :nth-child(6) { display: none; }
}
#columns-picker > summary::-webkit-details-marker { display: none; }

/* Empty states (ui.emptyState) */
.ui-empty { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 40px 16px; text-align: center; }
.ui-empty > i { font-size: 28px; color: #8e98a8; margin-bottom: 8px; }
.ui-empty-success > i { color: var(--ui-success); }
.ui-empty-title { margin: 0; font: 600 15px/1.4 var(--ui-font); color: #041a3e; }
.ui-empty-text { margin: 0; font-size: 14px; color: var(--ui-text-muted); }
.ui-empty .ui-btn { margin-top: 12px; }
a.ui-btn { display: inline-flex; align-items: center; text-decoration: none; }

/* Row actions menu (ui.menu / ui.menuButton). Opens instantly (used all day); after a choice
   the chosen line flashes and the menu fades in 120 ms, so you see it registered. */
.ui-menu { position: fixed; z-index: 70; min-width: 210px; background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18); padding: 6px; }
.ui-menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 12px; border: 0; border-radius: 8px; background: none; color: #1f2937; font: 500 14px/1.3 var(--ui-font); text-align: left; cursor: pointer; }
.ui-menu-item i { width: 16px; text-align: center; color: #6b7280; }
.ui-menu-item:hover, .ui-menu-item:focus { background: #f1f5f9; outline: none; }
.ui-menu-danger, .ui-menu-danger i { color: #b91c1c; }
.ui-menu-danger:hover, .ui-menu-danger:focus { background: #fef2f2; }
.ui-menu-out { pointer-events: none; animation: ui-fade-out 0.12s var(--ui-ease-out) forwards; }
.ui-menu-chosen { background: #e2e8f0 !important; }
.ui-menu-sep { margin: 4px 0; border-top: 1px solid #f1f5f9; }
.ui-menu-btn { width: 32px; height: 32px; border: 0; border-radius: 999px; background: none; color: #6b7280; cursor: pointer; }
.ui-menu-btn:hover, .ui-menu-btn[aria-expanded="true"] { background: #f1f5f9; color: #041a3e; }

/* Tooltip (ui.js): appears without motion (it was waited for), small and high-contrast. */
.ui-tip { position: fixed; z-index: 90; max-width: 260px; padding: 5px 9px; border-radius: 6px; pointer-events: none;
    background: var(--ui-surface-inverse); color: #fff; font: 500 12px/1.35 var(--ui-font); box-shadow: 0 4px 12px rgba(15, 23, 42, 0.2); }

/* File name with a middle ellipsis (ui.fileName): the head shrinks, the tail (version + extension) never does. */
.ui-fname { display: inline-flex; max-width: 100%; min-width: 0; white-space: nowrap; vertical-align: bottom; }
.ui-fname-head { overflow: hidden; text-overflow: ellipsis; min-width: 1.5em; }
.ui-fname-tail { flex-shrink: 0; }

