/* Dashboard custom CSS bovenop Tailwind CDN.
 *
 * Brand-kleuren uit de mockup (TBT-I43). Tailwind kan deze gebruiken
 * via bv. ``style="color: var(--brand-purple)"`` of via de inline-
 * tailwind.config in base.html.
 */

:root {
    --brand-purple: #7e1f6f;
    --brand-purple-dark: #5e1855;
    --brand-purple-light: #faf3f8;

    /* Statuskleuren. De basisvarianten zijn bedoeld voor NIET-tekst: bolletjes,
       randen, accentlijnen. Daar geldt WCAG's 3:1-eis voor grafische objecten en die
       halen ze (waiting 3,19:1 · ready 3,30:1 op wit).

       Voor TEKST gelden 4,5:1 en zakken die twee er dus onder (audit-ronde 3, U9).
       Daarvoor zijn de ``-text``-varianten: de 700-tonen halen 5,02:1. Twee aparte
       tokens i.p.v. één donkerder token voor alles, want de bolletjes en accentlijnen
       worden met een donkerdere tint visueel zwaarder dan bedoeld. */
    --status-urgent: #dc2626;        /* 4,83:1 — voldoet ook als tekst */
    --status-urgent-bg: #fef2f2;
    --status-urgent-text: #dc2626;
    --status-waiting: #d97706;       /* 3,19:1 — NIET voor tekst */
    --status-waiting-bg: #fffbeb;
    --status-waiting-text: #b45309;  /* 5,02:1 */
    --status-ready: #16a34a;         /* 3,30:1 — NIET voor tekst */
    --status-ready-bg: #f0fdf4;
    --status-ready-text: #15803d;    /* 5,02:1 */
    --status-closed: #6b7280;        /* 4,83:1 — voldoet ook als tekst */
    --status-closed-bg: #f9fafb;
    --status-closed-text: #6b7280;

    --bg-app: #fafaf7;
    --bg-card: #ffffff;
    --bg-subtle: #f5f5f0;

    --text-primary: #1f2937;
    --text-muted: #6b7280;
}

body {
    background: var(--bg-app);
    color: var(--text-primary);
    font-family: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", system-ui, sans-serif;
}

/* Card-component — wit, vlak met lichte rand (rustiger dan zware schaduw). */
.tb-card {
    background: var(--bg-card);
    border-radius: 0.875rem;
    border: 1px solid rgba(17, 24, 39, 0.07);
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03);
    padding: 1.25rem 1.5rem;
}

/* Brand-knop */
.tb-btn-primary {
    background: var(--brand-purple);
    color: white;
    border-radius: 0.625rem;
    padding: 0.5rem 1rem;
    font-weight: 500;
    transition: background 0.15s ease;
}
.tb-btn-primary:hover {
    background: var(--brand-purple-dark);
}

.tb-btn-secondary {
    background: white;
    color: var(--text-primary);
    border: 1px solid #e5e7eb;
    border-radius: 0.625rem;
    padding: 0.5rem 1rem;
    font-weight: 500;
}
.tb-btn-secondary:hover {
    background: var(--bg-subtle);
}

/* Status-pills */
.tb-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.625rem;
    border-radius: 9999px;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.25rem;
}
.tb-pill-urgent {
    background: var(--status-urgent-bg);
    color: var(--status-urgent);
}
.tb-pill-waiting {
    background: var(--status-waiting-bg);
    /* 3,07:1 op de eigen achtergrond met de basiskleur → onder de 4,5:1 die WCAG voor
       tekst eist. De -text-variant haalt 4,84:1 (audit-ronde 3, U9). */
    color: var(--status-waiting-text);
}
.tb-pill-ready {
    background: var(--status-ready-bg);
    color: var(--status-ready-text);  /* 3,15:1 → 4,79:1 */
}
.tb-pill-closed {
    background: var(--status-closed-bg);
    color: var(--status-closed);
}

/* Status-dot (kleine cirkel links van klantnaam in de ticketlijst) */
.tb-dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 9999px;
}
.tb-dot-urgent { background: var(--status-urgent); }
.tb-dot-waiting { background: var(--status-waiting); }
.tb-dot-ready { background: var(--status-ready); }
.tb-dot-closed { background: var(--status-closed); }

/* Owner-chip (initialen-cirkel) */
.tb-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 9999px;
    background: var(--brand-purple-light);
    color: var(--brand-purple);
    font-size: 0.75rem;
    font-weight: 600;
}

/* Top-nav */
.tb-topbar {
    border-bottom: 1px solid #e5e7eb;
    background: white;
}
.tb-topbar h1 {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--brand-purple);
}
.tb-topbar h1 .tb-brand-suffix {
    color: var(--brand-purple);
}
.tb-topbar p {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    margin-top: 0.125rem;
}

/* Zichtbare toetsenbord-focus (WCAG 2.4.7). Alleen bij keyboard-navigatie
 * dankzij :focus-visible, zodat muisklikken geen outline tonen. */
a:focus-visible,
button:focus-visible,
select:focus-visible,
textarea:focus-visible,
input:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--brand-purple);
    outline-offset: 2px;
    border-radius: 0.375rem;
}

/* Rij-affordances (bulk-selectie in de ticketlijst): rustig verborgen, maar
 * nooit ontoegankelijk. Zichtbaar op hover, toetsenbord-focus binnen de rij en
 * wanneer het ticket is aangevinkt. Op touch-toestellen (geen hover) staan ze
 * altijd zichtbaar — anders zou selectie onmogelijk zijn. */
.tb-reveal {
    opacity: 0;
    transition: opacity 0.15s ease;
}
.group:hover .tb-reveal,
.group:focus-within .tb-reveal,
.tb-reveal:focus-within,
.tb-reveal:has(:checked) {
    opacity: 1;
}
@media (hover: none) {
    .tb-reveal {
        opacity: 1;
    }
}

/* Afwijzen-disclosure: verberg de default marker (driehoekje/pijl) zodat de
 * <summary> als een gewone knop leest. */
.tb-reject > summary {
    list-style: none;
}
.tb-reject > summary::-webkit-details-marker {
    display: none;
}

/* Flash-toast: verschijnt na een actie (bv. bulk-toewijzing), verdwijnt
 * vanzelf. Zonder hyperscript — een pure CSS-animatie fade't in en na ~4s weer
 * uit; een globale 'animationend'-listener in base.html verwijdert het element. */
@keyframes tb-toast-life {
    0% { opacity: 0; transform: translateY(-0.25rem); }
    8% { opacity: 1; transform: translateY(0); }
    85% { opacity: 1; transform: translateY(0); }
    100% { opacity: 0; transform: translateY(-0.25rem); }
}
.tb-toast {
    animation: tb-toast-life 4s ease forwards;
    /* De container heeft pointer-events:none zodat toasts geen kliks onder zich
       blokkeren; de toast zelf moet ze wél krijgen (sluitknop). */
    pointer-events: auto;
}

/* Fouttoasts blijven staan tot ze weggeklikt worden (audit-ronde 3, U8): de melding
   die je écht moet lezen — "dit voorstel is intussen al verwerkt" — verdween anders
   na 4 seconden terwijl je nog naar het formulier keek. Alleen de fade-in. */
@keyframes tb-toast-enter {
    from { opacity: 0; transform: translateY(-0.25rem); }
    to   { opacity: 1; transform: translateY(0); }
}
.tb-toast-persistent {
    animation: tb-toast-enter 0.15s ease forwards;
}
.tb-toast-close {
    opacity: 0.6;
    padding: 0 0.125rem;
}
.tb-toast-close:hover {
    opacity: 1;
}

/* Laadtoestand van het detail-paneel (audit-ronde 3, U7).
 *
 * Tijdens de fetch bleef het vórige ticket volledig zichtbaar en klikbaar: je opende
 * ticket B, zag ticket A, en kon op zijn goedkeur-knop drukken. De dimmer maakt
 * zichtbaar dat de inhoud niet meer geldig is; ``pointer-events: none`` maakt hem ook
 * echt onaanraakbaar. De vertraging voorkomt geflikker bij een snelle respons — onder
 * ~150 ms zie je niets, en dat is precies wat je wil. */
.tb-pane-loading {
    position: relative;
    opacity: 0.45;
    pointer-events: none;
    transition: opacity 0.12s ease 0.15s;
}

/* Split-pane: de rij die momenteel in het detail-paneel getoond wordt. */
.tb-row-active {
    background: var(--brand-purple-light);
    box-shadow: inset 3px 0 0 0 var(--brand-purple);
}

/* --- Ticket-detail: reading-pane layout (Optie A) ------------------------
 * Het detail-paneel scrollt ZELF i.p.v. de hele pagina (lijst links blijft
 * staan). Leestekst begrensd op ~66 tekens. Sticky header houdt klant + status
 * in beeld. Container-query (i.p.v. viewport-breakpoint) zodat de layout op de
 * PANEELbreedte reageert, niet op de vensterbreedte — dát was de oorzaak van de
 * te smalle kolommen. */
#detail-pane.tb-detail-pane {
    max-height: calc(100vh - 8.5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}
/* Lijst links scrollt óók onafhankelijk: met veel tickets werd de pagina
 * anders lang en bewoog het geheel mee bij het scrollen van het detail. Nu
 * blijft de pagina (nagenoeg) staan en scrollt elke kolom apart. Alleen op
 * desktop (split-pane); op mobiel = normale document-scroll. */
@media (min-width: 1024px) {
    .tb-list-col {
        position: sticky;
        top: 1.5rem;
        max-height: calc(100vh - 8.5rem);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
}
#ticket-detail-root {
    container-type: inline-size;
}

/* --- Twee onafhankelijk scrollbare zones (feedback Benjamin, punt 4) --------
 * Op desktop scrollt het paneel niet meer zélf; de header + beslis-balk staan
 * vast en dáártussen scrollen twee zones apart (mail boven, AI/acties onder),
 * met een versleepbare horizontale scheiding. Op mobiel (geen media-match)
 * stapelen de zones en scrollt het paneel als één (ongewijzigd gedrag). */
@media (min-width: 1024px) {
    #detail-pane.tb-detail-pane {
        overflow: hidden; /* de zones scrollen, niet het paneel */
    }
    #ticket-detail-root {
        display: flex;
        flex-direction: column;
        height: calc(100vh - 8.5rem);
        min-height: 0;
    }
    /* Vaste stukken boven/onder mogen niet meekrimpen — enkel de split (flex:1)
     * geeft ruimte. */
    #ticket-detail-root > .tb-detail-header,
    #ticket-detail-root > .tb-actionbar {
        flex-shrink: 0;
    }
    .tb-detail-split {
        flex: 1 1 auto;
        min-height: 0;
        min-width: 0;
        display: grid;
        /* rij 1 = mailzone (versleepbaar via --tb-top-h), rij 2 = handle,
         * rij 3 = AI/acties (neemt de rest). */
        grid-template-rows: var(--tb-top-h, 42%) 0.75rem minmax(0, 1fr);
    }
    .tb-detail-zone {
        overflow-y: auto;
        /* Horizontale containment (feedback Benjamin, Aldi Zemst): brede tabellen/
         * afbeeldingen mogen het paneel niet verbreden — ``min-width: 0`` +
         * ``overflow-x`` houden ze binnen de zone; de mail-iframe scrollt zelf. */
        overflow-x: hidden;
        overscroll-behavior: contain;
        min-height: 0;
        min-width: 0;
        padding-right: 0.25rem;
    }
    .tb-detail-vgutter {
        cursor: row-resize;
        touch-action: none;
        position: relative;
    }
    .tb-detail-vgutter::before {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: 50%;
        height: 2px;
        transform: translateY(-50%);
        background: rgba(17, 24, 39, 0.12);
        border-radius: 2px;
        transition: background 0.15s ease, height 0.15s ease;
    }
    .tb-detail-vgutter:hover::before,
    .tb-detail-vgutter:focus-visible::before {
        background: var(--brand-purple);
        height: 3px;
    }
    .tb-detail-vgutter:focus-visible {
        outline: 2px solid var(--brand-purple);
        outline-offset: -3px;
        border-radius: 0.25rem;
    }
}
/* Mobiel: geen handle (zones stapelen, paneel scrollt als één). */
.tb-detail-vgutter {
    display: none;
}
@media (min-width: 1024px) {
    .tb-detail-vgutter {
        display: block;
    }
}
body.tb-vresizing {
    cursor: row-resize;
    user-select: none;
}

.tb-detail-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--bg-app);
    border-bottom: 1px solid rgba(17, 24, 39, 0.07);
}
/* Leestekst (mailbody, vrije tekst): begrens de regellengte voor leesbaarheid. */
.tb-prose {
    max-width: 66ch;
    /* Scrollen i.p.v. klippen (feedback Benjamin ronde 2, D6). De detail-zone staat op
     * ``overflow-x: hidden`` zodat een brede tabel het paneel niet kan oprekken — dat is
     * juist, maar het betekende dat brede NIET-iframe-inhoud (een lange regel of
     * ASCII-tabel in een eerder thread-bericht) werd afgekapt zonder uitweg. De mail-HTML
     * scrolt binnen zijn iframe; deze regel geeft de plaintext-weergave hetzelfde recht.
     *
     * ``overflow-wrap`` breekt lange ononderbroken tokens (URL's, serienummers) zodat de
     * scrollbalk de uitzondering blijft en niet de regel. */
    overflow-x: auto;
    overflow-wrap: anywhere;
}
/* KPI-tegels (categorie/urgentie/volledigheid): val terug op 2 kolommen in een
 * heel smal paneel zodat ze niet samengeperst raken. */
@container (max-width: 26rem) {
    .tb-kpi-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (prefers-reduced-motion: reduce) {
    .tb-toast {
        animation-duration: 4s;
        animation-timing-function: step-end;
    }
    /* Persistente toasts blijven zichtbaar; alleen de beweging valt weg. */
    .tb-toast-persistent {
        animation: none;
        opacity: 1;
    }
}

/* ==========================================================================
 * Usability-ronde: densiteit, resizer, auto-grow, inklapbare secties
 * ========================================================================== */

/* --- TEST-modus: compacte badge + dunne rand i.p.v. een volle balk --------- */
.tb-test-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    background: var(--status-waiting-bg);
    color: var(--status-waiting-text);  /* tekst: 4,84:1 i.p.v. 3,07:1 (U9) */
    border: 1px solid var(--status-waiting);  /* rand: 3:1 volstaat */
    white-space: nowrap;
}
/* Dunne amber rand rond het hele scherm — permanent zichtbaar signaal dat er
 * niets live gebeurt, zonder een volledige rij op te offeren. */
.tb-test-frame {
    position: fixed;
    inset: 0;
    border: 3px solid var(--status-waiting);
    pointer-events: none;
    z-index: 45;
}

/* --- Resizable split-pane (lijst | sleep-handle | detail), alleen desktop -- */
@media (min-width: 1024px) {
    .tb-split {
        display: grid;
        /* Plain track-list (géén var()-fallback met komma — die maakt de hele
         * property "invalid at computed value time" waardoor de grid naar één
         * kolom terugvalt en de panelen stapelen). De resizer-JS overschrijft
         * grid-template-columns rechtstreeks via inline-style. */
        grid-template-columns: minmax(0, 1fr) 1.25rem minmax(0, 1.3fr);
        align-items: start;
    }
    .tb-split-gutter {
        position: sticky;
        top: 1.5rem;
        height: calc(100vh - 8.5rem);
        cursor: col-resize;
        touch-action: none;
    }
    .tb-split-gutter::before {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        left: 50%;
        width: 2px;
        transform: translateX(-50%);
        background: rgba(17, 24, 39, 0.12);
        border-radius: 2px;
        transition: background 0.15s ease, width 0.15s ease;
    }
    .tb-split-gutter:hover::before,
    .tb-split-gutter:focus-visible::before {
        background: var(--brand-purple);
        width: 3px;
    }
    .tb-split-gutter:focus-visible {
        outline: 2px solid var(--brand-purple);
        outline-offset: -3px;
        border-radius: 0.25rem;
    }
}
/* Mobiel: geen handle (kolommen stapelen). */
.tb-split-gutter {
    display: none;
}
@media (min-width: 1024px) {
    .tb-split-gutter {
        display: block;
    }
}
body.tb-resizing {
    cursor: col-resize;
    user-select: none;
}

/* --- Auto-groeiende tekstvakken: CSS-first (field-sizing), JS-fallback ----- */
textarea.js-autogrow {
    field-sizing: content;
    min-block-size: 3lh;
    max-block-size: 60vh;
    overflow-y: auto;
}

/* --- Inklapbare secties: <details class="tb-card tb-collapse"> ------------- */
.tb-collapse > summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    user-select: none;
}
.tb-collapse > summary::-webkit-details-marker {
    display: none;
}
/* Chevron rechts; wisselt ▸ (dicht) / ▾ (open) — visuele affordance. */
.tb-collapse > summary::after {
    content: "\25B8";
    margin-left: auto;
    color: var(--text-muted);
    font-size: 0.75rem;
    flex-shrink: 0;
}
.tb-collapse[open] > summary::after {
    content: "\25BE";
}
.tb-collapse[open] > summary {
    margin-bottom: 0.75rem;
}
.tb-collapse > summary:focus-visible {
    outline: 2px solid var(--brand-purple);
    outline-offset: 2px;
    border-radius: 0.375rem;
}

/* --- Sticky beslis-balk onderaan het detailpaneel ------------------------- */
/* Blijft in beeld terwijl de inhoud (verzoek + AI) scrollt — de primaire
 * beslissingen zijn altijd bereikbaar. Sticky t.o.v. #detail-pane-scroll in het
 * split-paneel, of t.o.v. de viewport op de volledige detailpagina. */
.tb-actionbar {
    position: sticky;
    bottom: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.25rem;
    padding: 0.625rem 0.25rem;
    background: var(--bg-app);
    border-top: 1px solid rgba(17, 24, 39, 0.12);
}

/* --- Densiteit: compactere kaarten binnen het detailpaneel ---------------- */
#ticket-detail-root .tb-card {
    padding: 0.85rem 1rem;
}

/* --- Filter-toolbar: consistente pills + meelevende actieve staat --------- */
/* Eén stijl voor élke filter-pill (én de 'Meer'-select). De actieve staat volgt
 * de klik client-side (.is-active), want HTMX verwisselt enkel de ticketlijst. */
.tb-filter-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.75rem;
    border-radius: 9999px;
    font-size: 0.875rem;
    line-height: 1.375rem;
    background: #fff;
    border: 1px solid #e5e7eb;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.tb-filter-pill:hover {
    background: var(--bg-subtle);
}
.tb-filter-pill.is-active {
    background: var(--brand-purple);
    border-color: var(--brand-purple);
    color: #fff;
}
.tb-filter-count {
    font-size: 0.75rem;
    opacity: 0.6;
}
.tb-filter-pill.is-active .tb-filter-count {
    color: #fff;
    opacity: 0.8;
}
/* 'Meer'-select als pill (eigen chevron; native pijl weg). */
.tb-filter-select {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 1.6rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.55rem center;
}
.tb-filter-select.is-active {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

/* --- Toolbar-selects (filter + sorteren) ---------------------------------- */
.tb-toolbar-select {
    font-size: 0.875rem;
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    padding: 0.375rem 0.6rem;
    color: var(--text-primary);
    cursor: pointer;
}
.tb-toolbar-select:focus {
    outline: none;
    box-shadow: 0 0 0 2px var(--brand-purple);
}

/* --- Mail-bericht als HTML in een gesandboxte iframe ---------------------- */
/* Hoogte wordt via JS op de inhoud gezet (auto-grow); breedte vol, geen rand. */
.tb-mail-frame {
    width: 100%;
    border: 0;
    display: block;
    background: #fff;
    min-height: 4rem;
    border-radius: 0.5rem;
}
