// ============================================================
// pages.jsx — page components for all 7 sections
// ============================================================

const { useState, useEffect, useMemo, useRef } = React;

// ------------------ shared bits ------------------

const PhSlot = ({ id, label, style, src, radius, shape, alt }) => (
  <image-slot
    id={id}
    placeholder={label}
    shape={shape || "rounded"}
    radius={radius != null ? String(radius) : "10"}
    style={style}
    src={src || undefined}
    alt={alt != null ? alt : (label || "")}
  ></image-slot>
);

const Eyebrow = ({ children }) => <div className="eyebrow">{children}</div>;

// ------------------ LIGHTBOX (global) ------------------

function openLightbox(images, idx, alts) {
  window.dispatchEvent(new CustomEvent("dmhf:lightbox", {
    detail: { images: Array.isArray(images) ? images : [images], idx: idx || 0, alts: alts || null }
  }));
}

// Tastaturstøtte for klikkbare bilder o.l.: gjør elementet fokuserbart og
// lar Enter/mellomrom utløse samme handling som klikk.
const zoomKeys = (fn) => ({
  role: "button",
  tabIndex: 0,
  onKeyDown: (e) => {
    // ignorer tastetrykk som bobler fra knapper inni elementet (f.eks. karusellpiler)
    if (e.target !== e.currentTarget) return;
    if (e.key === "Enter" || e.key === " ") { e.preventDefault(); fn(); }
  }
});

function Lightbox({ images, startIdx, alts, onClose }) {
  const [idx, setIdx] = useState(startIdx || 0);
  const touchStartX = useRef(null);
  const closeBtnRef = useRef(null);

  useEffect(() => {
    const scrollbarW = window.innerWidth - document.documentElement.clientWidth;
    document.body.style.paddingRight = scrollbarW + "px";
    document.body.style.overflow = "hidden";
    // flytt fokus inn i dialogen, og tilbake dit brukeren var ved lukking
    const prevFocus = document.activeElement;
    closeBtnRef.current?.focus();
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      if (e.key === "ArrowRight") setIdx((i) => (i + 1) % images.length);
      if (e.key === "ArrowLeft") setIdx((i) => (i - 1 + images.length) % images.length);
    };
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
      document.body.style.paddingRight = "";
      if (prevFocus && prevFocus.focus) prevFocus.focus();
    };
  }, []);

  const onTouchStart = (e) => { touchStartX.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (touchStartX.current === null) return;
    const dx = e.changedTouches[0].clientX - touchStartX.current;
    if (dx < -40) setIdx((i) => (i + 1) % images.length);
    else if (dx > 40) setIdx((i) => (i - 1 + images.length) % images.length);
    touchStartX.current = null;
  };

  return (
    <div onClick={onClose} onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}
      role="dialog" aria-modal="true" aria-label="Bildevisning" style={{
      position:"fixed", inset:0, background:"rgba(0,0,0,0.92)", zIndex:9999,
      display:"flex", alignItems:"center", justifyContent:"center", touchAction:"pan-y"
    }}>
      <img src={images[idx]} alt={(alts && alts[idx]) || ""} onClick={(e) => e.stopPropagation()} style={{
        maxWidth:"92vw", maxHeight:"88vh", objectFit:"contain", borderRadius:6,
        boxShadow:"0 8px 40px rgba(0,0,0,0.6)"
      }} />
      {images.length > 1 && (
        <>
          <button onClick={(e) => { e.stopPropagation(); setIdx((i) => (i - 1 + images.length) % images.length); }} aria-label="Forrige bilde" style={{
            position:"fixed", left:12, top:"50%", transform:"translateY(-50%)",
            background:"rgba(255,255,255,0.15)", color:"#fff", border:"none", borderRadius:"50%",
            width:44, height:44, fontSize:22, cursor:"pointer", backdropFilter:"blur(4px)"
          }}>‹</button>
          <button onClick={(e) => { e.stopPropagation(); setIdx((i) => (i + 1) % images.length); }} aria-label="Neste bilde" style={{
            position:"fixed", right:12, top:"50%", transform:"translateY(-50%)",
            background:"rgba(255,255,255,0.15)", color:"#fff", border:"none", borderRadius:"50%",
            width:44, height:44, fontSize:22, cursor:"pointer", backdropFilter:"blur(4px)"
          }}>›</button>
          <div style={{position:"fixed", bottom:20, left:0, right:0, display:"flex", justifyContent:"center", gap:8}}>
            {images.map((_, i) => (
              <button key={i} onClick={(e) => { e.stopPropagation(); setIdx(i); }} aria-label={`Bilde ${i + 1} av ${images.length}`} style={{
                width: i === idx ? 22 : 8, height:8, borderRadius:4, border:"none",
                cursor:"pointer", padding:0,
                background: i === idx ? "#fff" : "rgba(255,255,255,0.4)",
                transition:"all 0.25s ease"
              }} />
            ))}
          </div>
        </>
      )}
      <button ref={closeBtnRef} onClick={onClose} aria-label="Lukk bildevisning" style={{
        position:"fixed", top:14, right:14, background:"rgba(255,255,255,0.15)",
        color:"#fff", border:"none", borderRadius:"50%", width:40, height:40,
        fontSize:20, cursor:"pointer", backdropFilter:"blur(4px)"
      }}>✕</button>
    </div>
  );
}

function GlobalLightbox() {
  const [lb, setLb] = useState(null);
  useEffect(() => {
    const h = (e) => setLb(e.detail);
    window.addEventListener("dmhf:lightbox", h);
    return () => window.removeEventListener("dmhf:lightbox", h);
  }, []);
  if (!lb) return null;
  return <Lightbox images={lb.images} startIdx={lb.idx} alts={lb.alts} onClose={() => setLb(null)} />;
}

// Wrapper som gjør PhSlot-bilder klikkbare. Med `images` (flere bilder) åpner
// klikk hele serien i lightboxen; ellers bare `src`.
const ClickSlot = ({ id, label, src, style, radius, shape, images, alt, alts }) => {
  const list = images && images.length ? images : (src ? [src] : []);
  const desc = alt != null ? alt : label;
  const open = () => list.length && openLightbox(list, 0, alts || (desc ? [desc] : null));
  return (
    <div style={{width:"100%", height:"100%", cursor: list.length ? "zoom-in" : "default"}}
      onClick={open}
      {...(list.length ? zoomKeys(open) : {})}
      aria-label={list.length ? `Vis større bilde: ${desc}` : undefined}>
      <PhSlot id={id} label={label} src={src} style={style} radius={radius} shape={shape} alt={desc} />
    </div>
  );
};

// ------------------ IMAGE SLIDER ------------------

function ImageSlider({ images, aspectRatio, radius, alts }) {
  const [idx, setIdx] = useState(0);
  const touchStartX = useRef(null);
  const ratio = aspectRatio || "16/9";
  const rad = radius != null ? radius : 10;

  const prev = (e) => { e.stopPropagation(); setIdx((i) => (i - 1 + images.length) % images.length); };
  const next = (e) => { e.stopPropagation(); setIdx((i) => (i + 1) % images.length); };

  const onTouchStart = (e) => { touchStartX.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (touchStartX.current === null) return;
    const dx = e.changedTouches[0].clientX - touchStartX.current;
    if (dx < -40) setIdx((i) => (i + 1) % images.length);
    else if (dx > 40) setIdx((i) => (i - 1 + images.length) % images.length);
    touchStartX.current = null;
  };

  if (!images || images.length === 0) return null;
  if (images.length === 1) return (
    <img src={images[0]} alt={(alts && alts[0]) || ""} loading="lazy"
      onClick={() => openLightbox(images, 0, alts)}
      {...zoomKeys(() => openLightbox(images, 0, alts))} style={{
      width:"100%", borderRadius:rad, objectFit:"cover", aspectRatio:ratio,
      display:"block", cursor:"zoom-in"
    }} />
  );

  return (
    <div style={{position:"relative", userSelect:"none", touchAction:"pan-y"}}
      onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>
      <div style={{position:"relative", overflow:"hidden", borderRadius:rad, aspectRatio:ratio, background:"var(--cream-3)", cursor:"zoom-in"}}
        onClick={() => openLightbox(images, idx, alts)}
        {...zoomKeys(() => openLightbox(images, idx, alts))}
        aria-label="Vis bildeserien i full størrelse">
        {images.map((src, i) => (
          <img key={i} src={src} alt={(alts && alts[i]) || ""} loading="lazy" style={{
            position:"absolute", inset:0, width:"100%", height:"100%",
            objectFit:"cover", borderRadius:rad,
            opacity: i === idx ? 1 : 0,
            transition:"opacity 0.3s ease",
            pointerEvents:"none"
          }} />
        ))}
        <button onClick={prev} aria-label="Forrige" style={{
          position:"absolute", left:8, top:"50%", transform:"translateY(-50%)",
          background:"rgba(0,0,0,0.45)", color:"#fff", border:"none", borderRadius:"50%",
          width:36, height:36, fontSize:18, cursor:"pointer", display:"flex",
          alignItems:"center", justifyContent:"center", backdropFilter:"blur(4px)", zIndex:2
        }}>‹</button>
        <button onClick={next} aria-label="Neste" style={{
          position:"absolute", right:8, top:"50%", transform:"translateY(-50%)",
          background:"rgba(0,0,0,0.45)", color:"#fff", border:"none", borderRadius:"50%",
          width:36, height:36, fontSize:18, cursor:"pointer", display:"flex",
          alignItems:"center", justifyContent:"center", backdropFilter:"blur(4px)", zIndex:2
        }}>›</button>
      </div>
      <div style={{display:"flex", justifyContent:"center", gap:6, marginTop:8}}>
        {images.map((_, i) => (
          <button key={i} onClick={() => setIdx(i)} aria-label={`Bilde ${i+1}`} style={{
            width: i === idx ? 20 : 7, height:7,
            borderRadius:4, border:"none", cursor:"pointer", padding:0,
            // prikkene står på den lyse passepartouten også i mørk modus
            background: i === idx ? "#2a2622" : "rgba(0,0,0,0.2)",
            transition:"all 0.25s ease"
          }} />
        ))}
      </div>
    </div>
  );
}

// ------------------ EVENT LIST (expandable) ------------------

function EventList({ events }) {
  const [open, setOpen] = useState(null);
  return (
    <div className="events">
      {events.map((e, i) => (
        <div className="event-row" key={i}>
          <div className="event-date">
            <span className="day">{e.day}</span>
            <span className="mon">{e.mon} {e.year}</span>
          </div>
          <div className="event-body">
            <h4>{e.title}</h4>
            <div className="meta">{e.meta}</div>
            {e.body && (
              <div style={{marginTop: 12}}>
                {e.body.map((p, j) => (
                  <p key={j} style={{color:"var(--ink-soft)", fontSize:16, maxWidth:580, lineHeight:1.6, marginBottom: 8}}>
                    {p}
                  </p>
                ))}
              </div>
            )}
            {e.images && e.images.length > 0 && (
              <div style={{display:"flex", gap:16, marginTop:16, flexWrap:"wrap", alignItems:"flex-start"}}>
                {e.images.map((img, j) => {
                  const imgAlt = (e.imagesAlt && e.imagesAlt[j]) || `${e.title} — bilde ${j + 1}`;
                  return (
                  <div className="frame-valnott" key={j} style={{width:"calc(50% - 8px)"}}>
                    <div className="passepartout">
                      <img src={img} alt={imgAlt} loading="lazy"
                        onClick={() => openLightbox(e.images, j, e.imagesAlt)}
                        {...zoomKeys(() => openLightbox(e.images, j, e.imagesAlt))}
                        style={{objectFit:"cover", maxHeight:220, cursor:"zoom-in"}} />
                    </div>
                  </div>
                  );
                })}
              </div>
            )}
            {open === i && e.detail && (
              <p style={{marginTop: 12, color:"var(--ink-soft)", fontSize:16, maxWidth:580, lineHeight:1.6}}>
                {e.detail}
              </p>
            )}
          </div>
          {e.detail && (
            <div className="event-action">
              <a className="btn-quiet" style={{cursor:"pointer"}} onClick={() => setOpen(open === i ? null : i)}
                {...zoomKeys(() => setOpen(open === i ? null : i))} aria-expanded={open === i}>
                {open === i ? "Skjul ↑" : "Les mer →"}
              </a>
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

// ------------------ COUNT-UP (hero-statistikk) ------------------

function CountUp({ end, suffix }) {
  const ref = useRef(null);
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
      setVal(end);
      return;
    }
    const io = new IntersectionObserver(([entry]) => {
      if (!entry.isIntersecting) return;
      io.disconnect();
      const t0 = performance.now();
      const dur = 1400;
      const tick = (t) => {
        const p = Math.min(1, (t - t0) / dur);
        setVal(Math.round(end * (1 - Math.pow(1 - p, 3))));
        if (p < 1) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
    }, { threshold: 0.5 });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [end]);
  return <div className="stat-num" ref={ref}>{val}{suffix || ""}</div>;
}

// ------------------ FEATURED NEWS ------------------

function FeaturedNews({ news }) {
  const imgs = news.images && news.images.length > 1 ? news.images : (news.img ? [news.img] : []);
  const imgAlts = news.images && news.images.length > 1
    ? (news.imagesAlt || news.images.map((_, i) => `${news.title} — bilde ${i + 1}`))
    : [news.imgAlt || news.title];
  const scrollToNews = () => document.getElementById("nyheter")?.scrollIntoView({ behavior: "smooth" });
  return (
    <div className={"featured-news" + (imgs.length > 0 ? "" : " featured-news--noimg")}>
      <div>
        <Eyebrow>Siste nytt</Eyebrow>
        <h3 style={{marginTop:6, marginBottom:8}}>{news.title}</h3>
        <div className="meta" style={{marginBottom:12}}>{news.tag} · {news.date}</div>
        <p style={{color:"var(--ink-soft)", fontSize:17, lineHeight:1.6}}>{news.teaser}</p>
        <div style={{marginTop:16}}>
          <a className="btn-quiet" style={{cursor:"pointer"}} onClick={scrollToNews} {...zoomKeys(scrollToNews)}>Alle nyheter ↓</a>
        </div>
      </div>
      {imgs.length > 0 && (
        <div className="featured-news-img">
          <div className="frame-valnott">
            <div className="passepartout">
              <ImageSlider images={imgs} alts={imgAlts} aspectRatio="4/3" radius={0} />
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ------------------ HOME ------------------

function HomePage({ go }) {
  const D = window.SITE_DATA;
  return (
    <main>
      {/* HERO */}
      <section className="hero" data-screen-label="01 Hjem · Hero">
        <div className="hero-grid">
          <div>
            <div className="hero-eyebrow">
              <span className="dot"></span>
              Stiftet 1935 · Drammensmarka
            </div>
            <h1>
              Hytteliv i Drammensmarka med folk du kjenner.
            </h1>
            <p className="hero-lede">
              Drammensmarka Hytteeierforening samler 175 medlemmer i Drammensmarka.
            </p>
            <div className="hero-actions">
              <a className="btn btn-primary" href="#kart" onClick={(e) => { e.preventDefault(); go("kart"); }}>Se hyttekartet</a>
              <a className="btn btn-ghost" href="#historie" onClick={(e) => { e.preventDefault(); go("historie"); }}>Vår historie</a>
            </div>
            <div className="hero-stats">
              <div>
                <CountUp end={D.brand.medlemmer} />
                <div className="stat-label">Medlemmer</div>
              </div>
              <div>
                <CountUp end={new Date().getFullYear() - D.brand.founded} />
                <div className="stat-label">År i marka</div>
              </div>
              <div>
                <CountUp end={2} suffix="×" />
                <div className="stat-label">Hyttenytt i året</div>
              </div>
            </div>
          </div>
          <div className="hero-image">
            <div className="frame-valnott frame-valnott--hero">
              <div className="passepartout">
                <ClickSlot id="hero" label="Hovedbilde fra marka" alt="Kveldssol gjennom furutrær i Drammensmarka" src="assets/foto-kveldssol-furu.jpg" radius="0" style={{width:"100%", height:"100%"}} />
              </div>
            </div>
          </div>
        </div>
      </section>

      <div className="genserstripe" aria-hidden="true"></div>

      {/* SISTE NYTT */}
      {D.news && D.news[0] && (
        <section className="section bg-paper" style={{paddingTop:28, paddingBottom:28}} data-screen-label="01 Hjem · Siste nytt">
          <div className="container">
            <FeaturedNews news={D.news[0]} />
          </div>
        </section>
      )}

      {/* WELCOME */}
      <section className="section bg-cream-2" data-screen-label="01 Hjem · Velkommen">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Velkommen</Eyebrow>
              <h2>En forening for dem som er glade i marka.</h2>
            </div>
            <div className="read">
              <p style={{fontSize: 21, lineHeight: 1.55, color: "var(--ink-soft)"}}>Drammensmarka Hytteeierforening ble stiftet en novemberkveld i 1935 av en gruppe hytteeiere som ville sikre felles vei og godt naboskap. I dag teller foreningen 175 medlemmer.</p>
              <p>Vi holder årsmøte hver vår, gir ut medlemsbladet <em>Hyttenytt</em> to ganger i året, og samles på arrangement og høstsamling.</p>
              <p style={{marginTop: 28}}>
                <a className="btn-quiet" href="#historie" onClick={(e) => { e.preventDefault(); go("historie"); }}>Les om foreningens historie →</a>
              </p>
            </div>
          </div>
        </div>
      </section>

      {/* HVA VI GJØR */}
      <section className="section" data-screen-label="01 Hjem · Hva vi gjør">
        <div className="container">
          <div className="section-head">
            <div><Eyebrow>Hva vi gjør</Eyebrow><h2>Fem kjerneoppgaver</h2></div>
          </div>
          <div className="hviggjor-grid">
            {D.hvaViGjor.map((k, i) => (
              <div className="hviggjor-card" key={i}>
                <h4>{k.title}</h4>
                <p>{k.body}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* EVENTS */}
      <section id="arrangementer" className="section bg-paper" data-screen-label="01 Hjem · Arrangementer">
        <div className="container">
          <div className="section-head">
            <div>
              <Eyebrow>Hva skjer</Eyebrow>
              <h2>Arrangementer i 2026</h2>
            </div>
            <div className="right">Møter og turer er åpne for alle medlemmer.</div>
          </div>
          <EventList events={D.events} />
        </div>
      </section>

      {/* NEWS */}
      <section id="nyheter" className="section" data-screen-label="01 Hjem · Nyheter">
        <div className="container">
          <div className="section-head">
            <div>
              <Eyebrow>Hyttenytt og kunngjøringer</Eyebrow>
              <h2>Siste nytt fra foreningen</h2>
            </div>
            <div className="right"><a className="btn-quiet" href="#hyttenytt" onClick={(e) => { e.preventDefault(); go("hyttenytt"); }}>Alle nyheter →</a></div>
          </div>
          <div className="news-grid">
            {/* news[0] vises allerede i full bredde i «Siste nytt»-seksjonen over —
                hoppes over her så bildene bare vises én gang */}
            {D.news.slice(1).map((n, i) => (
              <a className="news-card" key={i}>
                <div className="frame-valnott" style={{display: n.images && n.images.length > 1 ? "none" : "block"}}>
                  <div className="passepartout">
                    <div className="ph">
                      <ClickSlot id={n.slot} label={`Bilde · ${n.tag}`} alt={n.imgAlt || n.title} src={n.img} radius="0" style={{width:"100%", height:"100%"}} />
                    </div>
                  </div>
                </div>
                {n.images && n.images.length > 1 && (
                  <div className="frame-valnott" style={{marginBottom:12}}>
                    <div className="passepartout">
                      <ImageSlider images={n.images} alts={n.imagesAlt || n.images.map((_, j) => `${n.title} — bilde ${j + 1}`)} aspectRatio="4/3" radius={0} />
                    </div>
                  </div>
                )}
                <div className="news-meta">
                  <span className="news-badge">{n.tag}</span>
                  <span className="news-date">{n.date}</span>
                </div>
                <h4>{n.title}</h4>
                <p>{n.teaser}</p>
              </a>
            ))}
          </div>
        </div>
      </section>

      {/* GALLERY */}
      <section className="section bg-paper" data-screen-label="01 Hjem · Galleri">
        <div className="container">
          <div className="section-head">
            <div>
              <Eyebrow>Bilder fra marka</Eyebrow>
              <h2>Året rundt i Drammensmarka</h2>
            </div>
            <div className="right">Fra medlemmenes egne kameraer.</div>
          </div>
          <div className="gallery">
            {/* Salongvegg: 4 kolonner × 7 rader (28 celler) — big(4) + 8 høye(16)
                + 3 brede(6) + 2 små(2) går akkurat opp, så veggen blir hel. */}
            {[
              // bånd 1: praktbildet + to stående
              { id:"gal-1",  label:"Skyer over åsen", src:"assets/foto-IMG_3919.jpg", cls:"g-big", gf:"gf-gold-lg" },
              { id:"gal-3",  label:"Skispor i sol", src:"assets/foto-skispor-vinter.jpg", cls:"g-tall", gf:"gf-oval", shape:"circle" },
              { id:"gal-2",  label:"Kveldshimmel over marka", src:"assets/foto-IMG_3508.jpg", cls:"g-tall", gf:"gf-walnut" },
              // bånd 2: fire stående i varierte rammer
              { id:"gal-4",  label:"Ved bergveggen", src:"assets/foto-IMG_0847.jpg", cls:"g-tall", gf:"gf-mat" },
              { id:"gal-5",  label:"Spor i snøen", src:"assets/foto-IMG_3905.jpg", cls:"g-tall", gf:"gf-thin" },
              { id:"gal-7",  label:"Snøtunge trær", src:"assets/foto-IMG_3907.jpg", cls:"g-tall", gf:"gf-walnut" },
              { id:"gal-13", label:"Vintersol", src:"assets/foto-IMG_3906.jpg", cls:"g-tall", gf:"gf-oval", shape:"circle" },
              // bånd 3: to stående + to brede stablet
              { id:"gal-11", label:"Benken på Furumotomta i skogen", src:"assets/foto-benk-furumotomta-skog.jpg", cls:"g-tall", gf:"gf-thin" },
              { id:"gal-15", label:"Furu i vinterlys", src:"assets/foto-IMG_3945.jpg", cls:"g-tall", gf:"gf-gold" },
              { id:"gal-10", label:"Benken på Furumotomta, sett fra stien", src:"assets/foto-benk-furumotomta-utsikt.jpg", cls:"g-wide", gf:"gf-gold" },
              { id:"gal-12", label:"Badestampen", src:"assets/foto-badestamp.jpg", cls:"g-wide", gf:"gf-walnut" },
              // nederste rad: bred + to små (medaljong + passepartout)
              { id:"gal-9",  label:"Benken på Furumotomta", src:"assets/foto-benk-furumotomta.jpg", cls:"g-wide", gf:"gf-mat" },
              { id:"gal-6",  label:"Vak i isen", src:"assets/foto-IMG_3927.jpg", cls:"", gf:"gf-oval-cream", shape:"circle" },
              { id:"gal-14", label:"Lav vintersol", src:"assets/foto-IMG_3925.jpg", cls:"", gf:"gf-mat" },
            ].map((g) => (
              <div className={g.cls + " gframe " + g.gf} key={g.id}>
                <ClickSlot id={g.id} label={g.label} src={g.src} shape={g.shape} radius="0" style={{width:"100%", height:"100%"}} />
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* QUICK LINKS */}
      <section className="section snarvei-band" data-screen-label="01 Hjem · Snarveier">
        <div className="container">
          <Eyebrow>Snarveier</Eyebrow>
          <h2 style={{marginBottom: 32}}>Finn fram raskt</h2>
          <div className="qlinks">
            <a className="qlink" href="#arsmoter" onClick={(e) => { e.preventDefault(); go("arsmoter"); }}>
              <span className="num">01</span>
              <span className="label">Årsmøter</span>
              <span className="desc">Referater og protokoller fra alle møter siden 2020.</span>
            </a>
            <a className="qlink" href="#okonomi" onClick={(e) => { e.preventDefault(); go("okonomi"); }}>
              <span className="num">02</span>
              <span className="label">Økonomi</span>
              <span className="desc">Regnskap, budsjett og medlemskontingent.</span>
            </a>
            <a className="qlink" href="#vedtekter" onClick={(e) => { e.preventDefault(); go("vedtekter"); }}>
              <span className="num">03</span>
              <span className="label">Vedtekter</span>
              <span className="desc">Foreningens vedtekter.</span>
            </a>
            <a className="qlink" href="#kart" onClick={(e) => { e.preventDefault(); go("kart"); }}>
              <span className="num">04</span>
              <span className="label">Hyttekart</span>
              <span className="desc">Kart over hytteområdet.</span>
            </a>
          </div>
        </div>
      </section>
    </main>
  );
}

// ------------------ HISTORIE ------------------

function HistoriePage() {
  const D = window.SITE_DATA;
  return (
    <main data-screen-label="02 Historie">
      <header className="page-head">
        <div className="container">
          <div className="crumbs"><a href="#hjem" onClick={(e) => { e.preventDefault(); window.navigate("hjem"); }}>Hjem</a> · <span>Historie</span></div>
          <h1>Ni tiår i marka.</h1>
          <p className="lede">
            Fra en gruppe hytteeiere en novemberkveld i 1935 til 175 medlemmer i dag —
            her er noen merkesteiner i Drammensmarka Hytteeierforenings historie.
          </p>
        </div>
      </header>
      <div className="genserstripe" aria-hidden="true"></div>
      <section className="section">
        <div className="container">
          <blockquote className="lead-quote" style={{marginBottom: 40}}>
            «Formålet er å ivareta hytteeiernes felles interesser i Drammensmarka, fremme interessen for skog, hytteliv og naturvern, og holde foreningens ambulansehytte ved Landfalltjern i orden.»
            <cite>— Fra vedtektene av 1935</cite>
          </blockquote>

          <div className="timeline">
            {D.history.map((h, i) => (
              <div className="tl-row" key={i}>
                <div className="tl-year">{h.year}</div>
                <div className="tl-body">
                  <h3>{h.title}</h3>
                  <p>{h.body}</p>
                  {(h.slot || h.img) && (
                    <div className="frame-valnott" style={{maxWidth:520, marginTop:18}}>
                      <div className="passepartout">
                        <div className="ph" style={{marginTop:0, maxWidth:"none"}}>
                          <ClickSlot id={h.slot || `h-${h.year}`} label={`Bilde fra ${h.year}`} alt={h.imgAlt || `${h.title} (${h.year})`} src={h.img || undefined} radius="0" style={{width:"100%", height:"100%"}} />
                        </div>
                      </div>
                    </div>
                  )}
                </div>
              </div>
            ))}
          </div>

          <div style={{marginTop: 56}}>
            <div className="section-head">
              <div>
                <Eyebrow>Fra arkivet</Eyebrow>
                <h2>Glimt fra marka gjennom årene</h2>
              </div>
              <div className="right">Sveip eller klikk for å bla</div>
            </div>
            <div className="frame-valnott">
              <div className="passepartout">
                <ImageSlider
                  aspectRatio="16/9"
                  radius={0}
                  images={[
                    "assets/foto-gammel-hytte.jpg",
                    "assets/foto-hytte.jpg",
                    "assets/foto-hytte-bergvegg.jpg",
                    "assets/foto-myr.jpg",
                    "assets/foto-IMG_3533.jpg"
                  ]}
                  alts={[
                    "Gammel hytte i Drammensmarka",
                    "Hytte i skogen",
                    "Hytte ved bergveggen",
                    "Myrlandskap i marka",
                    "Skogsbilde fra marka"
                  ]}
                />
              </div>
            </div>
          </div>

          <div className="callout" style={{marginTop: 44}}>
            <h3 style={{marginBottom: 12}}>Har du gamle bilder eller historier?</h3>
            <p style={{margin:0, color:"var(--ink-soft)"}}>
              Vi samler stadig på materiale fra foreningens historie. Send bilder,
              brev eller fortellinger til <a href="mailto:post@dmhf.no">post@dmhf.no</a>.
            </p>
          </div>
        </div>
      </section>
    </main>
  );
}

// ------------------ ÅRSMØTER ------------------

function ArsmoterPage() {
  const D = window.SITE_DATA;
  const [open, setOpen] = useState(0);
  const latest = D.meetings[0];
  return (
    <main data-screen-label="03 Årsmøter">
      <header className="page-head">
        <div className="container">
          <div className="crumbs"><a href="#hjem" onClick={(e) => { e.preventDefault(); window.navigate("hjem"); }}>Hjem</a> · <span>Årsmøter</span></div>
          <h1>Årsmøter og protokoller.</h1>
          <p className="lede">
            Foreningen avholder ordinært årsmøte hver vår. Her finner
            du referater, regnskap og innkallinger fra de siste årene.
          </p>
        </div>
      </header>
      <div className="genserstripe" aria-hidden="true"></div>

      <section className="section">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Siste årsmøte</Eyebrow>
              <h2 style={{marginBottom: 18}}>{latest.title}</h2>
              <p style={{color:"var(--ink-muted)", marginBottom: 24}}>{latest.when}</p>
              <div className="frame-valnott" style={{maxWidth:420}}>
                <div className="passepartout">
                  <div style={{aspectRatio:"4/3", overflow:"hidden", lineHeight:0}}>
                    <ClickSlot id="am-tverken" label="Tverråsen" src="assets/foto-tverken.jpg" radius="0" style={{width:"100%", height:"100%"}} />
                  </div>
                </div>
              </div>
            </div>
            <div className="card">
              <h4 style={{fontFamily:"var(--serif)", fontSize: 22, marginBottom: 14}}>Sammendrag</h4>
              <p style={{color:"var(--ink-soft)"}}>{latest.summary}</p>
              {latest.protokoll && (
                <p style={{marginTop: 16, marginBottom: 0}}>
                  <a href={latest.protokoll} target="_blank" rel="noopener">Last ned protokollen (PDF) ↓</a>
                </p>
              )}
              <hr className="rule" style={{margin:"22px 0"}} />
              <dl style={{margin:0, display:"grid", gridTemplateColumns:"160px 1fr", gap:"10px 16px", fontSize:16}}>
                <dt style={{color:"var(--ink-muted)"}}>Møtested</dt><dd>Sturlahuset</dd>
                <dt style={{color:"var(--ink-muted)"}}>Neste årsmøte</dt><dd>Våren 2027 — innkalling kommer i Hyttenytt</dd>
              </dl>
            </div>
          </div>
        </div>
      </section>

      <section className="section snarvei-band">
        <div className="container">
          <div className="section-head">
            <div>
              <Eyebrow>Arkiv</Eyebrow>
              <h2>Tidligere årsmøter</h2>
            </div>
            <div className="right">Klikk en rad for å se sammendrag</div>
          </div>

          <div className="amlist">
            {D.meetings.map((m, i) => (
              <div className={"am-row " + (open === i ? "open" : "")} key={i}>
                <div className="am-summary" onClick={() => setOpen(open === i ? -1 : i)}
                  {...zoomKeys(() => setOpen(open === i ? -1 : i))} aria-expanded={open === i}>
                  <span className="y">{m.year}</span>
                  <h4>{m.title}</h4>
                  <span className="when">{m.when}</span>
                  <span className="chev">{open === i ? "−" : "+"}</span>
                </div>
                <div className="am-detail">
                  <p>{m.summary}</p>
                  {m.protokoll && (
                    <p style={{marginTop: 12}}>
                      <a href={m.protokoll} target="_blank" rel="noopener">Last ned protokollen (PDF) ↓</a>
                    </p>
                  )}
                  {m.images && m.images.length > 0 && (
                    <div style={{display:"flex", gap:12, marginTop:16, flexWrap:"wrap"}}>
                      {m.images.map((img, j) => (
                        <img key={j} src={img} alt={(m.imagesAlt && m.imagesAlt[j]) || `${m.title} — bilde ${j + 1}`} loading="lazy"
                          onClick={() => openLightbox(m.images, j, m.imagesAlt)}
                          {...zoomKeys(() => openLightbox(m.images, j, m.imagesAlt))}
                          style={{width:"calc(50% - 6px)", maxWidth:280, borderRadius:8, objectFit:"cover", maxHeight:200, cursor:"zoom-in"}} />
                      ))}
                    </div>
                  )}
                  {m.bylawProposals && (
                    <div style={{marginTop: 16}}>
                      <strong style={{fontSize: 14, color:"var(--ink-muted)"}}>Forslag til vedtektsendringer (til neste årsmøte):</strong>
                      <ul style={{marginTop: 8, paddingLeft: 20, fontSize: 15, color:"var(--ink-soft)"}}>
                        {m.bylawProposals.map((p, j) => (
                          <li key={j} style={{marginBottom: 6}}><strong>{p.par}:</strong> {p.text}</li>
                        ))}
                      </ul>
                    </div>
                  )}
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>
    </main>
  );
}

// ------------------ CHART HELPERS ------------------

function GrasrotChart({ data }) {
  const W = 640, H = 200;
  const padL = 50, padR = 12, padT = 28, padB = 48;
  const cW = W - padL - padR, cH = H - padT - padB;
  const max = Math.max(...data.map(d => d.belop));
  const n = data.length;
  const slotW = cW / n;
  const barW = Math.max(18, slotW - 8);
  const fmtK = v => v >= 1000 ? Math.round(v / 1000) + 'k' : String(v);
  return (
    <svg viewBox={`0 0 ${W} ${H}`} style={{width:'100%',overflow:'visible',fontFamily:'var(--sans)',fontSize:11}}>
      {data.map((d, i) => {
        const bH = Math.max(2, Math.round((d.belop / max) * cH));
        const cx = padL + (i + 0.5) * slotW;
        const x = cx - barW / 2;
        const y = padT + cH - bH;
        return (
          <g key={i}>
            <rect x={x} y={y} width={barW} height={bH} fill="var(--forest)" rx={2} opacity={0.8} />
            <text x={cx} y={y - 5} textAnchor="middle" fill="var(--ink-soft)" fontSize={9}>{fmtK(d.belop)}</text>
            <text x={cx} y={H - 6} textAnchor="end" fill="var(--ink-muted)" fontSize={9}
              transform={`rotate(-45 ${cx} ${H - 6})`}>{d.ar}</text>
          </g>
        );
      })}
      <line x1={padL} y1={padT} x2={padL} y2={padT + cH} stroke="var(--rule)" strokeWidth={1} />
      <line x1={padL} y1={padT + cH} x2={W - padR} y2={padT + cH} stroke="var(--rule)" strokeWidth={1} />
      <text x={padL - 4} y={padT + cH + 4} textAnchor="end" fill="var(--ink-muted)" fontSize={9}>0</text>
      <text x={padL - 4} y={padT + 4} textAnchor="end" fill="var(--ink-muted)" fontSize={9}>{fmtK(max)}</text>
    </svg>
  );
}

function BankChart({ termin, kalender }) {
  const W = 640, H = 210;
  const padL = 58, padR = 12, padT = 36, padB = 44;
  const cW = W - padL - padR, cH = H - padT - padB;
  const all = [...termin, ...kalender];
  const max = Math.max(...all.map(d => d.total));
  const min = Math.min(...all.map(d => d.total)) - 15000;
  const range = max - min;
  const n = all.length;
  const toX = i => padL + Math.round((i / (n - 1)) * cW);
  const toY = v => padT + cH - Math.round(((v - min) / range) * cH);
  const fmtK = v => Math.round(v / 1000) + 'k';
  const tPts = termin.map((d, i) => ({ x: toX(i), y: toY(d.total), label: d.aar }));
  const kPts = kalender.map((d, i) => ({ x: toX(i + termin.length), y: toY(d.total), label: d.aar, est: d.estimert }));
  const pathD = pts => pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ');
  return (
    <svg viewBox={`0 0 ${W} ${H}`} style={{width:'100%',overflow:'visible',fontFamily:'var(--sans)',fontSize:11}}>
      <line x1={padL} y1={14} x2={padL + 20} y2={14} stroke="var(--ink-muted)" strokeWidth={2} strokeDasharray="4 3" />
      <text x={padL + 24} y={18} fill="var(--ink-muted)" fontSize={10}>Termin (okt–okt)</text>
      <line x1={padL + 148} y1={14} x2={padL + 168} y2={14} stroke="var(--forest)" strokeWidth={2.5} />
      <text x={padL + 172} y={18} fill="var(--ink-soft)" fontSize={10}>Kalenderår (jan–des)</text>
      <path d={pathD(tPts)} fill="none" stroke="var(--ink-muted)" strokeWidth={2} strokeDasharray="4 3" />
      <path d={pathD(kPts)} fill="none" stroke="var(--forest)" strokeWidth={2.5} />
      {tPts.length > 0 && kPts.length > 0 && (
        <line x1={tPts[tPts.length - 1].x} y1={tPts[tPts.length - 1].y}
          x2={kPts[0].x} y2={kPts[0].y}
          stroke="var(--rule)" strokeWidth={1} strokeDasharray="2 3" />
      )}
      {tPts.map((p, i) => (
        <g key={`t${i}`}>
          <circle cx={p.x} cy={p.y} r={4} fill="var(--ink-muted)" />
          <text x={p.x} y={H - 6} textAnchor="end" fill="var(--ink-muted)" fontSize={9}
            transform={`rotate(-45 ${p.x} ${H - 6})`}>{p.label}</text>
        </g>
      ))}
      {kPts.map((p, i) => (
        <g key={`k${i}`}>
          <circle cx={p.x} cy={p.y} r={4} fill={p.est ? "none" : "var(--forest)"} stroke="var(--forest)" strokeWidth={1.5} />
          {p.est && <text x={p.x} y={p.y - 8} textAnchor="middle" fill="var(--ink-muted)" fontSize={9}>est.</text>}
          <text x={p.x} y={H - 6} textAnchor="end" fill="var(--ink-soft)" fontSize={9}
            transform={`rotate(-45 ${p.x} ${H - 6})`}>{p.label}</text>
        </g>
      ))}
      <line x1={padL} y1={padT} x2={padL} y2={padT + cH} stroke="var(--rule)" />
      <line x1={padL} y1={padT + cH} x2={W - padR} y2={padT + cH} stroke="var(--rule)" />
      <text x={padL - 4} y={padT + cH + 4} textAnchor="end" fill="var(--ink-muted)" fontSize={9}>{fmtK(min)}</text>
      <text x={padL - 4} y={padT + 4} textAnchor="end" fill="var(--ink-muted)" fontSize={9}>{fmtK(max)}</text>
    </svg>
  );
}

// ------------------ ØKONOMI ------------------

function OkonomiPage() {
  const F = window.SITE_DATA.finance;
  const toNum = (s) => parseInt(String(s).replace(/\s/g, ""), 10) || 0;
  const fmt = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, " ");
  const budsjettInntekter = F.budget2026Income.reduce((sum, r) => sum + toNum(r[1]), 0);
  const budsjettUtgifter = F.budget2026Expense.reduce((sum, r) => sum + toNum(r[1]), 0);
  return (
    <main data-screen-label="04 Økonomi">
      <header className="page-head">
        <div className="container">
          <div className="crumbs"><a href="#hjem" onClick={(e) => { e.preventDefault(); window.navigate("hjem"); }}>Hjem</a> · <span>Økonomi</span></div>
          <h1>Foreningens økonomi.</h1>
          <p className="lede">
            Sammendrag av regnskap for 2025 og budsjett for 2026. Fullstendige
            tall finner du i protokollen fra siste årsmøte.
          </p>
        </div>
      </header>
      <div className="genserstripe" aria-hidden="true"></div>

      <section className="section">
        <div className="container">
          <Eyebrow>Nøkkeltall 2025</Eyebrow>
          <h2 style={{marginBottom: 28}}>I korte trekk</h2>
          <div className="fin-grid">
            {F.summary.map((s, i) => (
              <div className="fin-cell" key={i}>
                <div className="label">{s.label}</div>
                <div className="num">{s.num}</div>
                <div className={"delta " + (s.neg ? "neg" : "")}>{s.delta}</div>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="section bg-paper">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Inntekter</Eyebrow>
              <h2>Slik finansieres foreningen</h2>
              <p style={{color:"var(--ink-soft)", marginTop: 18}}>
                Hovedinntekten er medlemskontingenten, sammen med egenandeler fra
                arrangementer og Grasrotandelen fra Norsk Tipping.
                I tillegg til driftsinntektene kom renteinntekter på kr {F.renteinntekter} i 2025.
              </p>
            </div>
            <div>
              <table className="ledger">
                <thead>
                  <tr><th>Post</th><th className="num">Beløp (NOK)</th></tr>
                </thead>
                <tbody>
                  {F.income.map((r, i) => (
                    <tr key={i}><td>{r[0]}</td><td className="num">{r[1]}</td></tr>
                  ))}
                  <tr className="total"><td>Sum inntekter</td><td className="num">{F.incomeTotal}</td></tr>
                  <tr><td>Renteinntekter (finansinntekt)</td><td className="num">{F.renteinntekter}</td></tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </section>

      <section className="section">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Utgifter</Eyebrow>
              <h2>Hvor pengene går</h2>
              <p style={{color:"var(--ink-soft)", marginTop: 18}}>
                De største postene er arrangementer for medlemmene, trykk og
                utsendelse av Hyttenytt, og vanlig foreningsdrift — porto,
                postboks, regnskap og styremøter. Detaljene ser du i tabellen.
              </p>
            </div>
            <div>
              <table className="ledger">
                <thead>
                  <tr><th>Post</th><th className="num">Beløp (NOK)</th></tr>
                </thead>
                <tbody>
                  {F.expense.map((r, i) => (
                    <tr key={i}><td>{r[0]}</td><td className="num">{r[1]}</td></tr>
                  ))}
                  <tr className="total"><td>Sum utgifter</td><td className="num">{F.expenseTotal}</td></tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </section>

      <section className="section bg-paper">
        <div className="container">
          <Eyebrow>Grasrotandel</Eyebrow>
          <h2 style={{marginBottom: 8}}>Bidrag fra Norsk Tipping</h2>
          <p style={{color:"var(--ink-soft)", marginBottom: 28, maxWidth: 580}}>
            Betalende medlemmer kan knytte sin Norsk Tipping-konto til foreningen.
            Foreningen mottar 5 % av spillerinnsatsen — uten kostnad for spilleren.
            Frem til 2021 ble regnskapet ført per termin (oktober–oktober).
          </p>
          <GrasrotChart data={F.grasrot} />
        </div>
      </section>

      <section className="section">
        <div className="container">
          <Eyebrow>Bankbeholdning</Eyebrow>
          <h2 style={{marginBottom: 8}}>Utvikling over tid</h2>
          <p style={{color:"var(--ink-soft)", marginBottom: 28, maxWidth: 580}}>
            Stiplet linje viser termin-regnskap (oktober–oktober). Heltrukket linje
            viser kalenderår (januar–desember) fra og med 2021.
          </p>
          <BankChart termin={F.bankTermin} kalender={F.bankKalender} />
        </div>
      </section>

      <section className="section">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Budsjett 2026</Eyebrow>
              <h2>Plan for 2026</h2>
              <p style={{color:"var(--ink-soft)", marginTop: 18}}>
                Budsjettert overskudd kr {fmt(budsjettInntekter - budsjettUtgifter)}.
                Godkjent på årsmøtet 22. april 2026.
              </p>
            </div>
            <div>
              <table className="ledger">
                <thead>
                  <tr><th>Inntekter</th><th className="num">Beløp (NOK)</th></tr>
                </thead>
                <tbody>
                  {F.budget2026Income.map((r, i) => (
                    <tr key={i}><td>{r[0]}</td><td className="num">{r[1]}</td></tr>
                  ))}
                  <tr className="total"><td>Sum inntekter</td><td className="num">{fmt(budsjettInntekter)}</td></tr>
                </tbody>
              </table>
              <table className="ledger" style={{marginTop: 24}}>
                <thead>
                  <tr><th>Utgifter</th><th className="num">Beløp (NOK)</th></tr>
                </thead>
                <tbody>
                  {F.budget2026Expense.map((r, i) => (
                    <tr key={i}><td>{r[0]}</td><td className="num">{r[1]}</td></tr>
                  ))}
                  <tr className="total"><td>Sum utgifter</td><td className="num">{fmt(budsjettUtgifter)}</td></tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </section>

      <section className="section snarvei-band">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Medlemskontingent</Eyebrow>
              <h2>kr 300 per hytte per år</h2>
            </div>
            <div className="read">
              <p>
                Kontingenten dekker drift av foreningen, utgivelse av Hyttenytt og
                arrangementer for medlemmene. Faktura sendes ut i første halvår.
                Du kan også betale via Vipps til <strong>#924386 — Drammensmarka HEF</strong>, eller skanne QR-koden i bunnen av siden.
              </p>
              <p>
                Spørsmål om medlemskap eller faktura: <a href="mailto:post@dmhf.no">post@dmhf.no</a>.
              </p>
              <div className="frame-valnott" style={{marginTop:28}}>
                <div className="passepartout">
                  <div style={{aspectRatio:"16/9", overflow:"hidden", lineHeight:0}}>
                    <ClickSlot id="okonomi-utsikt" label="Sommerutsikt fra marka" src="assets/foto-utsikt-sommer.jpg" radius="0" style={{width:"100%", height:"100%"}} />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
    </main>
  );
}

// ------------------ VEDTEKTER ------------------

function VedtekterPage() {
  const B = window.SITE_DATA.bylaws;
  const [active, setActive] = useState("§1");
  useEffect(() => {
    const onScroll = () => {
      const top = window.scrollY + 140;
      let cur = active;
      for (const b of B) {
        const el = document.getElementById("§" + b.n);
        if (el && el.offsetTop <= top) cur = "§" + b.n;
      }
      if (cur !== active) setActive(cur);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, [active, B]);

  return (
    <main data-screen-label="05 Vedtekter">
      <header className="page-head">
        <div className="container">
          <div className="crumbs"><a href="#hjem" onClick={(e) => { e.preventDefault(); window.navigate("hjem"); }}>Hjem</a> · <span>Vedtekter</span></div>
          <h1>Vedtekter.</h1>
          <p className="lede">
            Foreningens vedtekter, sist endret på årsmøtet 15. oktober 2022. Spørsmål
            kan rettes til styret.
          </p>
        </div>
      </header>
      <div className="genserstripe" aria-hidden="true"></div>

      <section className="section">
        <div className="container">
          <div className="bylaws-grid">
            <aside className="toc">
              <h5>Innhold</h5>
              <ol>
                {B.map((b) => (
                  <li key={b.n}>
                    {/* preventDefault: hash-endring til «#§1» ville trigge
                        ruteren i index.html og sende brukeren til forsiden */}
                    <a
                      href={"#§" + b.n}
                      className={active === "§" + b.n ? "active" : ""}
                      onClick={(e) => {
                        e.preventDefault();
                        document.getElementById("§" + b.n)?.scrollIntoView({ behavior: "smooth" });
                      }}
                    >
                      <span className="num">§ {b.n}</span>
                      <span>{b.title}</span>
                    </a>
                  </li>
                ))}
              </ol>
            </aside>

            <div className="bylaws-body">
              {B.map((b) => (
                <section key={b.n} id={"§" + b.n}>
                  <span className="pn">§ {b.n}</span>
                  <h2>{b.title}</h2>
                  <p>{b.body}</p>
                </section>
              ))}
              <section>
                <span className="pn">Vedtatt</span>
                <h2 style={{fontSize: 22}}>Sist endret 15. oktober 2022</h2>
                <p style={{color:"var(--ink-muted)"}}>
                  Vedtektene ble revidert i sin helhet på årsmøtet 3. oktober 2015.
                  Siste endring ble vedtatt på årsmøtet 15. oktober 2022 (forslag C,
                  18 stemmer for): § 3 endres til at årsmøtet avholdes hvert år i løpet
                  av 1. halvår. Årsmøteprotokollen er gjengitt i Hyttenytt nr. 1/2023,
                  side 6–8.
                </p>
                <p style={{color:"var(--ink-muted)"}}>Originalprotokollen oppbevares hos styret. Henvendelser om vedtektene kan rettes til <a href="mailto:post@dmhf.no">post@dmhf.no</a>.</p>
                <div className="callout" style={{marginTop:24}}>
                  <p style={{margin:0}}>Forslag til endring av § 3 og § 5 er kunngjort i Hyttenytt – behandles på neste årsmøte.</p>
                </div>
              </section>
            </div>
          </div>
        </div>
      </section>
    </main>
  );
}

// ------------------ KART ------------------

function KartPage() {
  const C = window.SITE_DATA.cabins;
  const mapRef = useRef(null);
  const mapObj = useRef(null);
  const markersRef = useRef([]);
  const markersById = useRef({});
  const placingPinRef = useRef(null);
  const [showOwners, setShowOwners] = useState(true);
  const [query, setQuery] = useState("");
  const [selected, setSelected] = useState(null);
  const [placingMode, setPlacingMode] = useState(false);
  const [pickedCoord, setPickedCoord] = useState(null);
  const [copied, setCopied] = useState(false);
  const [focusId, setFocusId] = useState(null);

  const placed = useMemo(() => C.filter((c) => c.lat != null && c.lon != null), [C]);
  const unplaced = useMemo(() => C.filter((c) => c.lat == null && c.kind !== "landmark"), [C]);

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return placed;
    return placed.filter((c) =>
      [c.id, c.name, c.owner, c.note].filter(Boolean).join(" ").toLowerCase().includes(q)
    );
  }, [query, placed]);

  useEffect(() => {
    if (mapObj.current || !mapRef.current) return;
    const L = window.L;
    const map = L.map(mapRef.current, {
      center: [59.7775, 10.1648],
      zoom: 12,
      scrollWheelZoom: false,
    });
    L.tileLayer("https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", {
      attribution: "Kartdata © OpenStreetMap-bidragsytere · SRTM | Kart © OpenTopoMap (CC-BY-SA)",
      maxZoom: 17,
      subdomains: "abc",
    }).addTo(map);
    mapObj.current = map;
  }, []);

  useEffect(() => {
    const map = mapObj.current;
    if (!map) return;
    const onClick = (e) => {
      if (!placingMode) return;
      setPickedCoord({ lat: e.latlng.lat, lng: e.latlng.lng });
      // place / move the temporary pin
      if (placingPinRef.current) map.removeLayer(placingPinRef.current);
      placingPinRef.current = window.L.marker([e.latlng.lat, e.latlng.lng], {
        icon: window.L.divIcon({
          className: '',
          html: '<div class="placing-pin"></div>',
          iconSize: [24, 24],
          iconAnchor: [12, 12],
        }),
        interactive: false,
        zIndexOffset: 1000,
      }).addTo(map);
    };
    map.on("click", onClick);
    map.getContainer().style.cursor = placingMode ? "crosshair" : "";
    if (!placingMode && placingPinRef.current) {
      map.removeLayer(placingPinRef.current);
      placingPinRef.current = null;
    }
    return () => {
      map.off("click", onClick);
      if (map.getContainer()) map.getContainer().style.cursor = "";
    };
  }, [placingMode]);

  useEffect(() => {
    const L = window.L;
    const map = mapObj.current;
    if (!map) return;
    markersRef.current.forEach((m) => map.removeLayer(m));
    markersRef.current = [];
    markersById.current = {};

    filtered.forEach((c) => {
      const isLm = c.kind === "landmark";
      const icon = L.divIcon({
        className: "",
        html: `<div class="cabin-marker ${isLm ? "landmark" : ""}"></div>`,
        iconSize: [14, 14],
        iconAnchor: [7, 7],
      });
      const m = L.marker([c.lat, c.lon], { icon }).addTo(map);
      m.on("click", () => { if (!placingMode) setSelected(c); });
      const ownerLine = c.owner && showOwners && c.name ? `<div class="owner">${c.owner}</div>` : "";
      m.bindTooltip(
        `<strong>${c.name || c.owner || c.id}</strong>${ownerLine}`,
        { direction: "top", offset: [0, -10], className: "cabin-tt" }
      );
      markersRef.current.push(m);
      markersById.current[c.id] = m;
    });
  }, [filtered, showOwners, placingMode]);

  // «Vis på kart»: fokuser markøren for en valgt hytte og vis navnet dens.
  useEffect(() => {
    const map = mapObj.current;
    if (!map || !focusId) return;
    const cabin = C.find((c) => c.id === focusId);
    const marker = markersById.current[focusId];
    if (!cabin || !marker) return;
    map.flyTo([cabin.lat, cabin.lon], 15, { duration: 0.7 });
    marker.openTooltip();
  }, [focusId, filtered, C]);

  const coordStr = pickedCoord
    ? `${pickedCoord.lat.toFixed(7)}° N, ${pickedCoord.lng.toFixed(7)}° Ø`
    : null;

  const copyCoord = () => {
    if (!coordStr) return;
    navigator.clipboard.writeText(`${pickedCoord.lat.toFixed(7)}, ${pickedCoord.lng.toFixed(7)}`).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };

  const mapCabinCount = filtered.filter((c) => c.kind !== "landmark").length;
  const totalCabins = placed.filter((c) => c.kind !== "landmark").length;

  // Hytter som både har bilde og koordinater — vises i egen seksjon med «Vis på kart».
  const withPhoto = useMemo(
    () => placed.filter((c) => c.photo && c.kind !== "landmark"),
    [placed]
  );

  const showOnMap = (cabin) => {
    setPlacingMode(false);
    setQuery("");
    setFocusId(null);
    // nullstill først slik at klikk på samme hytte igjen re-trigger fokus-effekten
    requestAnimationFrame(() => setFocusId(cabin.id));
    mapRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
  };

  return (
    <main data-screen-label="06 Hyttekart">
      <header className="page-head">
        <div className="container">
          <div className="crumbs"><a href="#hjem" onClick={(e) => { e.preventDefault(); window.navigate("hjem"); }}>Hjem</a> · <span>Hyttekart</span></div>
          <h1>Hyttekartet.</h1>
          <p className="lede">
            Kartet viser registrerte hytter med koordinater i Drammensmarka.
            Klikk en markør for hyttenavn og informasjon.
          </p>
        </div>
      </header>
      <div className="genserstripe" aria-hidden="true"></div>

      <section className="section">
        <div className="container">
          <div className="map-toolbar">
            <input
              type="text"
              placeholder="Søk etter hyttenavn eller adresse…"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
            />
            <label className="toggle">
              <input
                type="checkbox"
                checked={showOwners}
                onChange={(e) => setShowOwners(e.target.checked)}
              />
              Vis adresse
            </label>
            <button
              className={"btn " + (placingMode ? "btn-primary" : "btn-ghost")}
              style={{fontSize: 14, padding: "7px 16px", cursor: "pointer"}}
              onClick={() => { setPlacingMode(!placingMode); setPickedCoord(null); setCopied(false); }}
            >
              {placingMode ? "Avslutt plassering" : "Finn koordinater på kartet"}
            </button>
            <span className="count">{mapCabinCount} av {totalCabins} hytter på kart</span>
          </div>

          {placingMode && (
            <div className="placement-info">
              <strong>Plasseringsmodus:</strong> Klikk på kartet der hytta di ligger for å hente koordinater.
              {pickedCoord ? (
                <div className="coord-result">
                  <code>{coordStr}</code>
                  <button className="btn btn-ghost" style={{fontSize:13, padding:"4px 12px", cursor:"pointer"}} onClick={copyCoord}>
                    {copied ? "✓ Kopiert" : "Kopier"}
                  </button>
                  <span className="coord-hint">
                    Send koordinatene til <a href="mailto:post@dmhf.no">post@dmhf.no</a> for å registrere din hytte på kartet.
                  </span>
                </div>
              ) : (
                <span style={{color:"var(--ink-muted)", fontSize:14, marginLeft: 12}}>Klikk på kartet…</span>
              )}
            </div>
          )}

          <div className="map-frame">
            <div className="passepartout">
              <div id="map" ref={mapRef}></div>
            </div>
          </div>

          <div className="map-legend">
            <span><span className="swatch"></span>Medlemshytte</span>
            <span><span className="swatch lm"></span>Landemerke (Landfallhytta, Furumotomta, Spiralen)</span>
          </div>

          <div className="callout" style={{marginTop: 40}}>
            <h3 style={{marginBottom: 8, fontSize: 22}}>Registrer hytta di på kartet</h3>
            <p style={{margin:0, color:"var(--ink-soft)"}}>
              Bruk «Finn koordinater på kartet» over for å hente posisjonen, og send
              koordinatene til <a href="mailto:post@dmhf.no">post@dmhf.no</a> — oppgi hyttenummer og navn.
              {" "}Send gjerne med et bilde, byggeår og info om hytta hvis du ønsker det.
            </p>
          </div>
        </div>
      </section>

      {withPhoto.length > 0 && (
        <section className="section bg-paper">
          <div className="container">
            <div className="section-head">
              <div>
                <Eyebrow>Hytter med bilde</Eyebrow>
                <h2>Bli kjent med hyttene</h2>
              </div>
              <div className="right">Trykk «Vis på kart» for å finne hytta i kartet over</div>
            </div>
            <div className="cabin-photo-grid">
              {withPhoto.map((c) => {
                const cabinName = c.name || c.owner || c.id;
                const rawPhotos = c.photos || (c.photo ? [c.photo] : []);
                const cabinPhotos = rawPhotos.map((p) => (typeof p === "string" ? p : p.src));
                const cabinAlts = rawPhotos.map((p) =>
                  typeof p === "string" || !p.label ? `Hytta ${cabinName}` : `Hytta ${cabinName}, ${p.label}`);
                return (
                <div className="cabin-photo-card" key={c.id}>
                  <div className="frame-valnott">
                    <div className="passepartout">
                      <div className="ph" style={{aspectRatio:"4/3", maxWidth:"none", marginTop:0}}>
                        <ClickSlot id={"kart-foto-" + c.id} label={cabinName} alt={`Hytta ${cabinName}`} alts={cabinAlts} src={c.photo} images={cabinPhotos} radius="0" style={{width:"100%", height:"100%"}} />
                      </div>
                      {/* Alltid til stede så alle rammer får samme høyde og
                          titlene under står på linje — prikker kun når flere bilder */}
                      <div className="cabin-photo-dots" aria-hidden="true">
                        {cabinPhotos.length > 1 && cabinPhotos.map((_, i) => (
                          <span key={i} className={i === 0 ? "active" : ""} />
                        ))}
                      </div>
                    </div>
                  </div>
                  <button
                    type="button"
                    className={"btn btn-primary cabin-photo-btn" + (focusId === c.id ? " is-active" : "")}
                    onClick={() => showOnMap(c)}
                  >
                    <span aria-hidden="true">📍</span> Vis på kart
                  </button>
                  <div className="cabin-photo-body">
                    <h4>{c.name || c.owner || c.id}</h4>
                    {c.owner && c.name && <div className="cabin-photo-addr">{c.owner}</div>}
                    {c.note && <p>{c.note}</p>}
                  </div>
                </div>
                );
              })}
            </div>
          </div>
        </section>
      )}

      {unplaced.length > 0 && (
        <section className="section bg-cream-2">
          <div className="container">
            <div className="section-head">
              <div>
                <Eyebrow>Hytteliste</Eyebrow>
                <h2>Hytter uten kartkoordinater</h2>
              </div>
              <div className="right" style={{fontSize:14, color:"var(--ink-muted)"}}>{unplaced.length} hytter ikke kartfestet ennå</div>
            </div>
            <div className="cabin-list-grid">
              {unplaced.map((c) => (
                <button className="cabin-list-card" key={c.id} onClick={() => setSelected(c)}>
                  <div className="cabin-list-badge">{c.id}</div>
                  <div className="cabin-list-info">
                    <div className="cabin-list-name">{c.name || c.owner || "Uten navn"}</div>
                    {c.name && c.owner && <div className="cabin-list-addr">{c.owner}</div>}
                  </div>
                </button>
              ))}
            </div>
          </div>
        </section>
      )}

      {selected && (
        <CabinModal cabin={selected} showOwner={showOwners} onClose={() => setSelected(null)} />
      )}
    </main>
  );
}

function CabinSubmitBox({ cabin }) {
  const mapRef = useRef(null);
  const mapObj = useRef(null);
  const markerRef = useRef(null);
  const [coords, setCoords] = useState(null);
  const [copied, setCopied] = useState(false);
  const [infoText, setInfoText] = useState('');
  const [builtYear, setBuiltYear] = useState('');

  useEffect(() => {
    if (mapObj.current || !mapRef.current) return;
    const L = window.L;
    const map = L.map(mapRef.current, {
      center: [59.763, 10.171],
      zoom: 12,
      scrollWheelZoom: true,
    });
    L.tileLayer("https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", {
      attribution: "© OpenStreetMap · OpenTopoMap (CC-BY-SA)",
      maxZoom: 17,
    }).addTo(map);
    map.on("click", (e) => {
      const { lat, lng } = e.latlng;
      const c = { lat: lat.toFixed(6), lon: lng.toFixed(6) };
      setCoords(c);
      if (markerRef.current) markerRef.current.setLatLng(e.latlng);
      else markerRef.current = L.marker(e.latlng).addTo(map);
    });
    const ro = new ResizeObserver(() => map.invalidateSize());
    ro.observe(mapRef.current);
    mapObj.current = map;
    return () => { ro.disconnect(); map.remove(); mapObj.current = null; markerRef.current = null; };
  }, []);

  const copyAll = () => {
    const lines = [
      `Hytte: ${cabin.id} – ${cabin.name || cabin.owner || ""}`,
      cabin.owner ? `Adresse: ${cabin.owner}` : null,
      coords
        ? `Koordinater: ${coords.lat}° N, ${coords.lon}° Ø`
        : "Koordinater: (klikk på kartet for å velge)",
      builtYear ? `Byggeår: ${builtYear}` : null,
      infoText ? `Info: ${infoText}` : null,
    ].filter(Boolean).join("\n");
    navigator.clipboard.writeText(lines).catch(() => {});
    setCopied(true);
    setTimeout(() => setCopied(false), 2200);
  };

  return (
    <div className="cabin-submit-box">
      <div className="cabin-submit-map" ref={mapRef}></div>
      <div className="cabin-submit-row">
        <span className="cabin-submit-coords">
          {coords
            ? `${coords.lat}° N, ${coords.lon}° Ø`
            : "Klikk i kartet for å finne koordinater"}
        </span>
        <button className="btn btn-ghost cabin-submit-copy" onClick={copyAll}>
          {copied ? "✓ Kopiert" : "Kopier alt"}
        </button>
      </div>
      <div className="cabin-submit-fields">
        <label className="cabin-submit-fieldlabel">Byggeår</label>
        <input
          className="cabin-submit-input"
          type="text"
          inputMode="numeric"
          placeholder="f.eks. 1965"
          value={builtYear}
          onChange={(e) => setBuiltYear(e.target.value)}
        />
        <label className="cabin-submit-fieldlabel">Info om hytten</label>
        <textarea
          className="cabin-submit-textarea"
          rows={3}
          placeholder="Byggestil, historikk, særpreg — alt som kan hjelpe oss å identifisere hytten."
          value={infoText}
          onChange={(e) => setInfoText(e.target.value)}
        />
      </div>
      <p className="cabin-submit-text">
        Send koordinater og gjerne et bilde til{" "}
        <a href={`mailto:post@dmhf.no?subject=Koordinater ${cabin.id} ${cabin.name || cabin.owner || ""}`}>
          post@dmhf.no
        </a>{" "}
        — vi legger hytten inn på kartet.
      </p>
    </div>
  );
}

function CabinModal({ cabin, showOwner, onClose }) {
  // Støtter både ett bilde (photo) og flere (photos: [{src, label}] eller ["sti.jpg"]).
  const photos = (cabin.photos || (cabin.photo ? [cabin.photo] : []))
    .map((p) => (typeof p === "string" ? { src: p, label: null } : p));
  const modalName = cabin.name || cabin.owner || cabin.id;
  const photoAlts = photos.map((p) => (p.label ? `Hytta ${modalName}, ${p.label}` : `Hytta ${modalName}`));
  const [imgIdx, setImgIdx] = useState(0);
  const closeBtnRef = useRef(null);

  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    // flytt fokus inn i modalen, og tilbake dit brukeren var ved lukking
    const prevFocus = document.activeElement;
    closeBtnRef.current?.focus();
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
      if (prevFocus && prevFocus.focus) prevFocus.focus();
    };
  }, [onClose]);

  const isLm = cabin.kind === "landmark";
  const hasCoords = cabin.lat != null && cabin.lon != null;

  return (
    <React.Fragment>
      <div className="modal-backdrop" onClick={onClose}>
        <div className="modal" onClick={(e) => e.stopPropagation()}>
          <div className="modal-head">
            <div>
              <span className="num">{isLm ? "Landemerke" : cabin.id}</span>
              <h3>{cabin.name || cabin.owner || cabin.id}</h3>
            </div>
            <button className="modal-close" ref={closeBtnRef} onClick={onClose} aria-label="Lukk">×</button>
          </div>

          <div className="modal-body">
            {(hasCoords || isLm) ? (
              <React.Fragment>
                <div
                  className={"cabin-img-wrap" + (photos.length ? " cabin-img-zoomable" : "")}
                  onClick={photos.length ? () => openLightbox(photos.map((p) => p.src), imgIdx, photoAlts) : undefined}
                  {...(photos.length ? zoomKeys(() => openLightbox(photos.map((p) => p.src), imgIdx, photoAlts)) : {})}
                  aria-label={photos.length ? `Vis større bilde av ${cabin.name || cabin.owner || cabin.id}` : undefined}
                >
                  <image-slot
                    id={"cabin-" + cabin.id}
                    placeholder={`Bilde av ${cabin.name || cabin.owner || cabin.id}`}
                    shape="rounded"
                    radius="6"
                    fit="contain"
                    src={(photos[imgIdx] && photos[imgIdx].src) || undefined}
                    alt={photoAlts[imgIdx] || ""}
                  ></image-slot>
                </div>
                {photos.length > 1 && (
                  <div className="cabin-thumbs">
                    {photos.map((p, i) => (
                      <button
                        key={p.src}
                        className={"cabin-thumb" + (i === imgIdx ? " active" : "")}
                        onClick={() => setImgIdx(i)}
                        aria-label={p.label ? `Vis bilde fra ${p.label}` : `Vis bilde ${i + 1}`}
                      >
                        <img src={p.src} alt={photoAlts[i] || ""} loading="lazy" />
                        {p.label && <span>{p.label}</span>}
                      </button>
                    ))}
                  </div>
                )}
              </React.Fragment>
            ) : (
              <CabinSubmitBox cabin={cabin} />
            )}

            {/* Info box */}
            <div className="cabin-info-box">
              {!isLm && cabin.owner && (
                <div className="cabin-info-row">
                  <span className="cabin-info-label">Adresse</span>
                  <span className="cabin-info-val">{cabin.owner}</span>
                </div>
              )}
              <div className="cabin-info-row">
                <span className="cabin-info-label">Koordinater</span>
                {hasCoords ? (
                  <span className="cabin-info-val" style={{fontFamily:"var(--mono)", fontSize:13}}>
                    {cabin.lat.toFixed(6)}° N, {cabin.lon.toFixed(6)}° Ø
                  </span>
                ) : (
                  <span className="cabin-info-val" style={{color:"var(--ink-muted)"}}>Ikke registrert — bruk «Finn koordinater» på kartet</span>
                )}
              </div>
              {cabin.note && (
                <div className="cabin-info-row">
                  <span className="cabin-info-label">Notat</span>
                  <span className="cabin-info-val">{cabin.note}</span>
                </div>
              )}
            </div>

          </div>
        </div>
      </div>
    </React.Fragment>
  );
}

// ------------------ HYTTENYTT ------------------

function HyttenyttPage() {
  const H = window.SITE_DATA.hyttenytt;
  const latest = H.issues.find((i) => i.featured) || H.issues[0];

  return (
    <main data-screen-label="07 Hyttenytt">
      <header className="page-head">
        <div className="container">
          <div className="crumbs"><a href="#hjem" onClick={(e) => { e.preventDefault(); window.navigate("hjem"); }}>Hjem</a> · <span>Hyttenytt</span></div>
          <h1>Hyttenytt.</h1>
          <p className="lede">
            Medlemsbladet til Drammensmarka Hytteeierforening — kommer ut vår og høst.
          </p>
        </div>
      </header>
      <div className="genserstripe" aria-hidden="true"></div>

      {/* SISTE UTGAVE */}
      <section className="section">
        <div className="container">
          <div className="hn-feature">
            <div className="frame-valnott">
              <div className="passepartout">
                <div className="hn-cover">
                  <span className="badge">Siste utgave</span>
                  <PhSlot
                    id={"hn-cover-" + latest.yr + "-" + latest.no}
                    label={`Forside · Hyttenytt nr. ${latest.no} / ${latest.yr}`}
                    src={latest.cover}
                    radius="0"
                    style={{width:"100%", height:"100%"}}
                  />
                </div>
              </div>
            </div>
            <div>
              <Eyebrow>Hyttenytt nr. {latest.no} / {latest.yr}</Eyebrow>
              <h2 style={{marginBottom: 16}}>{latest.theme}</h2>
              <div className="meta">{latest.date} · {latest.pages} sider</div>
              <p style={{fontSize: 19, color:"var(--ink-soft)", maxWidth: 560, marginTop: 20}}>
                {latest.teaser}
              </p>
            </div>
          </div>
        </div>
      </section>

      {/* ARKIV */}
      <section className="section bg-paper">
        <div className="container">
          <div className="section-head">
            <div>
              <Eyebrow>Arkiv</Eyebrow>
              <h2>Tidligere utgaver</h2>
            </div>
            <div className="right">Papirutgaven sendes til alle medlemmer</div>
          </div>
          <div className="hn-grid">
            {H.issues.filter((i) => i !== latest).map((i) => (
              <div className="hn-issue" key={i.yr + "-" + i.no}>
                <div className="frame-valnott" style={{marginBottom:16}}>
                  <div className="passepartout">
                    <div className="hn-issue-cover">
                      <ClickSlot
                        id={"hn-arkiv-" + i.yr + "-" + i.no}
                        label={`Forside · Hyttenytt nr. ${i.no} / ${i.yr}`}
                        src={i.cover}
                        radius="0"
                        style={{width:"100%", height:"100%"}}
                      />
                    </div>
                  </div>
                </div>
                <div className="meta">Nr. {i.no} / {i.yr} · {i.date} · {i.pages} sider</div>
                <h4>{i.theme}</h4>
                <p>{i.teaser}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* OM BLADET */}
      <section className="section bg-cream-2">
        <div className="container">
          <div className="two-col">
            <div>
              <Eyebrow>Om bladet</Eyebrow>
              <h2>To ganger i året — vår og høst.</h2>
            </div>
            <div className="read">
              <p style={{fontSize: 20, color:"var(--ink-soft)"}}>{H.intro}</p>
              <p>
                Redaksjonen tar gjerne imot bilder, historier og leserinnlegg.
                Send til <a href="mailto:post@dmhf.no">post@dmhf.no</a> innen 1. mars (vårutgaven) eller 1. oktober (høstutgaven).
              </p>
            </div>
          </div>
        </div>
      </section>
    </main>
  );
}

// expose
Object.assign(window, { HomePage, HistoriePage, ArsmoterPage, OkonomiPage, VedtekterPage, KartPage, HyttenyttPage, GlobalLightbox });
