/* global React */
const { useState: useStateApp, useMemo: useMemoApp, useEffect: useEffectApp } = React;

// ============================================================
// Header global — logo + radar de carga + navegação
// ============================================================
function HeaderCarga({ blocos, weekLabel, onPrev, onNext, onToday, hospitais }) {
  const total = window.calcCargaTotal(blocos);
  const cls = window.classifyCarga(total);
  const cadeias = window.calcCadeias(blocos);
  const max = 80;
  const pct = Math.min((total / max) * 100, 100);
  const totalFmt = total.toFixed(total % 1 ? 1 : 0);
  // Total $ da semana (só se algum hospital tem remuneração ativa)
  const remuSemana = window.calcRemuneracaoPeriodo
    ? window.calcRemuneracaoPeriodo(blocos, hospitais)
    : null;
  const mostraDinheiro = remuSemana && remuSemana.totalBruto > 0;

  const radarColor = cls.zone === 'ok' ? 'var(--ok)'
                   : cls.zone === 'warn' ? 'var(--warn)'
                   : 'var(--err)';
  const bgZone = cls.zone === 'ok' ? 'var(--ok-bg)'
              : cls.zone === 'warn' ? 'var(--warn-bg)'
              : 'var(--err-bg)';

  // Mostra alerta inline só em warn/err — em ok, header fica numa linha só
  const mostrarAlerta = cls.zone !== 'ok';
  const cadeiaInfo = cadeias.length > 0 ? (() => {
    const maior = Math.round(Math.max(...cadeias.map(c => c.horas)));
    return cadeias.length === 1
      ? `${maior}h contínuas sem descanso`
      : `${cadeias.length} blocos sem descanso (maior ${maior}h)`;
  })() : null;

  return (
    <header style={{
      position: 'sticky', top: 0, zIndex: 20,
      background: 'rgba(255, 250, 243, 0.94)',
      backdropFilter: 'blur(10px)',
      borderBottom: '1px solid var(--line)',
    }}>
      {/* Responsive: em desktop fica 3-col, em mobile (<720px) stacka 2 linhas */}
      <style>{`
        .app-header-grid {
          max-width: 1280px;
          margin: 0 auto;
          padding: 10px 24px;
          display: grid;
          grid-template-columns: auto 1fr auto;
          gap: var(--s-5);
          align-items: center;
        }
        @media (max-width: 720px) {
          .app-header-grid {
            grid-template-columns: 1fr auto;
            gap: 8px;
            padding: 8px 14px;
          }
          .app-header-radar {
            grid-column: 1 / -1 !important;
            max-width: 100% !important;
          }
          .app-header-logo h1 { font-size: 16px !important; white-space: nowrap; }
          .app-header-logo .handwritten { font-size: 11px !important; }
          .app-header-radar .radar-num { font-size: 22px !important; }
          .app-header-nav button { padding: 4px 10px !important; font-size: 11px !important; min-height: 28px !important; }
          .app-header-nav .icon-btn { width: 28px !important; height: 28px !important; }
          /* Esconde o sub-alerta longo em mobile — badge PESADA já comunica */
          .app-header-radar .radar-alerta { display: none !important; }
        }
      `}</style>
      <div className="app-header-grid">
        {/* Logo + label da semana — coluna estreita */}
        <div className="app-header-logo" style={{display:'flex', flexDirection:'column', minWidth: 0}}>
          <div style={{display:'flex', alignItems:'baseline', gap: 6, flexWrap:'wrap'}}>
            <h1 style={{
              fontFamily: 'var(--font-display)',
              fontSize: 20, fontWeight: 600, letterSpacing: '-0.02em',
              color: 'var(--ink)', margin: 0, lineHeight: 1.1,
            }}>Colo Ritmo</h1>
            <span className="handwritten" style={{
              fontSize: 14, color: 'var(--colo-blue-tag)',
              transform: 'rotate(-4deg)', display:'inline-block',
            }}>pediatria</span>
          </div>
          <div className="small" style={{marginTop: 1, fontSize: 11, color:'var(--ink-3)'}}>{weekLabel}</div>
        </div>

        {/* Carga semanal — número compacto + barra inline */}
        <div className="app-header-radar" style={{
          maxWidth: 560, width: '100%', justifySelf: 'center',
          display: 'grid', gap: 4,
        }}>
          <div style={{display: 'flex', alignItems: 'baseline', gap: 'var(--s-2)', flexWrap: 'wrap'}}>
            <span className="radar-num" style={{
              fontFamily: 'var(--font-display)',
              fontSize: 28, fontWeight: 500, lineHeight: 1,
              color: radarColor, letterSpacing: '-0.02em',
            }}>{totalFmt}</span>
            <span style={{
              fontFamily:'var(--font-body)', fontSize: 12,
              color: 'var(--ink-2)', fontWeight: 500,
            }}>
              h <span style={{color:'var(--ink-3)'}}>esta semana</span>
            </span>
            {/* Barra inline */}
            <div style={{
              position: 'relative', flex: 1,
              height: 4, borderRadius: 999,
              background: 'var(--bg-alt)', overflow: 'hidden',
              minWidth: 80, marginLeft: 'var(--s-2)',
            }}>
              <div style={{
                position: 'absolute', left: 0, top: 0, bottom: 0,
                width: `${pct}%`, background: radarColor,
                transition: 'width var(--dur-3) var(--ease)',
                borderRadius: 999,
              }}/>
              <div style={{position:'absolute', left:'60%', top:-1, bottom:-1, width:1, background:'var(--line-2)'}}/>
              <div style={{position:'absolute', left:'75%', top:-1, bottom:-1, width:1, background:'var(--line-2)'}}/>
            </div>
            <span style={{
              padding: '2px 8px',
              fontSize: 10, fontWeight: 700,
              background: bgZone, color: radarColor,
              borderRadius: 'var(--r-pill)',
              textTransform: 'uppercase', letterSpacing: '0.04em',
              whiteSpace: 'nowrap',
            }}>{cls.label}</span>
            {mostraDinheiro && (
              <span style={{
                marginLeft: 'var(--s-2)', whiteSpace:'nowrap',
                fontFamily:'ui-monospace, SFMono-Regular, monospace',
                fontSize: 13, fontWeight: 600,
                color: 'var(--ok, #5A6E50)',
              }} title={`Bruto: ${window.fmtBRL(remuSemana.totalBruto)}${remuSemana.totalLiquido !== remuSemana.totalBruto ? ` · Líquido: ${window.fmtBRL(remuSemana.totalLiquido)}` : ''}`}>
                {window.fmtBRL(remuSemana.totalLiquido !== remuSemana.totalBruto ? remuSemana.totalLiquido : remuSemana.totalBruto)}
              </span>
            )}
          </div>

          {/* Linha de alerta — só se warn ou err. Escondida em mobile (badge já informa) */}
          {mostrarAlerta && (
            <p className="radar-alerta" style={{
              margin: 0, fontSize: 11,
              color: cls.zone === 'err' ? 'var(--err)' : 'var(--warn)',
              lineHeight: 1.3, textWrap: 'pretty',
            }}>
              {cls.sub}{cadeiaInfo ? ` · ${cadeiaInfo}` : ''}
            </p>
          )}
        </div>

        {/* Navegação compacta */}
        <div className="app-header-nav" style={{display:'flex', gap: 4, alignItems: 'center', visibility: onPrev ? 'visible' : 'hidden'}}>
          <IconBtn onClick={onPrev} aria-label="Semana anterior">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
          </IconBtn>
          <button onClick={onToday} style={{
            padding: '6px 14px',
            border: '1px solid var(--line-2)',
            background: 'var(--bg)',
            borderRadius: 'var(--r-pill)',
            fontSize: 12, fontWeight: 600,
            color: 'var(--ink)', cursor: 'pointer',
            fontFamily: 'var(--font-body)',
            minHeight: 32,
          }}>Hoje</button>
          <IconBtn onClick={onNext} aria-label="Próxima semana">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
          </IconBtn>
        </div>
      </div>
    </header>
  );
}

function IconBtn({ children, onClick, ...rest }) {
  return (
    <button onClick={onClick} className="icon-btn" style={{
      width: 32, height: 32,
      border: '1px solid var(--line)',
      background: 'var(--bg)',
      borderRadius: 999,
      cursor: 'pointer',
      color: 'var(--ink-2)',
      display: 'grid', placeItems: 'center',
      transition: 'all var(--dur-1) var(--ease)',
    }} {...rest}>{children}</button>
  );
}

// ============================================================
// Tabs simples para alternar entre views
// ============================================================
function Tabs({ value, onChange, options }) {
  return (
    <div className="tabs-bar" style={{
      display: 'inline-flex', gap: 4,
      padding: 4,
      background: 'var(--bg-alt)',
      borderRadius: 'var(--r-pill)',
      border: '1px solid var(--line)',
      maxWidth: '100%',
    }}>
      {options.map(opt => {
        const active = String(value) === String(opt.id);
        return (
          <button key={opt.id} type="button" onClick={() => onChange(opt.id)}
            data-active={active ? 'true' : 'false'}
            style={{
              padding: '10px 18px',
              minHeight: 40,
              background: active ? 'var(--bg)' : 'transparent',
              color: active ? 'var(--ink)' : 'var(--ink-2)',
              border: active ? '1px solid var(--line)' : '1px solid transparent',
              borderRadius: 'var(--r-pill)',
              fontSize: 13, fontWeight: active ? 700 : 500,
              cursor: 'pointer',
              fontFamily: 'var(--font-body)',
              boxShadow: active ? 'var(--shadow-sm)' : 'none',
              transition: 'all var(--dur-1) var(--ease)',
              display: 'flex', alignItems: 'center', gap: 6,
            }}>
            {opt.label}
          </button>
        );
      })}
    </div>
  );
}

// ============================================================
// FAB de adicionar plantão + modal
// ============================================================
function AddBlocoFAB({ onAdd, onAddRecorrencia, hospitais, dataDefault, blocosTodos }) {
  const HOSPS = hospitais || window.HOSPITAIS;
  const [open, setOpen] = useStateApp(false);
  const [tipo, setTipo] = useStateApp('plantao'); // plantao | sono | bloqueio
  const dataInicial = dataDefault || window.HOJE_ISO;
  const [form, setForm] = useStateApp({ hospitalId: HOSPS[0]?.id || 1, data: dataInicial, horaInicio: 7, duracao: 12 });
  // Recorrência (apenas plantão): 'nunca' | 'weekly' | 'biweekly' | 'monthly'
  const [repetir, setRepetir] = useStateApp('nunca');
  // Default "até": 6 meses depois da data
  const ateDefault = useMemoApp(() => {
    const d = window.fromISO(dataInicial);
    d.setMonth(d.getMonth() + 6);
    return window.toISO(d);
  }, [dataInicial]);
  const [ate, setAte] = useStateApp(ateDefault);

  useEffectApp(() => {
    setForm(f => ({ ...f, data: dataInicial }));
    setAte(ateDefault);
  }, [dataInicial, ateDefault]);

  // Quando troca de tipo (sono/bloqueio), recorrência não se aplica
  useEffectApp(() => { if (tipo !== 'plantao') setRepetir('nunca'); }, [tipo]);

  const reset = () => {
    setOpen(false);
    setTipo('plantao');
    setForm({ hospitalId: HOSPS[0]?.id || 1, data: dataInicial, horaInicio: 7, duracao: 12 });
    setRepetir('nunca');
    setAte(ateDefault);
  };

  // Calcular qual semana do mês uma data cai (1-5)
  const semanaDoMes = (iso) => {
    const d = window.fromISO(iso);
    return Math.ceil(d.getDate() / 7);
  };

  const submit = () => {
    if (tipo === 'plantao' && repetir !== 'nunca') {
      const rec = {
        id: `r${Date.now()}`,
        kind: repetir,
        diaSemana: window.diaSemanaBR(form.data),
        horaInicio: form.horaInicio,
        duracao: form.duracao,
        hospitalId: form.hospitalId,
        desde: form.data,
        ate: ate,
      };
      if (repetir === 'monthly') rec.monthlyWeek = semanaDoMes(form.data);
      onAddRecorrencia && onAddRecorrencia(rec);
    } else {
      const novo = tipo === 'plantao'
        ? { tipo: 'plantao', ...form }
        : tipo === 'sono'
        ? { tipo: 'sono', data: form.data, horaInicio: form.horaInicio, duracao: form.duracao }
        : tipo === 'outros'
        ? { tipo: 'outros', data: form.data, horaInicio: form.horaInicio, duracao: form.duracao, motivo: form.motivo, categoria: form.categoria }
        : { tipo: 'bloqueio', data: form.data, horaInicio: form.horaInicio, duracao: form.duracao, motivo: form.motivo };
      onAdd(novo);
    }
    reset();
  };

  // Live conflict detection (só pra ocorrência única — recorrência não checa)
  const projetado = tipo === 'plantao'
    ? { tipo: 'plantao', ...form }
    : { tipo, data: form.data, horaInicio: form.horaInicio, duracao: form.duracao };
  const checaConflito = open && repetir === 'nunca';
  const conflitos = checaConflito ? window.detectarConflitos(projetado, blocosTodos || []) : [];
  const cadeia = checaConflito && tipo === 'plantao' ? window.cadeiaSeAdicionar(projetado, blocosTodos || []) : null;

  // Preview textual da recorrência
  const previewRec = (() => {
    if (tipo !== 'plantao' || repetir === 'nunca') return null;
    const dow = window.diaSemanaBR(form.data);
    const dia = window.DIAS_COMPLETO[dow].toLowerCase();
    if (repetir === 'weekly')   return `Toda ${dia}`;
    if (repetir === 'biweekly') return `A cada 2 ${dia}s`;
    if (repetir === 'monthly')  {
      const ord = ['1ª','2ª','3ª','4ª','5ª'][semanaDoMes(form.data) - 1];
      return `${ord} ${dia} do mês`;
    }
    return null;
  })();

  return (
    <>
      <style>{`
        @media (max-width: 720px) {
          .fab-add-bloco {
            bottom: 20px !important; right: 20px !important;
            padding: 14px !important;
            width: 56px; height: 56px;
            justify-content: center;
          }
          .fab-add-bloco span { display: none; }
          .fab-add-bloco svg { width: 22px; height: 22px; }
        }
      `}</style>
      <button onClick={() => setOpen(true)} className="fab-add-bloco" style={{
        position: 'fixed', bottom: 32, right: 32, zIndex: 25,
        padding: '14px 22px',
        background: 'var(--ink)',
        color: 'var(--bg)',
        border: 0,
        borderRadius: 'var(--r-pill)',
        fontFamily: 'var(--font-body)',
        fontSize: 14, fontWeight: 700,
        cursor: 'pointer',
        display: 'flex', alignItems: 'center', gap: 8,
        boxShadow: 'var(--shadow-lg)',
      }}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
        <span>Adicionar atividade</span>
      </button>

      {open && (
        <div onClick={() => setOpen(false)} style={{
          position: 'fixed', inset: 0, zIndex: 50,
          background: 'rgba(58, 46, 42, 0.3)',
          backdropFilter: 'blur(2px)',
          display: 'grid', placeItems: 'center',
          padding: 20, overflowY: 'auto',
        }}>
          <div onClick={e => e.stopPropagation()} style={{
            background: 'var(--bg)',
            borderRadius: 'var(--r-lg)',
            padding: 'var(--s-6)',
            width: '100%', maxWidth: 460,
            maxHeight: 'calc(100vh - 40px)', overflowY: 'auto',
            boxShadow: 'var(--shadow-lg)',
          }}>
            <h2 className="h2" style={{fontSize: 26}}>{
              tipo === 'plantao' ? 'Adicionar plantão'
              : tipo === 'sono' ? 'Sono protegido'
              : tipo === 'outros' ? 'Atividade pessoal'
              : 'Bloqueio'
            }</h2>
            <p className="small" style={{marginTop: 4, marginBottom: 'var(--s-4)'}}>
              {tipo === 'plantao' && 'Cada bloco entra na soma da semana e nas cadeias contínuas.'}
              {tipo === 'sono' && 'Janela de descanso planejada — não soma na carga, mas protege na grade.'}
              {tipo === 'outros' && 'Personal, manicure, treino, reunião, consulta — atividades pessoais.'}
              {tipo === 'bloqueio' && 'Marca o horário como indisponível: feriado, evento familiar, descanso.'}
            </p>

            {/* Tabs de tipo */}
            <div style={{
              display: 'inline-flex', gap: 4, padding: 4,
              background: 'var(--bg-alt)', borderRadius: 'var(--r-pill)',
              border: '1px solid var(--line)', marginBottom: 'var(--s-4)',
            }}>
              {[{id:'plantao',l:'Plantão'},{id:'sono',l:'Sono'},{id:'outros',l:'Outros'},{id:'bloqueio',l:'Bloqueio'}].map(t => {
                const active = tipo === t.id;
                return (
                  <button key={t.id} type="button" onClick={() => setTipo(t.id)}
                    style={{
                      padding: '6px 14px', fontSize: 12, fontWeight: active ? 700 : 500,
                      background: active ? 'var(--bg)' : 'transparent',
                      color: active ? 'var(--ink)' : 'var(--ink-2)',
                      border: active ? '1px solid var(--line)' : '1px solid transparent',
                      borderRadius: 'var(--r-pill)', cursor: 'pointer', fontFamily: 'var(--font-body)',
                    }}>{t.l}</button>
                );
              })}
            </div>

            <div style={{display: 'grid', gap: 'var(--s-4)'}}>
              {tipo === 'plantao' && (
                <div>
                  <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Hospital</label>
                  <select className="input" value={form.hospitalId} onChange={e => setForm({...form, hospitalId: parseInt(e.target.value)})}>
                    {HOSPS.map(h => <option key={h.id} value={h.id}>{h.nome}</option>)}
                  </select>
                </div>
              )}
              <div>
                <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Data</label>
                <input className="input" type="date" value={form.data}
                  onChange={e => setForm({...form, data: e.target.value})}/>
                <div className="small" style={{marginTop: 4, fontSize: 11}}>
                  {window.DIAS_COMPLETO[window.diaSemanaBR(form.data)]}
                </div>
              </div>
              <div style={{display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'var(--s-3)'}}>
                <div>
                  <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Início</label>
                  <input className="input" type="number" min="0" max="23" value={form.horaInicio}
                    onChange={e => setForm({...form, horaInicio: parseInt(e.target.value) || 0})}/>
                </div>
                <div>
                  <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Duração (h)</label>
                  <input className="input" type="number" min="1" max="36" value={form.duracao}
                    onChange={e => setForm({...form, duracao: parseInt(e.target.value) || 1})}/>
                </div>
              </div>
              {tipo === 'bloqueio' && (
                <div>
                  <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Motivo (opcional)</label>
                  <input className="input" value={form.motivo || ''}
                    onChange={e => setForm({...form, motivo: e.target.value})}
                    placeholder="ex.: aniversário Helena, viagem"/>
                </div>
              )}

              {tipo === 'outros' && (
                <>
                  <div>
                    <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Categoria</label>
                    <div style={{display:'flex', flexWrap:'wrap', gap: 4}}>
                      {[
                        { id: 'manicure', l: '💅 Manicure' },
                        { id: 'treino', l: '🏃 Treino' },
                        { id: 'reuniao', l: '👥 Reunião' },
                        { id: 'consulta', l: '🩺 Consulta' },
                        { id: 'familia', l: '👨‍👩‍👧 Família' },
                        { id: 'pessoal', l: '💆 Pessoal' },
                      ].map(c => {
                        const active = form.categoria === c.id;
                        return (
                          <button key={c.id} type="button"
                            onClick={() => setForm({...form, categoria: c.id})}
                            style={{
                              padding: '6px 12px', fontSize: 12, fontWeight: active ? 700 : 500,
                              background: active ? 'var(--ink)' : 'var(--bg)',
                              color: active ? 'var(--bg)' : 'var(--ink-2)',
                              border: '1px solid ' + (active ? 'var(--ink)' : 'var(--line)'),
                              borderRadius: 'var(--r-pill)', cursor:'pointer',
                            }}>{c.l}</button>
                        );
                      })}
                    </div>
                  </div>
                  <div>
                    <label className="eyebrow" style={{display:'block', marginBottom: 6}}>Descrição (opcional)</label>
                    <input className="input" value={form.motivo || ''}
                      onChange={e => setForm({...form, motivo: e.target.value})}
                      placeholder="ex.: unha com Carla, treino funcional"/>
                  </div>
                </>
              )}

              {tipo === 'plantao' && (
                <div style={{
                  padding: 'var(--s-3) var(--s-4)',
                  background: 'var(--bg-alt)',
                  borderRadius: 'var(--r-md)',
                  border: '1px solid var(--line)',
                }}>
                  <label className="eyebrow" style={{display:'block', marginBottom: 8}}>Repetir</label>
                  <div style={{display:'flex', flexWrap:'wrap', gap: 4}}>
                    {[
                      {id:'nunca', l:'Nunca'},
                      {id:'weekly', l:'Toda semana'},
                      {id:'biweekly', l:'A cada 2 sem.'},
                      {id:'monthly', l:'Mensal'},
                    ].map(r => {
                      const active = repetir === r.id;
                      return (
                        <button key={r.id} type="button" onClick={() => setRepetir(r.id)} style={{
                          padding: '6px 12px', fontSize: 12, fontWeight: active ? 700 : 500,
                          background: active ? 'var(--ink)' : 'var(--bg)',
                          color: active ? 'var(--bg)' : 'var(--ink-2)',
                          border: '1px solid ' + (active ? 'var(--ink)' : 'var(--line)'),
                          borderRadius: 'var(--r-pill)', cursor: 'pointer',
                          fontFamily: 'var(--font-body)',
                        }}>{r.l}</button>
                      );
                    })}
                  </div>
                  {repetir !== 'nunca' && (
                    <div style={{marginTop: 'var(--s-3)', display:'grid', gap: 'var(--s-2)'}}>
                      <div style={{
                        fontSize: 12, fontStyle: 'italic',
                        color: 'var(--colo-blue-tag)',
                      }}>
                        {previewRec} · {window.fmtHora(form.horaInicio)} · {form.duracao}h
                      </div>
                      <div>
                        <label className="eyebrow" style={{display:'block', marginBottom: 4, fontSize: 10}}>Repetir até</label>
                        <input className="input" type="date" value={ate} min={form.data}
                          onChange={e => setAte(e.target.value)}/>
                      </div>
                    </div>
                  )}
                </div>
              )}

              {(conflitos.length > 0 || (cadeia && cadeia.horas > 24)) && (
                <window.ConflitosPanel conflitos={conflitos} cadeia={cadeia} hospitais={HOSPS}/>
              )}

              <div style={{display: 'flex', gap: 'var(--s-2)', marginTop: 'var(--s-3)'}}>
                <button className="btn btn--ghost" onClick={() => setOpen(false)} style={{flex:1, justifyContent:'center'}}>Cancelar</button>
                <button className="btn" onClick={submit} style={{flex:1, justifyContent:'center', background: 'var(--ink)', color: 'var(--bg)'}}>
                  {repetir !== 'nunca' ? 'Criar série' : 'Adicionar'}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

// ============================================================
// Legenda compacta
// ============================================================
function Legenda({ hospitais }) {
  const HOSPS = hospitais || window.HOSPITAIS;
  return (
    <div style={{
      display: 'flex', flexWrap: 'wrap', gap: 'var(--s-5)',
      padding: 'var(--s-4) var(--s-5)',
      background: 'var(--bg)',
      border: '1px solid var(--line)',
      borderRadius: 'var(--r-md)',
      fontSize: 12, color: 'var(--ink-2)',
      alignItems: 'center',
    }}>
      {HOSPS.map(h => (
        <LegItem key={h.id} color={h.cor} label={`${h.abrev} · ${h.endereco?.split(',')[0] || ''}`}/>
      ))}
      <span style={{width: 1, height: 16, background: 'var(--line-2)'}}/>
      <LegItem color="#A4D498" label="Sono protegido" wash/>
      <LegItem stripe label="Deslocamento (auto)"/>
      <LegItem dashed label="Cedido"/>
      <span style={{flex:1}}/>
      <span style={{display: 'flex', alignItems: 'center', gap: 6, color: 'var(--err)', fontWeight: 600}}>
        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
        Cadeia contínua &gt; 24h
      </span>
    </div>
  );
}

function LegItem({ color, label, stripe, dashed, wash }) {
  let style = { width: 14, height: 14, borderRadius: 4 };
  if (stripe) {
    style.background = '#9BC2E7';
    style.backgroundImage = 'repeating-linear-gradient(45deg, rgba(255,255,255,0.45) 0 3px, transparent 3px 7px)';
    style.opacity = 0.7;
  } else if (dashed) {
    style.backgroundImage = 'repeating-linear-gradient(45deg, var(--colo-sand-50) 0 4px, transparent 4px 8px)';
    style.border = '1px dashed var(--line-2)';
  } else {
    style.background = color;
    if (wash) style.opacity = 0.6;
  }
  return (
    <span style={{display: 'flex', alignItems: 'center', gap: 6}}>
      <span style={style}/>
      {label}
    </span>
  );
}

// ============================================================
// TabsDropdown — agrupa opções secundárias num pop-over
// Usado pra "Mais visualizações" e "Configurar" (gear)
// ============================================================
function TabsDropdown({ label, options, currentId, onChange, iconOnly }) {
  const [open, setOpen] = useStateApp(false);
  const ref = React.useRef(null);
  useEffectApp(() => {
    const click = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    if (open) document.addEventListener('mousedown', click);
    return () => document.removeEventListener('mousedown', click);
  }, [open]);

  const ativo = options.some(o => o.id === currentId);
  const itemAtivo = options.find(o => o.id === currentId);

  return (
    <div ref={ref} style={{position:'relative'}}>
      <button
        type="button"
        onClick={() => setOpen(o => !o)}
        aria-label={label}
        aria-expanded={open}
        aria-haspopup="menu"
        style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: iconOnly ? 0 : '10px 14px',
          width: iconOnly ? 44 : 'auto',
          height: 44,
          minHeight: 44,
          background: ativo ? 'var(--bg)' : 'var(--bg-alt)',
          color: ativo ? 'var(--ink)' : 'var(--ink-2)',
          border: '1px solid ' + (ativo ? 'var(--line-2)' : 'var(--line)'),
          borderRadius: iconOnly ? 999 : 'var(--r-pill)',
          fontSize: 13, fontWeight: ativo ? 700 : 500,
          fontFamily: 'var(--font-body)',
          cursor: 'pointer',
          boxShadow: ativo ? 'var(--shadow-sm)' : 'none',
          justifyContent: 'center',
        }}
      >
        {iconOnly ? (
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
        ) : (
          <>
            {ativo && itemAtivo ? itemAtivo.label : label}
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
          </>
        )}
      </button>

      {open && (
        <div role="menu" style={{
          position: 'absolute', top: 'calc(100% + 6px)', left: 0,
          minWidth: 200,
          background: 'var(--bg)',
          border: '1px solid var(--line)',
          borderRadius: 'var(--r-md)',
          boxShadow: 'var(--shadow-md)',
          padding: 6, zIndex: 22,
          display: 'grid', gap: 2,
        }}>
          {options.map(opt => {
            const sel = opt.id === currentId;
            return (
              <button key={opt.id} role="menuitem"
                onClick={() => { onChange(opt.id); setOpen(false); }}
                style={{
                  textAlign: 'left',
                  padding: '10px 14px',
                  background: sel ? 'var(--bg-alt)' : 'transparent',
                  color: 'var(--ink)',
                  border: 0,
                  borderRadius: 'var(--r-sm)',
                  fontSize: 13, fontWeight: sel ? 700 : 500,
                  cursor: 'pointer',
                  fontFamily: 'var(--font-body)',
                  minHeight: 40,
                }}>
                {opt.label}
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ============================================================
// BannerConflitos — fica abaixo do header quando há conflitos
// ============================================================
function BannerConflitos({ count, onResolver }) {
  if (!count) return null;
  return (
    <div className="banner-conflitos" role="alert" style={{
      padding: '12px 32px',
      display: 'flex', alignItems: 'center', gap: 12,
      fontFamily: 'var(--font-body)', position: 'sticky', top: 0, zIndex: 19,
    }}>
      <div style={{
        width: 32, height: 32, borderRadius: 999,
        background: 'var(--err)', color: '#fff',
        display: 'grid', placeItems: 'center', flexShrink: 0,
      }}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/>
          <line x1="12" y1="9" x2="12" y2="13"/>
          <line x1="12" y1="17" x2="12.01" y2="17"/>
        </svg>
      </div>
      <div style={{flex: 1, minWidth: 0}}>
        <div style={{fontWeight: 700, fontSize: 14, color: 'var(--ink)'}}>
          {count} conflito{count === 1 ? '' : 's'} de horário {count === 1 ? 'pendente' : 'pendentes'}
        </div>
        <div className="small" style={{fontSize: 12, color: 'var(--ink-2)', marginTop: 1}}>
          Plantões em horários sobrepostos. Toque pra resolver.
        </div>
      </div>
      <button onClick={onResolver} className="btn"
        style={{background: 'var(--err)', color: '#fff', flexShrink: 0}}>
        Resolver
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
      </button>
    </div>
  );
}

// ============================================================
// ModalConflitos — pop-up chamativo, 1x por sessão
// ============================================================
function ModalConflitos({ count, onResolver, onDispensar }) {
  if (!count) return null;
  return (
    <div onClick={onDispensar} style={{
      position: 'fixed', inset: 0, zIndex: 60,
      background: 'rgba(58, 46, 42, 0.5)',
      backdropFilter: 'blur(4px)',
      display: 'grid', placeItems: 'center',
      padding: 20,
      animation: 'fadeIn 200ms var(--ease)',
    }}>
      <style>{`@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } } @keyframes scaleIn { from { transform: scale(0.95); opacity: 0 } to { transform: scale(1); opacity: 1 } }`}</style>
      <div onClick={e => e.stopPropagation()} role="dialog" aria-modal="true" style={{
        background: 'var(--bg)',
        borderRadius: 'var(--r-xl)',
        padding: 'var(--s-7)',
        width: '100%', maxWidth: 480,
        boxShadow: 'var(--shadow-lg)',
        borderTop: '6px solid var(--err)',
        animation: 'scaleIn 280ms var(--ease)',
        textAlign: 'center',
      }}>
        <div style={{
          width: 64, height: 64, borderRadius: 999,
          background: 'var(--err-bg)',
          display: 'grid', placeItems: 'center',
          margin: '0 auto var(--s-4)',
        }}>
          <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--err)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/>
            <line x1="12" y1="9" x2="12" y2="13"/>
            <line x1="12" y1="17" x2="12.01" y2="17"/>
          </svg>
        </div>
        <h2 className="h2" style={{fontSize: 28, marginBottom: 8}}>
          {count} conflito{count === 1 ? '' : 's'} na sua agenda
        </h2>
        <p className="lede" style={{fontSize: 15, marginBottom: 'var(--s-5)', maxWidth: 380, margin: '0 auto var(--s-5)'}}>
          {count === 1
            ? 'Você tem dois plantões marcados ao mesmo tempo. Vamos resolver agora?'
            : 'Você tem plantões em horários sobrepostos. Vamos resolver agora?'}
        </p>
        <div style={{display: 'flex', gap: 'var(--s-3)', justifyContent: 'center', flexWrap: 'wrap'}}>
          <button onClick={onDispensar} className="btn btn--ghost"
            style={{justifyContent:'center', minWidth: 140}}>
            Mais tarde
          </button>
          <button onClick={onResolver} className="btn"
            style={{background:'var(--err)', color:'#fff', justifyContent:'center', minWidth: 140}}>
            Resolver agora
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { HeaderCarga, Tabs, TabsDropdown, AddBlocoFAB, Legenda, BannerConflitos, ModalConflitos });
