{
  "id": "ahv-template-photo-collections-desktop",
  "file": "AHV Template Photo Collections Desktop.dc.html",
  "sourceSha256": "bff74ec58b00f7b3f5945ee30426cf6d5a808bb5506e31758ead6401eb3c178b",
  "variant": "desktop",
  "template": "\n<helmet>\n<link href=\"/ahv/fonts/ahv-33eeac48ab44.css\" rel=\"stylesheet\">\n\n<style>\nbody{margin:0;background:#F7F4EA;color:#2A2118;font-family:'Mulish',sans-serif;font-size:18px;line-height:1.7}\na{color:#006038;text-decoration:none}a:hover{color:#004226;text-decoration:underline}\n:focus-visible{outline:3px solid #6B7726;outline-offset:2px;box-shadow:0 0 0 6px rgba(247,244,234,.85)}\na:active,button:active{filter:brightness(.88)}\nbutton{font-family:inherit;cursor:pointer}\nh1,h2,h3,h4{font-weight:400;margin:0}\n*{box-sizing:border-box}\n@media (prefers-reduced-motion:reduce){*{transition:none !important;animation:none !important}}\n[data-gallery-chapter]{scroll-margin-top:80px}\n[data-gallery-tile]{touch-action:pan-y pinch-zoom}\n[data-gallery-tile] img{width:100%;height:auto;display:block}\ndialog[data-gallery-dialog]{width:100%;max-width:none;height:100%;max-height:none;margin:0;padding:24px;border:0;background:rgba(26,20,12,.96);color:#F7F4EA;display:none;flex-direction:column;align-items:center;justify-content:center;gap:12px;inset:0;overflow:hidden}\ndialog[data-gallery-dialog][open]{display:flex}\ndialog[data-gallery-dialog]::backdrop{background:rgba(26,20,12,.6)}\n[data-gallery-stage]{touch-action:pan-x pan-y pinch-zoom;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}\n[data-gallery-facade]{position:relative;display:block;width:100%;padding:0;border:0;background:#1A140C;border-radius:4px;overflow:hidden;cursor:pointer}\n[data-gallery-facade] img{width:100%;height:auto;display:block;aspect-ratio:16/9;object-fit:cover}\n[data-gallery-facade] span{position:absolute;left:50%;top:50%;width:72px;height:72px;margin:-36px 0 0 -36px;border-radius:50%;background:#EEB41E;color:#2A2118;display:flex;align-items:center;justify-content:center;font-size:30px;line-height:1;box-shadow:0 2px 12px rgba(0,0,0,.35)}\n[data-gallery-facade]:hover span{filter:brightness(.95)}\n[data-gallery-iframe]{width:100%;aspect-ratio:16/9;height:auto;border:0;display:block;border-radius:4px;background:#000}\n</style>\n<meta name=\"description\" content=\"Fotos von Kairali – The Ayurvedic Healing Village, Palakkad: das Krankenhaus, seine Behandlungen und seine Umgebung.\">\n<link rel=\"canonical\" href=\"https://ayurvedichealingvillage.com/de/property-gallery/\">\n<meta name=\"robots\" content=\"noindex, nofollow\">\n<link rel=\"icon\" href=\"/ahv/assets/img/logo_color-da22eb.svg\" sizes=\"192x192\">\n</helmet>\n<div data-screen-label=\"Photo collections template — Desktop 1440\">\n<a href=\"#main-content\" style=\"position:fixed;left:-9999px;top:12px;z-index:220;background:#5A4420;color:#F7F4EA;padding:14px 24px;border-radius:4px;font-weight:700;font-size:15px\" style-focus=\"left:16px\">Zum Hauptinhalt springen</a>\n<dc-import name=\"AHV Chrome Header\" hint-size=\"100%,72px\"></dc-import>\n<main id=\"main-content\">\n\n  <section style=\"width:min(1220px,94%);margin:0 auto;padding:30px 0 26px\">\n    <nav aria-label=\"Navigationspfad\" style=\"font-size:15px;color:#75695A;display:flex;gap:10px;align-items:center;flex-wrap:wrap\">\n      <sc-for list=\"{{ crumbs }}\" as=\"c\" hint-placeholder-count=\"2\">\n        <a href=\"{{ c.url }}\" onClick=\"{{ guard }}\" style=\"display:inline-flex;align-items:center;min-height:44px\">{{ c.label }}</a>\n        <span aria-hidden=\"true\" style=\"color:#C9BFA8\">/</span>\n      </sc-for>\n      <span aria-current=\"page\" style=\"color:#2A2118\">{{ crumbLast }}</span>\n    </nav>\n    <p style=\"margin:0;font-weight:700;font-size:12.5px;letter-spacing:2.6px;text-transform:uppercase;color:#8F6212\">Kairali — The Ayurvedic Healing Village · Seit 1908</p>\n    <div style=\"display:grid;grid-template-columns:minmax(0,7fr) minmax(0,6fr);gap:28px 72px;align-items:start;padding-top:12px\">\n      <h1 style=\"font-family:'Marcellus',serif;font-size:clamp(34px,3.6vw,54px);line-height:1.12;margin:0;text-wrap:balance\">{{ h1 }}</h1>\n      <div style=\"min-width:0\">\n        <p style=\"font-size:18px;line-height:1.7;color:#514A3F;max-width:66ch;margin:0;border-left:3px solid #C1882C;padding-left:20px;text-wrap:pretty\">{{ intro }}</p>\n        <p style=\"margin:14px 0 0 23px;font-weight:700;font-size:13px;letter-spacing:2px;text-transform:uppercase;color:#5A4420\">{{ tally }}</p>\n      </div>\n    </div>\n    <nav aria-label=\"Abschnitte\" style=\"margin-top:26px;border-top:1px solid #E9E2D3;padding-top:18px\">\n      <ul style=\"list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:10px\">\n        <sc-for list=\"{{ chapterLinks }}\" as=\"c\" hint-placeholder-count=\"4\">\n          <li style=\"margin:0\"><a href=\"{{ c.href }}\" data-cta=\"gallery-chapter-jump\" style=\"display:inline-flex;align-items:center;min-height:44px;padding:0 18px;border:1px solid #C9BFA8;border-radius:22px;background:#FFFFFF;color:#5A4420;font-weight:700;font-size:13px;letter-spacing:1.5px;text-transform:uppercase;text-decoration:none\" style-hover=\"background:#FAF6EC;text-decoration:none\"><span aria-hidden=\"true\" style=\"color:#C1882C;margin-right:9px\">◆</span>{{ c.label }}</a></li>\n        </sc-for>\n      </ul>\n    </nav>\n  </section>\n\n  <figure style=\"width:100%;max-width:1440px;margin:0 auto\">\n    <button type=\"button\" data-gallery-tile=\"1\" data-gallery-index=\"0\" data-cta=\"gallery-tile-open\" aria-haspopup=\"dialog\" aria-label=\"{{ heroName }}\" onClick=\"{{ heroOpen }}\" style=\"display:block;width:100%;padding:0;border:0;background:#E0D7C4;overflow:hidden\">{{ heroEl }}</button>\n    <figcaption style=\"width:min(1220px,94%);margin:12px auto 0;font-size:16.5px;line-height:1.55;color:#514A3F;text-wrap:pretty\">{{ heroCaption }}</figcaption>\n  </figure>\n\n  <sc-for list=\"{{ chapters }}\" as=\"ch\" hint-placeholder-count=\"3\">\n    <section id=\"{{ ch.id }}\" data-gallery-chapter=\"1\" aria-labelledby=\"{{ ch.hid }}\" style=\"width:min(1220px,94%);margin:0 auto;padding:56px 0 8px\">\n      <div style=\"display:flex;justify-content:space-between;align-items:baseline;gap:24px;flex-wrap:wrap;border-bottom:1px solid #E9E2D3;padding-bottom:14px\">\n        <h2 id=\"{{ ch.hid }}\" style=\"font-family:'Marcellus',serif;font-size:clamp(26px,2.4vw,34px);line-height:1.18;text-wrap:balance\">{{ ch.title }}</h2>\n        <p style=\"margin:0;font-weight:700;font-size:13px;letter-spacing:2px;text-transform:uppercase;color:#5A4420\">{{ ch.tally }}</p>\n      </div>\n      <p style=\"font-size:18px;line-height:1.7;color:#514A3F;max-width:72ch;margin:18px 0 26px;text-wrap:pretty\">{{ ch.intro }}</p>\n      <ul role=\"list\" style=\"list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;align-items:flex-start;gap:24px 14px\">\n        <sc-for list=\"{{ ch.images }}\" as=\"p\" hint-placeholder-count=\"6\">\n          <li style=\"flex-grow:{{ p.grow }};flex-shrink:1;flex-basis:min({{ p.basis }}px,48%);min-width:0;margin:0\">\n            <figure style=\"margin:0\">\n              <button type=\"button\" data-gallery-tile=\"1\" data-gallery-index=\"{{ p.i }}\" data-cta=\"gallery-tile-open\" aria-haspopup=\"dialog\" aria-label=\"{{ p.name }}\" onClick=\"{{ p.open }}\" style=\"display:block;width:100%;padding:0;border:0;background:#E0D7C4;border-radius:4px;overflow:hidden;position:relative\" style-hover=\"filter:brightness(1.04)\">{{ p.imgEl }}</button>\n              <figcaption style=\"margin:8px 0 0;font-size:16px;line-height:1.55;color:#514A3F;text-wrap:pretty\">{{ p.caption }}</figcaption>\n            </figure>\n          </li>\n        </sc-for>\n        <li aria-hidden=\"true\" style=\"flex:9999 1 0;min-width:0;margin:0\"></li>\n      </ul>\n      <sc-if value=\"{{ ch.hasVideo }}\" hint-placeholder-val=\"{{ false }}\">\n        <div style=\"margin-top:34px;display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:24px 48px;align-items:start;border-top:1px solid #E9E2D3;padding-top:28px\">\n          <figure style=\"margin:0\">\n            {{ ch.videoEl }}\n            <figcaption style=\"margin:8px 0 0;font-size:16px;line-height:1.55;color:#514A3F;text-wrap:pretty\">{{ ch.videoCaption }}</figcaption>\n          </figure>\n          <div style=\"min-width:0\">\n            <p style=\"margin:0 0 6px;font-weight:700;font-size:13px;letter-spacing:2.6px;text-transform:uppercase;color:#8F6212\">Video</p>\n            <h3 style=\"font-family:'Marcellus',serif;font-size:24px;line-height:1.25;margin:0 0 12px;text-wrap:balance\">{{ ch.videoTitle }}</h3>\n            <p style=\"font-size:17px;line-height:1.7;color:#514A3F;margin:0;text-wrap:pretty\">{{ ch.videoDesc }}</p>\n            <a href=\"{{ ch.videoWatch }}\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"display:inline-flex;align-items:center;min-height:44px;margin-top:6px;font-weight:700;font-size:15px\">Auf YouTube ansehen (öffnet einen neuen Tab)</a>\n          </div>\n        </div>\n      </sc-if>\n      <sc-if value=\"{{ ch.hasLink }}\" hint-placeholder-val=\"{{ false }}\">\n        <p style=\"margin:26px 0 0\"><a href=\"{{ ch.linkHref }}\" onClick=\"{{ guard }}\" data-cta=\"gallery-chapter-link\" style=\"display:inline-flex;align-items:center;gap:10px;min-height:44px;font-weight:700;font-size:15.5px;letter-spacing:.3px\"><span aria-hidden=\"true\" style=\"color:#C1882C\">◆</span>{{ ch.linkLabel }}<span aria-hidden=\"true\">→</span></a></p>\n      </sc-if>\n    </section>\n  </sc-for>\n\n  <section aria-labelledby=\"closing-h\" style=\"margin-top:56px;background:#FFFFFF;border-top:1px solid #E9E2D3;border-bottom:1px solid #E9E2D3;padding:56px 24px;background-image:repeating-linear-gradient(135deg,rgba(193,136,44,.05) 0 1px,transparent 1px 9px)\">\n    <div style=\"max-width:760px;margin:0 auto;text-align:center\">\n      <ul style=\"list-style:none;margin:0 auto 34px;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 32px;text-align:left;max-width:640px\">\n        <li style=\"display:flex;gap:12px;align-items:baseline;font-size:17px;color:#2A2118\"><span aria-hidden=\"true\" style=\"color:#C1882C\">◆</span>NABH-zertifiziertes Krankenhaus</li>\n        <li style=\"display:flex;gap:12px;align-items:baseline;font-size:17px;color:#2A2118\"><span aria-hidden=\"true\" style=\"color:#C1882C\">◆</span>118+ Jahre Tradition</li>\n        <li style=\"display:flex;gap:12px;align-items:baseline;font-size:17px;color:#2A2118\"><span aria-hidden=\"true\" style=\"color:#C1882C\">◆</span>Individuell abgestimmte Programme</li>\n        <li style=\"display:flex;gap:12px;align-items:baseline;font-size:17px;color:#2A2118\"><span aria-hidden=\"true\" style=\"color:#C1882C\">◆</span>Gewinner des World Luxury Award</li>\n      </ul>\n      <h2 id=\"closing-h\" style=\"font-family:'Marcellus',serif;font-size:26px;line-height:1.25;margin:0 0 12px\">Sie sind unsicher, welches Programm passt?</h2>\n      <p style=\"font-size:16.5px;line-height:1.7;color:#514A3F;max-width:56ch;margin:0 auto 28px;text-wrap:pretty\">Beschreiben Sie Ihr Anliegen in eigenen Worten – das Patientenbetreuungsteam oder ein Ayurveda-Arzt weist Ihnen den Weg zum passenden Programm.</p>\n      <div style=\"display:flex;flex-wrap:wrap;gap:14px;justify-content:center\">\n        <a href=\"https://ayurvedichealingvillage.com/de/kostenlose-online-beratung/\" onClick=\"{{ guard }}\" data-cta=\"gallery-cta-consultation\" style=\"display:inline-flex;align-items:center;justify-content:center;height:52px;padding:0 26px;border-radius:4px;background:#EEB41E;color:#2A2118;font-weight:700;font-size:14px;letter-spacing:1.5px;text-transform:uppercase;text-decoration:none\" style-hover=\"filter:brightness(.95);text-decoration:none\">Kostenlose ärztliche Konsultation</a> <a href=\"https://wa.me/919289838797\" onClick=\"{{ guard }}\" style=\"display:inline-flex;align-items:center;justify-content:center;height:52px;padding:0 26px;border-radius:4px;border:1.5px solid #006038;color:#006038;font-weight:700;font-size:14px;letter-spacing:1.5px;text-transform:uppercase;text-decoration:none\" style-hover=\"background:#F2F6F1;text-decoration:none\" target=\"_blank\" rel=\"noopener noreferrer\">WhatsApp-Patientenbetreuung</a> <a href=\"https://ayurvedichealingvillage.com/de/kontakt/\" onClick=\"{{ guard }}\" style=\"display:inline-flex;align-items:center;justify-content:center;height:52px;padding:0 26px;border-radius:4px;border:1.5px solid #5A4420;color:#5A4420;font-weight:700;font-size:14px;letter-spacing:1.5px;text-transform:uppercase;text-decoration:none\" style-hover=\"background:#FAF6EC;text-decoration:none\">Jetzt anfragen</a>\n      </div>\n    </div>\n  </section>\n</main>\n<dc-import name=\"AHV Chrome Footer\" hint-size=\"100%,620px\"></dc-import>\n\n<dialog id=\"gallery-dialog\" data-gallery-dialog=\"1\" aria-labelledby=\"gallery-dialog-h\" onClose=\"{{ dlgClosed }}\" onKeyDown=\"{{ dlgKey }}\">\n  <div style=\"width:100%;max-width:1280px;display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap\">\n    <div style=\"min-width:0\">\n      <h2 id=\"gallery-dialog-h\" style=\"font-family:'Marcellus',serif;font-size:20px;line-height:1.25;color:#F7F4EA\">{{ dlgLabel }}</h2>\n      <p aria-live=\"polite\" style=\"margin:2px 0 0;font-weight:700;font-size:13px;letter-spacing:2px;text-transform:uppercase;color:#EEB41E;min-height:24px\">{{ counter }}</p>\n    </div>\n    <button type=\"button\" id=\"gallery-close\" data-cta=\"gallery-lightbox-close\" onClick=\"{{ close }}\" style=\"display:inline-flex;align-items:center;justify-content:center;gap:10px;min-width:44px;min-height:48px;padding:0 20px;border:1px solid rgba(247,244,234,.5);border-radius:4px;background:transparent;color:#F7F4EA;font-weight:700;font-size:13.5px;letter-spacing:2px;text-transform:uppercase\" style-hover=\"background:rgba(247,244,234,.12)\">Schließen<span aria-hidden=\"true\">✕</span></button>\n  </div>\n  <button type=\"button\" id=\"gallery-zoom\" aria-pressed=\"{{ zoomPressed }}\" onClick=\"{{ toggleZoom }}\" style=\"flex:none;min-height:44px;padding:8px 18px;border:1px solid rgba(247,244,234,.5);border-radius:4px;background:transparent;color:#F7F4EA;font-weight:700\">{{ zoomLabel }}</button>\n  <div data-gallery-stage=\"1\" tabindex=\"0\" aria-label=\"Foto. In Originalgröße zum Verschieben scrollen oder ziehen\" onPointerDown=\"{{ swipeStart }}\" onPointerMove=\"{{ panMove }}\" onPointerUp=\"{{ swipeEnd }}\" onPointerCancel=\"{{ panEnd }}\" style=\"flex:1;width:100%;min-height:0;overflow:auto;display:flex;align-items:flex-start;justify-content:flex-start\">\n    <sc-if value=\"{{ dlgOpen }}\" hint-placeholder-val=\"{{ false }}\">{{ expandedEl }}</sc-if>\n  </div>\n  <p style=\"display:{{ curCapDisplay }};width:100%;max-width:1280px;margin:0;color:#F7F4EA;font-size:18.5px;line-height:1.5;text-wrap:pretty\">{{ curCaption }}</p>\n  <div style=\"width:100%;max-width:1280px;display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap\">\n    <button type=\"button\" data-cta=\"gallery-lightbox-prev\" onClick=\"{{ prev }}\" style=\"display:inline-flex;align-items:center;justify-content:center;gap:10px;min-width:44px;min-height:48px;padding:0 20px;border:1px solid rgba(247,244,234,.5);border-radius:4px;background:transparent;color:#F7F4EA;font-weight:700;font-size:13.5px;letter-spacing:2px;text-transform:uppercase\" style-hover=\"background:rgba(247,244,234,.12)\"><span aria-hidden=\"true\">←</span>Zurück</button>\n    <button type=\"button\" data-cta=\"gallery-lightbox-next\" onClick=\"{{ next }}\" style=\"display:inline-flex;align-items:center;justify-content:center;gap:10px;min-width:44px;min-height:48px;padding:0 22px;border:1.5px solid #EEB41E;border-radius:4px;background:#EEB41E;color:#2A2118;font-weight:700;font-size:13.5px;letter-spacing:2px;text-transform:uppercase\" style-hover=\"filter:brightness(.95)\">Weiter<span aria-hidden=\"true\">→</span></button>\n  </div>\n</dialog>\n</div>\n",
  "logic": "\nclass Component extends DCLogic {\n  state = { i: null, playing: {}, zoom: false };\n  componentDidMount() {\n    document.documentElement.lang = 'de'; this.syncHead();\n    this._onPop = () => { if (this.state.i != null) this.close(); };\n    window.addEventListener('popstate', this._onPop);\n    const d = this.dialog();\n    if (d) { this._onDlgClose = () => { if (this.state.i != null) this.closed(); }; d.addEventListener('close', this._onDlgClose); }\n  }\n  componentDidUpdate() { this.syncHead(); }\n  componentWillUnmount() {\n    document.body.style.overflow = '';\n    if (this._photoObserver) this._photoObserver.disconnect();\n    window.removeEventListener('popstate', this._onPop);\n    const d = this.dialog(); if (d && this._onDlgClose) d.removeEventListener('close', this._onDlgClose);\n  }\n  dialog() { return document.getElementById('gallery-dialog'); }\n\n  route() {\n    const D = window.AHV_PHOTO_COLLECTIONS;\n    if (!D) return null;\n    const want = this.props.route || '/property-gallery/';\n    return D.routes.find(r => r.path === want) || D.routes[0];\n  }\n  syncHead() {\n    const R = this.route(); if (!R || this._head === R.path) return;\n    this._head = R.path;\n    void (R.head.title); /* title governed by the route manifest */\n    const set = (sel, attr, val) => { const el = document.head.querySelector(sel); if (el) el.setAttribute(attr, val); };\n    set('meta[name=\"description\"]', 'content', R.head.description);\n    set('link[rel=\"canonical\"]', 'href', R.head.canonical);\n    set('meta[name=\"robots\"]', 'content', R.head.robots);\n  }\n  /* The lightbox sequence: hero first, then every chapter's tiles in page order. */\n  flat() {\n    const R = this.route(); if (!R) return [];\n    if (this._flatFor === R) return this._flat;\n    const out = [];\n    if (R.hero) out.push(Object.assign({}, R.hero, { chapter: R.h1, k: 1, n: 1 }));\n    R.chapters.forEach(ch => ch.images.forEach((p, k) => out.push(Object.assign({}, p, { chapter: ch.title, k: k + 1, n: ch.images.length }))));\n    this._flatFor = R; this._flat = out;\n    return out;\n  }\n  open(i) {\n    this._from = i;\n    this.setState({ i, zoom: false });\n    const d = this.dialog();\n    if (d && !d.open) { try { d.showModal(); } catch (e) { d.setAttribute('open', ''); } }\n    document.body.style.overflow = 'hidden';\n    setTimeout(() => { const c = document.getElementById('gallery-close'); if (c) c.focus(); }, 30);\n  }\n  close() {\n    const d = this.dialog();\n    if (d && d.open) d.close(); else this.closed();\n  }\n  closed() {\n    const from = this._from;\n    this.setState({ i: null, zoom: false });\n    document.body.style.overflow = '';\n    setTimeout(() => { const b = document.querySelector('button[data-gallery-index=\"' + from + '\"]'); if (b) b.focus(); }, 30);\n  }\n  go(d) {\n    if (this.state.i == null) return;\n    const n = this.flat().length; if (!n) return;\n    this.setState(s => ({ i: (s.i + d + n) % n, zoom: false }));\n  }\n  goTo(i) { if (this.state.i == null) return; this.setState({ i, zoom: false }); }\n  play(id) { this.setState(s => ({ playing: Object.assign({}, s.playing, { [id]: true }) })); }\n\n  // AHV viewer pan repair 20260929\n  panStart(e) {\n    if (!this.state.zoom || e.pointerType !== 'mouse' || e.button !== 0) return;\n    e.preventDefault();\n    const el = e.currentTarget;\n    this._pan = { x: e.clientX, y: e.clientY, left: el.scrollLeft, top: el.scrollTop };\n    el.setPointerCapture(e.pointerId);\n  }\n  panMove(e) {\n    if (!this._pan) return;\n    e.currentTarget.scrollLeft = this._pan.left + this._pan.x - e.clientX;\n    e.currentTarget.scrollTop = this._pan.top + this._pan.y - e.clientY;\n  }\n  panEnd() { this._pan = null; }\n  renderVals() {\n    const R = this.route();\n    const guard = () => {}; /* preview-only nav guard neutralised for the published site */\n    if (!R) return { guard, chapters: [], chapterLinks: [], crumbs: [] };\n    const A = 'https://ayurvedichealingvillage.com';\n    const MOBILE = false;\n    const rowH = this.props.rowHeight ?? 250;\n    const eager = MOBILE ? 2 : 3;\n    const sizes = MOBILE ? '100vw' : '(min-width:1240px) 400px, 33vw';\n    const crumbs = R.crumbs.slice(0, -1).map(c => ({ label: c.label, url: A + c.path }));\n    const flat = this.flat();\n    const open = this.state.i != null;\n    const cur = open ? flat[this.state.i] : null;\n    const total = flat.length;\n    const videos = R.chapters.filter(ch => ch.video).length;\n\n    const loadPhoto = (el) => {\n      if (!el || el.getAttribute('src')) return;\n      const set = el.getAttribute('data-ahv-photo-srcset');\n      if (set) el.setAttribute('srcset', set);\n      el.setAttribute('src', el.getAttribute('data-ahv-photo-src'));\n    };\n    if (!this._photoObserver && typeof IntersectionObserver !== 'undefined') {\n      this._photoObserver = new IntersectionObserver(entries => {\n        entries.forEach(entry => {\n          if (entry.isIntersecting) { loadPhoto(entry.target); this._photoObserver.unobserve(entry.target); }\n        });\n      }, {rootMargin: '600px 0px'});\n    }\n    const img = (p, opts) => React.createElement('img', Object.assign({\n      loading: 'lazy', decoding: 'async',\n      'data-ahv-photo-src': p.src,\n      'data-ahv-photo-srcset': p.src768 ? (p.src768 + ' 768w, ' + p.src + ' 1600w') : '',\n      sizes: p.src768 ? sizes : undefined,\n      alt: p.alt || '', width: p.width, height: p.height,\n      ref: el => { if (!el) return; if (this._photoObserver) this._photoObserver.observe(el); else loadPhoto(el); },\n      style: { width: '100%', height: 'auto', aspectRatio: p.width + '/' + p.height, display: 'block' }\n    }, opts));\n\n    let idx = 0;\n    const chapters = R.chapters.map((ch, ci) => {\n      const V = ch.video;\n      const playing = !!(V && this.state.playing[V.youtubeId]);\n      let videoEl = null;\n      if (V) {\n        videoEl = playing\n          ? React.createElement('iframe', {\n              'data-gallery-iframe': '1',\n              src: 'https://www.youtube-nocookie.com/embed/' + V.youtubeId + '?autoplay=1&rel=0&modestbranding=1',\n              title: V.title, width: 1280, height: 720, allowFullScreen: true,\n              allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',\n              referrerPolicy: 'strict-origin-when-cross-origin' })\n          : React.createElement('button', {\n              type: 'button', 'data-gallery-facade': '1', 'data-cta': 'gallery-video-play',\n              'aria-label': 'Abspielen: ' + V.title, onClick: () => this.play(V.youtubeId) },\n              React.createElement('img', { src: V.poster.src, alt: 'Vorschaubild des Films: ' + V.title, width: V.poster.width, height: V.poster.height, loading: 'lazy', decoding: 'async' }),\n              React.createElement('span', { 'aria-hidden': 'true' }, '\\u25B6'));\n      }\n      return {\n        id: ch.id, hid: ch.id + '-h', title: ch.title, intro: ch.intro,\n        tally: ch.images.length + (ch.images.length === 1 ? ' Foto' : ' photographs'),\n        images: ch.images.map((p, k) => {\n          idx += 1;\n          const i = idx;\n          const ar = p.width / p.height;\n          return {\n            i, name: p.caption, caption: p.caption,\n            ordinal: (k + 1) + ' von ' + ch.images.length,\n            grow: Math.round(ar * 100), basis: Math.round(ar * rowH),\n            imgEl: img(p, { loading: (ci === 0 && k < eager) ? 'eager' : 'lazy' }),\n            open: () => this.open(i)\n          };\n        }),\n        hasVideo: !!V,\n        videoTitle: V ? V.title : '', videoDesc: V ? V.description : '',\n        videoCaption: V ? V.caption : '', videoWatch: V ? ('https://www.youtube.com/watch?v=' + V.youtubeId) : '',\n        videoEl,\n        hasLink: !!ch.linkTo, linkHref: ch.linkTo ? (A + ch.linkTo) : '', linkLabel: ch.linkLabel || ''\n      };\n    });\n\n    return {\n      guard, crumbs, crumbLast: R.crumbs[R.crumbs.length - 1].label,\n      h1: R.h1, intro: R.intro.text,\n      tally: (total - 1) + ' Fotos · ' + R.chapters.length + ' Kapitel' + (videos ? ' · ' + videos + (videos === 1 ? ' Video' : ' Videos') : ''),\n      chapterLinks: R.chapters.map(ch => ({ href: '#' + ch.id, label: ch.title })),\n      heroEl: R.hero ? img(R.hero, { loading: 'eager', fetchpriority: 'high', sizes: '100vw' }) : null,\n      heroName: R.hero ? R.hero.caption : '', heroCaption: R.hero ? R.hero.caption : '',\n      heroOpen: () => this.open(0),\n      chapters,\n      dlgOpen: open,\n      dlgLabel: cur ? cur.chapter : R.h1,\n      counter: cur ? (cur.k + ' von ' + cur.n) : '',\n      curCaption: cur && cur.caption ? cur.caption : '',\n      curCapDisplay: cur && cur.caption ? 'block' : 'none',\n      expandedEl: cur ? React.createElement('img', { src: cur.src, alt: cur.alt || '', width: cur.width, height: cur.height, decoding: 'async',\n        style: this.state.zoom ? { display: 'block', flexShrink: 0, margin: '0 auto', width: cur.width + 'px', height: 'auto', maxWidth: 'none', background: '#000' } : { display: 'block', flexShrink: 0, margin: 'auto', width: 'auto', height: 'auto', maxWidth: 'min(1280px,100%)', maxHeight: MOBILE ? 'calc(100vh - 230px)' : 'calc(100vh - 220px)', objectFit: 'contain', borderRadius: '4px', background: '#000' } }) : null,\n      zoomLabel: this.state.zoom ? 'An Bildschirm anpassen' : 'Originalgröße', zoomPressed: this.state.zoom ? 'true' : 'false', toggleZoom: () => this.setState(s => ({ zoom: !s.zoom })),\n      panStart: (e) => this.panStart(e), panMove: (e) => this.panMove(e), panEnd: () => this.panEnd(), close: () => this.close(), prev: () => this.go(-1), next: () => this.go(1),\n      dlgClosed: () => { if (this.state.i != null) this.closed(); },\n      swipeStart: (e) => { if (this.state.zoom) { this.panStart(e); return; } this._sx = e.clientX; this._sy = e.clientY; },\n      swipeEnd: (e) => {\n        if (this.state.zoom) { this.panEnd(); this._sx = null; return; }\n        if (this._sx == null) return;\n        const dx = e.clientX - this._sx, dy = e.clientY - this._sy; this._sx = null;\n        if (Math.abs(dx) >= 40 && Math.abs(dx) > Math.abs(dy)) this.go(dx < 0 ? 1 : -1);\n      },\n      dlgKey: (e) => {\n        if (e.key === 'Escape') { e.preventDefault(); this.close(); return; }\n        if (this.state.zoom && ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Startseite', 'End'].includes(e.key)) return;\n        if (e.key === 'ArrowLeft') { e.preventDefault(); this.go(-1); return; }\n        if (e.key === 'ArrowRight') { e.preventDefault(); this.go(1); return; }\n        if (e.key === 'Home') { e.preventDefault(); this.goTo(0); return; }\n        if (e.key === 'End') { e.preventDefault(); this.goTo(total - 1); return; }\n      }\n    };\n  }\n}\n",
  "props": "{\"route\":{\"editor\":\"enum\",\"default\":\"/property-gallery/\",\"options\":[\"/property-gallery/\",\"/photo-gallery/\",\"/product-gallery/\",\"/villas-gallery/\",\"/treatments-gallery/\",\"/yoga-gallery/\",\"/retreats-gallery/\",\"/sight-seeing-gallery/\"],\"tsType\":\"string\",\"section\":\"Template test\"},\"rowHeight\":{\"editor\":\"range\",\"default\":250,\"min\":170,\"max\":320,\"step\":10,\"unit\":\"px\",\"tsType\":\"number\",\"section\":\"Collection\"}}",
  "scripts": [
    "/ahv/l10n/de/assets/photo-collections-data.js"
  ],
  "locale": "de"
}
