<script setup>
/*
 * MelissaTimelineHoje — linha do tempo "Hoje" do MelissaLayout
 * ------------------------------------------------------------
 * Mostra os eventos do dia em duas modalidades responsivas:
 *   - Horizontal (lg+): scroll horizontal com pilulas posicionadas
 *     por hora, eco lateral pra eventos off-screen, cursor "Agora"
 *     e auto-scroll inicial centrado no horario atual
 *   - Vertical (< lg): tipo calendario "dia" com slots de 48px/h,
 *     pilulas absolutas e cursor "Agora" tipo Google Calendar
 *
 * Tudo deriva-se das props (range de horas, eco, posicoes, status).
 * Nao acessa state externo direto — eh um componente puro de
 * apresentacao + interacoes locais (scroll, eco-click).
 *
 * Props:
 *   - eventos: Array — raw eventosHojeReais (passa direto)
 *   - now: Date — relogio atual (atualizado pelo pai a cada 1s)
 *   - workRules: Array — regras semanais da agenda (filtra por dow)
 *   - agendaSettings: Object|null — config da agenda (range fallback)
 *   - feriados: Array — feriados do mes (procura entry pra hoje)
 *   - filtroTipo: String|null — filtro ativo (sessao/supervisao/reuniao)
 *
 * Emit:
 *   - evento(ev) — clique numa pilula (pai abre dialog)
 *   - clear-filter — clique no X do chip de filtro
 */
import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue';

const props = defineProps({
    eventos: { type: Array, default: () => [] },
    now: { type: Date, required: true },
    workRules: { type: Array, default: () => [] },
    agendaSettings: { type: Object, default: null },
    feriados: { type: Array, default: () => [] },
    filtroTipo: { type: String, default: null }
});

const emit = defineEmits(['evento', 'clear-filter', 'iniciar-cronometro']);

// Helper exposto no template: mostra o botao ⏱ so quando o evento esta
// em curso E tem patient_id (atividade livre/bloqueio nao tem paciente).
function podeIniciarCrono(ev) {
    return isEvEmCurso(ev) && !!ev?.patient_id;
}

// ───────────────────────────────────────────────────────────────
// Range de horas (HORA_INICIO/HORA_FIM) — derivado de:
//   1. workRules do dia da semana atual (se houver)
//   2. agendaSettings (fallback global 08–18h)
// Range expande pra incluir eventos fora do expediente — sessao
// excepcional nao some da timeline.
// ───────────────────────────────────────────────────────────────
function _timeStrToHour(s, fallback) {
    const str = String(s || '').slice(0, 5);
    const [h, m] = str.split(':').map(Number);
    if (Number.isFinite(h) && Number.isFinite(m)) return h + m / 60;
    return fallback;
}

const todayRules = computed(() => {
    const dow = props.now.getDay(); // 0=dom .. 6=sab
    return (props.workRules || []).filter((r) => r.dia_semana === dow && r.ativo !== false);
});

const isFolga = computed(() => todayRules.value.length === 0);

const todayFeriado = computed(() => {
    const d = props.now;
    const k = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
    return (props.feriados || []).find((f) => f.data === k) || null;
});

function _baseRange() {
    const rules = todayRules.value;
    if (rules.length > 0) {
        const starts = rules.map((r) => _timeStrToHour(r.hora_inicio, 8));
        const ends = rules.map((r) => _timeStrToHour(r.hora_fim, 18));
        return { start: Math.min(...starts), end: Math.max(...ends) };
    }
    const s = props.agendaSettings;
    const fbStart = (s?.usar_horario_admin_custom && s?.admin_inicio_visualizacao) || s?.agenda_custom_start || '08:00';
    const fbEnd = (s?.usar_horario_admin_custom && s?.admin_fim_visualizacao) || s?.agenda_custom_end || '18:00';
    return { start: _timeStrToHour(fbStart, 8), end: _timeStrToHour(fbEnd, 18) };
}

const HORA_INICIO = computed(() => {
    const { start } = _baseRange();
    const minEv = props.eventos.length ? Math.min(...props.eventos.map((e) => e.startH)) : Infinity;
    return Math.max(0, Math.floor(Math.min(start, minEv)));
});

const HORA_FIM = computed(() => {
    const { end } = _baseRange();
    const maxEv = props.eventos.length ? Math.max(...props.eventos.map((e) => e.endH)) : -Infinity;
    return Math.min(24, Math.ceil(Math.max(end, maxEv)));
});

const hoursRange = computed(() => {
    const arr = [];
    for (let h = HORA_INICIO.value; h <= HORA_FIM.value; h++) arr.push(h);
    return arr;
});

// ───────────────────────────────────────────────────────────────
// Filtro + lista visivel + label do chip
// ───────────────────────────────────────────────────────────────
const eventosVisiveis = computed(() => {
    if (!props.filtroTipo) return props.eventos;
    return props.eventos.filter((ev) => ev.tipo === props.filtroTipo);
});

const filtroLabel = computed(() => {
    if (!props.filtroTipo) return '';
    const map = { sessao: 'atendimentos', supervisao: 'supervisões', reuniao: 'reuniões' };
    return map[props.filtroTipo] || '';
});

// ───────────────────────────────────────────────────────────────
// Helpers de status (cor, icone, em-curso) usados em pilulas
// ───────────────────────────────────────────────────────────────
function statusKey(ev) {
    const s = String(ev?.status || '').toLowerCase();
    if (s === 'realizada') return 'realizado';
    if (s === 'cancelada') return 'cancelado';
    return s || 'agendado';
}
function statusIcon(ev) {
    const s = statusKey(ev);
    if (s === 'realizado') return 'pi pi-check';
    if (s === 'faltou')    return 'pi pi-times';
    if (s === 'cancelado') return 'pi pi-ban';
    if (s === 'remarcar')  return 'pi pi-refresh';
    return null;
}
function isEvEmCurso(ev) {
    const s = statusKey(ev);
    if (s === 'realizado' || s === 'cancelado' || s === 'faltou') return false;
    const d = props.now;
    const h = d.getHours() + d.getMinutes() / 60;
    return typeof ev?.startH === 'number' && typeof ev?.endH === 'number'
        && h >= ev.startH && h < ev.endH;
}
function pillStatusClass(ev) {
    const s = statusKey(ev);
    return [
        `tl-pill--${s}`,
        { 'tl-pill--em-curso': isEvEmCurso(ev) }
    ];
}

// ───────────────────────────────────────────────────────────────
// Posicionamento das pilulas (horizontal + vertical) e cursor
// ───────────────────────────────────────────────────────────────
function eventStyle(ev) {
    const total = HORA_FIM.value - HORA_INICIO.value;
    const left = ((ev.startH - HORA_INICIO.value) / total) * 100;
    const width = ((ev.endH - ev.startH) / total) * 100;
    return {
        left: `${left}%`,
        width: `${width}%`,
        backgroundColor: ev.color,
        // Expoe a cor pra CSS (glow/pulse usa color-mix com essa var)
        '--ev-color': ev.color
    };
}

const VT_HOUR_PX = 48; // altura de cada slot de hora em px
function eventStyleVertical(ev) {
    return {
        top: `${(ev.startH - HORA_INICIO.value) * VT_HOUR_PX}px`,
        height: `${(ev.endH - ev.startH) * VT_HOUR_PX}px`,
        backgroundColor: ev.color,
        '--ev-color': ev.color
    };
}

const nowCursorLeft = computed(() => {
    const d = props.now;
    const h = d.getHours() + d.getMinutes() / 60;
    if (h < HORA_INICIO.value || h > HORA_FIM.value) return '-100%';
    const total = HORA_FIM.value - HORA_INICIO.value;
    return `${((h - HORA_INICIO.value) / total) * 100}%`;
});

const nowCursorTop = computed(() => {
    const d = props.now;
    const h = d.getHours() + d.getMinutes() / 60;
    if (h < HORA_INICIO.value || h > HORA_FIM.value) return '-100%';
    return `${(h - HORA_INICIO.value) * VT_HOUR_PX}px`;
});

function fmtHora(h) {
    const horas = Math.floor(h);
    const mins = Math.round((h - horas) * 60);
    return `${String(horas).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;
}

// ───────────────────────────────────────────────────────────────
// Scroll/eco do horizontal — minimap pulsante de cores nas bordas
// ───────────────────────────────────────────────────────────────
const tlHScrollEl = ref(null);
const tlScrollState = ref({ scrollL: 0, viewW: 0, innerW: 0 });

function _updateTlScrollState() {
    const el = tlHScrollEl.value;
    if (!el) {
        tlScrollState.value = { scrollL: 0, viewW: 0, innerW: 0 };
        return;
    }
    const inner = el.firstElementChild;
    tlScrollState.value = {
        scrollL: el.scrollLeft,
        viewW: el.clientWidth,
        innerW: inner ? (inner.scrollWidth || inner.offsetWidth) : 0
    };
}

function onTimelineScroll() {
    _updateTlScrollState();
}

const tlEcoState = computed(() => {
    const { scrollL, viewW, innerW } = tlScrollState.value;
    const total = HORA_FIM.value - HORA_INICIO.value;
    const empty = { left: [], right: [], vStart: HORA_INICIO.value, vEnd: HORA_FIM.value };
    if (total <= 0 || !innerW || !viewW || innerW <= viewW) return empty;
    const vStart = HORA_INICIO.value + (scrollL / innerW) * total;
    const vEnd = HORA_INICIO.value + ((scrollL + viewW) / innerW) * total;
    const left = [];
    const right = [];
    for (const ev of eventosVisiveis.value) {
        if (ev.endH <= vStart) left.push(ev);
        else if (ev.startH >= vEnd) right.push(ev);
    }
    return { left, right, vStart, vEnd };
});

// Esquerda: HORA_INICIO -> vStart mapeado 0-100%.
// Direita:  vEnd -> HORA_FIM mapeado 0-100%.
function ecoTickStyle(ev, side) {
    const { vStart, vEnd } = tlEcoState.value;
    let topPct = 50;
    if (side === 'left') {
        const span = vStart - HORA_INICIO.value;
        if (span > 0) topPct = ((ev.startH - HORA_INICIO.value) / span) * 100;
    } else {
        const span = HORA_FIM.value - vEnd;
        if (span > 0) topPct = ((ev.startH - vEnd) / span) * 100;
    }
    return {
        top: `${Math.max(0, Math.min(100, topPct))}%`,
        backgroundColor: ev.color
    };
}

function scrollToEvent(ev) {
    const el = tlHScrollEl.value;
    if (!el) return;
    const inner = el.firstElementChild;
    if (!inner) return;
    const innerWidth = inner.scrollWidth || inner.offsetWidth;
    const visibleWidth = el.clientWidth;
    const total = HORA_FIM.value - HORA_INICIO.value;
    if (total <= 0) return;
    const ratio = (ev.startH - HORA_INICIO.value) / total;
    const target = Math.max(0, Math.min(innerWidth - visibleWidth, ratio * innerWidth - visibleWidth / 2));
    el.scrollTo({ left: target, behavior: 'smooth' });
}

// ───────────────────────────────────────────────────────────────
// Auto-scroll inicial: centra "agora" na viewport ao montar (jornadas
// longas ex: 02h-23h nao abrem com cursor off-screen). Roda uma vez.
// ResizeObserver mantem o eco atualizado quando viewport muda.
// ───────────────────────────────────────────────────────────────
let _tlAutoScrolled = false;

function _scrollTimelineToNow() {
    const el = tlHScrollEl.value;
    if (!el) return;
    const d = props.now;
    const h = d.getHours() + d.getMinutes() / 60;
    const total = HORA_FIM.value - HORA_INICIO.value;
    if (total <= 0 || h < HORA_INICIO.value || h > HORA_FIM.value) return;
    const inner = el.firstElementChild;
    if (!inner) return;
    const innerWidth = inner.scrollWidth || inner.offsetWidth;
    const visibleWidth = el.clientWidth;
    if (innerWidth <= visibleWidth) return; // sem overflow, nada a rolar
    const ratio = (h - HORA_INICIO.value) / total;
    el.scrollLeft = Math.max(0, ratio * innerWidth - visibleWidth / 2);
}

onMounted(() => {
    const stop = watch(
        [HORA_INICIO, HORA_FIM],
        () => {
            nextTick(() => {
                if (!_tlAutoScrolled) {
                    _scrollTimelineToNow();
                    const el = tlHScrollEl.value;
                    const inner = el?.firstElementChild;
                    if (inner && inner.scrollWidth > el.clientWidth) {
                        _tlAutoScrolled = true;
                        stop();
                    }
                }
                _updateTlScrollState();
            });
        },
        { immediate: true }
    );

    const el = tlHScrollEl.value;
    if (el && typeof ResizeObserver !== 'undefined') {
        const ro = new ResizeObserver(() => _updateTlScrollState());
        ro.observe(el);
        if (el.firstElementChild) ro.observe(el.firstElementChild);
        onBeforeUnmount(() => ro.disconnect());
    }
});
</script>

<template>
    <section class="glass-panel mt-8 px-5 py-4 max-w-5xl w-full mx-auto">
        <!-- Header: titulo, badges (folga/feriado), chip de filtro, "Agora" -->
        <div class="flex items-center justify-between mb-3">
            <div class="flex items-center gap-2 text-white/90 text-sm font-medium">
                <i class="pi pi-clock text-xs" />
                Linha do tempo — Hoje
                <span
                    v-if="todayFeriado"
                    class="tl-day-badge tl-day-badge--feriado"
                    :title="`Feriado: ${todayFeriado.nome}`"
                >
                    <i class="pi pi-star text-[0.6rem]" />
                    Feriado{{ todayFeriado.nome ? `: ${todayFeriado.nome}` : '' }}
                </span>
                <span
                    v-else-if="isFolga"
                    class="tl-day-badge tl-day-badge--folga"
                    title="Hoje não é dia de trabalho na sua agenda — sessões fora do expediente continuam permitidas."
                >
                    <i class="pi pi-moon text-[0.6rem]" />
                    Folga
                </span>
                <button
                    v-if="filtroTipo"
                    type="button"
                    class="filtro-chip"
                    :title="`Mostrando apenas ${filtroLabel}. Clique pra mostrar tudo.`"
                    @click="emit('clear-filter')"
                >
                    {{ filtroLabel }}
                    <i class="pi pi-times text-[0.6rem]" />
                </button>
            </div>
            <div class="text-xs text-white/70 flex items-center gap-1.5">
                <span class="pulse-dot w-2.5 h-0.5 rounded-full bg-red-500" />
                Agora
            </div>
        </div>

        <!-- Horizontal (lg+) — scroll horizontal com pilulas + cursor "agora" + eco lateral.
             Auto-scroll inicial centra "agora" pra jornadas longas (02h-23h). Frame
             relativo abriga o eco como overlay absolute. -->
        <div class="tl-h-frame hidden lg:block">
            <div ref="tlHScrollEl" class="tl-h-scroll" @scroll.passive="onTimelineScroll">
                <div class="tl-h-inner relative" :style="{ '--m-tl-cols': HORA_FIM - HORA_INICIO }">
                    <div class="flex justify-between mb-1">
                        <div v-for="h in hoursRange" :key="h" class="flex-1 text-left">
                            <span class="text-[0.65rem] text-white/55 font-medium">{{ h }}h</span>
                        </div>
                    </div>
                    <div class="relative h-9 bg-white/5 rounded-md overflow-visible border border-white/10">
                        <div
                            v-for="ev in eventosVisiveis"
                            :key="ev.id"
                            class="tl-event-pill absolute h-[30px] rounded flex items-center px-2 overflow-hidden cursor-pointer min-w-[32px] hover:brightness-110 transition-[filter,opacity] duration-200 z-10"
                            :class="pillStatusClass(ev)"
                            :style="eventStyle(ev)"
                            :title="ev.label"
                            @click="emit('evento', ev)"
                        >
                            <span class="tl-event-pill__label text-[0.8rem] font-semibold truncate">{{ ev.label }}</span>
                            <i
                                v-if="statusIcon(ev)"
                                :class="['tl-event-pill__status', statusIcon(ev)]"
                                aria-hidden="true"
                            />
                            <!-- Botao ⏱ overlay — so em sessoes em curso com
                                 paciente. stopPropagation pra nao disparar
                                 o click do pill que abre o evento. -->
                            <button
                                v-if="podeIniciarCrono(ev)"
                                type="button"
                                class="tl-event-pill__crono"
                                title="Iniciar cronômetro"
                                aria-label="Iniciar cronômetro"
                                @click.stop="emit('iniciar-cronometro', ev)"
                            >
                                <i class="pi pi-stopwatch" />
                            </button>
                        </div>
                        <div
                            class="absolute top-0 h-full flex flex-col items-center pointer-events-none z-20"
                            :style="{ left: nowCursorLeft }"
                        >
                            <div class="w-0.5 h-full bg-red-500 opacity-90" />
                            <div class="absolute -top-0.5 w-[7px] h-[7px] rounded-full bg-red-500" />
                        </div>
                    </div>
                </div>
            </div>

            <!-- Eco lateral — minimap pulsante de cores. Tracinhos posicionados
                 por tempo, mostrando "forma" do dia off-screen. Click = scroll
                 suave ate o evento. -->
            <div
                v-if="tlEcoState.left.length"
                class="tl-eco tl-eco--left"
                :title="`${tlEcoState.left.length} antes — clique pra centralizar`"
            >
                <button
                    v-for="ev in tlEcoState.left"
                    :key="`eco-l-${ev.id}`"
                    type="button"
                    class="tl-eco__tick"
                    :style="ecoTickStyle(ev, 'left')"
                    :title="`${fmtHora(ev.startH)} · ${ev.label}`"
                    @click="scrollToEvent(ev)"
                />
            </div>
            <div
                v-if="tlEcoState.right.length"
                class="tl-eco tl-eco--right"
                :title="`${tlEcoState.right.length} à frente — clique pra centralizar`"
            >
                <button
                    v-for="ev in tlEcoState.right"
                    :key="`eco-r-${ev.id}`"
                    type="button"
                    class="tl-eco__tick"
                    :style="ecoTickStyle(ev, 'right')"
                    :title="`${fmtHora(ev.startH)} · ${ev.label}`"
                    @click="scrollToEvent(ev)"
                />
            </div>
        </div>

        <!-- Vertical (< lg) — calendario "dia" empilhado. Slots de 48px/h. -->
        <div class="vt lg:hidden" :style="{ '--m-vt-rows': HORA_FIM - HORA_INICIO }">
            <div
                v-for="h in hoursRange"
                :key="h"
                class="vt-row"
                :style="{ top: `${(h - HORA_INICIO) * VT_HOUR_PX}px` }"
            >
                <span class="vt-hour">{{ h }}h</span>
                <div class="vt-line" />
            </div>

            <div
                v-for="ev in eventosVisiveis"
                :key="ev.id"
                class="vt-event hover:brightness-110 transition-[filter,opacity] duration-200"
                :class="pillStatusClass(ev)"
                :style="eventStyleVertical(ev)"
                :title="ev.label"
                @click="emit('evento', ev)"
            >
                <i
                    v-if="statusIcon(ev)"
                    :class="['vt-event__status', statusIcon(ev)]"
                    aria-hidden="true"
                />
                <div class="vt-event-time">
                    {{ fmtHora(ev.startH) }} – {{ fmtHora(ev.endH) }}
                </div>
                <div class="vt-event-label">{{ ev.label }}</div>
                <!-- Botao ⏱ overlay — so em sessoes em curso com paciente.
                     stopPropagation pra nao disparar o click do pill. -->
                <button
                    v-if="podeIniciarCrono(ev)"
                    type="button"
                    class="vt-event__crono"
                    title="Iniciar cronômetro"
                    aria-label="Iniciar cronômetro"
                    @click.stop="emit('iniciar-cronometro', ev)"
                >
                    <i class="pi pi-stopwatch" />
                </button>
            </div>

            <div class="vt-now" :style="{ top: nowCursorTop }">
                <div class="vt-now-dot" />
                <div class="vt-now-line" />
            </div>
        </div>
    </section>
</template>

<style scoped>
/* glass-panel base — redeclarado scoped (o do pai esta em scoped tambem
   e nao atravessa). Overrides light mode (.win11-root :is(.glass-panel...))
   estao em <style> nao-scoped do pai e continuam aplicando. */
.glass-panel {
    background: var(--m-bg-soft);
    backdrop-filter: blur(24px) saturate(140%);
    -webkit-backdrop-filter: blur(24px) saturate(140%);
    border: 1px solid var(--m-border);
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}

/* ─── Chip do filtro ativo (header da timeline) ────────────── */
.filtro-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: 6px;
    padding: 2px 8px 2px 10px;
    border-radius: 9999px;
    background: var(--m-bg-soft-hover);
    border: 1px solid var(--m-border-strong);
    color: var(--m-text);
    font-size: 0.7rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 140ms ease;
}
.filtro-chip:hover {
    background: var(--m-border-strong);
}

/* ─── Badge "Folga" / "Feriado" ──────────────────────────────
   Sinaliza dia nao-util sem bloquear: sessoes fora do expediente
   continuam permitidas e visiveis na timeline. */
.tl-day-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 6px;
    padding: 2px 8px;
    border-radius: 9999px;
    font-size: 0.7rem;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
}
.tl-day-badge--folga {
    background: var(--m-bg-soft-hover);
    color: var(--m-text-muted);
    border: 1px solid var(--m-border-strong);
}
.tl-day-badge--feriado {
    background: color-mix(in srgb, rgb(245, 158, 11) 18%, transparent);
    color: rgb(245, 158, 11);
    border: 1px solid color-mix(in srgb, rgb(245, 158, 11) 38%, transparent);
}
/* Light mode: amber-600 saturado ficaria estridente; baixa pra amber-700
   sobre amber-50 — legivel em fundo claro e mantem a identidade do feriado.
   Em scoped CSS, ancestor `html:not(.app-dark)` nao recebe o hash do
   componente — so o leaf `.tl-day-badge--feriado` recebe; o selector
   funciona normalmente. */
html:not(.app-dark) .tl-day-badge--feriado {
    background: color-mix(in srgb, rgb(217, 119, 6) 12%, transparent);
    color: rgb(180, 83, 9);
    border-color: color-mix(in srgb, rgb(217, 119, 6) 32%, transparent);
}

/* ─── Timeline vertical (< lg) — tipo calendario "dia" ─────── */
.vt {
    position: relative;
    /* --m-vt-rows = HORA_FIM - HORA_INICIO (set inline; fallback 12 = 8-20) */
    height: calc(var(--m-vt-rows, 12) * 48px + 24px);
    margin-top: 0.75rem;
}
.vt-row {
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    display: flex;
    align-items: center;
}
.vt-hour {
    width: 36px;
    text-align: right;
    padding-right: 8px;
    color: var(--m-text-muted);
    font-size: 0.65rem;
    font-weight: 500;
    flex-shrink: 0;
    /* Texto centrado na linha (transform shift up half) */
    transform: translateY(-50%);
    background: transparent;
    line-height: 1;
}
.vt-line {
    flex: 1;
    height: 1px;
    background: var(--m-bg-soft);
}
.vt-event {
    position: absolute;
    left: 44px;
    right: 4px;
    padding: 4px 10px;
    border-radius: 4px;
    color: white;
    cursor: pointer;
    overflow: hidden;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 24px;
}
.vt-event-time {
    font-size: 0.62rem;
    opacity: 0.85;
    line-height: 1.1;
}
.vt-event-label {
    font-size: 0.78rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.2;
}

/* ─── Pilula (horizontal) — label sempre branco sobre cor saturada.
   Override .text-white global flipava em light mode pra dark e quebrava
   contraste sobre indigo/verde/vermelho — forcar branco aqui. */
.tl-event-pill__label {
    color: #fff;
    flex: 1;
    min-width: 0;
}

/* ─── Status overlays nas pilulas (horizontal + vertical) ──────
   Cada status ganha tratamento especifico — icone no canto + variacao
   de opacidade/borda/hatch. var --ev-color (set no inline style do
   eventStyle) alimenta o pulse "em curso" com a cor do proprio evento. */
.tl-event-pill {
    transition: filter 200ms ease, opacity 200ms ease, box-shadow 240ms ease;
}
.tl-event-pill__status,
.vt-event__status {
    flex-shrink: 0;
    display: inline-grid;
    place-items: center;
    width: 14px;
    height: 14px;
    border-radius: 9999px;
    background: rgba(0, 0, 0, 0.28);
    color: #fff;
    font-size: 0.55rem;
    margin-left: 6px;
    line-height: 1;
}
.vt-event__status {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 16px;
    height: 16px;
    font-size: 0.6rem;
    margin-left: 0;
}

/* Botao ⏱ "Iniciar cronometro" — overlay no canto sup. direito do
   pill em sessoes em curso. Cor solida pra destacar contra o bg
   colorido do evento; pulso sutil pra chamar atencao sem irritar. */
.tl-event-pill__crono,
.vt-event__crono {
    position: absolute;
    top: 3px;
    right: 3px;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 9999px;
    cursor: pointer;
    font-family: inherit;
    padding: 0;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
    transition: background-color 160ms ease, transform 160ms ease, border-color 160ms ease;
    animation: tl-crono-pulse 2s ease-in-out infinite;
    z-index: 2;
}
.tl-event-pill__crono:hover,
.vt-event__crono:hover {
    background: rgba(16, 185, 129, 0.85);  /* emerald-500 — convida ao "play" */
    border-color: rgba(255, 255, 255, 0.6);
    transform: scale(1.08);
    animation-play-state: paused;
}
.tl-event-pill__crono > i,
.vt-event__crono > i {
    font-size: 0.7rem;
}
@keyframes tl-crono-pulse {
    0%, 100% { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 0 0 0 rgba(16, 185, 129, 0.45); }
    50%      { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 0 0 6px rgba(16, 185, 129, 0); }
}

/* Realizado: glow verde sutil (cor do bg ja eh verde) — celebra o feito */
.tl-pill--realizado {
    box-shadow: 0 0 0 1px rgba(16, 185, 129, 0.28), 0 4px 12px rgba(16, 185, 129, 0.18);
}

/* Faltou: opacidade reduzida + label tachado */
.tl-pill--faltou {
    opacity: 0.78;
}
.tl-pill--faltou .tl-event-pill__label,
.tl-pill--faltou .vt-event-label {
    text-decoration: line-through;
    text-decoration-color: rgba(255, 255, 255, 0.55);
    text-decoration-thickness: 1.5px;
}

/* Cancelado: hatching diagonal + opacidade + label tachado */
.tl-pill--cancelado {
    opacity: 0.6;
    background-image: repeating-linear-gradient(
        135deg,
        rgba(255, 255, 255, 0.0) 0,
        rgba(255, 255, 255, 0.0) 4px,
        rgba(255, 255, 255, 0.22) 4px,
        rgba(255, 255, 255, 0.22) 6px
    );
}
.tl-pill--cancelado .tl-event-pill__label,
.tl-pill--cancelado .vt-event-label {
    text-decoration: line-through;
    text-decoration-color: rgba(255, 255, 255, 0.5);
}

/* Remarcar: ring ambar puxa atencao (status transiente, precisa decisao) */
.tl-pill--remarcar {
    box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.6), 0 4px 14px rgba(245, 158, 11, 0.25);
}

/* Em curso: pulse glow na cor do proprio evento via --ev-color */
.tl-pill--em-curso {
    animation: tl-pill-em-curso 2.2s ease-in-out infinite;
    z-index: 12;
}
@keyframes tl-pill-em-curso {
    0%, 100% {
        box-shadow:
            0 0 0 0 color-mix(in srgb, var(--ev-color, #6366f1) 55%, transparent),
            0 0 0 1px rgba(255, 255, 255, 0.14);
    }
    50% {
        box-shadow:
            0 0 0 6px color-mix(in srgb, var(--ev-color, #6366f1) 0%, transparent),
            0 0 18px 2px color-mix(in srgb, var(--ev-color, #6366f1) 60%, transparent);
    }
}

/* ─── Timeline horizontal: scroll quando o range eh grande ────
   --m-tl-cols (set inline) = HORA_FIM - HORA_INICIO
   --m-tl-slot-w = largura minima por hora (default 80px). */
.tl-h-scroll {
    overflow-x: auto;
    overflow-y: visible;
    /* respiro pra pilulas e cursor "Agora" nao cortarem na borda */
    padding-bottom: 4px;
    scrollbar-width: thin;
    scrollbar-color: var(--m-border-strong) transparent;
}
.tl-h-scroll::-webkit-scrollbar { height: 6px; }
.tl-h-scroll::-webkit-scrollbar-track { background: transparent; }
.tl-h-scroll::-webkit-scrollbar-thumb {
    background: var(--m-border-strong);
    border-radius: 9999px;
}
.tl-h-inner {
    min-width: calc(var(--m-tl-cols, 12) * var(--m-tl-slot-w, 80px));
}

/* ─── Eco lateral: minimap pulsante de cores nas bordas ────────
   Faixas verticais de 8px coladas nas bordas do scroll, mostrando
   tracinhos coloridos (cor do status) pra cada evento off-screen. */
.tl-h-frame { position: relative; }
.tl-eco {
    position: absolute;
    top: 16px;     /* alinha com topo da barra (descontando linha de horas) */
    bottom: 8px;   /* respiro do scrollbar */
    width: 8px;
    z-index: 6;
    pointer-events: auto;
    border-radius: 4px;
    background: color-mix(in srgb, var(--m-bg-soft) 70%, transparent);
    border: 1px solid var(--m-border);
    box-shadow: 0 0 0 0 transparent;
    animation: tl-eco-pulse 2400ms ease-in-out infinite;
    transition: opacity 180ms ease;
}
.tl-eco--left  { left: -2px; }
.tl-eco--right { right: -2px; }

.tl-eco__tick {
    position: absolute;
    left: 1px;
    right: 1px;
    height: 4px;
    transform: translateY(-50%);
    border: 0;
    padding: 0;
    border-radius: 2px;
    cursor: pointer;
    opacity: 0.85;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
    transition: opacity 140ms ease, transform 140ms ease, height 140ms ease;
}
.tl-eco__tick:hover {
    opacity: 1;
    height: 6px;
    transform: translateY(-50%) scaleX(2.2);
    z-index: 1;
}
.tl-eco--left  .tl-eco__tick:hover { transform-origin: left center; }
.tl-eco--right .tl-eco__tick:hover { transform-origin: right center; }

@keyframes tl-eco-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--p-primary-color) 0%, transparent);
    }
    50% {
        box-shadow: 0 0 10px 1px color-mix(in srgb, var(--p-primary-color) 35%, transparent);
    }
}

/* Light mode: faixa precisa contrastar mais com bloom claro */
html:not(.app-dark) .tl-eco {
    background: color-mix(in srgb, var(--m-bg-soft-hover) 90%, transparent);
    border-color: var(--m-border-strong);
}

/* ─── Cursor "Agora" do vertical (mobile) ─────────────────── */
.vt-now {
    position: absolute;
    left: 32px;
    right: 0;
    z-index: 2;
    pointer-events: none;
    display: flex;
    align-items: center;
    transform: translateY(-50%);
}
.vt-now-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgb(239, 68, 68);
    flex-shrink: 0;
    animation: pulse 1.6s ease-in-out infinite;
}
.vt-now-line {
    flex: 1;
    height: 2px;
    background: rgb(239, 68, 68);
    box-shadow: 0 0 6px rgba(239, 68, 68, 0.5);
    margin-left: 2px;
}

/* ─── Pulse no "Agora" (header) ────────────────────────────── */
.pulse-dot {
    animation: pulse 1.6s ease-in-out infinite;
}
@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}
</style>
