// Maison 57 — Wohnungen: erst das Gefühl, dann das Werkzeug.
// Kopf, Wohngefühl, Kategorie-Highlights (aus der Flächenaufstellung), Material,
// Flexizone/Freiflächen, Typen-Galerie, Finder (Liste + Gebäudeschnitt), Vormerkung.
const {
  Button: WBtn, TextLink: WTextLink,
  Reveal: WReveal, WordReveal: WWordReveal, LineMask: WLineMask, RevealImage: WRevealImage,
} = window.Maison57DesignSystem_40d525;
const WIMG = '/assets/renderings/';
const WStore = window.M57Store;
const planHref = (u) => (window.M57_PLAN ? window.M57_PLAN.href(u) : null);
const zeigePlan = (u) => { if (window.M57ZeigePlan) window.M57ZeigePlan(u); };
const WSECTION = 'clamp(4rem, 8vw, 6.5rem)';

/* Kategorie-Highlights — je Wohnungskategorie die Kennzahlen aus der
   Flächenaufstellung, vor Ausstattung und Highlights. Deep-Link in den Finder. */
function KategorieHighlights({ onFinder }) {
  const cats = [
    { img: 'interior-wohnen-garten.webp', name: 'Gartenwohnungen', geschoss: 'Erdgeschoss', facts: [['Einheiten', '8'], ['Zimmer', '2 bis 4'], ['Wohnfläche', 'ab 53,3 m²'], ['Garten', 'bis 217,5 m²']], filter: { frei: ['Garten'] } },
    { img: 'interior-wohnen-balkon.webp', name: 'Stadtwohnungen', geschoss: '1. und 2. Obergeschoss', facts: [['Einheiten', '18'], ['Zimmer', '2 bis 3'], ['Wohnfläche', 'ab 54,2 m²'], ['Balkon', 'bis 26,6 m²']], filter: { frei: ['Balkon'] } },
    { img: 'interior-wohnen-terrasse.webp', name: 'Terrassenwohnungen', geschoss: '2. Obergeschoss und Dachgeschoss', facts: [['Einheiten', '5'], ['Zimmer', '2 bis 4'], ['Wohnfläche', 'ab 50,1 m²'], ['Terrassen', 'bis 68,7 m²']], filter: { frei: ['Dachterrasse'] } },
  ];
  return (
    <section style={{ maxWidth: 'var(--content-max)', margin: '0 auto', padding: '0 var(--page-inset-lg)' }}>
      <h2 style={{ overflow: 'hidden', margin: '0 0 clamp(2rem, 3.5vw, 3rem)', paddingBottom: '0.12em' }}>
        <WLineMask innerStyle={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'clamp(1.75rem, 3vw, 2.75rem)', letterSpacing: '-0.015em', color: 'var(--umbra)' }}>Drei Arten zu wohnen</WLineMask>
      </h2>
      <div className="m57-teaser" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 'clamp(1.5rem, 3vw, 2.5rem)' }}>
        {cats.map((c, i) => (
          <WReveal key={c.name} delay={i * 120}>
            <div>
              <WRevealImage src={WIMG + c.img} alt={c.name} ratio="4 / 3" delay={i * 120} />
              <div style={{ marginTop: 'var(--space-4)' }}>
                <div style={{ fontFamily: 'var(--font-display)', fontSize: '1.4rem', color: 'var(--umbra)' }}>{c.name}</div>
                <div style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)', marginTop: '0.15rem' }}>{c.geschoss}</div>
                <div style={{ borderTop: '1px solid var(--sandstein)', marginTop: 'var(--space-4)' }}>
                  {c.facts.map((f) => (
                    <div key={f[0]} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', padding: 'var(--space-2) 0', borderBottom: '1px solid var(--sandstein-40)' }}>
                      <span style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--umbra-60)' }}>{f[0]}</span>
                      <span className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--umbra)', fontVariantNumeric: 'tabular-nums' }}>{f[1]}</span>
                    </div>
                  ))}
                </div>
                <div style={{ marginTop: 'var(--space-4)' }}>
                  <WTextLink onClick={() => onFinder(c.filter)}>Im Finder ansehen</WTextLink>
                </div>
              </div>
            </div>
          </WReveal>
        ))}
      </div>
    </section>
  );
}

function ViewSwitch({ view, setView }) {
  const tabStyle = (active) => ({
    background: 'none', border: 'none', cursor: 'pointer', padding: '0.2rem 0',
    fontFamily: 'var(--font-text)', fontSize: 'var(--text-body)',
    color: active ? 'var(--umbra)' : 'var(--umbra-60)', fontWeight: active ? 500 : 400,
    borderBottom: active ? '2px solid var(--waldgruen)' : '2px solid transparent',
  });
  return (
    <div style={{ display: 'flex', gap: 'var(--space-6)' }}>
      <button style={tabStyle(view === 'liste')} onClick={() => setView('liste')}>Liste</button>
      <button style={tabStyle(view === 'gebaeude')} onClick={() => setView('gebaeude')}>Gebäude</button>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Finder: stehende Filterspalte links, Ergebnisliste als Karten rechts.
   Aufbau nach dem Muster von noma.wien, gesetzt in unserer Sprache:
   Radius 0, Haarlinien statt Pillen, ein Akzent in Waldgrün, sentence case.
--------------------------------------------------------------------------- */

const F_ZIMMER = ['2', '3', '4'];
const F_HAUS = ['5', '7'];
const F_GESCHOSS = ['EG', '1.OG', '2.OG', 'DG'];
const F_FREI = ['Garten', 'Balkon', 'Dachterrasse'];
const F_STATUS = [['verfuegbar', 'Verfügbar'], ['reserviert', 'Reserviert'], ['verkauft', 'Verkauft'], ['inaktiv', 'Demnächst']];
const FL_MIN = 50;
const FL_MAX = 130;

const leererFilter = () => ({ zimmer: [], haus: [], geschoss: [], frei: [], status: [], flaeche: [FL_MIN, FL_MAX] });

/* Deep-Links aus den Kategorie-Teasern liefern teils Strings ({ geschoss: 'DG' }),
   teils Arrays ({ frei: ['Garten'] }). Beides auf Arrays normalisieren. */
function normFilter(f) {
  const out = leererFilter();
  Object.keys(f || {}).forEach((k) => {
    if (k === 'flaeche' && Array.isArray(f.flaeche)) { out.flaeche = f.flaeche; return; }
    if (!(k in out) || k === 'flaeche') return;
    const v = f[k];
    out[k] = v == null ? [] : (Array.isArray(v) ? v.map(String) : [String(v)]);
  });
  return out;
}

/* Freiflaeche gesamt steht im Titelblock jedes Verkaufsplans und kommt 1:1 aus
   data.js; hier wird nichts mehr zusammengerechnet. */
function freiGesamt(u) { return u.freiGesamt || null; }

const SORTEN = [['top', 'Top-Nr.'], ['klein', 'Wohnfläche aufsteigend'], ['gross', 'Wohnfläche absteigend'], ['zimmer', 'Zimmer'], ['preis', 'Preis aufsteigend'], ['preisab', 'Preis absteigend']];
function sortiere(list, key) {
  const k = list.slice();
  const nr = (u) => parseInt(String(u.top), 10) || 0;
  if (key === 'klein') k.sort((x, y) => x.flaecheNum - y.flaecheNum);
  else if (key === 'gross') k.sort((x, y) => y.flaecheNum - x.flaecheNum);
  else if (key === 'zimmer') k.sort((x, y) => x.zimmer - y.zimmer || x.haus - y.haus || nr(x) - nr(y));
  // Einheiten ohne gepflegten Preis stehen bei der Preissortierung am Ende.
  else if (key === 'preis') k.sort((x, y) => (x.verkaufspreis || Infinity) - (y.verkaufspreis || Infinity));
  else if (key === 'preisab') k.sort((x, y) => (y.verkaufspreis || -1) - (x.verkaufspreis || -1));
  else k.sort((x, y) => x.haus - y.haus || nr(x) - nr(y));
  // In Justimmo noch nicht aktivierte Wohnungen (ausgegraut) stehen immer am Ende.
  const grau = (u) => (u.status === 'inaktiv' ? 1 : 0);
  return k.map((u, i) => [u, i]).sort((x, y) => grau(x[0]) - grau(y[0]) || x[1] - y[1]).map((p) => p[0]);
}

function Chip({ active, onClick, children }) {
  return (
    <button type="button" onClick={onClick} aria-pressed={active} style={{
      fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', lineHeight: 1,
      padding: '0.45rem 0.7rem', cursor: 'pointer', borderRadius: 0,
      border: '1px solid ' + (active ? 'var(--waldgruen)' : 'var(--sandstein)'),
      background: active ? 'var(--waldgruen)' : 'transparent',
      color: active ? 'var(--warmweiss)' : 'var(--umbra)',
      transition: 'background-color 180ms ease, border-color 180ms ease, color 180ms ease',
    }}>{children}</button>
  );
}

function FGruppe({ titel, children }) {
  return (
    <div style={{ paddingTop: 'var(--space-5)', marginTop: 'var(--space-5)', borderTop: '1px solid var(--sandstein-40)' }}>
      <div style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)', marginBottom: 'var(--space-3)' }}>{titel}</div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.35rem' }}>{children}</div>
    </div>
  );
}

/* Zweigriffiger Bereichsregler: zwei übereinanderliegende Range-Felder,
   Griffe quadratisch, damit Radius 0 auch hier gilt. */
function Bereich({ titel, min, max, wert, onChange, einheit }) {
  const [a, b] = wert;
  const pct = (v) => ((v - min) / (max - min)) * 100;
  return (
    <div style={{ paddingTop: 'var(--space-5)', marginTop: 'var(--space-5)', borderTop: '1px solid var(--sandstein-40)' }}>
      <div className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)', marginBottom: 'var(--space-3)', fontVariantNumeric: 'tabular-nums' }}>
        {titel}: {a} bis {b} {einheit}
      </div>
      <div className="m57-range">
        <span className="trk"></span>
        <span className="sel" style={{ left: pct(a) + '%', right: (100 - pct(b)) + '%' }}></span>
        <input type="range" min={min} max={max} value={a} aria-label={titel + ', von'}
          onChange={(e) => onChange([Math.min(Number(e.target.value), b), b])} />
        <input type="range" min={min} max={max} value={b} aria-label={titel + ', bis'}
          onChange={(e) => onChange([a, Math.max(Number(e.target.value), a)])} />
      </div>
    </div>
  );
}

function FilterSpalte({ f, setF, reset, aktiv }) {
  const toggle = (k, v) => setF((s) => ({ ...s, [k]: s[k].includes(v) ? s[k].filter((x) => x !== v) : s[k].concat(v) }));
  const an = (k, v) => f[k].includes(v);
  return (
    <aside className="m57-filterspalte" style={{ position: 'sticky', top: 'calc(var(--space-6) + 60px)', alignSelf: 'start' }}>
      <div style={{ border: '1px solid var(--sandstein)', background: 'var(--surface-card)', padding: 'clamp(1rem, 2vw, 1.4rem)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 'var(--space-4)' }}>
          <span style={{ fontFamily: 'var(--font-display)', fontSize: '1.15rem', color: 'var(--umbra)' }}>Filter</span>
          <button type="button" onClick={reset} disabled={!aktiv} style={{
            background: 'none', border: 'none', padding: 0, cursor: aktiv ? 'pointer' : 'default',
            fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)',
            color: aktiv ? 'var(--waldgruen)' : 'var(--sandstein)',
            textDecoration: aktiv ? 'underline' : 'none', textUnderlineOffset: '0.2em',
          }}>Zurücksetzen</button>
        </div>
        <FGruppe titel="Zimmer">
          {F_ZIMMER.map((z) => <Chip key={z} active={an('zimmer', z)} onClick={() => toggle('zimmer', z)}>{z} Zimmer</Chip>)}
        </FGruppe>
        <Bereich titel="Wohnfläche" min={FL_MIN} max={FL_MAX} wert={f.flaeche} einheit="m²"
          onChange={(v) => setF((s) => ({ ...s, flaeche: v }))} />
        <FGruppe titel="Haus">
          {F_HAUS.map((h) => <Chip key={h} active={an('haus', h)} onClick={() => toggle('haus', h)}>Haus {h}</Chip>)}
        </FGruppe>
        <FGruppe titel="Geschoss">
          {F_GESCHOSS.map((g) => <Chip key={g} active={an('geschoss', g)} onClick={() => toggle('geschoss', g)}>{g}</Chip>)}
        </FGruppe>
        <FGruppe titel="Freiflächen">
          {F_FREI.map((x) => <Chip key={x} active={an('frei', x)} onClick={() => toggle('frei', x)}>{x}</Chip>)}
        </FGruppe>
        <FGruppe titel="Status">
          {F_STATUS.map(([k, l]) => <Chip key={k} active={an('status', k)} onClick={() => toggle('status', k)}>{l}</Chip>)}
        </FGruppe>
      </div>
    </aside>
  );
}

/* Status kommt aus Justimmo (store.js). 'inaktiv' = in Justimmo noch nicht
   aktiviert: ausgegraut, ohne Preis. Ohne Status (Justimmo noch nicht geladen
   oder nicht erreichbar) steht kein Etikett. */
function StatusTag({ status }) {
  const map = {
    verfuegbar: ['Verfügbar', 'var(--waldgruen)', 'var(--waldgruen)'],
    reserviert: ['Reserviert', 'var(--umbra-60)', 'var(--sandstein)'],
    verkauft: ['Verkauft', 'var(--sandstein)', 'var(--sandstein-40)'],
    inaktiv: ['Demnächst', 'var(--umbra-60)', 'var(--sandstein-40)'],
  };
  if (!map[status]) return null;
  const [label, farbe, rand] = map[status];
  return (
    <span style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', color: farbe, border: '1px solid ' + rand, padding: '0.2rem 0.45rem', lineHeight: 1.3, whiteSpace: 'nowrap' }}>{label}</span>
  );
}

function Wert({ titel, wert, klein }) {
  return (
    <div style={{ minWidth: 0 }}>
      <div style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', color: 'var(--umbra-60)' }}>{titel}</div>
      <div className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: klein ? 'var(--text-label)' : 'var(--text-small)', color: 'var(--umbra)', marginTop: '0.15rem', fontVariantNumeric: 'tabular-nums', lineHeight: 1.45 }}>{wert}</div>
    </div>
  );
}

function WohnungsKarte({ u, gewaehlt, onWaehlen, onOpen, onAnfrage }) {
  const href = planHref(u);
  // Preise kommen aus dem Backend (Preisliste). Ohne gepflegten Wert steht kein
  // Preisfeld auf der Karte, "auf Anfrage" gibt es nicht mehr (Kunde 25.09.2026).
  const hatPreis = !!u.verkaufspreis;
  const preis = hatPreis ? '€ ' + Number(u.verkaufspreis).toLocaleString('de-DE') : null;
  const gesamt = freiGesamt(u);
  const grau = u.status === 'inaktiv';
  const weg = u.status === 'verkauft' || grau;
  return (
    <div style={{ border: '1px solid var(--sandstein)', background: 'var(--surface-card)', padding: 'clamp(1rem, 2vw, 1.35rem) clamp(1.1rem, 2.2vw, 1.6rem)', opacity: grau ? 0.45 : weg ? 0.62 : 1, filter: grau ? 'grayscale(1)' : 'none' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 'var(--space-5)' }}>
        <div style={{ display: 'flex', gap: 'var(--space-4)', alignItems: 'flex-start', minWidth: 0 }}>
          <input type="checkbox" checked={gewaehlt} onChange={onWaehlen} disabled={weg}
            aria-label={'Haus ' + u.haus + ', Top ' + u.top + ' für eine gemeinsame Anfrage merken'}
            style={{ marginTop: '0.4rem', width: '14px', height: '14px', flex: 'none', accentColor: 'var(--waldgruen)', cursor: weg ? 'default' : 'pointer' }} />
          <div style={{ minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-3)', flexWrap: 'wrap' }}>
              <button type="button" onClick={onOpen} className="tabular" style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', fontFamily: 'var(--font-display)', fontSize: 'clamp(1.15rem, 1.9vw, 1.5rem)', color: 'var(--umbra)', fontVariantNumeric: 'tabular-nums', textAlign: 'left' }}>Top {u.top}</button>
              <StatusTag status={u.status} />
            </div>
            <div style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--umbra-60)', marginTop: '0.2rem' }}>{u.zimmer} Zimmer · {u.geschoss} · Haus {u.haus}</div>
          </div>
        </div>
        {hatPreis && (
          <div style={{ textAlign: 'right', flex: 'none' }}>
            <div style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', color: 'var(--umbra-60)' }}>Kaufpreis</div>
            <div className="tabular" style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(1rem, 1.7vw, 1.3rem)', color: 'var(--umbra)', fontVariantNumeric: 'tabular-nums', marginTop: '0.15rem', whiteSpace: 'nowrap' }}>{preis}</div>
          </div>
        )}
      </div>
      <div className="m57-kartendaten" style={{ display: 'grid', gridTemplateColumns: '1fr 1.7fr 1fr auto', gap: 'var(--space-5)', alignItems: 'end', marginTop: 'var(--space-5)', paddingTop: 'var(--space-4)', borderTop: '1px solid var(--sandstein-40)' }}>
        <Wert titel="Wohnfläche" wert={u.ug ? <>{u.flaeche} m²<br /><span style={{ fontSize: 'var(--text-micro)', color: 'var(--umbra-60)' }}>EG, dazu UG {u.ug.gesamt} m²</span></> : u.flaeche + ' m²'} />
        <Wert titel="Freiflächen" wert={u.freiflaecheM2 || u.freiflaeche} klein />
        <Wert titel="Freifläche gesamt" wert={gesamt ? gesamt + ' m²' : '-'} />
        <div style={{ display: 'flex', gap: 'var(--space-3)', justifyContent: 'flex-end', flexWrap: 'wrap' }}>
          {href && <WBtn variant="outline" arrow={false} onClick={() => zeigePlan(u)}>Grundriss</WBtn>}
          <WBtn variant="filled" arrow={false} onClick={onAnfrage} disabled={weg}>Anfrage</WBtn>
        </div>
      </div>
    </div>
  );
}

/* Geschoss-Schnitt: beide Häuser gestapelt, Zellen flächenproportional zur
   Wohnfläche, Status-Färbung, Hover-Sync mit der Geschossliste, Klick öffnet Detail. */
function Schnitt({ units, active, onHover, onOpen }) {
  const ref = React.useRef(null);
  const [vis, setVis] = React.useState(false);
  const floors = ['DG', '2.OG', '1.OG', 'EG'];
  React.useEffect(() => {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setVis(true); return; }
    const el = ref.current; if (!el) return;
    let done = false;
    const show = () => { if (!done) { done = true; setVis(true); io.disconnect(); } };
    const io = new IntersectionObserver((es) => { if (es[0].isIntersecting) show(); }, { threshold: 0.25 });
    io.observe(el);
    const t = setTimeout(() => { const r = el.getBoundingClientRect(); const vh = window.innerHeight || 800; if (r.top < vh + 80 && r.bottom > -80) show(); }, 1000);
    return () => { clearTimeout(t); io.disconnect(); };
  }, []);
  const cell = (u, isHot) => ({
    flex: (u.flaecheNum || 60), minWidth: 0, textAlign: 'center', padding: '0.85rem 0.25rem',
    fontSize: 'var(--text-micro)', fontVariantNumeric: 'tabular-nums', cursor: 'pointer',
    borderRight: '1px solid ' + (isHot ? 'rgba(251,249,244,0.28)' : 'var(--sandstein-40)'),
    background: isHot ? 'var(--waldgruen)' : 'transparent',
    color: isHot ? 'var(--warmweiss)' : (u.status === 'verkauft' || u.status === 'inaktiv' ? 'var(--sandstein)' : u.status === 'reserviert' ? 'var(--umbra-60)' : 'var(--umbra)'),
    transition: 'background-color 200ms var(--ease-reveal), color 200ms ease',
  });
  return (
    <div ref={ref}>
      <div className="m57-building" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'clamp(2rem, 5vw, 4rem)' }}>
        {[5, 7].map((h) => (
          <div key={h}>
            <div style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)', marginBottom: 'var(--space-3)' }}>Schnitt Haus {h}, Geschosse gestapelt</div>
            <div style={{ borderBottom: '3px solid var(--umbra)' }}>
              {floors.map((fl, fi) => {
                const onFloor = units.filter((u) => u.haus === h && u.geschoss === fl);
                return (
                  <div key={fl} style={{ display: 'flex', border: '1px solid var(--sandstein)', borderBottom: 'none', transform: vis ? 'scaleY(1)' : 'scaleY(0)', transformOrigin: 'bottom', opacity: vis ? 1 : 0, transition: `transform 500ms var(--ease-reveal) ${fi * 90}ms, opacity 500ms ease ${fi * 90}ms` }}>
                    <div style={{ width: '3rem', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', padding: '0.6rem 0', color: 'var(--umbra-60)', borderRight: '1px solid var(--sandstein)', background: 'var(--surface-card)' }}>{fl}</div>
                    <div style={{ flex: 1, display: 'flex' }}>
                      {onFloor.length === 0
                        ? <div style={{ flex: 1, padding: '0.85rem 0', textAlign: 'center', color: 'var(--sandstein)', fontSize: 'var(--text-micro)' }}>-</div>
                        : onFloor.map((u) => {
                          const isHot = active && active.id === u.id;
                          return (
                            <div key={u.id} className="tabular" onMouseEnter={() => onHover(u)} onMouseLeave={() => onHover(null)} onClick={() => onOpen && onOpen(u)} title={'Top ' + u.top + ' · ' + u.flaeche + ' m²'} style={cell(u, isHot)}>{u.top}</div>
                          );
                        })}
                    </div>
                  </div>
                );
              })}
              <div style={{ display: 'flex', background: 'var(--umbra)', color: 'var(--warmweiss)' }}>
                <div style={{ width: '3rem', flex: 'none' }}></div>
                <div style={{ flex: 1, padding: '0.3rem 0', textAlign: 'center', fontSize: 'var(--text-micro)', letterSpacing: '0.04em' }}>Tiefgarage</div>
              </div>
            </div>
          </div>
        ))}
      </div>
      <div style={{ display: 'flex', gap: 'var(--space-6)', flexWrap: 'wrap', marginTop: 'var(--space-4)', fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', color: 'var(--umbra-60)' }}>
        <span>Fläche der Zellen maßstäblich zur Wohnfläche</span>
        <span style={{ color: 'var(--umbra)' }}>■ verfügbar</span>
        <span style={{ color: 'var(--umbra-60)' }}>■ reserviert</span>
        <span style={{ color: 'var(--sandstein)' }}>■ verkauft oder demnächst</span>
      </div>
    </div>
  );
}

function BuildingView({ units, onOpen }) {
  const houses = [5, 7];
  const floors = ['DG', '2.OG', '1.OG', 'EG'];
  const [hot, setHot] = React.useState(null);
  return (
    <div>
      <div className="m57-building" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'clamp(2rem, 5vw, 4rem)', paddingTop: 'clamp(1rem, 2vw, 1.5rem)' }}>
      {houses.map((h) => (
        <div key={h}>
          <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'var(--text-title)', color: 'var(--umbra)', margin: '0 0 var(--space-5)' }}>Haus {h}</h3>
          <div style={{ border: '1px solid var(--sandstein)' }}>
            {floors.map((fl) => {
              const onFloor = units.filter((u) => u.haus === h && u.geschoss === fl);
              return (
                <div key={fl} style={{ borderBottom: fl === 'EG' ? 'none' : '1px solid var(--sandstein)', padding: 'var(--space-4) var(--space-5)', display: 'flex', alignItems: 'center', gap: 'var(--space-5)' }}>
                  <span style={{ width: '3.5rem', flex: 'none', fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)' }}>{fl}</span>
                  <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
                    {onFloor.length === 0 ? <span style={{ color: 'var(--sandstein)', fontSize: 'var(--text-small)' }}>keine</span> : onFloor.map((u) => (
                      <button key={u.top} onClick={() => onOpen(u)} onMouseEnter={() => setHot(u)} onMouseLeave={() => setHot(null)} className="tabular"
                        style={{ cursor: 'pointer', fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', fontVariantNumeric: 'tabular-nums',
                          padding: '0.35rem 0.6rem', border: '1px solid ' + (hot && hot.id === u.id ? 'var(--waldgruen)' : 'var(--sandstein)'),
                          background: hot && hot.id === u.id ? 'var(--waldgruen)' : (u.status === 'verkauft' || u.status === 'inaktiv' ? 'transparent' : 'var(--surface-card)'),
                          color: hot && hot.id === u.id ? 'var(--warmweiss)' : (u.status === 'verkauft' || u.status === 'inaktiv' ? 'var(--sandstein)' : 'var(--umbra)'),
                          textDecoration: u.status === 'verkauft' ? 'line-through' : 'none', transition: 'background-color 180ms ease, border-color 180ms ease, color 180ms ease' }}>
                        {u.top} · {u.flaeche} m²
                      </button>
                    ))}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      ))}
      </div>
    </div>
  );
}

function EmptyState({ onReset }) {
  return (
    <div style={{ padding: 'clamp(4rem, 8vw, 7rem) 0', textAlign: 'center' }}>
      <p style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-body)', color: 'var(--umbra-90)', margin: '0 0 var(--space-4)' }}>Keine Wohnung entspricht dieser Auswahl.</p>
      <WTextLink onClick={onReset} arrow={false}>Filter zurücksetzen</WTextLink>
    </div>
  );
}

function Finder({ initialFilter, onOpenDetail, onAnfrage, auswahl, setAuswahl }) {
  const [view, setView] = React.useState('liste');
  const [sort, setSort] = React.useState('top');
  const [, force] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => WStore.subscribe(force), []);
  const [f, setF] = React.useState(() => normFilter(initialFilter));
  React.useEffect(() => { if (initialFilter) setF(normFilter(initialFilter)); }, [initialFilter]);
  const reset = () => setF(leererFilter());
  const aktiv = f.zimmer.length || f.haus.length || f.geschoss.length || f.frei.length || f.status.length
    || f.flaeche[0] !== FL_MIN || f.flaeche[1] !== FL_MAX;

  const all = WStore.units();
  const units = sortiere(all.filter((u) => {
    if (f.zimmer.length && !f.zimmer.includes(String(u.zimmer))) return false;
    if (f.haus.length && !f.haus.includes(String(u.haus))) return false;
    if (f.geschoss.length && !f.geschoss.includes(u.geschoss)) return false;
    if (f.frei.length && !f.frei.includes(u.freiflaeche)) return false;
    if (f.status.length && !f.status.includes(u.status)) return false;
    if (u.flaecheNum < f.flaeche[0] || u.flaecheNum > f.flaeche[1]) return false;
    return true;
  }), sort);
  const verfuegbar = all.filter((u) => u.status === 'verfuegbar').length;
  const statusBekannt = all.some((u) => u.status);
  const listKey = JSON.stringify(f) + view + sort;
  // Gemerkt wird die Einheiten-ID (H5-1, H7-1), nicht nur die Top-Nummer: Top 1 gibt es in beiden Haeusern.
  const merken = (u) => setAuswahl((s) => s.includes(u.id) ? s.filter((t) => t !== u.id) : s.concat(u.id));

  return (
    <div id="finder">
      <style>{`
        @keyframes m57rowIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
        @media (prefers-reduced-motion: reduce) { .m57-rowin { animation: none !important; } }
        .m57-range { position: relative; height: 24px; }
        .m57-range .trk { position: absolute; top: 11px; left: 0; right: 0; height: 1px; background: var(--sandstein); }
        .m57-range .sel { position: absolute; top: 11px; height: 1px; background: var(--umbra); }
        .m57-range input[type=range] { position: absolute; left: 0; top: 0; width: 100%; height: 24px; margin: 0;
          -webkit-appearance: none; appearance: none; background: none; pointer-events: none; }
        .m57-range input[type=range]:focus { outline: none; }
        .m57-range input[type=range]::-webkit-slider-runnable-track { height: 24px; background: none; }
        .m57-range input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; pointer-events: auto;
          width: 11px; height: 11px; margin-top: 6px; border-radius: 0; background: var(--waldgruen); border: none; cursor: ew-resize; }
        .m57-range input[type=range]::-moz-range-track { height: 24px; background: none; }
        .m57-range input[type=range]::-moz-range-thumb { pointer-events: auto;
          width: 11px; height: 11px; border-radius: 0; background: var(--waldgruen); border: none; cursor: ew-resize; }
        @media (max-width: 900px) {
          .m57-finder { grid-template-columns: 1fr !important; }
          .m57-filterspalte { position: static !important; }
        }
        @media (max-width: 640px) {
          .m57-kartendaten { grid-template-columns: 1fr 1fr !important; }
        }
      `}</style>
      <section style={{ maxWidth: 'var(--content-max)', margin: '0 auto', padding: '0 var(--page-inset-lg)' }}>
        <WReveal>
          <div style={{ maxWidth: '46ch' }}>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'clamp(1.75rem, 3vw, 2.75rem)', letterSpacing: '-0.015em', color: 'var(--umbra)', margin: 0 }}>Wohnungen finden und anfragen</h2>
            <p style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-lead)', lineHeight: 1.6, color: 'var(--umbra-90)', margin: 'var(--space-4) 0 0' }}>
              Wählen Sie Größe, Zimmer und Freifläche. Wir senden Ihnen Verfügbarkeit, Grundriss und Unterlagen persönlich zu.
            </p>
            <p className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)', margin: 'var(--space-3) 0 0', fontVariantNumeric: 'tabular-nums' }}>
              {statusBekannt ? <>Derzeit {verfuegbar} von 31 Wohnungen verfügbar. </> : null}Jeden Grundriss öffnen Sie mit einem Klick auf „Grundriss“.
            </p>
            <p style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', margin: 'var(--space-2) 0 0' }}>
              <a href={window.M57_PLAN.gesamt} download="Am-Waldrain_Verkaufsplaene_Gesamt.pdf" style={{ color: 'var(--waldgruen)', textDecoration: 'underline', textUnderlineOffset: '0.2em' }}>Alle Verkaufspläne als PDF herunterladen</a>
              <span style={{ color: 'var(--umbra-60)' }}> (16 MB, Stand {window.M57_PLAN.stand})</span>
            </p>
          </div>
        </WReveal>

        <div className="m57-finder" style={{ display: 'grid', gridTemplateColumns: 'clamp(210px, 23%, 270px) 1fr', gap: 'clamp(1.5rem, 3vw, 2.75rem)', alignItems: 'start', marginTop: 'clamp(2rem, 4vw, 3rem)' }}>
          <FilterSpalte f={f} setF={setF} reset={reset} aktiv={!!aktiv} />

          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 'var(--space-5)', flexWrap: 'wrap', paddingBottom: 'var(--space-2)' }}>
              <span className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--umbra)', fontVariantNumeric: 'tabular-nums' }}>
                {units.length} {units.length === 1 ? 'Wohnung' : 'Wohnungen'} gefunden
              </span>
              <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-6)', flexWrap: 'wrap' }}>
                <ViewSwitch view={view} setView={setView} />
                <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-3)' }}>
                  <span style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)' }}>Sortierung</span>
                  <select value={sort} onChange={(e) => setSort(e.target.value)} style={{
                    fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra)',
                    background: 'var(--surface-card)', border: '1px solid var(--sandstein)', borderRadius: 0,
                    padding: '0.4rem 0.6rem', cursor: 'pointer',
                  }}>
                    {SORTEN.map(([k, l]) => <option key={k} value={k}>{l}</option>)}
                  </select>
                </label>
              </div>
            </div>

            {units.length === 0 ? (
              <EmptyState onReset={reset} />
            ) : view === 'liste' ? (
              <div key={listKey} style={{ display: 'grid', gap: 'var(--space-4)', marginTop: 'var(--space-5)' }}>
                {units.map((u, i) => (
                  <div key={u.id} className="m57-rowin" style={{ animation: 'm57rowIn 350ms var(--ease-reveal) both', animationDelay: `${Math.min(i, 8) * 40}ms` }}>
                    <WohnungsKarte u={u} gewaehlt={auswahl.includes(u.id)} onWaehlen={() => merken(u)}
                      onOpen={() => onOpenDetail(u)} onAnfrage={() => onAnfrage(u)} />
                  </div>
                ))}
              </div>
            ) : (
              <div key={listKey} className="m57-rowin" style={{ animation: 'm57rowIn 350ms var(--ease-reveal) both', marginTop: 'var(--space-6)' }}>
                <BuildingView units={units} onOpen={onOpenDetail} />
              </div>
            )}
          </div>
        </div>
      </section>
    </div>
  );
}

/* Wohnraeume - die Innenaufnahmen aus den Verkaufsunterlagen als stille
   Auswahl: links die Raeume in grosser Serife, rechts das Bild, das mit der
   Auswahl wechselt (Hover am Desktop, Tap am Telefon). Auf schmalen Schirmen
   steht das Bild oben und bleibt beim Scrollen der Liste stehen. */
function Wohnraeume() {
  const raeume = [
    { label: 'Wohnraum mit Terrasse', einheit: 'Haus 5, Top 17+18', img: 'interior-wohnen-terrasse.webp' },
    { label: 'Wohnraum mit Garten', einheit: 'Haus 7, Top 2+3', img: 'interior-wohnen-garten.webp' },
    { label: 'Schlafzimmer', einheit: 'Haus 7, Top 2+3', img: 'interior-schlafen.webp' },
    { label: 'Wohnraum mit Balkon', einheit: 'Haus 7, Top 12', img: 'interior-wohnen-balkon.webp' },
    { label: 'Badezimmer', einheit: 'Haus 7, Top 13', img: 'interior-bad.webp' },
  ];
  const [active, setActive] = React.useState(0);
  return (
    <section style={{ maxWidth: 'var(--content-max)', margin: '0 auto', padding: '0 var(--page-inset-lg)' }}>
      <style>{`
        .m57-wohnraeume { display: grid; grid-template-columns: 1fr 1.35fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
        .m57-wohnraeume-bild { position: sticky; top: 96px; }
        @media (max-width: 900px) {
          .m57-wohnraeume { grid-template-columns: 1fr; gap: 1.5rem; }
          .m57-wohnraeume-bild { order: -1; }
        }
      `}</style>
      <h2 style={{ overflow: 'hidden', margin: '0 0 clamp(1.75rem, 3vw, 2.5rem)', paddingBottom: '0.1em' }}>
        <WLineMask innerStyle={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'clamp(1.5rem, 2.4vw, 2.25rem)', letterSpacing: '-0.015em', color: 'var(--umbra)' }}>Wohnräume</WLineMask>
      </h2>
      <div className="m57-wohnraeume">
        <div style={{ borderTop: '1px solid var(--sandstein)' }}>
          {raeume.map((r, i) => {
            const on = active === i;
            return (
              <div key={r.img} onMouseEnter={() => setActive(i)} onClick={() => setActive(i)}
                style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 'var(--space-5)', padding: 'clamp(0.7rem, 1.4vw, 1.1rem) 0', borderBottom: '1px solid var(--sandstein-40)', cursor: 'pointer' }}>
                <span style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'clamp(1.35rem, 2.4vw, 2.1rem)', lineHeight: 1.1, color: on ? 'var(--umbra)' : 'var(--sandstein)', transition: 'color 300ms ease' }}>{r.label}</span>
                <span className="tabular" style={{ flex: 'none', fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: on ? 'var(--umbra-90)' : 'var(--sandstein)', fontVariantNumeric: 'tabular-nums', transition: 'color 300ms ease', textAlign: 'right' }}>{r.einheit}</span>
              </div>
            );
          })}
        </div>
        <div className="m57-wohnraeume-bild">
          <div style={{ position: 'relative', aspectRatio: '4 / 3', overflow: 'hidden', background: 'var(--warmweiss)' }}>
            {raeume.map((r, i) => (
              <img key={r.img} src={WIMG + r.img} alt={(r.alt || r.label) + ', ' + r.einheit}
                style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', opacity: active === i ? 1 : 0, transition: 'opacity 500ms var(--ease-reveal)' }} />
            ))}
            <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: 'var(--space-5)', background: 'linear-gradient(to top, rgba(24,30,24,0.55), rgba(24,30,24,0))', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 'var(--space-4)' }}>
              <span style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(1.1rem, 1.6vw, 1.4rem)', color: 'var(--warmweiss)' }}>{raeume[active].label}</span>
              <span className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'rgba(251,249,244,0.85)', fontVariantNumeric: 'tabular-nums' }}>{raeume[active].einheit}</span>
            </div>
          </div>
        </div>
      </div>
      <p style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', color: 'var(--umbra-60)', margin: 'var(--space-4) 0 0' }}>Visualisierungen, Möblierung beispielhaft.</p>
    </section>
  );
}

/* Finder-Zeile: ein leiser Absprung in den Wohnungsfinder zwischen den
   Kapiteln, immer mit einem Satz, der sagt, was dort wartet. */
function FinderZeile({ text, label = 'Zum Wohnungsfinder', onFinder }) {
  return (
    <section style={{ maxWidth: 'var(--content-max)', margin: '0 auto', padding: '0 var(--page-inset-lg)' }}>
      <WReveal>
        <div style={{ borderTop: '1px solid var(--sandstein)', paddingTop: 'var(--space-6)', display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between', gap: 'var(--space-5)' }}>
          <p style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'clamp(1.15rem, 1.7vw, 1.45rem)', lineHeight: 1.35, color: 'var(--umbra)', margin: 0, maxWidth: '34ch' }}>{text}</p>
          <WBtn variant="filled" onClick={() => onFinder()}>{label}</WBtn>
        </div>
      </WReveal>
    </section>
  );
}

function WohnungenScreen({ onOpenDetail, onVormerkung, initialFinder }) {
  const [finderFilter, setFinderFilter] = React.useState(initialFinder || null);
  // Mehrfachauswahl aus dem Finder. Die gemerkten Tops laufen in das
  // Vormerkungs-Formular am Seitenende, damit eine Anfrage alle abdeckt.
  const [auswahl, setAuswahl] = React.useState([]);
  const gemerkt = auswahl.map((id) => WStore.unit(id)).filter(Boolean);
  const zurFormular = () => {
    const el = document.getElementById('vormerkung');
    const sc = window.__m57Scroller;
    if (el && sc) sc.scrollTo({ top: el.offsetTop - 40, behavior: 'smooth' });
  };
  const toFinder = (filter) => {
    setFinderFilter(filter || {});
    const el = document.getElementById('finder');
    const sc = window.__m57Scroller;
    if (el && sc) sc.scrollTo({ top: el.offsetTop - 80, behavior: 'smooth' });
  };
  React.useEffect(() => {
    if (initialFinder) { const t = setTimeout(() => toFinder(initialFinder), 350); return () => clearTimeout(t); }
  }, []);
  return (
    <div>
      <WohnungenKopf />
      <FullBleed img={WIMG + 'exterior-dachterrasse-h5-top-17-18.webp'} hoch={WIMG + 'exterior-dachterrasse-h5-top-17-18-hoch.webp'} alt="Dachterrasse von Haus 5, Top 17+18, mit Blick über Wien bei Sonnenuntergang" height="66vh">
        <p style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(1.5rem, 2.6vw, 2.25rem)', color: 'var(--warmweiss)', margin: 0 }}>
          <WWordReveal text="Räume, die dem *Licht* folgen." color="var(--warmweiss)" dimColor="rgba(251,249,244,0.35)" />
        </p>
      </FullBleed>
      <div style={{ paddingTop: WSECTION }}></div>
      <WohnungenTypen onFinder={toFinder} />
      <div style={{ paddingTop: WSECTION }}></div>
      <Wohnraeume />
      <div style={{ paddingTop: WSECTION }}></div>
      <FinderZeile text="Alle 31 Wohnungen im Überblick, nach Zimmern, Geschoss und Freifläche." onFinder={() => toFinder()} />
      <div style={{ paddingTop: WSECTION }}></div>
      <MaterialCollage />
      <div style={{ paddingTop: WSECTION }}></div>
      {/* Pool-Visualisierung Haus 7, Top 2+3 (19.10.2026): volle Breite, nicht volle Hoehe; Pool ist Sonderausstattung */}
      <FullBleed img={WIMG + 'exterior-pool-h7-top-2-3.webp'} hoch={WIMG + 'exterior-pool-h7-top-2-3-hoch.webp'}
        alt="Eigengarten von Haus 7, Top 2+3, mit Pool, Liegen und Sonnenschirmen" height="clamp(360px, 56vw, 74vh)">
        <p style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(1.5rem, 2.6vw, 2.25rem)', color: 'var(--warmweiss)', margin: 0 }}>
          <WWordReveal text="Ihr Garten. Auf Wunsch mit *Pool.*" color="var(--warmweiss)" dimColor="rgba(251,249,244,0.35)" />
        </p>
        <p style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-micro)', color: 'rgba(251,249,244,0.8)', margin: 'var(--space-3) 0 0' }}>
          Haus 7, Top 2+3. Pool als Sonderausstattung, Visualisierung.
        </p>
      </FullBleed>
      <div style={{ paddingTop: WSECTION }}></div>
      {window.Ausstattung ? <window.Ausstattung /> : null}
      <div style={{ paddingTop: WSECTION }}></div>
      <FinderZeile text="Welche Wohnung passt zu Ihnen? Der Finder zeigt, was noch frei ist." onFinder={() => toFinder()} />
      <div style={{ paddingTop: WSECTION }}></div>
      <BesonderheitenDuo onFinder={toFinder} />
      <div style={{ paddingTop: WSECTION }}></div>
      <section style={{ maxWidth: 'var(--content-max)', margin: '0 auto', padding: '0 var(--page-inset-lg)' }}>
        <WBtn variant="filled" onClick={() => window.__m57ToFinder && window.__m57ToFinder()}>Wohnung anfragen</WBtn>
      </section>
      <div style={{ paddingTop: WSECTION }}></div>
      <Finder initialFilter={finderFilter} onOpenDetail={onOpenDetail} onAnfrage={onVormerkung}
        auswahl={auswahl} setAuswahl={setAuswahl} />
      {auswahl.length > 0 && (
        <div style={{ position: 'sticky', bottom: 0, zIndex: 60, background: 'var(--warmweiss)', borderTop: '1px solid var(--sandstein)', marginTop: 'var(--space-6)' }}>
          <div style={{ maxWidth: 'var(--content-max)', margin: '0 auto', padding: 'var(--space-4) var(--page-inset-lg)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 'var(--space-5)', flexWrap: 'wrap' }}>
            <span className="tabular" style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--umbra)', fontVariantNumeric: 'tabular-nums' }}>
              {auswahl.length} {auswahl.length === 1 ? 'Wohnung' : 'Wohnungen'} gemerkt: {gemerkt.map((u) => `Haus ${u.haus} Top ${u.top}`).join(', ')}
            </span>
            <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-6)' }}>
              <button type="button" onClick={() => setAuswahl([])} style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', fontFamily: 'var(--font-text)', fontSize: 'var(--text-label)', color: 'var(--umbra-60)', textDecoration: 'underline', textUnderlineOffset: '0.2em' }}>Auswahl leeren</button>
              <WBtn variant="filled" onClick={zurFormular}>Auswahl anfragen</WBtn>
            </div>
          </div>
        </div>
      )}
      <div style={{ paddingTop: WSECTION }}></div>
      {window.FAQ ? <window.FAQ /> : null}
      <div style={{ paddingTop: WSECTION }}></div>
      {/* Ohne allgemeines Kontaktformular erscheint das Formular nur fuer gemerkte Wohnungen (Auswahl anfragen) */}
      {(window.M57_KONTAKTFORMULAR !== false || gemerkt.length > 0) && <VormerkungSection einheiten={gemerkt} />}
    </div>
  );
}

function DetailOverlay({ unit, onClose, onAnfrage }) {
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    if (unit) {
      const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      if (reduce) { setShown(true); return; }
      const t = setTimeout(() => setShown(true), 30);
      return () => clearTimeout(t);
    }
    setShown(false);
  }, [unit]);
  const close = () => { setShown(false); setTimeout(onClose, 320); };
  if (!unit) return null;
  const href = planHref(unit);
  const preis = unit.verkaufspreis ? '€ ' + Number(unit.verkaufspreis).toLocaleString('de-DE') : null;
  const facts = [
    ['Wohnfläche', unit.ug ? `${unit.flaeche} m² im Erdgeschoss` : `${unit.flaeche} m²`],
    ...(unit.ug ? [['Untergeschoss', `${unit.ug.gesamt} m², davon Flexizone ${unit.ug.flexizone} m²`]] : []),
    ['Zimmer', `${unit.zimmer}`],
    ['Freiflächen', unit.freiflaecheM2 || unit.freiflaeche],
    ['Freifläche gesamt', unit.freiGesamt ? unit.freiGesamt + ' m²' : '-'],
    ['Einlagerungsraum', unit.einlagerung ? unit.einlagerung + ' m²' : '-'],
    ['Geschoss', unit.geschoss],
    ['Haus', `Haus ${unit.haus}`],
    ['Stellplatz', 'optional, Tiefgarage'],
    ...(unit.status ? [['Status', window.M57_STATUS_LABEL[unit.status]]] : []),
    ...(preis ? [['Kaufpreis', preis]] : []),
  ];
  return (
    <div onClick={close} style={{ position: 'fixed', inset: 0, zIndex: 100, background: 'rgba(35,42,32,0.45)', display: 'flex', justifyContent: 'flex-end', opacity: shown ? 1 : 0, transition: 'opacity 320ms var(--ease-reveal)' }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: 'min(760px, 100%)', height: '100%', overflowY: 'auto', background: 'var(--surface-page)', transform: shown ? 'none' : 'translateX(40px)', opacity: shown ? 1 : 0, transition: 'transform 420ms var(--ease-reveal), opacity 320ms var(--ease-reveal)' }}>
        <div style={{ position: 'sticky', top: 0, zIndex: 2, background: 'var(--surface-page)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: 'var(--space-6) var(--space-8)', borderBottom: '1px solid var(--sandstein)' }}>
          <span className="tabular" style={{ fontFamily: 'var(--font-display)', fontSize: 'var(--text-title)', color: 'var(--umbra)' }}>Haus {unit.haus}, Top {unit.top}</span>
          <button onClick={close} aria-label="Schließen" style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '1.4rem', color: 'var(--umbra-60)', lineHeight: 1 }}>✕</button>
        </div>
        <div style={{ padding: 'var(--space-8)' }}>
          {href ? (
            <div style={{ marginBottom: 'var(--space-8)' }}>
              <button type="button" onClick={() => zeigePlan(unit)} aria-label="Grundriss vergrößern" style={{ display: 'block', width: '100%', padding: 0, border: 'none', background: 'none', cursor: 'zoom-in' }}>
                <window.PlanView src={href} label={'Top ' + unit.top} />
              </button>
            </div>
          ) : (
            <div style={{ background: 'var(--surface-card)', border: '1px solid var(--sandstein)', aspectRatio: '4 / 3', display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', color: 'var(--umbra-60)', fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', marginBottom: 'var(--space-8)', padding: 'var(--space-6)' }}>Grundriss Top {unit.top}</div>
          )}
          <div style={{ marginBottom: 'var(--space-6)' }}>
            {facts.map((row) => (
              <div key={row[0]} style={{ display: 'flex', justifyContent: 'space-between', padding: 'var(--space-3) 0', borderBottom: '1px solid var(--sandstein)' }}>
                <span style={{ color: 'var(--umbra-60)', fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)' }}>{row[0]}</span>
                <span className="tabular" style={{ color: 'var(--umbra)', fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', fontVariantNumeric: 'tabular-nums', textAlign: 'right', paddingLeft: 'var(--space-5)' }}>{row[1]}</span>
              </div>
            ))}
          </div>
          <p style={{ color: 'var(--umbra-90)', fontSize: 'var(--text-small)', lineHeight: 1.7, margin: '0 0 var(--space-6)' }}>Eichenparkett von Weitzer, Fußbodenheizung und Fußbodenkühlung aus Erdwärme, Holz-Alu-Fenster dreifach verglast.</p>
          <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-8)', flexWrap: 'wrap' }}>
            <WBtn variant="filled" onClick={() => onAnfrage(unit)}>Diese Wohnung anfragen</WBtn>
            {href && <button type="button" onClick={() => zeigePlan(unit)} style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--waldgruen)', textDecoration: 'underline', textUnderlineOffset: '0.2em' }}>Grundriss vergrößern</button>}
            {href && <a href={href} download={window.M57_PLAN.downloadName(unit)} style={{ fontFamily: 'var(--font-text)', fontSize: 'var(--text-small)', color: 'var(--waldgruen)', textDecoration: 'underline', textUnderlineOffset: '0.2em' }}>PDF herunterladen</a>}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { WohnungenScreen, DetailOverlay });
