/* ============================================================
   BAN YARO — Gesundheit & Impfpass (Sprint 3)
   Tabs: Impfungen | Tierarzt | Gewicht | Medikamente | Allergien | Dokumente
   + KI-Gesundheitszusammenfassung
   ============================================================ */

window.Page_health = (() => {

  let _container    = null;
  let _appState     = null;
  let _data         = {};
  let _praxen       = [];
  let _activeTab    = 'impfung';
  let _favoritVet   = null;
  let _healthDocs   = [];

  const BASE_TABS = [
    { key: 'impfung',      label: 'Impfpass',      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>' },
    { key: 'tierarzt',     label: 'Besuche',        icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>' },
    { key: 'gewicht',      label: 'Gewicht',        icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg>' },
    { key: 'medikament',   label: 'Medikamente',    icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>' },
    { key: 'allergie',     label: 'Allergien',      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#leaf"></use></svg>' },
    { key: 'dokument',     label: 'Dokumente',      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg>' },
    { key: 'praxen',       label: 'Praxen',         icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>' },
  ];
  const LAEUFIGKEIT_TAB = { key: 'laeufigkeit', label: 'Läufigkeit', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-female"></use></svg>' };

  function _getTabs() {
    const tabs = [...BASE_TABS];
    if (_appState?.activeDog?.geschlecht === 'w') tabs.splice(2, 0, LAEUFIGKEIT_TAB);
    return tabs;
  }


  // ----------------------------------------------------------
  // LIFECYCLE
  // ----------------------------------------------------------
  async function init(container, appState, params) {
    _container = container;
    _appState  = appState;
    if (params?.tab) {
      const valid = _getTabs().some(t => t.key === params.tab);
      if (valid) _activeTab = params.tab;
    }
    await _render();
    if (params?.openForm) {
      setTimeout(() => _showForm(null, _activeTab), 200);
    }
  }

  async function refresh() {
    if (!_appState.activeDog) return;
    if (_appState.dogs.length > 1) {
      _renderDogPicker();
      return;
    }
    _data = {};
    await _renderHealth();
  }

  async function onDogChange() {
    _data = {};
    await _renderHealth();
  }

  function openNew() {
    _showForm(null, _activeTab);
  }

  // ----------------------------------------------------------
  // RENDER — Einstieg: Picker bei mehreren Hunden, sonst direkt
  // ----------------------------------------------------------
  async function _render() {
    if (!_appState.activeDog) {
      _container.innerHTML = UI.emptyState({
        icon:   '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>',
        title:  'Noch kein Hund angelegt',
        text:   'Erstelle zuerst ein Hundeprofil.',
        action: `<button class="btn btn-primary" onclick="App.navigate('dog-profile')">Profil erstellen</button>`,
      });
      return;
    }

    if (_appState.dogs.length > 1) {
      _renderDogPicker();
    } else {
      await _renderHealth();
    }
  }

  // ----------------------------------------------------------
  // HUNDE-PICKER
  // ----------------------------------------------------------
  function _renderDogPicker() {
    const activeDogId = _appState.activeDog?.id;

    const cards = _appState.dogs.map(dog => {
      const isActive = dog.id === activeDogId;
      const av = dog.foto_url
        ? `<img src="${_esc(dog.foto_url)}" alt="${_esc(dog.name)}">`
        : `<span>${UI.icon('dog')}</span>`;
      return `
        <div class="diary-picker-card${isActive ? ' diary-picker-card--active' : ''}"
             data-dog-id="${dog.id}">
          <div class="diary-picker-av">${av}</div>
          <div class="diary-picker-name">${_esc(dog.name)}</div>
          ${dog.rasse ? `<div class="diary-picker-rasse">${_esc(dog.rasse)}</div>` : ''}
        </div>`;
    }).join('');

    _container.innerHTML = `
      <div class="diary-picker-wrap">
        <p class="diary-picker-hint">Wessen Gesundheitsakte?</p>
        <div class="diary-picker-grid">${cards}</div>
      </div>`;

    _container.querySelectorAll('.diary-picker-card').forEach(el => {
      el.addEventListener('click', async () => {
        const id = parseInt(el.dataset.dogId);
        if (id === _appState.activeDog?.id) {
          // Bereits aktiver Hund → direkt Health laden
          _data = {};
          await _renderHealth();
        } else {
          App.setActiveDog(id);
          // onDogChange() → _renderHealth() via _notifyDogChange()
        }
      });
    });
  }

  // ----------------------------------------------------------
  // HEALTH-ANSICHT — Tabs mit Einträgen
  // ----------------------------------------------------------
  async function _renderHealth() {
    const dog = _appState.activeDog;
    const transponderHtml = `
      <div class="health-transponder" id="health-transponder">
        <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#wave-sine"></use></svg>
        <span class="health-transponder-label">Transponder:</span>
        <span class="health-transponder-nr" id="health-transponder-nr">
          ${dog?.chip_nr ? `<strong>${_esc(dog.chip_nr)}</strong>` : '<em style="color:var(--c-text-muted)">nicht eingetragen</em>'}
        </span>
        <button class="btn btn-link btn-sm health-transponder-edit" id="health-transponder-edit"
                style="padding:0;font-size:var(--text-xs);color:var(--c-text-muted)">
          <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#pencil-simple"></use></svg>
        </button>
      </div>`;
    _container.innerHTML = `
      <div class="by-toolbar health-header">
        <button class="btn btn-secondary btn-sm" id="health-ki-btn">
          ${UI.icon('star')} KI-Zusammenfassung
        </button>
        <button class="btn btn-secondary btn-sm" id="health-ki-tierarzt-btn">
          <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#stethoscope"></use></svg> KI-Tierarzt
        </button>
      </div>
      ${transponderHtml}
      <div id="health-ki-berichte"></div>
      <div id="health-terminvorschlaege"></div>
      <div id="health-reminders"></div>
      <div class="by-tabs" id="by-tabs"></div>
      <div id="by-tab-content"></div>
    `;

    _renderTabBar();
    _container.querySelector('#health-ki-btn')
      .addEventListener('click', _showKiSummary);
    _container.querySelector('#health-ki-tierarzt-btn')
      .addEventListener('click', _showKiTierarzt);
    _container.querySelector('#health-transponder-edit')
      .addEventListener('click', () => _editTransponder(dog));

    await _loadAll();
    _renderErinnerungen();
    _renderTab();
    _loadKiBerichte(dog.id);
    _loadTerminvorschlaege(dog.id);
    _loadMeinTierarzt();
  }

  // ----------------------------------------------------------
  // ERINNERUNGEN — Banner über den Tabs
  // ----------------------------------------------------------
  function _getErinnerungen() {
    const REMINDER_TABS = ['impfung', 'entwurmung', 'medikament', 'laeufigkeit'];
    const now  = Date.now();
    const items = [];
    REMINDER_TABS.forEach(typ => {
      (_data[typ] || []).forEach(e => {
        if (!e.naechstes) return;
        const tage = Math.ceil((new Date(e.naechstes).getTime() - now) / 86400000);
        if (tage <= 60) items.push({ ...e, _tage: tage, _typ: typ });
      });
    });
    return items.sort((a, b) => a._tage - b._tage);
  }

  function _renderErinnerungen() {
    const el = _container.querySelector('#health-reminders');
    if (!el) return;

    const items = _getErinnerungen();

    // Nav-Badge aktualisieren (Anzahl überfälliger/bald fälliger Einträge)
    const overdueCount = items.filter(e => e._tage < 0).length;
    _updateHealthBadge(overdueCount || (items.length ? items.length : 0));

    if (!items.length) { el.innerHTML = ''; return; }

    const ICONS = {
      impfung:      '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#syringe"></use></svg>',
      entwurmung:   '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#bandaids"></use></svg>',
      medikament:   '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#pill"></use></svg>',
      tierarzt:     '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#stethoscope"></use></svg>',
      gewicht:      '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg>',
      allergie:     '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#warning-circle"></use></svg>',
      laeufigkeit:  '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#gender-female"></use></svg>',
    };

    el.innerHTML = `
      <div style="padding:var(--space-3) var(--space-4) 0">
        <div style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
                    color:var(--c-text-secondary);margin-bottom:var(--space-2)">
          <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#calendar-dots"></use></svg> Anstehende Erinnerungen
        </div>
        ${items.map(e => {
          const ampel = _impfAmpel(e.naechstes);
          const dateStr = UI.time.format(e.naechstes + 'T00:00:00');
          const ageLabel = e._tage < 0
            ? `Überfällig seit ${Math.abs(e._tage)} Tagen`
            : e._tage === 0 ? 'Heute fällig'
            : `In ${e._tage} Tagen`;
          return `
            <div style="display:flex;align-items:center;gap:var(--space-3);
                        padding:var(--space-2) var(--space-3);margin-bottom:var(--space-1);
                        background:var(--c-surface);border-radius:var(--radius-md);
                        border-left:3px solid ${ampel.color === 'red' ? '#ef4444' : ampel.color === 'yellow' ? '#f59e0b' : '#22c55e'}">
              <span style="font-size:1.2rem">${ICONS[e._typ] || '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#clipboard-text"></use></svg>'}</span>
              <div style="flex:1;min-width:0">
                <div style="font-size:var(--text-sm);font-weight:var(--weight-medium);
                            white-space:nowrap;overflow:hidden;text-overflow:ellipsis">
                  ${_esc(e.bezeichnung)}
                </div>
                <div style="font-size:var(--text-xs);color:var(--c-text-muted)">
                  ${ageLabel} · ${dateStr}
                </div>
              </div>
              <button class="btn btn-sm ${e._tage < 0 ? 'btn-primary' : 'btn-secondary'}"
                      data-action="reminder-erledigt"
                      data-entry-id="${e.id}" data-entry-typ="${e._typ}"
                      style="flex-shrink:0;white-space:nowrap">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#check"></use></svg> Erledigt
              </button>
            </div>`;
        }).join('')}
      </div>
    `;

    el.querySelectorAll('[data-action="reminder-erledigt"]').forEach(btn => {
      btn.addEventListener('click', () => {
        const id  = parseInt(btn.dataset.entryId);
        const typ = btn.dataset.entryTyp;
        const entry = (_data[typ] || []).find(e => e.id === id);
        if (!entry) return;
        // Neues Formular ohne id → Neu-Eintrag, vorausgefüllt
        const today = new Date().toISOString().slice(0, 10);
        let naechstes = '';
        if (entry.intervall_tage) {
          const next = new Date();
          next.setDate(next.getDate() + entry.intervall_tage);
          naechstes = next.toISOString().slice(0, 10);
        }
        _showForm({
          bezeichnung:   entry.bezeichnung,
          datum:         today,
          naechstes,
          intervall_tage: entry.intervall_tage,
          tierarzt_id:   entry.tierarzt_id,
          tierarzt_name: entry.tierarzt_name,
          charge_nr:     entry.charge_nr,
        }, typ);
      });
    });
  }

  function _updateHealthBadge(count) {
    ['[data-page="health"] .nav-item-icon',
     '[data-page="health"] .sidebar-item-icon'].forEach(sel => {
      document.querySelectorAll(sel).forEach(el => {
        let badge = el.querySelector('.nav-badge');
        if (count > 0) {
          if (!badge) {
            badge = document.createElement('span');
            badge.className = 'nav-badge';
            el.appendChild(badge);
          }
          badge.textContent = count > 9 ? '9+' : count;
        } else if (badge) {
          badge.remove();
        }
      });
    });
  }

  function _renderTabBar() {
    const tabsEl = _container.querySelector('#by-tabs');
    tabsEl.innerHTML = _getTabs().map(t => `
      <button class="by-tab${t.key === _activeTab ? ' active' : ''}"
              data-tab="${t.key}">
        ${t.icon} ${t.label}
      </button>
    `).join('');
    const count = tabsEl.querySelectorAll('.by-tab').length;
    tabsEl.style.setProperty('--health-tab-cols', Math.ceil(count / 2));
    tabsEl.querySelectorAll('.by-tab').forEach(btn => {
      btn.addEventListener('click', () => {
        _activeTab = btn.dataset.tab;
        tabsEl.querySelectorAll('.by-tab').forEach(b => b.classList.remove('active'));
        btn.classList.add('active');
        _renderTab();
      });
    });
  }

  // ----------------------------------------------------------
  // DATEN LADEN
  // ----------------------------------------------------------
  async function _loadAll() {
    const dogId = _appState.activeDog.id;
    try {
      const all = await API.health.list(dogId);
      _data = {};
      _getTabs().forEach(t => { _data[t.key] = []; });
      _data['laeufigkeit'] = _data['laeufigkeit'] || [];
      all.forEach(e => {
        if (_data[e.typ] !== undefined) _data[e.typ].push(e);
      });
    } catch (err) {
      UI.toast.error('Gesundheitsdaten konnten nicht geladen werden.');
    }
    try {
      _praxen = await API.tieraerzte.list();
    } catch (err) {
      // silent fail
    }
    try {
      _data['gewicht_chart'] = await API.health.gewichtVerlauf(dogId);
    } catch (err) {
      _data['gewicht_chart'] = [];
    }
    try {
      _favoritVet = await API.tieraerzte.myFavorite();
    } catch (err) {
      _favoritVet = null;
    }
    try {
      _healthDocs = await API.healthDocs.list(dogId);
    } catch (err) {
      _healthDocs = [];
    }
  }

  // ----------------------------------------------------------
  // TAB-INHALT RENDERN
  // ----------------------------------------------------------
  function _renderTab() {
    const content = _container.querySelector('#by-tab-content');
    if (!content) return;

    const entries = _data[_activeTab] || [];

    switch (_activeTab) {
      case 'impfung':      content.innerHTML = _renderImpfungen(entries);    break;
      case 'tierarzt':     content.innerHTML = _renderTierarzt(entries);     break;
      case 'gewicht':      content.innerHTML = _renderGewicht(entries);      break;
      case 'laeufigkeit':  content.innerHTML = _renderLaeufigkeit(entries);  break;
      case 'medikament':   content.innerHTML = _renderMedikamente(entries);  break;
      case 'allergie':     content.innerHTML = _renderAllergien(entries);    break;
      case 'dokument':     content.innerHTML = _renderDokumente(entries);    break;
      case 'praxen':       content.innerHTML = _renderPraxen();              break;
    }

    _bindTabEvents(content);
  }

  // ----------------------------------------------------------
  // EMPTY-STATE HELPER
  // ----------------------------------------------------------
  function _emptyState(icon, title, text, cta = '') {
    return `<div class="empty-state">
      <svg class="ph-icon empty-state-icon" aria-hidden="true">
        <use href="/icons/phosphor.svg#${icon}"></use>
      </svg>
      <div class="empty-state-title">${title}</div>
      ${text ? `<p class="empty-state-text">${text}</p>` : ''}
      ${cta ? `<div class="empty-state-cta">${cta}</div>` : ''}
    </div>`;
  }

  // ----------------------------------------------------------
  // IMPFUNGEN — mit Ampel-Status
  // ----------------------------------------------------------
  function _renderImpfungen(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Impfung eintragen</button>`;
    const helpIcon = UI.help('Trage Impfdatum und nächsten Termin ein — wir erinnern dich rechtzeitig.');

    if (!entries.length) return _emptyState(
      'syringe',
      'Noch keine Impfungen',
      `Trage alle Impfungen ein, um nichts zu verpassen. ${helpIcon}`,
      addBtn
    );

    const items = entries.map(e => {
      const ampel  = _impfAmpel(e.naechstes);
      const praxis = _praxen.find(p => p.id === e.tierarzt_id);
      const vetName = praxis?.name || e.tierarzt_name || '';
      return `
        <div class="health-card" data-id="${e.id}" data-action="open-entry">
          <div class="health-card-ampel ampel-${ampel.color}" title="${ampel.label}"></div>
          <div class="health-card-body">
            <div class="health-card-title">${_esc(e.bezeichnung)}</div>
            <div class="health-card-meta">
              ${UI.time.format(e.datum + 'T00:00:00')}
              ${e.charge_nr ? ` · Ch.-Nr: ${_esc(e.charge_nr)}` : ''}
            </div>
            ${vetName ? `<div style="font-size:var(--text-sm);color:var(--c-text-secondary);margin-top:var(--space-1)"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ${_esc(vetName)}</div>` : ''}
            ${e.naechstes ? `<div class="health-card-next ampel-text-${ampel.color}">
              Nächste Impfung: ${UI.time.format(e.naechstes + 'T00:00:00')} ${ampel.icon}
            </div>` : ''}
            ${e.notiz ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
            <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                    data-action="open-note" data-entry-id="${e.id}"
                    data-label="${_esc(e.bezeichnung)}"
                    onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
          </div>
        </div>
      `;
    }).join('');

    return `<div class="health-list">${items}</div>
            <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>`;
  }

  function _impfAmpel(naechstesStr) {
    if (!naechstesStr) return { color: 'grey', label: 'Kein Folgedatum', icon: '' };
    const diff = (new Date(naechstesStr) - Date.now()) / 86400000; // Tage
    if (diff < 0)  return { color: 'red',    label: 'Überfällig!',        icon: '🔴' };
    if (diff < 60) return { color: 'yellow', label: 'Bald fällig',        icon: '🟡' };
    return             { color: 'green',  label: 'Aktuell',             icon: '🟢' };
  }

  // ----------------------------------------------------------
  // TIERARZTBESUCHE
  // ----------------------------------------------------------
  function _renderTierarzt(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Besuch eintragen</button>`;
    if (!entries.length) return UI.emptyState({
      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>', title: 'Noch keine Tierarztbesuche', text: 'Halte alle Tierarztbesuche fest.', action: addBtn
    });

    const items = entries.map(e => {
      const praxis = _praxen.find(p => p.id === e.tierarzt_id);
      const praxisName = praxis?.name || e.tierarzt_name || '';
      const praxisOrt  = praxis ? [praxis.plz, praxis.ort].filter(Boolean).join(' ') : '';
      return `
        <div class="health-card" data-id="${e.id}" data-action="open-entry">
          <div class="health-card-body">
            <div class="health-card-title">${_esc(e.bezeichnung)}</div>
            <div class="health-card-meta">
              ${UI.time.format(e.datum + 'T00:00:00')}
              ${e.kosten != null ? ` · ${Number(e.kosten).toFixed(2)} €` : ''}
            </div>
            ${praxisName ? `
              <div style="display:flex;align-items:center;gap:var(--space-1);
                          margin-top:var(--space-1);font-size:var(--text-sm);color:var(--c-text-secondary)">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ${_esc(praxisName)}${praxisOrt ? ` · ${_esc(praxisOrt)}` : ''}
              </div>` : ''}
            ${e.diagnose ? `<div class="health-card-note"><b>Diagnose:</b> ${_esc(e.diagnose)}</div>` : ''}
            ${e.notiz    ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
            <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                    data-action="open-note" data-entry-id="${e.id}"
                    data-label="${_esc(e.bezeichnung)}"
                    onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
          </div>
        </div>
      `;
    }).join('');

    return `<div class="health-list">${items}</div>
            <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>`;
  }

  // ----------------------------------------------------------
  // GEWICHT — Großanzeige + SVG-Diagramm
  // ----------------------------------------------------------
  function _renderGewicht(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Gewicht eintragen</button>`;

    if (!entries.length) return UI.emptyState({
      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#scales"></use></svg>', title: 'Noch keine Gewichtseinträge', action: addBtn
    });

    const sorted = [...entries].sort((a, b) => a.datum.localeCompare(b.datum));
    const latest = sorted[sorted.length - 1];
    const prev   = sorted.length >= 2 ? sorted[sorted.length - 2] : null;
    const delta  = prev ? (parseFloat(latest.wert) - parseFloat(prev.wert)) : null;

    const deltaHtml = delta !== null ? (() => {
      const sign  = delta > 0 ? '+' : '';
      const color = delta > 0 ? 'var(--c-warning)' : delta < 0 ? 'var(--c-success)' : 'var(--c-text-muted)';
      const arrow = delta > 0 ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#trend-up"></use></svg>' : delta < 0 ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#trend-down"></use></svg>' : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#arrow-right"></use></svg>';
      return `<div style="font-size:var(--text-sm);color:${color};margin-top:var(--space-1)">
        ${arrow} ${sign}${delta.toFixed(1)} kg seit letzter Messung
      </div>`;
    })() : '';

    const chartEntries = _data['gewicht_chart'] || [];
    const chart = _renderWeightChart(chartEntries);

    const items = sorted.slice().reverse().map(e => `
      <div class="health-card" data-id="${e.id}" data-action="open-entry"
           style="padding:var(--space-3) var(--space-4)">
        <div style="display:flex;justify-content:space-between;align-items:center;width:100%">
          <span style="font-size:var(--text-sm);color:var(--c-text-secondary)">
            ${UI.time.format(e.datum + 'T00:00:00')}
          </span>
          <span style="font-weight:var(--weight-bold);font-size:var(--text-lg)">
            ${e.wert} <span style="font-size:var(--text-sm);color:var(--c-text-secondary)">${e.einheit || 'kg'}</span>
          </span>
        </div>
        ${e.notiz ? `<div class="health-card-note" style="padding-top:var(--space-1)">${_esc(e.notiz)}</div>` : ''}
        <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-1);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                data-action="open-note" data-entry-id="${e.id}"
                data-label="Gewicht ${_esc(e.datum)}"
                onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
      </div>
    `).join('');

    return `
      <div style="text-align:center;padding:var(--space-5) var(--space-4) var(--space-2)">
        <div style="font-size:3rem;font-weight:var(--weight-bold);color:var(--c-text);line-height:1">
          ${latest.wert}
          <span style="font-size:1.1rem;font-weight:var(--weight-normal);color:var(--c-text-secondary)">kg</span>
        </div>
        ${deltaHtml}
      </div>
      ${chart ? `<div class="health-chart-wrap">
        <div style="font-size:var(--text-xs);color:var(--c-text-secondary);
                    padding:var(--space-2) var(--space-3) 0;display:flex;align-items:center;gap:var(--space-1)">
          Gewichtsverlauf ${UI.help('Wird aus allen Einträgen mit Gewichtsangabe berechnet.')}
        </div>
        ${chart}
      </div>` : ''}
      <div class="health-list" style="margin-top:var(--space-2)">${items}</div>
      <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>
    `;
  }

  function _weightChart(entries) {
    const W = 340, H = 160, PX = 36, PY = 16, PB = 28;
    const vals   = entries.map(e => parseFloat(e.wert));
    const minV   = Math.min(...vals);
    const maxV   = Math.max(...vals);
    const range  = maxV - minV || 1;
    const innerW = W - PX * 2;
    const innerH = H - PY - PB;

    const toX = i => PX + (i / (entries.length - 1)) * innerW;
    const toY = v => PY + (1 - (v - minV) / range) * innerH;
    const pts  = entries.map((e, i) => [toX(i), toY(parseFloat(e.wert))]);

    // Smooth bezier path
    const linePath = pts.reduce((acc, [x, y], i) => {
      if (i === 0) return `M ${x},${y}`;
      const [px, py] = pts[i - 1];
      const cpx = (px + x) / 2;
      return `${acc} C ${cpx},${py} ${cpx},${y} ${x},${y}`;
    }, '');

    const fillPath = `${linePath} L ${pts[pts.length - 1][0]},${H - PB} L ${pts[0][0]},${H - PB} Z`;

    // Grid lines
    const gridLines = [0, 0.5, 1].map(frac => {
      const v = maxV - frac * range;
      const y = toY(v);
      return `
        <line x1="${PX}" y1="${y}" x2="${W - PX}" y2="${y}"
              stroke="var(--c-border-light)" stroke-width="1" stroke-dasharray="4,4"/>
        <text x="${PX - 5}" y="${y + 4}" font-size="9" fill="var(--c-text-muted)" text-anchor="end">
          ${v.toFixed(1)}
        </text>`;
    }).join('');

    // X-axis labels
    const xIdxs = entries.length <= 3
      ? entries.map((_, i) => i)
      : [0, Math.round((entries.length - 1) / 2), entries.length - 1];
    const xLabels = [...new Set(xIdxs)].map(i => {
      const [m, d] = entries[i].datum.slice(5).split('-');
      return `<text x="${toX(i)}" y="${H - 6}" font-size="9" fill="var(--c-text-muted)"
                    text-anchor="middle">${d}.${m}.</text>`;
    }).join('');

    // Dots
    const dots = pts.map(([x, y], i) => {
      const isLast = i === pts.length - 1;
      return `<circle cx="${x}" cy="${y}" r="${isLast ? 5 : 3.5}"
                fill="${isLast ? 'var(--c-primary)' : 'var(--c-surface)'}"
                stroke="var(--c-primary)" stroke-width="2"/>`;
    }).join('');

    const gId = `wg${Math.random().toString(36).slice(2, 7)}`;
    return `
      <svg viewBox="0 0 ${W} ${H}" style="width:100%;display:block">
        <defs>
          <linearGradient id="${gId}" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%"   stop-color="var(--c-primary)" stop-opacity="0.22"/>
            <stop offset="100%" stop-color="var(--c-primary)" stop-opacity="0.02"/>
          </linearGradient>
        </defs>
        ${gridLines}
        <path d="${fillPath}" fill="url(#${gId})"/>
        <path d="${linePath}" fill="none" stroke="var(--c-primary)"
              stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
        ${dots}
        ${xLabels}
      </svg>
    `;
  }

  // ----------------------------------------------------------
  // GEWICHTSVERLAUF-CHART (dedizierter Endpoint /health/gewicht)
  // ----------------------------------------------------------
  function _renderWeightChart(entries) {
    // entries: [{datum, gewicht}, ...]
    if (!entries || entries.length < 2) {
      return '<p class="health-chart-empty">Mindestens 2 Gewichtseinträge für den Verlauf nötig.</p>';
    }

    const W = 300, H = 120, PAD = 24;
    const weights = entries.map(e => e.gewicht);
    const min = Math.min(...weights), max = Math.max(...weights);
    const range = max - min || 1;

    // x: gleichmäßig verteilt, y: normalisiert
    const pts = entries.map((e, i) => {
      const x = PAD + (i / (entries.length - 1)) * (W - 2 * PAD);
      const y = H - PAD - ((e.gewicht - min) / range) * (H - 2 * PAD);
      return { x, y, ...e };
    });

    const polyline = pts.map(p => `${p.x},${p.y}`).join(' ');
    const area = `${pts[0].x},${H - PAD} ` + polyline + ` ${pts[pts.length - 1].x},${H - PAD}`;

    // Datenpunkte + Tooltips als title-Elemente
    const circles = pts.map(p =>
      `<circle cx="${p.x}" cy="${p.y}" r="4" fill="var(--c-primary)">
         <title>${p.datum}: ${p.gewicht} kg</title>
       </circle>`
    ).join('');

    const gId = `wg${Math.random().toString(36).slice(2, 7)}`;
    return `
      <div class="health-chart-wrap">
        <div class="health-chart-title">Gewichtsverlauf</div>
        <svg viewBox="0 0 ${W} ${H}" class="health-chart-svg" aria-label="Gewichtsverlauf">
          <defs>
            <linearGradient id="${gId}" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stop-color="var(--c-primary)" stop-opacity=".25"/>
              <stop offset="100%" stop-color="var(--c-primary)" stop-opacity="0"/>
            </linearGradient>
          </defs>
          <polygon points="${area}" fill="url(#${gId})"/>
          <polyline points="${polyline}" fill="none" stroke="var(--c-primary)" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"/>
          ${circles}
          <text x="${PAD - 2}" y="${H - PAD + 4}" font-size="9" fill="var(--c-text-secondary)" text-anchor="middle">${min}</text>
          <text x="${PAD - 2}" y="${PAD + 4}" font-size="9" fill="var(--c-text-secondary)" text-anchor="middle">${max}</text>
        </svg>
        <div class="health-chart-labels">
          <span>${entries[0].datum}</span>
          <span>${entries[entries.length - 1].datum}</span>
        </div>
      </div>
    `;
  }

  // ----------------------------------------------------------
  // LÄUFIGKEIT — Timeline + Vorhersage
  // ----------------------------------------------------------
  function _renderLaeufigkeit(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">${UI.icon('plus')} Läufigkeit eintragen</button>`;

    const sorted = [...entries].sort((a, b) => b.datum.localeCompare(a.datum)); // neueste zuerst

    // Durchschnittlicher Abstand berechnen
    let avgInterval = null;
    if (sorted.length >= 2) {
      const asc = [...sorted].reverse();
      const diffs = [];
      for (let i = 1; i < asc.length; i++) {
        diffs.push(Math.round((new Date(asc[i].datum) - new Date(asc[i-1].datum)) / 86400000));
      }
      avgInterval = Math.round(diffs.reduce((a, b) => a + b, 0) / diffs.length);
    }

    // Nächste vorhergesagte Läufigkeit
    const last = sorted[0];
    let nextPrediction = null;
    if (last?.naechstes) {
      nextPrediction = last.naechstes;
    } else if (last?.datum && (last?.intervall_tage || avgInterval)) {
      const iv = last.intervall_tage || avgInterval;
      const d = new Date(last.datum);
      d.setDate(d.getDate() + iv);
      nextPrediction = d.toISOString().slice(0, 10);
    }

    // Banner für nächste Läufigkeit
    let banner = '';
    if (nextPrediction) {
      const ampel = _impfAmpel(nextPrediction);
      const tage  = Math.ceil((new Date(nextPrediction) - Date.now()) / 86400000);
      const label = tage < 0  ? `Überfällig seit ${Math.abs(tage)} Tagen`
                  : tage === 0 ? 'Könnte heute beginnen'
                  : tage <= 14 ? `In ${tage} Tagen`
                  : UI.time.format(nextPrediction + 'T00:00:00');
      banner = `
        <div style="margin:var(--space-4) var(--space-4) 0;padding:var(--space-3) var(--space-4);
                    background:var(--c-surface);border-radius:var(--radius-lg);
                    border-left:4px solid ${ampel.color === 'red' ? 'var(--c-danger)' : ampel.color === 'yellow' ? 'var(--c-warning)' : 'var(--c-primary)'};
                    display:flex;align-items:center;gap:var(--space-3)">
          <span style="font-size:1.5rem">${UI.icon('gender-female')}</span>
          <div>
            <div style="font-size:var(--text-sm);font-weight:var(--weight-semibold)">Nächste Läufigkeit erwartet</div>
            <div style="font-size:var(--text-sm);color:var(--c-text-secondary)">${label}
              ${avgInterval ? ` · Ø ${avgInterval} Tage Abstand` : ''}
            </div>
          </div>
        </div>`;
    }

    if (!sorted.length) return `
      ${UI.emptyState({
        icon: UI.icon('gender-female'),
        title: 'Noch keine Läufigkeit eingetragen',
        text: 'Trage Läufigkeiten ein, um den Zyklus zu verfolgen.',
        action: addBtn,
      })}`;

    const items = sorted.map((e, i) => {
      const prev = sorted[i + 1];
      const interval = prev
        ? Math.round((new Date(e.datum) - new Date(prev.datum)) / 86400000)
        : null;
      return `
        <div class="health-card" data-id="${e.id}" data-action="open-entry">
          <div style="width:36px;height:36px;border-radius:50%;background:var(--c-primary);
                      display:flex;align-items:center;justify-content:center;
                      flex-shrink:0;color:var(--c-text-inverse)">
            ${UI.icon('gender-female')}
          </div>
          <div class="health-card-body">
            <div class="health-card-title">Läufigkeit · ${UI.time.format(e.datum + 'T00:00:00')}</div>
            <div class="health-card-meta">
              ${e.wert ? `Dauer: ${e.wert} Tage` : 'Dauer nicht angegeben'}
              ${interval ? ` · Abstand zur Vorherigen: ${interval} Tage` : ''}
            </div>
            ${e.notiz ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
            <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                    data-action="open-note" data-entry-id="${e.id}"
                    data-label="Läufigkeit ${_esc(e.datum)}"
                    onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
          </div>
        </div>`;
    }).join('');

    return `
      ${banner}
      <div class="health-list" style="margin-top:var(--space-4)">${items}</div>
      <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>`;
  }

  // ----------------------------------------------------------
  // MEDIKAMENTE
  // ----------------------------------------------------------
  function _renderMedikamente(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Medikament eintragen</button>`;
    if (!entries.length) return UI.emptyState({
      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>', title: 'Noch keine Medikamente', action: addBtn
    });

    const aktive   = entries.filter(e => e.aktiv);
    const inaktive = entries.filter(e => !e.aktiv);

    const renderGroup = (items, label) => items.length ? `
      <div class="by-section-label">${label}</div>
      ${items.map(e => `
        <div class="health-card${e.aktiv ? '' : ' health-card--inactive'}" data-id="${e.id}" data-action="open-entry">
          <div class="health-card-body">
            <div class="health-card-title">${_esc(e.bezeichnung)}</div>
            <div class="health-card-meta">
              ${e.dosierung ? _esc(e.dosierung) : ''}
              ${e.haeufigkeit ? ` · ${_esc(e.haeufigkeit)}` : ''}
              ${e.bis_datum ? ` · bis ${UI.time.format(e.bis_datum + 'T00:00:00')}` : ''}
            </div>
            ${e.notiz ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
            <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                    data-action="open-note" data-entry-id="${e.id}"
                    data-label="${_esc(e.bezeichnung)}"
                    onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
          </div>
        </div>
      `).join('')}
    ` : '';

    return `
      <div class="health-list">
        ${renderGroup(aktive, '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> Aktuelle Medikamente')}
        ${renderGroup(inaktive, 'Vergangene Medikamente')}
      </div>
      <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>
    `;
  }

  // ----------------------------------------------------------
  // ALLERGIEN
  // ----------------------------------------------------------
  function _renderAllergien(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Allergie eintragen</button>`;
    if (!entries.length) return UI.emptyState({
      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#leaf"></use></svg>', title: 'Noch keine Allergien eingetragen', action: addBtn
    });

    const SCHWEREGRAD = { leicht: '🟡', mittel: '🟠', schwer: '🔴' };

    const items = entries.map(e => `
      <div class="health-card" data-id="${e.id}" data-action="open-entry">
        <div class="health-card-body">
          <div class="health-card-title">
            ${e.schweregrad ? SCHWEREGRAD[e.schweregrad] || '' : ''} ${_esc(e.bezeichnung)}
          </div>
          <div class="health-card-meta">
            Erstmals: ${UI.time.format(e.datum + 'T00:00:00')}
            ${e.schweregrad ? ` · Schweregrad: ${_esc(e.schweregrad)}` : ''}
          </div>
          ${e.reaktion ? `<div class="health-card-note"><b>Reaktion:</b> ${_esc(e.reaktion)}</div>` : ''}
          ${e.notiz    ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
          <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                  data-action="open-note" data-entry-id="${e.id}"
                  data-label="${_esc(e.bezeichnung)}"
                  onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
        </div>
      </div>
    `).join('');

    return `<div class="health-list">${items}</div>
            <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>`;
  }

  // ----------------------------------------------------------
  // DOKUMENTE
  // ----------------------------------------------------------
  function _renderDokumente(entries) {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-entry">+ Dokument hinzufügen</button>`;
    if (!entries.length) return UI.emptyState({
      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg>', title: 'Noch keine Dokumente', text: 'Lade Impfpässe, Befunde und mehr hoch.', action: addBtn
    });

    const items = entries.map(e => {
      // media_items bevorzugen, legacy datei_url als Fallback
      const mediaList = e.media_items?.length
        ? e.media_items
        : (e.datei_url ? [{ id: null, url: e.datei_url, media_type: e.datei_typ || 'image' }] : []);
      const firstImg = mediaList.find(m => m.media_type !== 'pdf');
      const hasPdf   = mediaList.some(m => m.media_type === 'pdf');
      const count    = mediaList.length;

      return `
        <div class="health-card" data-id="${e.id}" data-action="open-entry">
          ${firstImg
            ? `<img src="${_esc(firstImg.url)}" class="health-doc-thumb" alt="Vorschau"
                    style="width:64px;height:64px;object-fit:cover;border-radius:var(--radius-md);flex-shrink:0">`
            : `<div style="width:48px;height:48px;display:flex;align-items:center;justify-content:center;
                           font-size:2rem;flex-shrink:0"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg></div>`}
          <div class="health-card-body">
            <div class="health-card-title">${_esc(e.bezeichnung)}</div>
            <div class="health-card-meta">
              ${UI.time.format(e.datum + 'T00:00:00')}
              ${count > 1 ? ` · ${count} Dateien` : ''}
            </div>
            ${e.notiz ? `<div class="health-card-note">${_esc(e.notiz)}</div>` : ''}
            <button class="btn btn-ghost btn-xs" style="margin-top:var(--space-2);font-size:var(--text-xs);color:var(--c-text-muted);padding:2px 6px"
                    data-action="open-note" data-entry-id="${e.id}"
                    data-label="${_esc(e.bezeichnung)}"
                    onclick="event.stopPropagation()"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</button>
            ${count
              ? `<div style="display:flex;gap:var(--space-2);margin-top:var(--space-2);align-items:center;flex-wrap:wrap">
                   ${mediaList.slice(0, 3).map(m => m.media_type === 'pdf'
                     ? `<a href="${_esc(m.url)}" target="_blank" rel="noopener"
                           class="btn btn-secondary btn-sm" style="display:inline-flex"
                           onclick="event.stopPropagation()">
                          <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg> PDF
                        </a>`
                     : `<a href="${_esc(m.url)}" target="_blank" rel="noopener"
                           class="btn btn-secondary btn-sm" style="display:inline-flex"
                           onclick="event.stopPropagation()">
                          <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#image"></use></svg> Bild
                        </a>`
                   ).join('')}
                 </div>`
              : `<span style="font-size:var(--text-xs);color:var(--c-text-muted)">Noch keine Datei hochgeladen</span>`}
          </div>
        </div>
      `;
    }).join('');

    return `<div class="health-list">${items}</div>
            <div style="text-align:center;padding:var(--space-4)">${addBtn}</div>
            ${_renderBefundeSection()}`;
  }

  // ----------------------------------------------------------
  // EVENTS BINDEN
  // ----------------------------------------------------------
  function _bindTabEvents(content) {
    content.querySelectorAll('[data-action="add-entry"]').forEach(btn => {
      btn.addEventListener('click', () => _showForm(null, _activeTab));
    });
    content.querySelectorAll('[data-action="open-entry"]').forEach(card => {
      const id = parseInt(card.dataset.id);
      const entry = (_data[_activeTab] || []).find(e => e.id === id);
      if (entry) card.addEventListener('click', () => _openDetail(entry));
    });
    content.querySelectorAll('[data-action="open-note"]').forEach(btn => {
      btn.addEventListener('click', e => {
        e.stopPropagation();
        const id    = parseInt(btn.dataset.entryId);
        const label = btn.dataset.label || '';
        _openNoteModal('health', id, label, null);
      });
    });
    // Praxis öffnen
    content.querySelectorAll('[data-action="open-praxis"]').forEach(el => {
      el.addEventListener('click', () => {
        const id = parseInt(el.dataset.praxisId);
        const p  = _praxen.find(x => x.id === id);
        if (p) _showPraxForm(p);
      });
    });
    // Dokument löschen
    content.querySelectorAll('[data-action="delete-dok"]').forEach(btn => {
      btn.addEventListener('click', async () => {
        const id    = parseInt(btn.dataset.id);
        const dogId = _appState.activeDog.id;
        const ok    = await UI.modal.confirm({
          title: 'Dokument löschen',
          text:  'Die Datei wird unwiderruflich gelöscht.',
          confirmText: 'Löschen',
          danger: true,
        });
        if (!ok) return;
        await UI.asyncButton(btn, async () => {
          await API.health.deleteDocument(dogId, id);
          const list = _data[_activeTab] || [];
          const entry = list.find(e => e.id === id);
          if (entry) { entry.datei_url = null; entry.datei_typ = null; }
          _renderTab();
          UI.toast.success('Dokument gelöscht.');
        });
      });
    });
    // Praxis hinzufügen
    content.querySelector('[data-action="add-praxis"]')
      ?.addEventListener('click', () => _showPraxForm(null));
    // Favorit-Toggle für Praxen
    content.querySelectorAll('[data-action="toggle-fav"]').forEach(btn => {
      btn.addEventListener('click', async (e) => {
        e.stopPropagation();
        const vetId = parseInt(btn.dataset.praxisId);
        await UI.asyncButton(btn, async () => {
          const res = await API.tieraerzte.toggleFavorite(vetId);
          if (res.is_favorite) {
            _favoritVet = _praxen.find(p => p.id === vetId) || null;
            UI.toast.success('Als Favorit-Tierarzt gespeichert.');
          } else {
            _favoritVet = null;
            UI.toast.success('Favorit entfernt.');
          }
          // is_favorite in _praxen aktualisieren
          _praxen = _praxen.map(p => ({ ...p, is_favorite: p.id === vetId ? res.is_favorite : false }));
          const elFav = _container.querySelector('#health-mein-tierarzt');
          if (elFav) _renderMeinTierarztKachel(elFav);
          _renderTab();
        });
      });
    });
    // Befunde & Dokumente
    if (_activeTab === 'dokument') {
      _bindBefundeEvents(content);
    }
  }

  // ----------------------------------------------------------
  // DETAIL-ANSICHT
  // ----------------------------------------------------------
  function _openDetail(entry) {
    const tabInfo = _getTabs().find(t => t.key === entry.typ) || BASE_TABS[0];
    const fields = _detailFields(entry);

    // Media-Items zusammenstellen (neue + legacy)
    const mediaItems = entry.media_items?.length
      ? entry.media_items
      : (entry.datei_url ? [{ id: null, url: entry.datei_url, media_type: entry.datei_typ || 'image' }] : []);

    const mediaHtml = mediaItems.length
      ? `<div class="health-media-gallery" style="margin-top:var(--space-4)">
          ${mediaItems.map(m => m.media_type === 'pdf'
            ? `<a href="${_esc(m.url)}" target="_blank" rel="noopener"
                  class="btn btn-secondary btn-sm health-media-gallery-pdf">
                 <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg> PDF öffnen
               </a>`
            : `<a href="${_esc(m.url)}" target="_blank" rel="noopener" class="health-media-gallery-img">
                 <img src="${_esc(m.url)}" alt="Bild" loading="lazy">
               </a>`
          ).join('')}
         </div>`
      : '';

    const body = `
      <div class="health-detail">
        ${fields}
        ${mediaHtml}
      </div>
      <button class="btn btn-secondary" style="width:100%;margin-top:var(--space-5)" id="health-detail-edit">Bearbeiten</button>
    `;

    const modalTitle = entry.typ === 'gewicht'
      ? `${tabInfo.icon} ${entry.wert} ${entry.einheit || 'kg'}`
      : entry.typ === 'laeufigkeit'
        ? `${tabInfo.icon} Läufigkeit ${UI.time.format(entry.datum + 'T00:00:00')}`
        : `${tabInfo.icon} ${_esc(entry.bezeichnung)}`;
    UI.modal.open({ title: modalTitle, body });

    document.getElementById('health-detail-edit')?.addEventListener('click', () => {
      UI.modal.close();
      _showForm(entry, entry.typ);
    });
  }

  function _detailFields(e) {
    const rows = [];
    if (e.datum)        rows.push(['Datum',      UI.time.format(e.datum + 'T00:00:00')]);
    if (e.typ === 'laeufigkeit' && e.wert) rows.push(['Dauer', `${e.wert} Tage`]);
    if (e.naechstes)    rows.push([e.typ === 'laeufigkeit' ? 'Nächste erwartet' : 'Nächstes', UI.time.format(e.naechstes + 'T00:00:00')]);
    if (e.typ === 'laeufigkeit' && e.deckdatum) rows.push(['Deckdatum', UI.time.format(e.deckdatum + 'T00:00:00')]);
    if (e.typ === 'laeufigkeit' && e.wurftermin) {
      const wurfDate = new Date(e.wurftermin + 'T00:00:00');
      const today = new Date(); today.setHours(0,0,0,0);
      const diffDays = Math.round((wurfDate - today) / 86400000);
      const zukunft = diffDays > 0 ? ` <span style="color:var(--c-primary);font-weight:600">in ${diffDays} Tagen</span>` : '';
      rows.push(['Wurftermin', UI.time.format(e.wurftermin + 'T00:00:00') + zukunft]);
    }
    if (e.tierarzt_id) {
      const praxis = _praxen.find(p => p.id === e.tierarzt_id);
      if (praxis) {
        const adresse = [praxis.strasse, [praxis.plz, praxis.ort].filter(Boolean).join(' ')].filter(Boolean).join(', ');
        const tel     = praxis.telefon ? ` · <a href="tel:${_esc(praxis.telefon)}">${_esc(praxis.telefon)}</a>` : '';
        const oh      = praxis.opening_hours ? `<br><small style="color:var(--c-text-secondary)">🕐 ${_esc(_fmtOeffnungszeiten(praxis.opening_hours))}</small>` : '';
        rows.push(['Praxis', `<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ${_esc(praxis.name)}${adresse ? `<br><small style="color:var(--c-text-secondary)">${_esc(adresse)}${tel}</small>` : tel}${oh}`]);
      }
    } else if (e.tierarzt_name) {
      rows.push(['Tierarzt',  _esc(e.tierarzt_name)]);
    }
    if (e.charge_nr)    rows.push(['Charge-Nr.', _esc(e.charge_nr)]);
    if (e.kosten != null) rows.push(['Kosten',   `${Number(e.kosten).toFixed(2)} €`]);
    if (e.diagnose)     rows.push(['Diagnose',   _esc(e.diagnose)]);
    if (e.wert)         rows.push(['Gewicht',    `${e.wert} ${e.einheit || 'kg'}`]);
    if (e.dosierung)    rows.push(['Dosierung',  _esc(e.dosierung)]);
    if (e.haeufigkeit)  rows.push(['Häufigkeit', _esc(e.haeufigkeit)]);
    if (e.bis_datum)    rows.push(['Bis',        UI.time.format(e.bis_datum + 'T00:00:00')]);
    if (e.schweregrad)  rows.push(['Schweregrad',_esc(e.schweregrad)]);
    if (e.reaktion)     rows.push(['Reaktion',   _esc(e.reaktion)]);
    if (e.notiz)        rows.push(['Notiz',      _esc(e.notiz)]);

    return `<dl class="health-detail-dl">${
      rows.map(([k, v]) => `<dt>${k}</dt><dd>${v}</dd>`).join('')
    }</dl>`;
  }

  // ----------------------------------------------------------
  // FORMULAR — Neu / Bearbeiten
  // ----------------------------------------------------------
  function _showForm(entry, typ) {
    const isEdit = !!(entry?.id);
    const today  = new Date().toISOString().slice(0, 10);
    const t      = typ || _activeTab;

    const commonFields = `
      ${t !== 'gewicht' && t !== 'laeufigkeit' ? `
        <div class="form-group">
          <label class="form-label">Bezeichnung *</label>
          <input class="form-control" type="text" name="bezeichnung"
                 value="${_esc(entry?.bezeichnung || '')}" required
                 placeholder="${_formPlaceholder(t)}">
        </div>` : ''}
      <div class="form-group">
        <label class="form-label">${t === 'laeufigkeit' ? 'Beginn der Läufigkeit *' : 'Start *'}</label>
        <input class="form-control" type="date" name="datum"
               value="${entry?.datum || today}" required>
      </div>
    `;

    const extraFields = _extraFormFields(entry, t);
    const notizField  = `
      <div class="form-group">
        <label class="form-label">Notiz</label>
        <textarea class="form-control" name="notiz" rows="3">${_esc(entry?.notiz || '')}</textarea>
      </div>
    `;

    // Multi-Upload-Bereich — zeige vorhandene media_items + neuen Upload
    const existingMedia = (entry?.media_items || []);
    const legacyFile = (!existingMedia.length && entry?.datei_url)
      ? [{ id: null, url: entry.datei_url, media_type: entry.datei_typ || 'image', _legacy: true }]
      : [];
    const allMedia = [...existingMedia, ...legacyFile];

    const mediaThumbsHtml = allMedia.map(m => {
      const isImg = m.media_type !== 'pdf';
      const removeBtn = m.id
        ? `<button type="button" class="health-media-remove" data-media-id="${m.id}"
                  title="Entfernen" aria-label="Datei entfernen">×</button>`
        : '';
      return `<div class="health-media-thumb" data-media-id="${m.id || ''}">
        ${isImg
          ? `<img src="${_esc(m.url)}" alt="Vorschau">`
          : `<div class="health-media-thumb-pdf"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg><span>PDF</span></div>`}
        ${removeBtn}
      </div>`;
    }).join('');

    const uploadField = `
      <div class="form-group" id="health-media-section">
        <label class="form-label">
          Dateien (Bilder / PDFs)
          ${UI.help('Befunde, Röntgenbilder, Laborwerte — mehrere Dateien möglich.')}
        </label>
        <div class="health-media-grid" id="health-media-grid">${mediaThumbsHtml}</div>
        <label class="btn btn-secondary btn-sm" style="cursor:pointer;display:inline-flex;align-items:center;gap:var(--space-2);margin-top:var(--space-2)">
          <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#plus"></use></svg> Datei hinzufügen
          <input type="file" name="datei_neu" accept="image/*,.pdf" multiple
                 style="position:absolute;opacity:0;width:1px;height:1px" id="health-file-input">
        </label>
        <div id="health-file-pending" style="margin-top:var(--space-2);display:flex;flex-wrap:wrap;gap:var(--space-2)"></div>
      </div>
    `;

    const body = `
      <form id="health-form" autocomplete="off">
        ${commonFields}
        ${extraFields}
        ${notizField}
        ${uploadField}
      </form>
    `;

    const footer = `
      <div style="display:flex;flex-direction:column;gap:var(--space-2);width:100%">
        <button type="submit" form="health-form" class="btn btn-primary" style="width:100%">${isEdit ? 'Speichern' : 'Erstellen'}</button>
        <div style="display:flex;gap:var(--space-2)">
          ${isEdit ? `<button type="button" class="btn btn-danger" id="health-form-delete">Löschen</button>` : ''}
          <button type="button" class="btn btn-secondary flex-1" id="health-form-cancel">Abbrechen</button>
        </div>
      </div>
    `;

    const tabInfo = _getTabs().find(tab => tab.key === t) || BASE_TABS[0];
    UI.modal.open({ title: `${tabInfo.icon} ${isEdit ? 'Bearbeiten' : tabInfo.label}`, body, footer });

    const form = document.getElementById('health-form');
    setTimeout(() => {
      form?.querySelector('[name="bezeichnung"]')?.focus();
      // "Praxis anlegen" Button im Formular
      form?.querySelector('[data-action="goto-praxen"]')?.addEventListener('click', () => {
        UI.modal.close();
        _activeTab = 'praxen';
        _renderTab();
      });
      // File-Input: Vorschau für ausstehende Uploads
      const fileInput  = document.getElementById('health-file-input');
      const pendingBox = document.getElementById('health-file-pending');
      if (fileInput && pendingBox) {
        fileInput.addEventListener('change', () => {
          pendingBox.innerHTML = '';
          Array.from(fileInput.files || []).forEach(f => {
            const isPdf = f.name.toLowerCase().endsWith('.pdf');
            const thumb = document.createElement('div');
            thumb.className = 'health-media-thumb health-media-thumb--pending';
            if (isPdf) {
              thumb.innerHTML = `<div class="health-media-thumb-pdf"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg><span>PDF</span></div><small>${_esc(f.name.slice(0, 18))}</small>`;
            } else {
              const img = document.createElement('img');
              img.src = URL.createObjectURL(f);
              thumb.appendChild(img);
            }
            pendingBox.appendChild(thumb);
          });
        });
      }
      // X-Buttons für vorhandene Media-Items
      document.querySelectorAll('#health-media-grid .health-media-remove').forEach(btn => {
        btn.addEventListener('click', async () => {
          const mediaId = parseInt(btn.dataset.mediaId);
          const dogId   = _appState.activeDog.id;
          if (!mediaId || !entry?.id) return;
          try {
            await API.health.deleteMedia(dogId, entry.id, mediaId);
            // Aus entry.media_items entfernen
            if (entry.media_items) entry.media_items = entry.media_items.filter(m => m.id !== mediaId);
            btn.closest('.health-media-thumb').remove();
            // Auch in _data aktualisieren
            const list = _data[t] || [];
            const idx = list.findIndex(x => x.id === entry.id);
            if (idx !== -1) list[idx].media_items = (list[idx].media_items || []).filter(m => m.id !== mediaId);
            UI.toast.success('Datei entfernt.');
          } catch (err) {
            UI.toast.error('Fehler beim Löschen.');
          }
        });
      });
    }, 150);

    document.getElementById('health-form-cancel')?.addEventListener('click', UI.modal.close);

    document.getElementById('health-form-delete')?.addEventListener('click', async () => {
      const ok = await UI.modal.confirm({
        title: 'Eintrag löschen?', message: 'Nicht rückgängig.', confirmText: 'Löschen', danger: true,
      });
      if (ok) {
        try {
          await API.health.delete(_appState.activeDog.id, entry.id);
          _data[t] = (_data[t] || []).filter(e => e.id !== entry.id);
          UI.modal.close();
          _renderTab();
          UI.toast.success('Eintrag gelöscht.');
        } catch (err) { UI.toast.error(err.message || 'Fehler.'); }
      }
    });

    form.addEventListener('submit', async e => {
      e.preventDefault();
      const btn = document.querySelector('[form="health-form"][type="submit"]') || form.querySelector('[type="submit"]');
      const fd  = UI.formData(form);

      await UI.asyncButton(btn, async () => {
        const payload = _buildPayload(fd, t);

        let saved;
        if (isEdit) {
          saved = await API.health.update(_appState.activeDog.id, entry.id, payload);
          const idx = (_data[t] || []).findIndex(x => x.id === entry.id);
          if (idx !== -1) _data[t][idx] = saved;
          UI.toast.success('Gespeichert.');
        } else {
          saved = await API.health.create(_appState.activeDog.id, { ...payload, typ: t });
          if (!_data[t]) _data[t] = [];
          _data[t].unshift(saved);
          UI.toast.success('Eintrag erstellt.');
        }

        // Gewicht im App-State aktualisieren (für neuen Eintrag UND bei Bearbeitung)
        if (t === 'gewicht' && saved.wert) {
          _appState.activeDog.gewicht_kg = saved.wert;
          _appState.dogs = _appState.dogs.map(d =>
            d.id === _appState.activeDog.id
              ? { ...d, gewicht_kg: saved.wert }
              : d
          );
        }

        // Multi-File-Upload
        const fileInput = form.querySelector('[name="datei_neu"]');
        const files = fileInput ? Array.from(fileInput.files || []) : [];
        if (files.length) {
          const dogId = _appState.activeDog.id;
          if (!saved.media_items) saved.media_items = [];
          for (const f of files) {
            try {
              const fd = new FormData();
              fd.append('file', f);
              const res = await API.health.uploadMedia(dogId, saved.id, fd);
              saved.media_items.push({ id: res.id, url: res.url, media_type: res.media_type });
              // Rückwärtskompatibilität: erste Datei auch als datei_url sichern
              if (!saved.datei_url) {
                saved.datei_url = res.url;
                saved.datei_typ = res.media_type;
              }
            } catch {
              UI.toast.warning(`Datei "${f.name}" konnte nicht hochgeladen werden.`);
            }
          }
        }

        UI.modal.close();
        _renderTab();
      });
    });
  }

  function _formPlaceholder(typ) {
    const ph = {
      impfung:      'z.B. Tollwut, DHPP, Leptospirose',
      tierarzt:     'z.B. Vorsorgeuntersuchung, Impfung',
      gewicht:      '',
      medikament:   'z.B. Frontline, Milbemax',
      allergie:     'z.B. Hühnchen, Gras, Hausstaub',
      dokument:     'z.B. Impfpass, Blutbild',
      laeufigkeit:  'Läufigkeit',
    };
    return ph[typ] || '';
  }

  // Intervall-Auswahl für wiederkehrende Einträge
  function _intervallField(entry) {
    const v = entry?.intervall_tage;
    const opts = [
      [null,  'Einmalig'],
      [30,    'Monatlich (30 Tage)'],
      [60,    'Alle 2 Monate'],
      [90,    'Vierteljährlich (90 Tage)'],
      [180,   'Halbjährlich'],
      [365,   'Jährlich'],
    ];
    return `
      <div class="form-group">
        <label class="form-label">Wiederholt sich</label>
        <select class="form-control" name="intervall_tage">
          ${opts.map(([days, label]) =>
            `<option value="${days ?? ''}" ${(v == days) ? 'selected' : ''}>${label}</option>`
          ).join('')}
        </select>
      </div>`;
  }

  // Wiederverwendbares Praxis-Dropdown für alle Formulare
  function _praxisSelectField(entry) {
    const aktivePraxen = _praxen.filter(p => p.aktiv);
    if (!aktivePraxen.length) return '';
    return `
      <div class="form-group">
        <label class="form-label">Behandelnde Praxis</label>
        <select class="form-control" name="tierarzt_id">
          <option value="">– optional –</option>
          ${aktivePraxen.map(p => `
            <option value="${p.id}" ${entry?.tierarzt_id === p.id ? 'selected' : ''}>
              ${_esc(p.name)}${p.ort ? ` · ${_esc(p.ort)}` : ''}
            </option>`).join('')}
        </select>
      </div>`;
  }

  function _extraFormFields(entry, typ) {
    switch (typ) {
      case 'impfung': return `
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--space-3)">
          <div class="form-group">
            <label class="form-label">Nächste Impfung</label>
            <input class="form-control" type="date" name="naechstes" value="${entry?.naechstes || ''}">
          </div>
          ${_intervallField(entry)}
        </div>
        ${_praxisSelectField(entry)}
        <div class="form-group">
          <label class="form-label">Chargen-Nr.</label>
          <input class="form-control" type="text" name="charge_nr" value="${_esc(entry?.charge_nr || '')}">
        </div>
      `;
      case 'entwurmung': return `
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--space-3)">
          <div class="form-group">
            <label class="form-label">Nächste Behandlung</label>
            <input class="form-control" type="date" name="naechstes" value="${entry?.naechstes || ''}">
          </div>
          ${_intervallField(entry)}
        </div>
        ${_praxisSelectField(entry)}
      `;
      case 'tierarzt': {
        const aktivePraxen = _praxen.filter(p => p.aktiv);
        const praxisField = aktivePraxen.length
          ? `<div class="form-group">
               <label class="form-label">Behandelnde Praxis</label>
               <select class="form-control" id="health-praxis-select" name="tierarzt_id">
                 <option value="">– Praxis wählen –</option>
                 ${aktivePraxen.map(p => `
                   <option value="${p.id}"
                           ${entry?.tierarzt_id === p.id ? 'selected' : ''}>
                     ${_esc(p.name)}${p.ort ? ` · ${_esc(p.ort)}` : ''}
                   </option>`).join('')}
               </select>
             </div>`
          : `<div class="form-group">
               <div style="padding:var(--space-3);background:var(--c-bg);border-radius:var(--radius-md);
                           font-size:var(--text-sm);color:var(--c-text-secondary)">
                 <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> Noch keine Praxis angelegt —
                 <button type="button" class="btn btn-ghost btn-sm" style="padding:0;font-size:inherit"
                         data-action="goto-praxen">Praxis im Tab Praxen anlegen</button>
               </div>
               <label class="form-label" style="margin-top:var(--space-2)">Tierarzt / Praxis (Freitext)</label>
               <input class="form-control" name="tierarzt_name"
                      value="${_esc(entry?.tierarzt_name || '')}" placeholder="Dr. Muster">
             </div>`;
        return `
          ${praxisField}
          <div class="form-group">
            <label class="form-label">Diagnose</label>
            <textarea class="form-control" name="diagnose" rows="2">${_esc(entry?.diagnose || '')}</textarea>
          </div>
          <div class="form-group">
            <label class="form-label">Kosten (€)</label>
            <input class="form-control" type="number" step="0.01" min="0" name="kosten"
                   value="${entry?.kosten ?? ''}">
          </div>
          <div class="form-group">
            <label class="form-label">Nächster Termin (optional)</label>
            <input class="form-control" type="date" name="naechstes" value="${entry?.naechstes || ''}">
          </div>
        `;
      }
      case 'gewicht': return `
        <div class="form-group">
          <label class="form-label">Gewicht (kg) *</label>
          <input class="form-control" type="number" step="0.01" min="0" name="wert"
                 value="${entry?.wert ?? ''}" required>
        </div>
      `;
      case 'medikament': return `
        <div class="form-group">
          <label class="form-label">Dosierung</label>
          <input class="form-control" type="text" name="dosierung"
                 value="${_esc(entry?.dosierung || '')}" placeholder="z.B. 1 Tablette">
        </div>
        <div class="form-group">
          <label class="form-label">Häufigkeit</label>
          <input class="form-control" type="text" name="haeufigkeit"
                 value="${_esc(entry?.haeufigkeit || '')}" placeholder="z.B. täglich, 2x wöchentlich">
        </div>
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
          <div class="form-group">
            <label class="form-label">Gabe bis (optional)</label>
            <input class="form-control" type="date" name="bis_datum" value="${entry?.bis_datum || ''}">
          </div>
          ${_intervallField(entry)}
        </div>
        ${_praxisSelectField(entry)}
        <div class="form-group">
          <label class="form-label" style="display:flex;align-items:center;gap:var(--space-2);cursor:pointer">
            <input type="checkbox" name="aktiv" ${entry?.aktiv !== 0 ? 'checked' : ''}>
            Aktuell aktiv
          </label>
        </div>
      `;
      case 'allergie': return `
        <div class="form-group">
          <label class="form-label">Schweregrad</label>
          <select class="form-control" name="schweregrad">
            <option value="">— unbekannt —</option>
            ${['leicht', 'mittel', 'schwer'].map(s =>
              `<option value="${s}" ${entry?.schweregrad === s ? 'selected' : ''}>${s}</option>`
            ).join('')}
          </select>
        </div>
        <div class="form-group">
          <label class="form-label">Reaktion / Symptome</label>
          <textarea class="form-control" name="reaktion" rows="2">${_esc(entry?.reaktion || '')}</textarea>
        </div>
      `;
      case 'laeufigkeit': {
        const prevCycles = (_data['laeufigkeit'] || []).filter(e => e !== entry && e?.datum);
        const sorted = [...prevCycles].sort((a, b) => a.datum.localeCompare(b.datum));
        const lastCycle = sorted[sorted.length - 1];

        // Abstand zur letzten Läufigkeit (in Tagen)
        let daysSinceLast = null;
        if (lastCycle) {
          daysSinceLast = Math.round((new Date() - new Date(lastCycle.datum)) / 86400000);
        }

        // Durchschnittlicher Zyklus aus ≥2 Einträgen, sonst gemessener Abstand
        let avgInterval = 0;
        if (sorted.length >= 2) {
          const intervals = [];
          for (let i = 1; i < sorted.length; i++) {
            intervals.push(Math.round((new Date(sorted[i].datum) - new Date(sorted[i-1].datum)) / 86400000));
          }
          avgInterval = Math.round(intervals.reduce((a, b) => a + b, 0) / intervals.length);
        } else if (daysSinceLast !== null) {
          avgInterval = daysSinceLast; // erster gemessener Abstand als Vorschlag
        }
        const defaultInterval = avgInterval || (entry?.intervall_tage) || 180;

        const lastInfo = lastCycle ? `
          <div style="font-size:var(--text-xs);color:var(--c-text-secondary);
                      background:var(--c-surface-2);border-radius:var(--radius-md);
                      padding:var(--space-2) var(--space-3);margin-bottom:var(--space-3)">
            Letzte Läufigkeit: <strong>${UI.time.format(lastCycle.datum + 'T00:00:00')}</strong>
            — vor <strong>${daysSinceLast} Tagen</strong>
          </div>` : '';
        return `
          ${lastInfo}
          <div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
            <div class="form-group">
              <label class="form-label">Dauer (Tage)</label>
              <input class="form-control" type="number" min="1" max="60" name="wert"
                     value="${entry?.wert ?? ''}" placeholder="z.B. 21"
                     id="laeufi-dauer">
            </div>
            <div class="form-group">
              <label class="form-label">Zyklusabstand (Tage)</label>
              <input class="form-control" type="number" min="60" max="400" name="intervall_tage"
                     value="${entry?.intervall_tage || defaultInterval}"
                     id="laeufi-interval">
            </div>
          </div>
          <div class="form-group">
            <label class="form-label">Nächste erwartet</label>
            <input class="form-control" type="date" name="naechstes"
                   value="${entry?.naechstes || ''}" id="laeufi-naechstes">
          </div>
          ${['breeder', 'admin'].includes(_appState.user?.rolle) ? `
          <div class="form-group" id="laeufi-zuechter-fields" style="margin-top:var(--space-4);
               padding-top:var(--space-4);border-top:1px solid var(--c-border)">
            <div style="font-size:var(--text-xs);font-weight:600;color:var(--c-text-secondary);
                        text-transform:uppercase;letter-spacing:0.05em;margin-bottom:var(--space-3)">
              Zucht (optional)
            </div>
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
              <div class="form-group">
                <label class="form-label">Deckdatum</label>
                <input class="form-control" type="date" name="deckdatum"
                       value="${entry?.deckdatum || ''}" id="laeufi-deckdatum">
              </div>
              <div class="form-group">
                <label class="form-label">Wurftermin (63 Tage nach Deckung)</label>
                <input class="form-control" type="date" name="wurftermin"
                       value="${entry?.wurftermin || ''}" id="laeufi-wurftermin" readonly
                       style="background:var(--c-surface-2)">
              </div>
            </div>
          </div>` : ''}
          <script>
            (function() {
              const datum = document.querySelector('[name="datum"]');
              const interval = document.getElementById('laeufi-interval');
              const naechstes = document.getElementById('laeufi-naechstes');
              function updateNext() {
                const d = datum?.value;
                const iv = parseInt(interval?.value) || 0;
                if (d && iv) {
                  const next = new Date(d);
                  next.setDate(next.getDate() + iv);
                  naechstes.value = next.toISOString().slice(0, 10);
                }
              }
              datum?.addEventListener('change', updateNext);
              interval?.addEventListener('change', updateNext);
              if (!naechstes?.value) updateNext();

              const deckdatum = document.getElementById('laeufi-deckdatum');
              const wurftermin = document.getElementById('laeufi-wurftermin');
              deckdatum?.addEventListener('change', e => {
                const deckDate = new Date(e.target.value);
                if (!isNaN(deckDate)) {
                  deckDate.setDate(deckDate.getDate() + 63);
                  wurftermin.value = deckDate.toISOString().split('T')[0];
                }
              });
            })();
          </script>
        `;
      }
      default: return '';
    }
  }

  function _buildPayload(fd, typ) {
    const p = {
      bezeichnung:   fd.bezeichnung || null,
      datum:         fd.datum || null,
      notiz:         fd.notiz || null,
      naechstes:     fd.naechstes || null,
      tierarzt_name: fd.tierarzt_name || null,
      charge_nr:     fd.charge_nr || null,
      diagnose:      fd.diagnose || null,
      dosierung:     fd.dosierung || null,
      haeufigkeit:   fd.haeufigkeit || null,
      bis_datum:     fd.bis_datum || null,
      schweregrad:   fd.schweregrad || null,
      reaktion:      fd.reaktion || null,
    };
    if (fd.wert) {
      p.wert = parseFloat(fd.wert.toString().replace(',', '.'));
      if (typ === 'gewicht') p.bezeichnung = `${p.wert} kg`;
    }
    if (typ === 'laeufigkeit') {
      p.bezeichnung = p.bezeichnung || 'Läufigkeit';
      p.deckdatum  = fd.deckdatum  || null;
      p.wurftermin = fd.wurftermin || null;
    }
    if (fd.kosten)      p.kosten      = parseFloat(fd.kosten.toString().replace(',', '.'));
    if (fd.tierarzt_id) {
      p.tierarzt_id = parseInt(fd.tierarzt_id);
      // Praxisname auch als tierarzt_name sichern (bleibt lesbar wenn Praxis inaktiv/gelöscht)
      const praxis = _praxen.find(x => x.id === p.tierarzt_id);
      if (praxis) p.tierarzt_name = praxis.name;
    }
    if (typ === 'medikament') {
      p.aktiv = 'aktiv' in fd ? 1 : 0;
    }
    p.intervall_tage = fd.intervall_tage ? parseInt(fd.intervall_tage) : null;
    // Gewicht-Einheit
    p.einheit = fd.einheit || 'kg';
    return p;
  }

  // ----------------------------------------------------------
  // PRAXEN — Liste
  // ----------------------------------------------------------
  function _renderPraxen() {
    const addBtn = `<button class="btn btn-primary btn-sm" data-action="add-praxis">+ Praxis hinzufügen</button>`;

    const aktive   = _praxen.filter(p => p.aktiv);
    const inaktive = _praxen.filter(p => !p.aktiv);

    if (!_praxen.length) return UI.emptyState({
      icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>', title: 'Noch keine Praxis eingetragen',
      text: 'Trage deine Tierarztpraxis ein für schnellen Zugriff.',
      action: addBtn
    });

    const renderCard = p => {
      const isFav = _favoritVet?.id === p.id || p.is_favorite;
      return `
      <div class="health-card praxis-card${!p.aktiv ? ' health-card--inactive' : ''}"
           data-praxis-id="${p.id}" data-action="open-praxis">
        <div style="font-size:1.5rem"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#${p.ist_notfallpraxis ? 'warning' : 'first-aid'}"></use></svg></div>
        <div class="health-card-body">
          <div class="health-card-title">
            ${_esc(p.name)}
            ${!p.aktiv ? '<span style="font-size:var(--text-xs);color:var(--c-text-secondary);font-weight:400"> · Ehemalig</span>' : ''}
          </div>
          ${(p.strasse || p.plz || p.ort) ? `
            <div class="health-card-meta">
              ${[p.strasse, [p.plz, p.ort].filter(Boolean).join(' ')].filter(Boolean).map(_esc).join(', ')}
            </div>` : ''}
          ${p.opening_hours ? `
            <div class="health-card-meta" style="margin-top:var(--space-1)">
              <svg class="ph-icon" aria-hidden="true" style="font-size:0.9em"><use href="/icons/phosphor.svg#clock"></use></svg>
              ${_esc(_fmtOeffnungszeiten(p.opening_hours))}
            </div>` : ''}
          <div style="display:flex;gap:var(--space-2);margin-top:var(--space-2);flex-wrap:wrap">
            ${p.telefon ? `
              <a href="tel:${_esc(p.telefon)}" class="btn btn-secondary btn-sm"
                 onclick="event.stopPropagation()">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#phone"></use></svg> Anrufen
              </a>` : ''}
            ${p.notfall_telefon ? `
              <a href="tel:${_esc(p.notfall_telefon)}" class="btn btn-danger btn-sm"
                 onclick="event.stopPropagation()">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#warning"></use></svg> Notfall
              </a>` : ''}
            <button class="btn btn-sm ${isFav ? 'btn-primary' : 'btn-secondary'}"
                    data-action="toggle-fav" data-praxis-id="${p.id}"
                    title="${isFav ? 'Favorit entfernen' : 'Als mein Tierarzt merken'}"
                    style="flex-shrink:0"
                    onclick="event.stopPropagation()">
              <svg class="ph-icon" aria-hidden="true">
                <use href="/icons/phosphor.svg#${isFav ? 'heart-fill' : 'heart'}"></use>
              </svg>
              ${isFav ? 'Mein Tierarzt' : 'Als Favorit'}
            </button>
          </div>
        </div>
      </div>
    `};


    const favCard = _favoritVet ? `
      <div style="margin-bottom:var(--space-4)">
        <div style="font-size:var(--text-xs);font-weight:600;color:var(--c-primary);
                    text-transform:uppercase;letter-spacing:.05em;margin-bottom:var(--space-2)">
          ${UI.icon('heart')} Mein Tierarzt
        </div>
        ${renderCard(_favoritVet)}
      </div>` : '';

    const ohneGesetzt = aktive.filter(p => p.id !== _favoritVet?.id);

    return `
      <div style="display:flex;justify-content:flex-end;margin-bottom:var(--space-3)">
        ${addBtn}
      </div>
      ${favCard}
      <div class="health-list">
        ${ohneGesetzt.map(renderCard).join('')}
        ${inaktive.length ? `
          <div style="margin-top:var(--space-4);padding-top:var(--space-3);
                      border-top:1px solid var(--c-border)">
            <p style="font-size:var(--text-sm);color:var(--c-text-secondary);
                      margin:0 0 var(--space-3)">Ehemalige Praxen</p>
            ${inaktive.map(renderCard).join('')}
          </div>` : ''}
      </div>
    `;
  }

  // ----------------------------------------------------------
  // PRAXEN — Formular (Neu / Bearbeiten)
  // ----------------------------------------------------------
  function _showPraxForm(praxis) {
    const isEdit = !!praxis;
    UI.modal.open({
      title: isEdit ? `${praxis.name} bearbeiten` : 'Praxis hinzufügen',
      body: `
        <form id="praxis-form" autocomplete="off">
          <div class="form-group">
            <label class="form-label">Name der Praxis *</label>
            <input class="form-control" type="text" name="name"
                   value="${_esc(praxis?.name || '')}" placeholder="Dr. Muster Tierarztpraxis" required>
          </div>
          <div class="form-group">
            <label class="form-label">Straße &amp; Hausnummer</label>
            <input class="form-control" type="text" name="strasse"
                   value="${_esc(praxis?.strasse || '')}" placeholder="Musterstraße 1">
          </div>
          <div style="display:grid;grid-template-columns:120px 1fr;gap:var(--space-3)">
            <div class="form-group">
              <label class="form-label">PLZ</label>
              <input class="form-control" type="text" name="plz" inputmode="numeric"
                     value="${_esc(praxis?.plz || '')}" placeholder="12345">
            </div>
            <div class="form-group">
              <label class="form-label">Ort</label>
              <input class="form-control" type="text" name="ort"
                     value="${_esc(praxis?.ort || '')}" placeholder="Musterstadt">
            </div>
          </div>
          <div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
            <div class="form-group">
              <label class="form-label">Telefon</label>
              <input class="form-control" type="tel" name="telefon"
                     value="${_esc(praxis?.telefon || '')}" placeholder="089 123456">
            </div>
            <div class="form-group">
              <label class="form-label">Notfall-Telefon</label>
              <input class="form-control" type="tel" name="notfall_telefon"
                     value="${_esc(praxis?.notfall_telefon || '')}" placeholder="089 999999">
            </div>
          </div>
          <div class="form-group">
            <label class="form-label">E-Mail</label>
            <input class="form-control" type="email" name="email"
                   value="${_esc(praxis?.email || '')}" placeholder="praxis@beispiel.de">
          </div>
          <div class="form-group">
            <label class="form-label">
              Öffnungszeiten
              <button type="button" id="praxis-osm-lookup" class="btn btn-secondary btn-sm"
                      style="margin-left:var(--space-2);font-size:var(--text-xs)">
                📍 Aus Karte laden
              </button>
            </label>
            <input class="form-control" type="text" name="opening_hours"
                   id="praxis-opening-hours"
                   value="${_esc(praxis?.opening_hours || '')}"
                   placeholder="z.B. Mo–Fr 08:00–18:00 · Sa 09:00–13:00">
            <div id="praxis-osm-results" style="display:none;margin-top:var(--space-2)"></div>
          </div>
          <div class="form-group">
            <label class="form-label">Notizen</label>
            <textarea class="form-control" name="notizen" rows="2"
                      placeholder="Besonderheiten, interne Hinweise…">${_esc(praxis?.notizen || '')}</textarea>
          </div>
          <div class="form-group">
            <label class="form-label" style="display:flex;align-items:center;gap:var(--space-2);cursor:pointer">
              <input type="checkbox" name="ist_notfallpraxis" ${praxis?.ist_notfallpraxis ? 'checked' : ''}>
              Notfallpraxis (24h / Wochenende)
            </label>
          </div>
          ${isEdit ? `
            <div class="form-group">
              <label class="form-label" style="display:flex;align-items:center;gap:var(--space-2);cursor:pointer">
                <input type="checkbox" name="inaktiv" ${!praxis?.aktiv ? 'checked' : ''}>
                Als ehemalige Praxis markieren (bei Umzug / Arztwechsel)
              </label>
            </div>` : ''}
        </form>
      `,
      footer: `
        <button type="button" class="btn btn-secondary flex-1" id="praxis-cancel">Abbrechen</button>
        <button type="submit" form="praxis-form" class="btn btn-primary flex-1">${isEdit ? 'Speichern' : 'Hinzufügen'}</button>
      `,
    });

    document.getElementById('praxis-cancel')?.addEventListener('click', UI.modal.close);

    // OSM-Lookup: Tierarztpraxen in der Nähe suchen und Öffnungszeiten übernehmen
    document.getElementById('praxis-osm-lookup')?.addEventListener('click', async btn => {
      const lookupBtn = document.getElementById('praxis-osm-lookup');
      const resultsEl = document.getElementById('praxis-osm-results');
      lookupBtn.disabled = true;
      lookupBtn.textContent = 'Suche…';
      try {
        const pos = await API.getLocation();
        const hits = await API.tieraerzte.osmNearby(pos.lat, pos.lon);
        if (!hits.length) {
          resultsEl.style.display = 'block';
          resultsEl.innerHTML = '<p style="font-size:var(--text-sm);color:var(--c-text-secondary)">Keine Praxen in der Nähe im OSM-Cache gefunden.</p>';
        } else {
          resultsEl.style.display = 'block';
          resultsEl.innerHTML = hits.map(h => `
            <div class="health-card" style="margin-bottom:var(--space-2)">
              <div style="cursor:pointer;flex:1"
                   data-osm-id="${_esc(h.osm_id)}"
                   data-name="${_esc(h.name)}"
                   data-oh="${_esc(h.opening_hours || '')}"
                   data-phone="${_esc(h.phone || '')}"
                   data-action="pick-osm">
                <div style="font-weight:600">${_esc(h.name)}</div>
                ${h.opening_hours_fmt ? `<div style="font-size:var(--text-sm);color:var(--c-text-secondary)">${_esc(h.opening_hours_fmt)}</div>` : '<div style="font-size:var(--text-sm);color:var(--c-text-muted)">Öffnungszeiten unbekannt</div>'}
                <div style="font-size:var(--text-xs);color:var(--c-text-secondary)">${h.distanz_km} km entfernt</div>
              </div>
              <button class="btn btn-secondary btn-sm" style="flex-shrink:0;align-self:flex-start"
                      data-action="korrigieren"
                      data-osm-id="${_esc(h.osm_id)}"
                      data-poi-name="${_esc(h.name)}"
                      data-current-oh="${_esc(h.opening_hours || '')}">
                ✏️
              </button>
            </div>
          `).join('');
          resultsEl.querySelectorAll('[data-action="pick-osm"]').forEach(el => {
            el.addEventListener('click', () => {
              const nameInput = document.querySelector('[name="name"]');
              const ohInput   = document.getElementById('praxis-opening-hours');
              const telInput  = document.querySelector('[name="telefon"]');
              if (nameInput && !nameInput.value) nameInput.value = el.dataset.name;
              if (ohInput)   ohInput.value   = el.dataset.oh;
              if (telInput && !telInput.value) telInput.value = el.dataset.phone;
              resultsEl.style.display = 'none';
              UI.toast.success('Daten übernommen.');
            });
          });
          resultsEl.querySelectorAll('[data-action="korrigieren"]').forEach(btn => {
            btn.addEventListener('click', e => {
              e.stopPropagation();
              _showPoiKorrekturModal(btn.dataset.osmId, btn.dataset.poiName, btn.dataset.currentOh);
            });
          });
        }
      } catch (err) {
        UI.toast.warning('Standort nicht verfügbar oder kein OSM-Cache in der Nähe.');
      } finally {
        lookupBtn.disabled = false;
        lookupBtn.textContent = '📍 Aus Karte laden';
      }
    });

    document.getElementById('praxis-form')?.addEventListener('submit', async e => {
      e.preventDefault();
      const btn = document.querySelector('[form="praxis-form"][type="submit"]') || e.target.querySelector('[type="submit"]');
      const fd  = UI.formData(e.target);

      await UI.asyncButton(btn, async () => {
        const payload = {
          name:             fd.name?.trim(),
          strasse:          fd.strasse || null,
          plz:              fd.plz    || null,
          ort:              fd.ort    || null,
          telefon:          fd.telefon || null,
          notfall_telefon:  fd.notfall_telefon || null,
          email:            fd.email || null,
          notizen:          fd.notizen || null,
          ist_notfallpraxis: 'ist_notfallpraxis' in fd,
          opening_hours:    fd.opening_hours || null,
        };
        if (!payload.name) { UI.toast.warning('Bitte einen Namen eingeben.'); return; }

        let saved;
        if (isEdit) {
          payload.aktiv = !('inaktiv' in fd);
          saved = await API.tieraerzte.update(praxis.id, payload);
          _praxen = _praxen.map(p => p.id === praxis.id ? saved : p);
          UI.toast.success('Praxis gespeichert.');
        } else {
          saved = await API.tieraerzte.create(payload);
          _praxen.push(saved);
          UI.toast.success(`${saved.name} hinzugefügt.`);
        }
        UI.modal.close();
        _renderTab();
      });
    });
  }

  // ----------------------------------------------------------
  // SYMPTOM-CHECK
  // ----------------------------------------------------------
  function _renderSymptomCheck(content) {
    content.innerHTML = `
      <div style="padding:var(--space-4)">
        <div class="card" style="padding:var(--space-4)">
          <p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-4)">
            Beschreibe die Symptome deines Hundes. Die KI gibt eine erste Einschätzung — kein Ersatz für den Tierarzt.
          </p>
          <div class="form-group">
            <label class="form-label" for="symptom-input">Symptome</label>
            <textarea id="symptom-input" class="form-control" rows="4"
                      placeholder="z.B. frisst nicht, trinkt viel, schläft mehr als sonst..."></textarea>
          </div>
          <button id="symptom-submit-btn" class="btn btn-primary" style="width:100%">
            Symptome analysieren <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#magnifying-glass"></use></svg>
          </button>
          <div id="symptom-result" style="display:none;margin-top:var(--space-5)"></div>
        </div>
      </div>
    `;

    content.querySelector('#symptom-submit-btn').addEventListener('click', async function () {
      const btn      = this;
      const textarea = content.querySelector('#symptom-input');
      const resultEl = content.querySelector('#symptom-result');
      const symptoms = textarea.value.trim();

      if (!symptoms) {
        UI.toast.warning('Bitte Symptome eingeben.');
        return;
      }

      await UI.asyncButton(btn, async () => {
        resultEl.style.display = 'none';
        resultEl.innerHTML = '';

        let result;
        try {
          result = await API.post(
            `/dogs/${_appState.activeDog.id}/health/symptom-check`,
            { symptoms }
          );
        } catch (err) {
          if (err.status === 402) {
            resultEl.innerHTML = `
              <div class="card" style="padding:var(--space-4);border:1px solid var(--c-warning)">
                <p style="margin:0;font-size:var(--text-sm)">
                  <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#star"></use></svg> Dieses Feature benötigt Ban Yaro Plus oder einen laufenden KI-Server.
                </p>
              </div>`;
          } else if (err.status === 503) {
            resultEl.innerHTML = `
              <div class="card" style="padding:var(--space-4);border:1px solid var(--c-danger)">
                <p style="margin:0;font-size:var(--text-sm)">
                  KI-Server nicht erreichbar. Bitte später versuchen.
                </p>
              </div>`;
          } else {
            UI.toast.error(err.message || 'Fehler bei der Symptomanalyse.');
            return;
          }
          resultEl.style.display = '';
          return;
        }

        const DRINGLICHKEIT = {
          beobachten:    { badgeClass: 'badge-success', icon: 'check-circle',    label: 'Beobachten' },
          tierarzt_heute:{ badgeClass: 'badge-warning', icon: 'warning',         label: 'Heute zum Tierarzt' },
          tierarzt:      { badgeClass: 'badge-warning', icon: 'warning',         label: 'Zum Tierarzt' },
          tierarzt_sofort:{ badgeClass: 'badge-danger', icon: 'first-aid-kit',   label: 'Sofort zum Tierarzt!' },
          notfall:       { badgeClass: 'badge-danger',  icon: 'first-aid-kit',   label: 'Notfall — sofort zum Tierarzt!' },
        };
        const d = DRINGLICHKEIT[result.dringlichkeit] || { badgeClass: 'badge-primary', icon: 'info', label: _esc(result.dringlichkeit) };

        const hinweiseHtml = (result.hinweise || []).length
          ? `<ul style="margin:var(--space-2) 0 0;padding-left:var(--space-5);font-size:var(--text-sm)">
               ${result.hinweise.map(h => `<li style="margin-bottom:var(--space-1)">${_esc(h)}</li>`).join('')}
             </ul>`
          : '';

        const zumTierarztHtml = result.zum_tierarzt_wenn
          ? `<div style="margin-top:var(--space-3);padding:var(--space-3);
                         background:var(--c-surface-alt,var(--c-surface));
                         border-radius:var(--radius-md);font-size:var(--text-sm)">
               <strong>Zum Tierarzt wenn:</strong> ${_esc(result.zum_tierarzt_wenn)}
             </div>`
          : '';

        resultEl.innerHTML = `
          <div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-3)">
            <span class="badge ${d.badgeClass}" style="display:inline-flex;align-items:center;gap:var(--space-1);font-size:var(--text-sm);padding:var(--space-1) var(--space-3)">
              <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#${d.icon}"></use></svg>
              ${d.label}
            </span>
          </div>
          ${result.einschaetzung
            ? `<p style="font-size:var(--text-sm);line-height:1.6;margin:0">${_esc(result.einschaetzung)}</p>`
            : ''}
          ${hinweiseHtml}
          ${zumTierarztHtml}
        `;
        resultEl.style.display = '';
      });
    });
  }

  // ----------------------------------------------------------
  // TRANSPONDER-BEARBEITUNG
  // ----------------------------------------------------------
  async function _editTransponder(dog) {
    const currentNr = dog?.chip_nr || '';
    UI.modal.open({
      title: 'Transpondernummer',
      body: `
        <div class="mb-3">
          <label class="form-label">Chip-Nummer (15-stellig)</label>
          <input id="transponder-input" class="form-control" type="text"
                 value="${_esc(currentNr)}" placeholder="z.B. 276009200123456" maxlength="20">
        </div>`,
      footer: `
        <button class="btn btn-secondary" onclick="UI.modal.close()">Abbrechen</button>
        <button class="btn btn-primary" id="transponder-save-btn">Speichern</button>`,
    });
    document.getElementById('transponder-save-btn').addEventListener('click', async () => {
      const nr = document.getElementById('transponder-input').value.trim() || null;
      const btn = document.getElementById('transponder-save-btn');
      UI.setLoading(btn, true);
      try {
        await API.dogs.update(dog.id, { chip_nr: nr });
        _appState.activeDog.chip_nr = nr;
        UI.modal.close();
        const nrEl = _container.querySelector('#health-transponder-nr');
        if (nrEl) nrEl.innerHTML = nr
          ? `<strong>${_esc(nr)}</strong>`
          : '<em style="color:var(--c-text-muted)">nicht eingetragen</em>';
      } catch (e) {
        UI.setLoading(btn, false);
        UI.toast('Fehler beim Speichern', 'error');
      }
    });
  }

  // ----------------------------------------------------------
  // KI-GESUNDHEITSBERICHTE (gespeicherte automatische Berichte)
  // ----------------------------------------------------------
  async function _loadKiBerichte(dogId) {
    const el = _container.querySelector('#health-ki-berichte');
    if (!el) return;
    try {
      const berichte = await API.health.kiBerichte(dogId);
      if (!berichte || berichte.length === 0) return;
      const neuester = berichte[0];
      const datum = neuester.erstellt_at
        ? new Date(neuester.erstellt_at).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })
        : '';
      const preview = neuester.bericht.length > 180
        ? _esc(neuester.bericht.slice(0, 180)) + '&hellip;'
        : _esc(neuester.bericht);
      el.innerHTML = `
        <div class="health-ki-bericht-banner" style="
          background:var(--c-surface-2,#f7f2eb);
          border:1px solid var(--c-border,#e2d9ce);
          border-radius:var(--radius-md,10px);
          padding:var(--space-3) var(--space-4);
          margin-bottom:var(--space-3);
          cursor:pointer;
        ">
          <div style="display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-1)">
            <svg class="ph-icon" aria-hidden="true" style="flex-shrink:0"><use href="/icons/phosphor.svg#star"></use></svg>
            <strong style="font-size:var(--text-sm)">KI-Gesundheitsbericht</strong>
            ${datum ? `<span style="font-size:var(--text-xs);color:var(--c-text-muted);margin-left:auto">${datum}</span>` : ''}
          </div>
          <div style="font-size:var(--text-sm);color:var(--c-text-muted);line-height:1.5">${preview}</div>
          ${berichte.length > 1 ? `<div style="font-size:var(--text-xs);color:var(--c-accent,#c4843a);margin-top:var(--space-1)">${berichte.length} Berichte gespeichert — zum Öffnen tippen</div>` : ''}
        </div>`;
      el.querySelector('.health-ki-bericht-banner').addEventListener('click', () => {
        const listeHtml = berichte.map((b, i) => {
          const d = b.erstellt_at
            ? new Date(b.erstellt_at).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })
            : '';
          return `<div style="${i > 0 ? 'border-top:1px solid var(--c-border);padding-top:var(--space-3);margin-top:var(--space-3)' : ''}">
            ${d ? `<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-bottom:var(--space-1)">${d}</div>` : ''}
            <div style="white-space:pre-wrap;line-height:1.7;font-size:var(--text-sm)">${_esc(b.bericht)}</div>
          </div>`;
        }).join('');
        UI.modal.open({
          title: `${UI.icon('star')} KI-Gesundheitsberichte`,
          body: listeHtml,
        });
      });
    } catch (_) {
      // Silently ignore — Berichte sind optional
    }
  }

  // ----------------------------------------------------------
  // KI-ZUSAMMENFASSUNG
  // ----------------------------------------------------------
  // TERMINVORSCHLÄGE
  // ----------------------------------------------------------
  async function _loadTerminvorschlaege(dogId) {
    const el = _container.querySelector('#health-terminvorschlaege');
    if (!el) return;
    try {
      const vorschlaege = await API.health.terminvorschlaege(dogId);
      if (!vorschlaege || !vorschlaege.length) return;

      const _fmtDatum = iso => new Date(iso + 'T00:00:00').toLocaleDateString('de-DE', {
        weekday: 'short', day: '2-digit', month: '2-digit', year: 'numeric'
      });

      el.innerHTML = `
        <div style="margin-bottom:var(--space-3)">
          <div style="font-size:var(--text-xs);font-weight:600;color:var(--c-text-muted);
                      text-transform:uppercase;letter-spacing:.05em;margin-bottom:var(--space-2)">
            Terminvorschläge
          </div>
          <div style="display:flex;flex-direction:column;gap:var(--space-2)">
            ${vorschlaege.map(v => {
              const badge = v.ueberfaellig
                ? `<span style="font-size:var(--text-xs);color:var(--c-danger);font-weight:600">Überfällig seit ${_fmtDatum(v.naechstes)}</span>`
                : `<span style="font-size:var(--text-xs);color:var(--c-warning);font-weight:600">Fällig am ${_fmtDatum(v.naechstes)}</span>`;
              return `
                <div class="health-card" style="flex-direction:row;align-items:center;gap:var(--space-3)">
                  <div style="flex:1;min-width:0">
                    <div style="font-weight:600;font-size:var(--text-sm)">${_esc(v.bezeichnung)}</div>
                    <div style="font-size:var(--text-xs);color:var(--c-text-secondary)">${_esc(v.label)}${v.praxis_name ? ' · ' + _esc(v.praxis_name) : ''}</div>
                    ${badge}
                  </div>
                  <div style="text-align:right;flex-shrink:0">
                    <div style="font-size:var(--text-xs);color:var(--c-text-muted)">Vorschlag</div>
                    <div style="font-size:var(--text-sm);font-weight:600">${_fmtDatum(v.datum_vorschlag)}</div>
                    <div style="font-size:var(--text-xs);color:var(--c-text-secondary)">${v.uhrzeit_vorschlag} Uhr</div>
                    <button class="btn btn-primary btn-sm" style="margin-top:var(--space-1)"
                            data-action="termin-anlegen"
                            data-v='${_esc(JSON.stringify(v))}'>
                      <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#calendar-plus"></use></svg> In Kalender
                    </button>
                  </div>
                </div>
              `;
            }).join('')}
          </div>
        </div>
      `;

      el.querySelectorAll('[data-action="termin-anlegen"]').forEach(btn => {
        btn.addEventListener('click', async () => {
          let v;
          try { v = JSON.parse(btn.dataset.v); } catch { return; }
          await _terminAnlegen(v, btn);
        });
      });
    } catch { /* still show health page if this fails */ }
  }

  async function _terminAnlegen(v, btn) {
    const titel = v.beim_tierarzt
      ? `${v.label}: ${v.bezeichnung} (Tierarzt)`
      : `${v.label}: ${v.bezeichnung}`;
    const beschreibung = v.praxis_name
      ? `Praxis: ${v.praxis_name}`
      : v.ueberfaellig
        ? `Überfällig seit ${v.naechstes}`
        : `Fällig am ${v.naechstes}`;

    UI.modal.open({
      title: `${UI.icon('calendar-plus')} Termin in Kalender eintragen`,
      body: `
        <form id="termin-form">
          <div class="form-group">
            <label class="form-label">Bezeichnung</label>
            <input class="form-control" type="text" name="titel" value="${_esc(titel)}" required>
          </div>
          <div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
            <div class="form-group">
              <label class="form-label">Datum</label>
              <input class="form-control" type="date" name="datum" value="${_esc(v.datum_vorschlag)}" required>
            </div>
            <div class="form-group">
              <label class="form-label">Uhrzeit</label>
              <input class="form-control" type="time" name="uhrzeit" value="${_esc(v.uhrzeit_vorschlag)}">
            </div>
          </div>
          <div class="form-group">
            <label class="form-label">Notiz</label>
            <input class="form-control" type="text" name="beschreibung" value="${_esc(beschreibung)}">
          </div>
        </form>
      `,
      footer: `
        <button type="button" class="btn btn-secondary flex-1" id="termin-cancel">Abbrechen</button>
        <button type="submit" form="termin-form" class="btn btn-primary flex-1">Speichern</button>
      `,
    });
    document.getElementById('termin-cancel')?.addEventListener('click', UI.modal.close);
    document.getElementById('termin-form')?.addEventListener('submit', async e => {
      e.preventDefault();
      const saveBtn = document.querySelector('[form="termin-form"][type="submit"]');
      const fd = UI.formData(e.target);
      await UI.asyncButton(saveBtn, async () => {
        await API.events.create({
          titel:       fd.titel,
          datum:       fd.datum,
          uhrzeit:     fd.uhrzeit || null,
          beschreibung: fd.beschreibung || null,
          typ:         v.beim_tierarzt ? 'tierarzt' : 'sonstiges',
          lat:         v.praxis_lat  ?? null,
          lon:         v.praxis_lon  ?? null,
          ort_name:    v.praxis_name ?? null,
        });
        UI.modal.close();
        UI.toast.success('Termin gespeichert — erscheint in deinem Kalender.');
      });
    });
  }

  // ----------------------------------------------------------
  // MEIN TIERARZT — Kachel
  // ----------------------------------------------------------
  async function _loadMeinTierarzt() {
    const el = _container.querySelector('#health-mein-tierarzt');
    if (!el) return;
    _renderMeinTierarztKachel(el);
  }

  function _renderMeinTierarztKachel(el) {
    if (!el) return;
    const vet = _favoritVet;
    const adresse = vet
      ? [vet.strasse, [vet.plz, vet.ort].filter(Boolean).join(' ')].filter(Boolean).join(', ')
      : '';

    el.innerHTML = `
      <div style="margin:var(--space-3) var(--space-4) 0">
        <div style="font-size:var(--text-xs);font-weight:600;color:var(--c-text-muted);
                    text-transform:uppercase;letter-spacing:.05em;margin-bottom:var(--space-2)">
          Mein Tierarzt
        </div>
        <div class="health-card" style="align-items:flex-start">
          <div style="font-size:1.6rem;flex-shrink:0">
            <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg>
          </div>
          <div class="health-card-body" style="flex:1;min-width:0">
            ${vet ? `
              <div class="health-card-title">${_esc(vet.name)}</div>
              ${adresse ? `<div class="health-card-meta">${_esc(adresse)}</div>` : ''}
              ${vet.telefon ? `
                <div style="margin-top:var(--space-2)">
                  <a href="tel:${_esc(vet.telefon)}" class="btn btn-secondary btn-sm"
                     onclick="event.stopPropagation()">
                    <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#phone"></use></svg> ${_esc(vet.telefon)}
                  </a>
                </div>` : ''}
              ${vet.notfall_telefon ? `
                <div style="margin-top:var(--space-1)">
                  <a href="tel:${_esc(vet.notfall_telefon)}" class="btn btn-danger btn-sm"
                     onclick="event.stopPropagation()">
                    <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#warning"></use></svg> Notfall: ${_esc(vet.notfall_telefon)}
                  </a>
                </div>` : ''}
            ` : `
              <div style="color:var(--c-text-muted);font-size:var(--text-sm)">
                Noch kein Tierarzt als Favorit gespeichert.
              </div>
              <button class="btn btn-secondary btn-sm" style="margin-top:var(--space-2)"
                      id="health-suche-tierarzt-btn">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#map-pin"></use></svg> Tierarzt suchen
              </button>
            `}
          </div>
          ${vet ? `
            <button class="btn btn-ghost btn-sm" id="health-remove-fav-btn"
                    title="Als Favorit entfernen" style="flex-shrink:0;color:var(--c-danger)">
              <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#heart-fill"></use></svg>
            </button>
          ` : ''}
        </div>
      </div>
    `;

    el.querySelector('#health-suche-tierarzt-btn')?.addEventListener('click', () => {
      App.navigate('map', { filter: 'tierarzt' });
    });

    el.querySelector('#health-remove-fav-btn')?.addEventListener('click', async (e) => {
      e.stopPropagation();
      const btn = e.currentTarget;
      await UI.asyncButton(btn, async () => {
        await API.tieraerzte.toggleFavorite(_favoritVet.id);
        _favoritVet = null;
        const elAgain = _container.querySelector('#health-mein-tierarzt');
        if (elAgain) _renderMeinTierarztKachel(elAgain);
        UI.toast.success('Tierarzt-Favorit entfernt.');
      });
    });
  }

  // ----------------------------------------------------------
  // BEFUNDE & DOKUMENTE — Sektion (unabhängig von den Tabs)
  // ----------------------------------------------------------
  // Diese Sektion erscheint im "dokument"-Tab als zweite Liste.
  // Wir ergänzen _renderDokumente um einen Abschnitt unten.

  function _renderBefundeSection() {
    const dog    = _appState.activeDog;
    const docs   = _healthDocs;
    const DOC_ICONS = {
      blutbild:   'drop',
      roentgen:   'file-text',
      rezept:     'note',
      impfausweis:'certificate',
      sonstiges:  'file-text',
    };
    const DOC_LABELS = {
      blutbild:   'Blutbild',
      roentgen:   'Röntgen',
      rezept:     'Rezept',
      impfausweis:'Impfausweis',
      sonstiges:  'Sonstiges',
    };

    const uploadBtn = `
      <button class="btn btn-primary btn-sm" id="health-docs-upload-btn">
        <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#upload"></use></svg> Befund hochladen
      </button>`;

    const items = docs.length
      ? docs.map(doc => {
          const icon   = DOC_ICONS[doc.typ] || 'file-text';
          const label  = DOC_LABELS[doc.typ] || doc.typ;
          const isImg  = !['pdf'].includes(doc.file_type);
          const datum  = doc.datum ? UI.time.format(doc.datum + 'T00:00:00') : '';
          return `
            <div class="health-card" style="align-items:flex-start">
              <div style="font-size:1.4rem;flex-shrink:0;color:var(--c-primary)">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#${_esc(icon)}"></use></svg>
              </div>
              <div class="health-card-body" style="flex:1;min-width:0">
                <div class="health-card-title">${_esc(doc.titel)}</div>
                <div class="health-card-meta">
                  ${_esc(label)}${datum ? ' · ' + datum : ''}
                  ${doc.vet_name ? ' · <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#first-aid"></use></svg> ' + _esc(doc.vet_name) : ''}
                </div>
                ${doc.beschreibung ? `<div class="health-card-note">${_esc(doc.beschreibung)}</div>` : ''}
                <div style="display:flex;gap:var(--space-2);margin-top:var(--space-2);flex-wrap:wrap">
                  <a href="${_esc(doc.file_path)}" target="_blank" rel="noopener"
                     class="btn btn-secondary btn-sm" onclick="event.stopPropagation()">
                    ${isImg
                      ? '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#image"></use></svg> Bild öffnen'
                      : '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg> PDF öffnen'}
                  </a>
                  <button class="btn btn-ghost btn-xs" style="color:var(--c-danger)"
                          data-action="delete-hdoc" data-doc-id="${doc.id}"
                          onclick="event.stopPropagation()">
                    <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#trash"></use></svg>
                  </button>
                </div>
              </div>
            </div>`;
        }).join('')
      : `<p style="font-size:var(--text-sm);color:var(--c-text-muted);padding:var(--space-3) 0">
           Noch keine Befunde hochgeladen.
         </p>`;

    return `
      <div style="margin-top:var(--space-5);padding-top:var(--space-4);
                  border-top:1px solid var(--c-border)">
        <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-3)">
          <div style="font-size:var(--text-xs);font-weight:600;color:var(--c-text-muted);
                      text-transform:uppercase;letter-spacing:.05em">
            <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#file-text"></use></svg> Befunde &amp; Dokumente
          </div>
          ${uploadBtn}
        </div>
        <div class="health-list" id="health-docs-list">${items}</div>
      </div>
    `;
  }

  function _bindBefundeEvents(content) {
    content.querySelector('#health-docs-upload-btn')?.addEventListener('click', () => {
      _showBefundUploadModal();
    });
    content.querySelectorAll('[data-action="delete-hdoc"]').forEach(btn => {
      btn.addEventListener('click', async (e) => {
        e.stopPropagation();
        const docId = parseInt(btn.dataset.docId);
        const ok = window.confirm('Befund wirklich löschen?');
        if (!ok) return;
        await UI.asyncButton(btn, async () => {
          await API.healthDocs.delete(docId);
          _healthDocs = _healthDocs.filter(d => d.id !== docId);
          _renderTab();
          UI.toast.success('Befund gelöscht.');
        });
      });
    });
  }

  function _showBefundUploadModal() {
    const aktivePraxen = _praxen.filter(p => p.aktiv);
    const dog = _appState.activeDog;

    UI.modal.open({
      title: `<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#upload"></use></svg> Befund hochladen`,
      body: `
        <form id="befund-form" autocomplete="off">
          <div class="form-group">
            <label class="form-label">Art des Dokuments *</label>
            <select class="form-control" name="typ" required>
              <option value="">– bitte wählen –</option>
              <option value="blutbild">Blutbild</option>
              <option value="roentgen">Röntgen</option>
              <option value="rezept">Rezept</option>
              <option value="impfausweis">Impfausweis</option>
              <option value="sonstiges">Sonstiges</option>
            </select>
          </div>
          <div class="form-group">
            <label class="form-label">Titel *</label>
            <input class="form-control" type="text" name="titel" required
                   placeholder="z.B. Blutbild März 2026">
          </div>
          <div class="form-group">
            <label class="form-label">Untersuchungsdatum</label>
            <input class="form-control" type="date" name="datum"
                   value="${new Date().toISOString().slice(0,10)}">
          </div>
          ${aktivePraxen.length ? `
            <div class="form-group">
              <label class="form-label">Tierarzt / Praxis</label>
              <select class="form-control" name="vet_id">
                <option value="">– optional –</option>
                ${aktivePraxen.map(p =>
                  `<option value="${p.id}">${_esc(p.name)}${p.ort ? ' · ' + _esc(p.ort) : ''}</option>`
                ).join('')}
              </select>
            </div>` : ''}
          <div class="form-group">
            <label class="form-label">Beschreibung</label>
            <textarea class="form-control" name="beschreibung" rows="2"
                      placeholder="Zusätzliche Infos (optional)"></textarea>
          </div>
          <div class="form-group">
            <label class="form-label">Datei * (PDF, JPG, PNG, WebP — max. 10 MB)</label>
            <label class="btn btn-secondary btn-sm" style="cursor:pointer;display:inline-flex;
                   align-items:center;gap:var(--space-2)">
              <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#plus"></use></svg> Datei auswählen
              <input type="file" name="file" id="befund-file-input"
                     accept=".pdf,image/*"
                     required
                     style="position:absolute;opacity:0;width:1px;height:1px">
            </label>
            <div id="befund-file-preview" style="margin-top:var(--space-2);font-size:var(--text-sm);
                 color:var(--c-text-secondary)"></div>
          </div>
        </form>
      `,
      footer: `
        <button type="button" class="btn btn-secondary flex-1" id="befund-cancel">Abbrechen</button>
        <button type="submit" form="befund-form" class="btn btn-primary flex-1">Hochladen</button>
      `,
    });

    document.getElementById('befund-cancel')?.addEventListener('click', UI.modal.close);

    document.getElementById('befund-file-input')?.addEventListener('change', function () {
      const preview = document.getElementById('befund-file-preview');
      if (this.files?.length) {
        const f = this.files[0];
        preview.textContent = `${f.name} (${(f.size / 1024 / 1024).toFixed(2)} MB)`;
      } else {
        preview.textContent = '';
      }
    });

    document.getElementById('befund-form')?.addEventListener('submit', async (e) => {
      e.preventDefault();
      const btn  = document.querySelector('[form="befund-form"][type="submit"]');
      const form = e.target;
      const fd   = UI.formData(form);
      const fileInput = form.querySelector('[name="file"]');
      const file = fileInput?.files?.[0];

      if (!fd.typ)   { UI.toast.warning('Bitte Art des Dokuments wählen.'); return; }
      if (!fd.titel) { UI.toast.warning('Bitte Titel eingeben.'); return; }
      if (!file)     { UI.toast.warning('Bitte eine Datei auswählen.'); return; }

      if (file.size > 10 * 1024 * 1024) {
        UI.toast.error('Datei ist zu groß. Maximum: 10 MB.');
        return;
      }

      await UI.asyncButton(btn, async () => {
        const formData = new FormData();
        formData.append('dog_id',       String(dog.id));
        formData.append('typ',          fd.typ);
        formData.append('titel',        fd.titel);
        formData.append('beschreibung', fd.beschreibung || '');
        formData.append('datum',        fd.datum || '');
        if (fd.vet_id) formData.append('vet_id', fd.vet_id);
        formData.append('file', file);

        try {
          const doc = await API.healthDocs.upload(formData);
          _healthDocs.unshift(doc);
          UI.modal.close();
          _renderTab();
          UI.toast.success('Befund hochgeladen.');
        } catch (err) {
          UI.toast.error(err.message || 'Fehler beim Hochladen.');
        }
      });
    });
  }

  // ----------------------------------------------------------
  async function _showKiSummary() {
    const btn = _container.querySelector('#health-ki-btn');
    UI.setLoading(btn, true);

    try {
      const { zusammenfassung } = await API.health.kiZusammenfassung(_appState.activeDog.id);
      UI.modal.open({
        title: `${UI.icon('star')} KI-Gesundheitsbericht`,
        body: `<div style="white-space:pre-wrap;line-height:1.7;font-size:var(--text-sm)">${_esc(zusammenfassung)}</div>`,
      });
    } catch (err) {
      if (err.status === 503) {
        UI.toast.error('KI ist momentan nicht verfügbar. Bitte später erneut versuchen.');
      } else if (err.status === 402) {
        UI.toast.warning('Diese Funktion ist Teil von Ban Yaro Premium.');
      } else {
        UI.toast.error(err.message || 'Fehler bei der KI-Zusammenfassung.');
      }
    } finally {
      UI.setLoading(btn, false);
    }
  }

  // ----------------------------------------------------------
  // HELPER
  // ----------------------------------------------------------
  function _esc(str) {
    if (!str) return '';
    return String(str)
      .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;');
  }

  function _showPoiKorrekturModal(osmId, poiName, currentOh) {
    UI.modal.open({
      title: 'Öffnungszeiten korrigieren',
      body: `
        <p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin-bottom:var(--space-3)">
          Korrektur für <strong>${_esc(poiName)}</strong>.<br>
          Dein Vorschlag wird von einem Moderator geprüft und dann für alle übernommen.
        </p>
        <form id="poi-korrektur-form">
          <div class="form-group">
            <label class="form-label">Aktuelle Angabe</label>
            <input class="form-control" type="text" value="${_esc(currentOh)}" disabled
                   style="color:var(--c-text-muted)">
          </div>
          <div class="form-group">
            <label class="form-label">Korrekte Öffnungszeiten *</label>
            <input class="form-control" type="text" name="new_value" required
                   placeholder="z.B. Mo–Fr 08:00–18:00 · Sa 09:00–13:00"
                   value="${_esc(currentOh)}">
          </div>
        </form>
      `,
      footer: `
        <button type="button" class="btn btn-secondary flex-1" id="poi-kor-cancel">Abbrechen</button>
        <button type="submit" form="poi-korrektur-form" class="btn btn-primary flex-1">Einreichen</button>
      `,
    });
    document.getElementById('poi-kor-cancel')?.addEventListener('click', UI.modal.close);
    document.getElementById('poi-korrektur-form')?.addEventListener('submit', async e => {
      e.preventDefault();
      const btn = document.querySelector('[form="poi-korrektur-form"][type="submit"]');
      const fd  = UI.formData(e.target);
      await UI.asyncButton(btn, async () => {
        await API.post(`/osm/pois/${encodeURIComponent(osmId)}/edit`, {
          poi_name:  poiName,
          field:     'opening_hours',
          new_value: fd.new_value.trim(),
        });
        UI.modal.close();
        UI.toast.success('Danke! Dein Vorschlag wird geprüft.');
      });
    });
  }

  function _fmtOeffnungszeiten(raw) {
    if (!raw) return '';
    if (raw.trim().toLowerCase() === '24/7') return '24/7 geöffnet';
    return raw.split(';').map(s => s.trim()).filter(Boolean).join(' · ');
  }

  // ----------------------------------------------------------
  // NOTIZ-MODAL (custom DOM, kein UI.modal um Konflikte zu vermeiden)
  // ----------------------------------------------------------
  async function _openNoteModal(parentType, parentId, parentLabel, locationName) {
    // Vorhandenes Modal entfernen falls noch offen
    document.getElementById('by-note-modal')?.remove();

    const overlay = document.createElement('div');
    overlay.id = 'by-note-modal';
    overlay.style.cssText = 'position:fixed;inset:0;z-index:2000;background:rgba(0,0,0,.55);display:flex;align-items:flex-end;justify-content:center';

    overlay.innerHTML = `
      <div style="background:var(--c-surface);border-radius:var(--radius-xl) var(--radius-xl) 0 0;
                  width:100%;max-width:640px;max-height:90vh;display:flex;flex-direction:column;
                  padding-bottom:env(safe-area-inset-bottom,0px)">
        <div style="padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--c-border);
                    display:flex;align-items:center;justify-content:space-between;flex-shrink:0">
          <div>
            <div style="font-weight:var(--weight-semibold);font-size:var(--text-base)"><svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#note-pencil"></use></svg> Notiz</div>
            <div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-top:2px">${_esc(parentLabel)}</div>
          </div>
          <button id="by-note-close" style="background:none;border:none;cursor:pointer;font-size:1.4rem;color:var(--c-text-muted);padding:4px 8px" aria-label="Schließen">×</button>
        </div>
        <div style="padding:var(--space-4) var(--space-5);flex:1;overflow-y:auto">
          <form id="by-note-form">
            <textarea id="by-note-text" class="form-control" rows="5"
                      placeholder="Notiz eingeben…"
                      style="width:100%;resize:vertical"></textarea>
          </form>
        </div>
        <div style="padding:var(--space-3) var(--space-5);border-top:1px solid var(--c-border);
                    display:flex;gap:var(--space-2);flex-shrink:0">
          <button type="button" id="by-note-cancel" class="btn btn-secondary flex-1">Abbrechen</button>
          <button type="submit" form="by-note-form" id="by-note-save" class="btn btn-primary flex-1">Speichern</button>
        </div>
      </div>
    `;

    document.body.appendChild(overlay);

    const textarea  = document.getElementById('by-note-text');
    const saveBtn   = document.getElementById('by-note-save');
    const cancelBtn = document.getElementById('by-note-cancel');
    const closeBtn  = document.getElementById('by-note-close');

    let existingNoteId = null;

    // Vorhandene Notiz laden
    try {
      const existing = await API.notes.get(parentType, parentId);
      if (existing?.id) {
        existingNoteId = existing.id;
        textarea.value = existing.text || '';
      }
    } catch (_) { /* keine Notiz vorhanden — ok */ }

    setTimeout(() => textarea.focus(), 100);

    const _close = () => overlay.remove();
    closeBtn.addEventListener('click', _close);
    cancelBtn.addEventListener('click', _close);
    overlay.addEventListener('click', e => { if (e.target === overlay) _close(); });

    document.getElementById('by-note-form').addEventListener('submit', async e => {
      e.preventDefault();
      const text = textarea.value.trim();
      UI.setLoading(saveBtn, true);
      try {
        const payload = { text, parent_label: parentLabel, location_name: locationName };
        if (existingNoteId) {
          await API.notes.update(existingNoteId, payload);
        } else {
          await API.notes.create(parentType, parentId, payload);
        }
        UI.toast.success('Notiz gespeichert.');
        _close();
      } catch (err) {
        UI.toast.error(err.message || 'Fehler beim Speichern.');
        UI.setLoading(saveBtn, false);
      }
    });
  }

  // ----------------------------------------------------------
  // KI-TIERARZTFRAGEN
  // ----------------------------------------------------------
  function _showKiTierarzt() {
    const dog      = _appState.activeDog;
    const dogName  = dog?.name  || '';
    const rasse    = dog?.rasse || '';
    const placeholder = dogName
      ? `Welche Symptome zeigt ${dogName}? z.B. frisst nicht, schläft viel, lahmt...`
      : 'Welche Symptome zeigt dein Hund? z.B. frisst nicht, schläft viel, lahmt...';

    UI.modal.open({
      title: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#stethoscope"></use></svg> KI-Tierarzt',
      body: `
        <p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-3)">
          Beschreibe die Symptome deines Hundes. Die KI gibt eine erste Orientierung —
          kein Ersatz für einen echten Tierarzt.
        </p>
        <div class="form-group">
          <textarea id="ki-tierarzt-symptom" class="form-control" rows="4"
                    placeholder="${_esc(placeholder)}"></textarea>
        </div>
        <div id="ki-tierarzt-result" style="display:none"></div>
        <div style="margin-top:var(--space-3);padding:var(--space-3);
                    background:#fff3cd;border-radius:var(--radius-md);
                    font-size:var(--text-xs);color:#856404;
                    border:1px solid #ffc107">
          <strong>&#9888;&#65039; Hinweis:</strong> Dies ist keine medizinische Diagnose.
          Bei ernsthaften oder sich verschlechternden Symptomen sofort zum Tierarzt.
        </div>`,
      footer: `
        <button class="btn btn-secondary" onclick="UI.modal.close()">Schließen</button>
        <button class="btn btn-primary" id="ki-tierarzt-submit-btn">Frage stellen</button>`,
    });

    document.getElementById('ki-tierarzt-submit-btn')
      .addEventListener('click', async function () {
        const btn       = this;
        const symptom   = document.getElementById('ki-tierarzt-symptom').value.trim();
        const resultEl  = document.getElementById('ki-tierarzt-result');

        if (!symptom) {
          UI.toast.warning('Bitte Symptome eingeben.');
          return;
        }

        await UI.asyncButton(btn, async () => {
          resultEl.style.display = 'none';
          resultEl.innerHTML = '';

          let result;
          try {
            result = await API.post('/ki/tierarzt', {
              symptom,
              dog_id:   dog?.id   || null,
              dog_name: dogName   || null,
              rasse:    rasse     || null,
            });
          } catch (err) {
            if (err.status === 429) {
              resultEl.innerHTML = `
                <div style="padding:var(--space-3);background:var(--c-surface);
                             border-radius:var(--radius-md);border:1px solid var(--c-warning);
                             font-size:var(--text-sm);color:var(--c-text-secondary)">
                  <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#clock"></use></svg>
                  5 Anfragen pro Tag erreicht. Morgen wieder verfügbar.
                </div>`;
            } else if (err.status === 503) {
              resultEl.innerHTML = `
                <div style="padding:var(--space-3);background:var(--c-surface);
                             border-radius:var(--radius-md);border:1px solid var(--c-danger);
                             font-size:var(--text-sm)">
                  KI momentan nicht verfügbar. Bitte später versuchen.
                </div>`;
            } else {
              UI.toast.error(err.message || 'Fehler bei der KI-Anfrage.');
              return;
            }
            resultEl.style.display = '';
            return;
          }

          const antwortHtml = _esc(result.antwort)
            .replace(/\n\n/g, '</p><p style="margin:var(--space-2) 0">')
            .replace(/\n/g, '<br>');
          const restHtml = result.limit - result.anfragen_heute > 0
            ? `<p style="font-size:var(--text-xs);color:var(--c-text-muted);margin:var(--space-3) 0 0">
                 Noch ${result.limit - result.anfragen_heute} von ${result.limit} Anfragen heute verfügbar.
               </p>`
            : `<p style="font-size:var(--text-xs);color:var(--c-text-muted);margin:var(--space-3) 0 0">
                 Tageslimit erreicht. Morgen wieder verfügbar.
               </p>`;

          resultEl.innerHTML = `
            <div style="margin-top:var(--space-4);padding:var(--space-4);
                        background:var(--c-surface);border-radius:var(--radius-md);
                        border:1px solid var(--c-border)">
              <div style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
                          margin-bottom:var(--space-2);color:var(--c-text-secondary)">
                <svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#stethoscope"></use></svg>
                Einschätzung
              </div>
              <p style="font-size:var(--text-sm);line-height:1.7;margin:0">${antwortHtml}</p>
              ${restHtml}
            </div>
            <div style="margin-top:var(--space-3);padding:var(--space-3);
                        background:#fee2e2;border-radius:var(--radius-md);
                        font-size:var(--text-xs);color:#991b1b;
                        border:1px solid #fca5a5">
              <strong>&#9888;&#65039; Dies ist keine medizinische Diagnose.</strong>
              Bei ernsthaften Symptomen sofort zum Tierarzt.
            </div>`;
          resultEl.style.display = '';

          // Submit-Button ausblenden wenn Limit erschöpft
          if (result.anfragen_heute >= result.limit) {
            btn.disabled = true;
            btn.textContent = 'Limit erreicht';
          }
        });
      });
  }

  return { init, refresh, openNew, onDogChange };

})();
