// Scenio landing · sections after the hero (brief §4), composed from the design system.
(() => {
if (!window.SCENIO_INIT) return; // host guard (C4-m10): the bundle carries this file too; it runs only on its host page, which sets window.SCENIO_INIT first
const NS = window.ScenioPaperCrimson_b9a328;
const { UButton, UBadge, UIcon, UCard, USkeleton, UEmpty, UAlert, UPageSection, UPageCard, UTable, UFooter, UFooterColumns, UPageLogos, ScenioOfferCard, ScenioPromotedCard, ScenioTestimonialCard, ScenioScrollTimeline, UTabs, USwitch } = NS;
const { useState, useEffect, useRef } = React;
const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
const L = (v, locale) => (v && typeof v === 'object' && !React.isValidElement(v) ? v[locale] : v);
// interim imagery (owner ruling @f66c304): the mockup crops from docs/design/assets/mockup/, one per slot, matched by name; every slot is sized for the FINAL file named in data-final (4:3 venues and services, 4:5 event types, 16:9 scenes) — the owner replaces them after release
const MOCK = '../../assets/mockup/';
const Photo = ({ className, name, alt = '', final }) => <img className={className} src={`${MOCK}${name}.png`} alt={alt} loading="lazy" decoding="async" data-interim="mockup" data-final={final} />;

function Reveal({ children, className = '', as: Tag = 'div', ...rest }) {
  const ref = useRef(null); const [inView, setIn] = useState(false);
  useEffect(() => { const el = ref.current; if (!el || !('IntersectionObserver' in window)) { setIn(true); return; } const io = new IntersectionObserver((es) => { es.forEach((e) => { if (e.isIntersecting) { setIn(true); io.disconnect(); } }); }, { threshold: .16 }); io.observe(el); return () => io.disconnect(); }, []);
  const kids = React.Children.map(children, (c, i) => (React.isValidElement(c) ? React.cloneElement(c, { style: { ...(c.props.style || {}), '--i': i } }) : c));
  return <Tag ref={ref} className={`reveal ${inView ? 'is-in' : ''} ${className}`} {...rest}>{kids}</Tag>;
}

// scroll choreography (§8, owner ruling: nothing below the hero arrives complete) — ONE observer lights every section; .is-lit draws the hairline, raises the label → title → description → links in sequence, and starts the §4 package figure. The figures inside each grid wipe up on their own stagger (landing.css, .reveal).
function useSectionChoreography(dep) {
  useEffect(() => {
    const sel = '.landing main .sc-ps';
    if (!('IntersectionObserver' in window)) { document.querySelectorAll(sel).forEach((el) => el.classList.add('is-lit')); return; }
    const io = new IntersectionObserver((es) => es.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('is-lit'); io.unobserve(e.target); } }), { threshold: .12, rootMargin: '0px 0px -8% 0px' });
    document.querySelectorAll(sel).forEach((el) => { if (!el.classList.contains('is-lit')) io.observe(el); });
    return () => io.disconnect();
  }, [dep]);
}

function ItemBody({ item, t }) {
  return <>
    <div className="item-media"><Photo className="item-photo" name={item.interim} final={item.photo} /></div>
    <div className="item-body">
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}><UBadge color={item.kind === 'venue' ? 'kind-venue' : 'kind-service'} variant="soft" size="xs" label={item.kind === 'venue' ? t.item.venue : t.item.service} />{item.ready && <UBadge color="flag-ready" variant="soft" size="xs" icon="i-hugeicons-tick-02" label={t.item.ready} />}</div>
      <div className="item-name">{item.name}</div>
      <div className="item-meta"><UIcon name="i-hugeicons-location-01" size={14} /><span>{item.location}</span>{item.capacity && <><span aria-hidden="true">·</span><UIcon name="i-hugeicons-user-group" size={14} /><span>{t.item.guests(item.capacity)}</span></>}</div>
    </div>
    <div className="item-foot"><span className="item-price">{(() => { const [pre, post = ''] = String(t.item.from).split('{amount}'); return <>{pre.trim() && <>{pre.trim()} </>}<b>{item.price}</b>{post}{item.perGuest && <span style={{ color: 'var(--muted)' }}> {String(t.item.perGuest).replace(/^\p{Lu}/u, (c) => c.toLowerCase())}</span>}</>; })()}</span><span className="item-rating"><UIcon name="i-hugeicons-star" size={14} color="var(--accent)" />{item.rating} · {t.item.reviews(item.reviews)}</span></div>
  </>;
}
// items/Card.vue recreated: UCard as a link, body flush
function ItemsCard({ item, t, style }) { return <UCard as="a" href="#" className="item" ui={{ body: { padding: 0, display: 'flex', flexDirection: 'column' } }} style={style}><ItemBody item={item} t={t} /></UCard>; }
function ItemsSkeleton({ style }) { return <UCard aria-busy="true" ui={{ body: { padding: 0 } }} style={style}><USkeleton height="auto" style={{ aspectRatio: '4/3', borderRadius: 0 }} /><div style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 10 }}><USkeleton width={64} height={18} /><USkeleton width="70%" height={16} /><USkeleton width="50%" height={12} /><USkeleton width="60%" height={14} style={{ marginTop: 6 }} /></div></UCard>; }

function Collection({ t, state, items, render, cols = 4, skeletons = 4, onRetry }) {
  if (state === 'skeleton') return <div className={`grid-${cols}`}>{Array.from({ length: skeletons }).map((_, i) => <ItemsSkeleton key={i} />)}</div>;
  if (state === 'empty') return <UEmpty variant="outline" icon="i-hugeicons-search-02" title={t.empty.title} description={t.empty.text} actions={[{ label: t.empty.action, color: 'primary', variant: 'soft' }]} />;
  if (state === 'error') return <UAlert color="error" title={t.error.title} actions={[{ label: t.error.retry, variant: 'outline', onClick: onRetry }]} />;
  return <Reveal className={`grid-${cols}`}>{items.map(render)}</Reveal>;
}

function Sections({ t, locale, state, reduced, mobile, onRetry }) {
  const D = window.SCENIO_DATA;
  useSectionChoreography(state);
  const [vendors, setVendors] = React.useState(() => ['owner', 'vendor'].includes((window.SCENIO_INIT || {}).role) || window.location.hash === '#providers');
  React.useEffect(() => { const open = (ev) => { const a = ev && ev.target && ev.target.closest ? ev.target.closest('a[href$="#providers"]') : null; if (ev && ev.type === 'click' && !a) return; if (a) ev.preventDefault(); setVendors(true); setTimeout(() => { const el = document.getElementById('providers'); if (el) el.classList.add('is-lit'); if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 72, behavior: 'smooth' }); }, 60); }; const onHash = () => { if (window.location.hash === '#providers') open(); }; if (window.location.hash === '#providers' || ['owner', 'vendor'].includes((window.SCENIO_INIT || {}).role)) setTimeout(() => { const el = document.getElementById('providers'); if (el) el.classList.add('is-lit'); }, 120); document.addEventListener('click', open, true); window.addEventListener('hashchange', onHash); return () => { document.removeEventListener('click', open, true); window.removeEventListener('hashchange', onHash); }; }, []);
  const linkBtn = (label) => [{ label, variant: 'link', color: 'primary', trailingIcon: 'i-hugeicons-arrow-right-01' }];
  return <>
    <UPageSection id="partners" ui={{ root: { paddingTop: mobile ? 40 : 64, paddingBottom: 0 } }}>
      <Reveal><UPageLogos title={t.partners.label} placeholderLabel={t.partners.placeholder} items={t.partners.items.map((alt) => ({ alt }))} /></Reveal>
    </UPageSection>
    <UPageSection id="venues" headline={t.venues.headline} title={t.venues.title} links={linkBtn(t.venues.link)}>
      <Collection t={t} state={state} items={D.venues} onRetry={onRetry} render={(v) => <ItemsCard key={v.id} item={v} t={t} />} />
    </UPageSection>
    <UPageSection id="events" hairline headline={t.events.headline} title={t.events.title}>
      <Reveal className="events">{D.events.map((e) => { const name = t.events.types[e.id]; return (
        <a key={e.id} href={`/discovery?eventType=${e.slug || e.id}`} aria-label={t.events.go(name)}>
          <div className="ev-media"><Photo className="ev-photo" name={e.interim} final={`events/${e.id}-4x5.png`} /><span className="ev-veil" aria-hidden="true" /><span className="ev-name">{name}</span><span className="ev-go" aria-hidden="true"><UIcon name="i-hugeicons-arrow-right-01" size={17} /></span></div>
          <span className="ev-meta">{L(e.meta, locale)}</span>
        </a>
      ); })}</Reveal>
    </UPageSection>
    <UPageSection id="services" hairline headline={t.services.headline} title={t.services.title} links={linkBtn(t.services.link)}>
      <Collection t={t} state={state} items={D.services} onRetry={onRetry} render={(s) => <ItemsCard key={s.id} item={s} t={t} />} />
    </UPageSection>
    <UPageSection id="offers" hairline headline={t.offers.headline} title={t.offers.title}>
      <Collection t={t} state={state} items={D.offers} cols={3} skeletons={3} onRetry={onRetry} render={(o, i) => (
        <ScenioOfferCard key={i} kind={o.kind} badge={t.offers.kinds[o.kind]} meta={L(o.meta, locale)} title={L(o.title, locale)} lines={o.lines.map((l) => ({ icon: l.icon, text: L(l.text, locale) }))} valueLabel={o.valueKind === 'date' ? t.offers.dateLabel : t.offers.fromLabel} value={L(o.value, locale)} cta={{ label: t.offers.cta, color: 'primary', variant: 'soft' }} to="#" />
      )} />
    </UPageSection>
    <UPageSection id="promoted" hairline headline={t.promoted.headline} title={t.promoted.title}>
      <Collection t={t} state={state} items={D.promoted} cols={2} skeletons={2} onRetry={onRetry} render={(item) => <ScenioPromotedCard key={item.id} kind={item.kind} locale={locale} to="#" item={{ id: item.id, name: item.name, photo: `${MOCK}${item.interim}.png`, city: item.location, capacity: item.capacity, price: Number(String(item.price).replace(/\D/g, '')), perGuest: item.perGuest, rating: parseFloat(String(item.rating).replace(',', '.')), reviews: item.reviews, ready: item.ready }} />} />
    </UPageSection>
    <UPageSection id="why" hairline headline={t.why.headline} title={t.why.title}>
      <div className="wy">
        <div className="wy-fig">
          <span className="wy-cap">{t.why.diagram.before}</span><span className="wy-cap-note">{t.why.diagram.beforeCount}</span>
          <div className="wy-stack">
            {t.why.diagram.items.map((label, i) => <span key={i} className="wy-slip" style={{ '--k': i }}>{label}</span>)}
            <div className="wy-pack"><span className="wy-pack-label">{t.why.diagram.after}</span><span className="wy-pack-note">{t.why.diagram.afterNote}</span></div>
          </div>
        </div>
        <ol className="wy-list">{t.why.items.map((w, i) => <li key={i}><span className="wy-num">{String(i + 1).padStart(2, '0')}</span><div><div className="why-title">{w.title}</div><p className="why-text">{w.text}</p></div></li>)}</ol>
      </div>
    </UPageSection>
    <UPageSection id="timeline" hairline headline={t.timeline.headline} title={t.timeline.title} ui={{ root: { paddingBottom: 0 }, header: { marginBottom: 0 } }} />
    <ScenioScrollTimeline stages={t.timeline.stages} reduced={reduced} mobile={mobile} />
    <UPageSection id="testimonials" hairline headline={t.testimonials.headline} title={t.testimonials.title}>
      {state === 'skeleton' ? <div className="grid-3">{[0, 1, 2].map((i) => <UCard key={i} aria-busy="true"><USkeleton height={14} /><USkeleton height={14} width="90%" style={{ marginTop: 8 }} /><USkeleton height={14} width="60%" style={{ marginTop: 8 }} /><USkeleton height={12} width={120} style={{ marginTop: 20 }} /></UCard>)}</div>
        : <Reveal className="grid-3">{t.testimonials.items.slice(0, 3).map((q, i) => <ScenioTestimonialCard key={i} quote={q.quote} name={q.name} meta={q.meta} rating={q.rating} />)}</Reveal>}
    </UPageSection>
    {vendors && <UPageSection id="providers" hairline headline={t.providers.headline} title={t.providers.title} description={t.providers.text} links={[{ label: t.providers.cta, color: 'primary', variant: 'solid', to: '/authentication?mode=register' }, { label: t.providers.secondary, variant: 'outline', color: 'neutral', to: '#' }]}>
      <Reveal className="pv">{t.providers.items.map((w, i) => <div key={i}><span className="pv-num">{String(i + 1).padStart(2, '0')}</span><div className="why-title">{w.title}</div><p className="why-text">{w.text}</p></div>)}</Reveal>
      <Plans t={t} locale={locale} />
    </UPageSection>}
    <Closing t={t} reduced={reduced} />
  </>;
}

// the plan strip (§4, owner ruling: the provider's first question is what it costs) — three tiers from the product's own subscription copy, the feature × tier matrix folded away behind one button
function Plans({ t, locale }) {
  const [show, setShow] = useState(false);
  const p = t.providers.plans;
  const [open, setOpen] = useState(false);
  const cols = p.cols.map((h, i) => ({ accessorKey: `c${i}`, header: h, meta: { class: { th: i ? 'text-right' : undefined, td: i ? 'text-right' : 'font-medium' } } }));
  const rows = p.matrix.map((r, k) => ({ id: k, ...Object.fromEntries(r.map((v, i) => [`c${i}`, v])) }));
  return (<div className="plans-wrap">
    <UButton color="neutral" variant="outline" className="plans-toggle" label={show ? (locale === 'pl' ? 'Ukryj subskrypcję' : 'Hide subscription') : (locale === 'pl' ? 'Pokaż subskrypcję' : 'Show subscription')} trailingIcon={show ? 'i-hugeicons-arrow-up-01' : 'i-hugeicons-arrow-down-01'} aria-expanded={show} onClick={() => setShow((v) => !v)} />
    {show && <div className="plans">
      <div className="plans-head"><div className="plans-label">{p.label}</div><div className="plans-title">{p.title}</div></div>
      <div className="plans-grid">{p.tiers.map((tier) => (
        <div key={tier.name} className={`plan${tier.popular ? ' plan--popular' : ''}`}>
          {tier.popular && <UBadge className="plan-flag" color="flag-recommended" variant="solid" size="sm" label={p.popular} />}
          <div className="plan-name">{tier.name}</div>
          <div className="plan-price"><b>{tier.price}</b><span>{p.per}</span></div>
          <ul className="plan-lines">{tier.lines.map((l, i) => <li key={i}><UIcon name="i-hugeicons-tick-02" size={16} color="var(--accent)" /><span>{l}</span></li>)}</ul>
          <UButton block color="primary" variant={tier.popular ? 'solid' : 'outline'} label={p.choose} to="/authentication?mode=register" />
        </div>
      ))}</div>
      <div className="plans-more">
        <UButton color="neutral" variant="outline" label={open ? p.close : p.open} trailingIcon={open ? 'i-hugeicons-arrow-up-01' : 'i-hugeicons-arrow-down-01'} aria-expanded={open} aria-controls="plans-matrix" onClick={() => setOpen((v) => !v)} />
        <p className="plans-note">{p.note}</p>
      </div>
      <div id="plans-matrix" className={`plans-table${open ? ' is-open' : ''}`} aria-hidden={open ? undefined : 'true'}>
        <UTable locale={locale} data={rows} columns={cols} ariaLabel={p.title} />
      </div>
    </div>}</div>
  );
}

// the closing band (brief §4, from the owner's mockup): a ~44 vh band, scenio-pattern §8.6: finish = clamp((vh − top) / (vh + h × .2)); the photograph translates (finish − .5) × 75px at scale 1.06. Interim: the mockup's candlelit plate (closing-live-celebration) as the one photograph; the day → night pair (night opacity .15 → .70, night at (finish − .5) × 50px) returns when closing/day.png and night.png exist (ASSET-GENERATION-PROMPTS §4).
function Closing({ t, reduced }) {
  const ref = useRef(null); const [f, setF] = useState(0);
  useEffect(() => {
    let raf = null; const on = () => { if (raf) return; raf = requestAnimationFrame(() => { raf = null; const el = ref.current; if (!el) return; const r = el.getBoundingClientRect(); const vh = window.innerHeight; setF(clamp((vh - r.top) / (vh + r.height * .2), 0, 1)); }); };
    on(); window.addEventListener('scroll', on, { passive: true }); window.addEventListener('resize', on); return () => { window.removeEventListener('scroll', on); window.removeEventListener('resize', on); if (raf) cancelAnimationFrame(raf); };
  }, []);
  return (
    <section id="closing" className="closing" data-on-photo="" ref={ref} aria-labelledby="closing-title">
      <div className="closing-plane" style={{ transform: reduced ? 'scale(1.06)' : `translateY(${(f - .5) * 75}px) scale(1.06)` }}><Photo className="closing-photo" name="closing-live-celebration" alt={t.closing.alt} final="closing/day.png · closing/night.png" /></div>
      <div className="closing-scrim" />
      <Reveal className="closing-copy">
        <p className="closing-eyebrow">{t.closing.eyebrow}</p>
        <h2 id="closing-title" className="closing-title">{t.closing.title}</h2>
        <p className="closing-text">{t.closing.text}</p>
        <div className="closing-ctas">
          <UButton size="lg" color="primary" variant="solid" label={t.closing.cta} to="/authentication?mode=register" />
          <UButton size="lg" color="neutral" variant="outline" className="closing-cta-quiet" label={t.closing.ctaSecondary} to="/discovery" />
        </div>
      </Reveal>
    </section>
  );
}

function Footer({ t, locale }) {
  const c = window.SCENIO_DATA.company;
  const ph = (v) => (!v || /^0+$/.test(v) ? <span className="muted">{t.footer.notSet}</span> : v);
  // H-f (owner 2026-09-24): canon's footer groups (stores/global/footer.ts) — the company block ("Firma") and the "Produkt" column on top, ONE legal row in the bottom band, the locale sentence; the client / provider columns and the doubled legal column are gone
  const PRODUCT_TO = ['/', '/discovery', '/auth', '#reviews'];
  const cols = [{ label: t.footer.product.label, children: t.footer.product.links.map((l, i) => ({ label: l, to: PRODUCT_TO[i] || '#' })) }];
  return (
    <UFooter locale={locale} top={<UFooterColumns columns={cols}>
      <address className="company">
        <span className="company-group">{t.footer.company}</span>
        <a href="/" className="lockup" aria-label="Scenio"><span className="mark" aria-hidden="true" /><span className="word">Scenio</span></a>
        <b className="legal">{c.name}</b>
        <div className="company-parts">
          <div className="company-part"><span className="lbl">{t.footer.address}</span><span className="val">{c.street}<br />{c.city}</span></div>
          <div className="company-part"><span className="lbl">{t.footer.contact}</span><span className="val"><a href={`mailto:${c.email}`}>{c.email}</a><br /><a href={`tel:${c.phone.replace(/\s/g, '')}`}>{c.phone}</a></span></div>
          <div className="company-part company-part--registry"><span className="lbl">{t.footer.registry}</span><span className="val">NIP {c.nip}<br />KRS {ph(c.krs)}<br />REGON {ph(c.regon)}</span></div>
        </div>
      </address>
    </UFooterColumns>}
      bottom={<>
        {/* W2.16: the legal row survives every width (it wraps), the cookie-settings trigger reopens the preferences, the payments / KSeF note stays (O3e); H-f: this is the one legal row */}
        <nav className="legal-row" aria-label={t.footer.legal.label}>{t.footer.legal.links.map((l) => <a key={l} href="#">{l}</a>)}<button type="button" className="legal-cookie" data-cookie-settings="" onClick={() => window.dispatchEvent(new CustomEvent('scenio:cookie-settings'))}>{t.footer.cookieSettings}</button></nav>
        <span>{t.footer.copy}</span><span>{t.footer.payments}</span><span>{t.footer.locale}</span>
      </>} />
  );
}

function DevBar({ t, state, setState, reduced, setReduced, p }) {
  return (
    <aside className="devbar" aria-label={t.states.label}>
      <span className="sc-micro">{t.states.label}</span>
      <UTabs variant="pill" value={state} onChange={setState} content={false} items={[{ label: t.states.ready, value: 'ready' }, { label: t.states.skeleton, value: 'skeleton' }, { label: t.states.empty, value: 'empty' }, { label: t.states.error, value: 'error' }]} />
      <USwitch checked={reduced} onChange={setReduced} label={t.states.reduced} />
      <span className="p">{t.states.progress} {p.toFixed(2)}</span>
    </aside>
  );
}
window.ScenioLanding = Object.assign(window.ScenioLanding || {}, { Sections, Footer, DevBar, ItemsCard, Reveal, Closing, Plans });
})();
