@rubytech/create-realagent-code 0.1.24 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/dist/index.js +81 -17
  2. package/package.json +1 -1
  3. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -90
  4. package/payload/platform/plugins/admin/PLUGIN.md +46 -23
  5. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +111 -126
  6. package/payload/platform/plugins/brochures/.claude-plugin/plugin.json +8 -0
  7. package/payload/platform/plugins/brochures/PLUGIN.md +36 -0
  8. package/payload/platform/plugins/brochures/commands/make-brochure.md +11 -0
  9. package/payload/platform/plugins/brochures/skills/a4-print-documents/SKILL.md +478 -0
  10. package/payload/platform/plugins/brochures/skills/brand-design/SKILL.md +192 -0
  11. package/payload/platform/plugins/brochures/skills/make-brochure/SKILL.md +354 -0
  12. package/payload/platform/plugins/brochures/skills/make-brochure/references/seller-brief-template.md +115 -0
  13. package/payload/platform/plugins/brochures/skills/property-brochure/SKILL.md +119 -0
  14. package/payload/platform/plugins/brochures/skills/property-brochure/references/build.md +270 -0
  15. package/payload/platform/plugins/brochures/skills/property-brochure/references/copy.md +211 -0
  16. package/payload/platform/plugins/brochures/skills/property-brochure/references/images.md +166 -0
  17. package/payload/platform/plugins/brochures/skills/property-brochure/references/index-landing.md +376 -0
  18. package/payload/platform/plugins/brochures/skills/property-brochure/references/index.html +1288 -0
  19. package/payload/platform/plugins/brochures/skills/property-brochure/references/placeholders.md +250 -0
  20. package/payload/platform/plugins/brochures/skills/property-brochure/references/registers.md +47 -0
  21. package/payload/platform/plugins/brochures/skills/property-brochure/references/seller-brief.md +56 -0
  22. package/payload/platform/plugins/brochures/skills/property-brochure/references/structure.md +249 -0
  23. package/payload/platform/plugins/brochures/skills/property-brochure/references/template.html +2370 -0
  24. package/payload/platform/plugins/brochures/skills/property-extract/SKILL.md +372 -0
  25. package/payload/platform/plugins/buyers/.claude-plugin/plugin.json +8 -0
  26. package/payload/platform/plugins/buyers/PLUGIN.md +35 -0
  27. package/payload/platform/plugins/buyers/skills/buyer-feedback/SKILL.md +109 -0
  28. package/payload/platform/plugins/buyers/skills/buyer-management/SKILL.md +42 -0
  29. package/payload/platform/plugins/buyers/skills/buyer-management/references/buyer-qualification-questions.md +16 -0
  30. package/payload/platform/plugins/buyers/skills/buyer-management/references/buyer-qualification.md +59 -0
  31. package/payload/platform/plugins/buyers/skills/buyer-management/references/buyer-scripts.md +63 -0
  32. package/payload/platform/plugins/buyers/skills/buyer-management/references/buyer-working-scripts.md +54 -0
  33. package/payload/platform/plugins/buyers/skills/buyer-management/references/feedback-collection.md +42 -0
  34. package/payload/platform/plugins/buyers/skills/buyer-management/references/offer-capture.md +38 -0
  35. package/payload/platform/plugins/buyers/skills/buyer-management/references/viewing-booking.md +32 -0
  36. package/payload/platform/plugins/buyers/skills/buyer-management/references/viewing-management.md +52 -0
  37. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/SKILL.md +407 -0
  38. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/care-fees-guide.md +68 -0
  39. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/divorce-sales-guide.md +61 -0
  40. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/downsizing-guide.md +45 -0
  41. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/first-time-buyers.md +92 -0
  42. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/first-time-sellers.md +78 -0
  43. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/probate-guide.md +53 -0
  44. package/payload/platform/plugins/buyers/skills/buyer-seller-guides/references/upsizing-guide.md +41 -0
  45. package/payload/platform/plugins/buyers/skills/property-enquiry/SKILL.md +126 -0
  46. package/payload/platform/plugins/buyers/skills/viewing-management/SKILL.md +111 -0
  47. package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +37 -0
  48. package/payload/platform/plugins/cloudflare/references/manual-setup.md +81 -1
  49. package/payload/platform/plugins/cloudflare/scripts/__tests__/tunnel-ingress.test.ts +241 -0
  50. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +267 -28
  51. package/payload/platform/plugins/cloudflare/scripts/tunnel-ingress.ts +291 -0
  52. package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +42 -0
  53. package/payload/platform/plugins/contacts/PLUGIN.md +18 -9
  54. package/payload/platform/plugins/docs/references/platform.md +2 -0
  55. package/payload/platform/plugins/docs/references/troubleshooting.md +12 -0
  56. package/payload/platform/plugins/email/PLUGIN.md +18 -9
  57. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts +17 -0
  58. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +1 -0
  59. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +185 -0
  60. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -0
  61. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js +34 -111
  62. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js.map +1 -1
  63. package/payload/platform/plugins/estate-business/.claude-plugin/plugin.json +8 -0
  64. package/payload/platform/plugins/estate-business/PLUGIN.md +65 -0
  65. package/payload/platform/plugins/estate-business/skills/business-growth/SKILL.md +133 -0
  66. package/payload/platform/plugins/estate-business/skills/business-growth/references/buy-back-your-time.md +37 -0
  67. package/payload/platform/plugins/estate-business/skills/business-growth/references/firewave-gost-scorecards.md +14 -0
  68. package/payload/platform/plugins/estate-business/skills/business-growth/references/keller-org-model.md +17 -0
  69. package/payload/platform/plugins/estate-business/skills/business-growth/references/lencioni-team-models.md +22 -0
  70. package/payload/platform/plugins/estate-business/skills/business-growth/references/listing-management-system.md +11 -0
  71. package/payload/platform/plugins/estate-business/skills/business-growth/references/net-figure-form.md +11 -0
  72. package/payload/platform/plugins/estate-business/skills/business-growth/references/serhant-bizinbox-notes.md +13 -0
  73. package/payload/platform/plugins/estate-business/skills/business-growth/references/team-roles-commission.md +14 -0
  74. package/payload/platform/plugins/estate-business/skills/business-growth/references/va-2026-ops.md +43 -0
  75. package/payload/platform/plugins/estate-business/skills/business-growth/references/wingman-structure.md +13 -0
  76. package/payload/platform/plugins/estate-business/skills/business-operations/SKILL.md +32 -0
  77. package/payload/platform/plugins/estate-business/skills/business-operations/references/crm-systems.md +57 -0
  78. package/payload/platform/plugins/estate-business/skills/business-operations/references/hiring-guide.md +59 -0
  79. package/payload/platform/plugins/estate-business/skills/business-operations/references/impact-framework.md +47 -0
  80. package/payload/platform/plugins/estate-business/skills/business-operations/references/minutes-equal-money.md +55 -0
  81. package/payload/platform/plugins/estate-business/skills/business-operations/references/team-management.md +48 -0
  82. package/payload/platform/plugins/estate-business/skills/commission-calculator/SKILL.md +40 -0
  83. package/payload/platform/plugins/estate-business/skills/exp-partnership/SKILL.md +52 -0
  84. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/12-reasons.md +39 -0
  85. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/95-5-system.md +66 -0
  86. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/agent-attraction-scripts.md +90 -0
  87. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/business-partnership.md +92 -0
  88. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/exp-model-overview.md +66 -0
  89. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/model-comparison.md +66 -0
  90. package/payload/platform/plugins/estate-business/skills/exp-partnership/references/revenue-share-explained.md +57 -0
  91. package/payload/platform/plugins/estate-business/skills/month-end-close/SKILL.md +69 -0
  92. package/payload/platform/plugins/estate-business/skills/payment-batch-stager/SKILL.md +42 -0
  93. package/payload/platform/plugins/estate-business/skills/period-reconciler/SKILL.md +42 -0
  94. package/payload/platform/plugins/estate-business/skills/personal-branding/SKILL.md +117 -0
  95. package/payload/platform/plugins/estate-business/skills/personal-branding/references/attraction-agent-notes.md +31 -0
  96. package/payload/platform/plugins/estate-business/skills/personal-branding/references/attraction-agent.md +58 -0
  97. package/payload/platform/plugins/estate-business/skills/personal-branding/references/authenticity-boundaries.md +28 -0
  98. package/payload/platform/plugins/estate-business/skills/personal-branding/references/become-a-brand-leader-notes.md +19 -0
  99. package/payload/platform/plugins/estate-business/skills/personal-branding/references/blast-formula.md +42 -0
  100. package/payload/platform/plugins/estate-business/skills/personal-branding/references/brand-leader.md +48 -0
  101. package/payload/platform/plugins/estate-business/skills/personal-branding/references/brand-strategy-system.md +59 -0
  102. package/payload/platform/plugins/estate-business/skills/personal-branding/references/content-engine.md +49 -0
  103. package/payload/platform/plugins/estate-business/skills/personal-branding/references/firewave-blast-and-blogging.md +23 -0
  104. package/payload/platform/plugins/estate-business/skills/personal-branding/references/gary-v-content.md +52 -0
  105. package/payload/platform/plugins/estate-business/skills/personal-branding/references/gary-v-principles.md +20 -0
  106. package/payload/platform/plugins/estate-business/skills/personal-branding/references/oversubscribed-positioning.md +18 -0
  107. package/payload/platform/plugins/estate-business/skills/personal-branding/references/platforms.md +41 -0
  108. package/payload/platform/plugins/estate-business/skills/personal-branding/references/priestley-oversubscribed.md +54 -0
  109. package/payload/platform/plugins/estate-business/skills/personal-branding/references/storeys-style-examples.md +25 -0
  110. package/payload/platform/plugins/estate-business/skills/personal-branding/references/visual-identity.md +27 -0
  111. package/payload/platform/plugins/estate-coaching/.claude-plugin/plugin.json +8 -0
  112. package/payload/platform/plugins/estate-coaching/PLUGIN.md +55 -0
  113. package/payload/platform/plugins/estate-coaching/skills/agent-performance/SKILL.md +371 -0
  114. package/payload/platform/plugins/estate-coaching/skills/agent-performance/references/atomic-habits.md +52 -0
  115. package/payload/platform/plugins/estate-coaching/skills/agent-performance/references/daily-routine-scorecard.md +104 -0
  116. package/payload/platform/plugins/estate-coaching/skills/agent-performance/references/hp6-model.md +63 -0
  117. package/payload/platform/plugins/estate-coaching/skills/agent-performance/references/twelve-week-year.md +71 -0
  118. package/payload/platform/plugins/estate-coaching/skills/bespoke-coaching/SKILL.md +36 -0
  119. package/payload/platform/plugins/estate-coaching/skills/bespoke-coaching/references/coaching-boundaries.md +56 -0
  120. package/payload/platform/plugins/estate-coaching/skills/bespoke-coaching/references/feedback-framework.md +61 -0
  121. package/payload/platform/plugins/estate-coaching/skills/bespoke-coaching/references/performance-framework.md +109 -0
  122. package/payload/platform/plugins/estate-coaching/skills/coaching-toolkit/SKILL.md +421 -0
  123. package/payload/platform/plugins/estate-coaching/skills/coaching-toolkit/references/coaching-exercises.md +86 -0
  124. package/payload/platform/plugins/estate-coaching/skills/coaching-toolkit/references/goal-setting.md +78 -0
  125. package/payload/platform/plugins/estate-coaching/skills/coaching-toolkit/references/one-to-one-framework.md +92 -0
  126. package/payload/platform/plugins/estate-coaching/skills/coaching-toolkit/references/soi-workbook.md +103 -0
  127. package/payload/platform/plugins/estate-coaching/skills/serhant-training/SKILL.md +410 -0
  128. package/payload/platform/plugins/estate-coaching/skills/serhant-training/references/agent-training-guide.md +70 -0
  129. package/payload/platform/plugins/estate-coaching/skills/serhant-training/references/business-in-a-box.md +72 -0
  130. package/payload/platform/plugins/estate-coaching/skills/serhant-training/references/buyers-guide.md +53 -0
  131. package/payload/platform/plugins/estate-coaching/skills/serhant-training/references/codo-method.md +72 -0
  132. package/payload/platform/plugins/estate-coaching/skills/serhant-training/references/website-planning-guide.md +79 -0
  133. package/payload/platform/plugins/estate-onboarding/.claude-plugin/plugin.json +8 -0
  134. package/payload/platform/plugins/estate-onboarding/PLUGIN.md +31 -0
  135. package/payload/platform/plugins/estate-onboarding/skills/bootstrap/SKILL.md +26 -0
  136. package/payload/platform/plugins/estate-onboarding/skills/bootstrap/references/onboarding-flow.md +63 -0
  137. package/payload/platform/plugins/estate-sales/.claude-plugin/plugin.json +8 -0
  138. package/payload/platform/plugins/estate-sales/PLUGIN.md +53 -0
  139. package/payload/platform/plugins/estate-sales/skills/chase-progression/SKILL.md +107 -0
  140. package/payload/platform/plugins/estate-sales/skills/negotiation/SKILL.md +35 -0
  141. package/payload/platform/plugins/estate-sales/skills/negotiation/references/deal-saving.md +47 -0
  142. package/payload/platform/plugins/estate-sales/skills/negotiation/references/negotiation-deep-guide.md +64 -0
  143. package/payload/platform/plugins/estate-sales/skills/negotiation/references/negotiation-prep-principles.md +29 -0
  144. package/payload/platform/plugins/estate-sales/skills/negotiation/references/negotiation-techniques.md +42 -0
  145. package/payload/platform/plugins/estate-sales/skills/negotiation/references/offer-presentation.md +43 -0
  146. package/payload/platform/plugins/estate-sales/skills/risk-scorer/SKILL.md +42 -0
  147. package/payload/platform/plugins/estate-sales/skills/sales-closer/SKILL.md +24 -0
  148. package/payload/platform/plugins/estate-sales/skills/sales-closer/references/serhant-emotion-stages.md +36 -0
  149. package/payload/platform/plugins/estate-sales/skills/sales-discovery/SKILL.md +30 -0
  150. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/chris-voss-discovery.md +88 -0
  151. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/firewave-gost-journey.md +68 -0
  152. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/phil-jones-openers.md +78 -0
  153. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/pre-listing-checklist.md +77 -0
  154. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/serhant-improv.md +22 -0
  155. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/tom-ferry-discovery.md +103 -0
  156. package/payload/platform/plugins/estate-sales/skills/sales-discovery/references/vendor-motivation-competitor.md +52 -0
  157. package/payload/platform/plugins/estate-sales/skills/sales-negotiation/SKILL.md +29 -0
  158. package/payload/platform/plugins/estate-sales/skills/sales-negotiation/references/chris-voss-negotiation.md +70 -0
  159. package/payload/platform/plugins/estate-sales/skills/sales-negotiation/references/phil-jones-price-words.md +40 -0
  160. package/payload/platform/plugins/estate-sales/skills/sales-negotiation/references/serhant-negotiation-plus.md +55 -0
  161. package/payload/platform/plugins/estate-sales/skills/sales-negotiation/references/tom-panos-commission-pricing.md +57 -0
  162. package/payload/platform/plugins/estate-sales/skills/sales-negotiation/references/tony-morris-questioning.md +54 -0
  163. package/payload/platform/plugins/estate-sales/skills/sales-progression/SKILL.md +27 -0
  164. package/payload/platform/plugins/estate-sales/skills/sales-progression/references/conveyancing-guide.md +54 -0
  165. package/payload/platform/plugins/estate-sales/skills/sales-progression/references/transaction-tracking.md +66 -0
  166. package/payload/platform/plugins/estate-teaching/.claude-plugin/plugin.json +8 -0
  167. package/payload/platform/plugins/estate-teaching/PLUGIN.md +31 -0
  168. package/payload/platform/plugins/estate-teaching/skills/content-directory/SKILL.md +39 -0
  169. package/payload/platform/plugins/estate-teaching/skills/content-directory/references/module-delivery.md +65 -0
  170. package/payload/platform/plugins/estate-teaching/skills/content-directory/references/progress-tracking.md +47 -0
  171. package/payload/platform/plugins/leads/.claude-plugin/plugin.json +8 -0
  172. package/payload/platform/plugins/leads/PLUGIN.md +62 -0
  173. package/payload/platform/plugins/leads/skills/chain-progression-tracker/SKILL.md +51 -0
  174. package/payload/platform/plugins/leads/skills/diary-builder/SKILL.md +38 -0
  175. package/payload/platform/plugins/leads/skills/enquiry-triage/SKILL.md +36 -0
  176. package/payload/platform/plugins/leads/skills/lead-nurturing/SKILL.md +137 -0
  177. package/payload/platform/plugins/leads/skills/lead-nurturing/references/buyer-search-letter.md +28 -0
  178. package/payload/platform/plugins/leads/skills/lead-nurturing/references/buyer-search-letters.md +37 -0
  179. package/payload/platform/plugins/leads/skills/lead-nurturing/references/database-reactivation.md +30 -0
  180. package/payload/platform/plugins/leads/skills/lead-nurturing/references/email-nurture-sequences.md +45 -0
  181. package/payload/platform/plugins/leads/skills/lead-nurturing/references/facebook-referrals.md +30 -0
  182. package/payload/platform/plugins/leads/skills/lead-nurturing/references/firewave-email-nurture-sequences.md +41 -0
  183. package/payload/platform/plugins/leads/skills/lead-nurturing/references/keller-33-touch.md +34 -0
  184. package/payload/platform/plugins/leads/skills/lead-nurturing/references/neighbour-letters.md +31 -0
  185. package/payload/platform/plugins/leads/skills/lead-nurturing/references/neighbour-notification-letter.md +20 -0
  186. package/payload/platform/plugins/leads/skills/lead-nurturing/references/ofi-follow-up-dialogue.md +22 -0
  187. package/payload/platform/plugins/leads/skills/lead-nurturing/references/ofi-follow-up.md +26 -0
  188. package/payload/platform/plugins/leads/skills/lead-nurturing/references/serhant-three-fs-plus.md +21 -0
  189. package/payload/platform/plugins/leads/skills/lead-nurturing/references/sharran-10x10x10.md +18 -0
  190. package/payload/platform/plugins/leads/skills/lead-nurturing/references/sms-templates.md +40 -0
  191. package/payload/platform/plugins/leads/skills/lead-nurturing/references/sphere-of-influence-notes.md +34 -0
  192. package/payload/platform/plugins/leads/skills/lead-nurturing/references/sphere-of-influence.md +60 -0
  193. package/payload/platform/plugins/leads/skills/lead-nurturing/references/tom-panos-sms-templates.md +59 -0
  194. package/payload/platform/plugins/leads/skills/morning-round/SKILL.md +72 -0
  195. package/payload/platform/plugins/leads/skills/prospecting/SKILL.md +33 -0
  196. package/payload/platform/plugins/leads/skills/prospecting/references/database-matching.md +30 -0
  197. package/payload/platform/plugins/leads/skills/prospecting/references/database-value.md +53 -0
  198. package/payload/platform/plugins/leads/skills/prospecting/references/prospecting-dialogues.md +24 -0
  199. package/payload/platform/plugins/leads/skills/prospecting/references/reactivation.md +34 -0
  200. package/payload/platform/plugins/listings/.claude-plugin/plugin.json +8 -0
  201. package/payload/platform/plugins/listings/PLUGIN.md +103 -0
  202. package/payload/platform/plugins/listings/skills/comparable-finder/SKILL.md +52 -0
  203. package/payload/platform/plugins/listings/skills/epc-checker/SKILL.md +38 -0
  204. package/payload/platform/plugins/listings/skills/home-preparation/SKILL.md +28 -0
  205. package/payload/platform/plugins/listings/skills/home-preparation/references/kerb-appeal.md +38 -0
  206. package/payload/platform/plugins/listings/skills/home-preparation/references/photo-day.md +59 -0
  207. package/payload/platform/plugins/listings/skills/home-preparation/references/situational-tips.md +50 -0
  208. package/payload/platform/plugins/listings/skills/home-preparation/references/staging-guide.md +52 -0
  209. package/payload/platform/plugins/listings/skills/listing-copy-writer/SKILL.md +55 -0
  210. package/payload/platform/plugins/listings/skills/listing-presentation/SKILL.md +286 -0
  211. package/payload/platform/plugins/listings/skills/listing-presentation/references/booking-script.md +51 -0
  212. package/payload/platform/plugins/listings/skills/listing-presentation/references/objection-scripts.md +193 -0
  213. package/payload/platform/plugins/listings/skills/listing-presentation/references/penhaul-presentation.md +123 -0
  214. package/payload/platform/plugins/listings/skills/listing-presentation/references/pre-listing-kit.md +139 -0
  215. package/payload/platform/plugins/listings/skills/listing-presentation/references/set-to-sell.md +55 -0
  216. package/payload/platform/plugins/listings/skills/listing-presentation/references/sharran-frameworks.md +107 -0
  217. package/payload/platform/plugins/listings/skills/local-market-stats/SKILL.md +33 -0
  218. package/payload/platform/plugins/listings/skills/new-instruction/SKILL.md +78 -0
  219. package/payload/platform/plugins/listings/skills/particulars-builder/SKILL.md +48 -0
  220. package/payload/platform/plugins/listings/skills/portal-launch-scheduler/SKILL.md +49 -0
  221. package/payload/platform/plugins/listings/skills/pricing-scenario-builder/SKILL.md +35 -0
  222. package/payload/platform/plugins/listings/skills/property-marketing/SKILL.md +337 -0
  223. package/payload/platform/plugins/listings/skills/property-marketing/references/auction-report-template.md +41 -0
  224. package/payload/platform/plugins/listings/skills/property-marketing/references/coming-soon-campaign.md +43 -0
  225. package/payload/platform/plugins/listings/skills/property-marketing/references/direct-mail-templates.md +121 -0
  226. package/payload/platform/plugins/listings/skills/property-marketing/references/eoi-form-template.md +62 -0
  227. package/payload/platform/plugins/listings/skills/property-marketing/references/monthly-scorecard.md +63 -0
  228. package/payload/platform/plugins/listings/skills/supplier-booker/SKILL.md +39 -0
  229. package/payload/platform/plugins/listings/skills/talk-track-composer/SKILL.md +36 -0
  230. package/payload/platform/plugins/listings/skills/terms-of-business-drafter/SKILL.md +54 -0
  231. package/payload/platform/plugins/listings/skills/valuation-prep/SKILL.md +69 -0
  232. package/payload/platform/plugins/loop/.claude-plugin/plugin.json +17 -0
  233. package/payload/platform/plugins/loop/PLUGIN.md +108 -0
  234. package/payload/platform/plugins/loop/mcp/dist/index.d.ts +2 -0
  235. package/payload/platform/plugins/loop/mcp/dist/index.d.ts.map +1 -0
  236. package/payload/platform/plugins/loop/mcp/dist/index.js +293 -0
  237. package/payload/platform/plugins/loop/mcp/dist/index.js.map +1 -0
  238. package/payload/platform/plugins/loop/mcp/dist/lib/crypto.d.ts +10 -0
  239. package/payload/platform/plugins/loop/mcp/dist/lib/crypto.d.ts.map +1 -0
  240. package/payload/platform/plugins/loop/mcp/dist/lib/crypto.js +88 -0
  241. package/payload/platform/plugins/loop/mcp/dist/lib/crypto.js.map +1 -0
  242. package/payload/platform/plugins/loop/mcp/dist/lib/loop-api.d.ts +82 -0
  243. package/payload/platform/plugins/loop/mcp/dist/lib/loop-api.d.ts.map +1 -0
  244. package/payload/platform/plugins/loop/mcp/dist/lib/loop-api.js +427 -0
  245. package/payload/platform/plugins/loop/mcp/dist/lib/loop-api.js.map +1 -0
  246. package/payload/platform/plugins/loop/mcp/dist/lib/neo4j.d.ts +5 -0
  247. package/payload/platform/plugins/loop/mcp/dist/lib/neo4j.d.ts.map +1 -0
  248. package/payload/platform/plugins/loop/mcp/dist/lib/neo4j.js +40 -0
  249. package/payload/platform/plugins/loop/mcp/dist/lib/neo4j.js.map +1 -0
  250. package/payload/platform/plugins/loop/mcp/dist/tools/customer-preferences.d.ts +10 -0
  251. package/payload/platform/plugins/loop/mcp/dist/tools/customer-preferences.d.ts.map +1 -0
  252. package/payload/platform/plugins/loop/mcp/dist/tools/customer-preferences.js +24 -0
  253. package/payload/platform/plugins/loop/mcp/dist/tools/customer-preferences.js.map +1 -0
  254. package/payload/platform/plugins/loop/mcp/dist/tools/feedback.d.ts +16 -0
  255. package/payload/platform/plugins/loop/mcp/dist/tools/feedback.d.ts.map +1 -0
  256. package/payload/platform/plugins/loop/mcp/dist/tools/feedback.js +35 -0
  257. package/payload/platform/plugins/loop/mcp/dist/tools/feedback.js.map +1 -0
  258. package/payload/platform/plugins/loop/mcp/dist/tools/key-deregister.d.ts +5 -0
  259. package/payload/platform/plugins/loop/mcp/dist/tools/key-deregister.d.ts.map +1 -0
  260. package/payload/platform/plugins/loop/mcp/dist/tools/key-deregister.js +19 -0
  261. package/payload/platform/plugins/loop/mcp/dist/tools/key-deregister.js.map +1 -0
  262. package/payload/platform/plugins/loop/mcp/dist/tools/key-list.d.ts +4 -0
  263. package/payload/platform/plugins/loop/mcp/dist/tools/key-list.d.ts.map +1 -0
  264. package/payload/platform/plugins/loop/mcp/dist/tools/key-list.js +14 -0
  265. package/payload/platform/plugins/loop/mcp/dist/tools/key-list.js.map +1 -0
  266. package/payload/platform/plugins/loop/mcp/dist/tools/key-register.d.ts +9 -0
  267. package/payload/platform/plugins/loop/mcp/dist/tools/key-register.d.ts.map +1 -0
  268. package/payload/platform/plugins/loop/mcp/dist/tools/key-register.js +60 -0
  269. package/payload/platform/plugins/loop/mcp/dist/tools/key-register.js.map +1 -0
  270. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-enquiry.d.ts +13 -0
  271. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-enquiry.d.ts.map +1 -0
  272. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-enquiry.js +41 -0
  273. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-enquiry.js.map +1 -0
  274. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-batch.d.ts +9 -0
  275. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-batch.d.ts.map +1 -0
  276. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-batch.js +16 -0
  277. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-batch.js.map +1 -0
  278. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-request.d.ts +15 -0
  279. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-request.d.ts.map +1 -0
  280. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-request.js +11 -0
  281. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match-request.js.map +1 -0
  282. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match.d.ts +10 -0
  283. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match.d.ts.map +1 -0
  284. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match.js +39 -0
  285. package/payload/platform/plugins/loop/mcp/dist/tools/marketing-match.js.map +1 -0
  286. package/payload/platform/plugins/loop/mcp/dist/tools/people-detail.d.ts +9 -0
  287. package/payload/platform/plugins/loop/mcp/dist/tools/people-detail.d.ts.map +1 -0
  288. package/payload/platform/plugins/loop/mcp/dist/tools/people-detail.js +125 -0
  289. package/payload/platform/plugins/loop/mcp/dist/tools/people-detail.js.map +1 -0
  290. package/payload/platform/plugins/loop/mcp/dist/tools/people-search.d.ts +18 -0
  291. package/payload/platform/plugins/loop/mcp/dist/tools/people-search.d.ts.map +1 -0
  292. package/payload/platform/plugins/loop/mcp/dist/tools/people-search.js +87 -0
  293. package/payload/platform/plugins/loop/mcp/dist/tools/people-search.js.map +1 -0
  294. package/payload/platform/plugins/loop/mcp/dist/tools/property-detail.d.ts +10 -0
  295. package/payload/platform/plugins/loop/mcp/dist/tools/property-detail.d.ts.map +1 -0
  296. package/payload/platform/plugins/loop/mcp/dist/tools/property-detail.js +82 -0
  297. package/payload/platform/plugins/loop/mcp/dist/tools/property-detail.js.map +1 -0
  298. package/payload/platform/plugins/loop/mcp/dist/tools/property-listed.d.ts +12 -0
  299. package/payload/platform/plugins/loop/mcp/dist/tools/property-listed.d.ts.map +1 -0
  300. package/payload/platform/plugins/loop/mcp/dist/tools/property-listed.js +32 -0
  301. package/payload/platform/plugins/loop/mcp/dist/tools/property-listed.js.map +1 -0
  302. package/payload/platform/plugins/loop/mcp/dist/tools/property-request.d.ts +15 -0
  303. package/payload/platform/plugins/loop/mcp/dist/tools/property-request.d.ts.map +1 -0
  304. package/payload/platform/plugins/loop/mcp/dist/tools/property-request.js +11 -0
  305. package/payload/platform/plugins/loop/mcp/dist/tools/property-request.js.map +1 -0
  306. package/payload/platform/plugins/loop/mcp/dist/tools/property-search.d.ts +16 -0
  307. package/payload/platform/plugins/loop/mcp/dist/tools/property-search.d.ts.map +1 -0
  308. package/payload/platform/plugins/loop/mcp/dist/tools/property-search.js +41 -0
  309. package/payload/platform/plugins/loop/mcp/dist/tools/property-search.js.map +1 -0
  310. package/payload/platform/plugins/loop/mcp/dist/tools/supplier.d.ts +13 -0
  311. package/payload/platform/plugins/loop/mcp/dist/tools/supplier.d.ts.map +1 -0
  312. package/payload/platform/plugins/loop/mcp/dist/tools/supplier.js +49 -0
  313. package/payload/platform/plugins/loop/mcp/dist/tools/supplier.js.map +1 -0
  314. package/payload/platform/plugins/loop/mcp/dist/tools/team-availability.d.ts +7 -0
  315. package/payload/platform/plugins/loop/mcp/dist/tools/team-availability.d.ts.map +1 -0
  316. package/payload/platform/plugins/loop/mcp/dist/tools/team-availability.js +19 -0
  317. package/payload/platform/plugins/loop/mcp/dist/tools/team-availability.js.map +1 -0
  318. package/payload/platform/plugins/loop/mcp/dist/tools/team-info.d.ts +5 -0
  319. package/payload/platform/plugins/loop/mcp/dist/tools/team-info.d.ts.map +1 -0
  320. package/payload/platform/plugins/loop/mcp/dist/tools/team-info.js +32 -0
  321. package/payload/platform/plugins/loop/mcp/dist/tools/team-info.js.map +1 -0
  322. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-create.d.ts +14 -0
  323. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-create.d.ts.map +1 -0
  324. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-create.js +11 -0
  325. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-create.js.map +1 -0
  326. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-detail.d.ts +9 -0
  327. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-detail.d.ts.map +1 -0
  328. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-detail.js +85 -0
  329. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-detail.js.map +1 -0
  330. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-search.d.ts +13 -0
  331. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-search.d.ts.map +1 -0
  332. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-search.js +44 -0
  333. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-search.js.map +1 -0
  334. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-update.d.ts +14 -0
  335. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-update.d.ts.map +1 -0
  336. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-update.js +18 -0
  337. package/payload/platform/plugins/loop/mcp/dist/tools/viewing-update.js.map +1 -0
  338. package/payload/platform/plugins/loop/mcp/package-lock.json +2549 -0
  339. package/payload/platform/plugins/loop/mcp/package.json +21 -0
  340. package/payload/platform/plugins/loop/mcp/src/__tests__/loop-swagger.snapshot.json +26467 -0
  341. package/payload/platform/plugins/loop/mcp/src/__tests__/swagger-write-coverage.test.ts +153 -0
  342. package/payload/platform/plugins/loop/mcp/src/index.ts +444 -0
  343. package/payload/platform/plugins/loop/mcp/src/lib/crypto.ts +105 -0
  344. package/payload/platform/plugins/loop/mcp/src/lib/loop-api.ts +604 -0
  345. package/payload/platform/plugins/loop/mcp/src/lib/neo4j.ts +51 -0
  346. package/payload/platform/plugins/loop/mcp/src/tools/customer-preferences.ts +66 -0
  347. package/payload/platform/plugins/loop/mcp/src/tools/feedback.ts +86 -0
  348. package/payload/platform/plugins/loop/mcp/src/tools/key-deregister.ts +27 -0
  349. package/payload/platform/plugins/loop/mcp/src/tools/key-list.ts +19 -0
  350. package/payload/platform/plugins/loop/mcp/src/tools/key-register.ts +95 -0
  351. package/payload/platform/plugins/loop/mcp/src/tools/marketing-enquiry.ts +113 -0
  352. package/payload/platform/plugins/loop/mcp/src/tools/marketing-match-batch.ts +53 -0
  353. package/payload/platform/plugins/loop/mcp/src/tools/marketing-match-request.ts +42 -0
  354. package/payload/platform/plugins/loop/mcp/src/tools/marketing-match.ts +84 -0
  355. package/payload/platform/plugins/loop/mcp/src/tools/people-detail.ts +245 -0
  356. package/payload/platform/plugins/loop/mcp/src/tools/people-search.ts +180 -0
  357. package/payload/platform/plugins/loop/mcp/src/tools/property-detail.ts +145 -0
  358. package/payload/platform/plugins/loop/mcp/src/tools/property-listed.ts +88 -0
  359. package/payload/platform/plugins/loop/mcp/src/tools/property-request.ts +42 -0
  360. package/payload/platform/plugins/loop/mcp/src/tools/property-search.ts +92 -0
  361. package/payload/platform/plugins/loop/mcp/src/tools/supplier.ts +129 -0
  362. package/payload/platform/plugins/loop/mcp/src/tools/team-availability.ts +52 -0
  363. package/payload/platform/plugins/loop/mcp/src/tools/team-info.ts +95 -0
  364. package/payload/platform/plugins/loop/mcp/src/tools/viewing-create.ts +41 -0
  365. package/payload/platform/plugins/loop/mcp/src/tools/viewing-detail.ts +171 -0
  366. package/payload/platform/plugins/loop/mcp/src/tools/viewing-search.ts +92 -0
  367. package/payload/platform/plugins/loop/mcp/src/tools/viewing-update.ts +53 -0
  368. package/payload/platform/plugins/loop/mcp/tsconfig.json +20 -0
  369. package/payload/platform/plugins/loop/mcp/vitest.config.ts +9 -0
  370. package/payload/platform/plugins/loop/skills/compliance-flag-checker/SKILL.md +53 -0
  371. package/payload/platform/plugins/loop/skills/priority-ranker/SKILL.md +40 -0
  372. package/payload/platform/plugins/loop/skills/tone-matched-drafter/SKILL.md +53 -0
  373. package/payload/platform/plugins/loop/skills/variance-narrator/SKILL.md +50 -0
  374. package/payload/platform/plugins/loop/skills/vendor-research/SKILL.md +54 -0
  375. package/payload/platform/plugins/memory/PLUGIN.md +58 -29
  376. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts +3 -1
  377. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
  378. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +105 -4
  379. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
  380. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  381. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +16 -3
  382. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  383. package/payload/platform/plugins/outlook/PLUGIN.md +14 -7
  384. package/payload/platform/plugins/replicate/PLUGIN.md +6 -3
  385. package/payload/platform/plugins/scheduling/PLUGIN.md +16 -8
  386. package/payload/platform/plugins/tasks/PLUGIN.md +28 -14
  387. package/payload/platform/plugins/teaching/.claude-plugin/plugin.json +8 -0
  388. package/payload/platform/plugins/teaching/PLUGIN.md +57 -0
  389. package/payload/platform/plugins/teaching/skills/interactive-tutor/SKILL.md +59 -0
  390. package/payload/platform/plugins/teaching/skills/interactive-tutor/references/assessment.md +70 -0
  391. package/payload/platform/plugins/teaching/skills/interactive-tutor/references/classroom-conduct.md +43 -0
  392. package/payload/platform/plugins/teaching/skills/interactive-tutor/references/teaching-modes.md +83 -0
  393. package/payload/platform/plugins/teaching/skills/lesson-planner/SKILL.md +48 -0
  394. package/payload/platform/plugins/teaching/skills/lesson-planner/references/context-gathering.md +41 -0
  395. package/payload/platform/plugins/teaching/skills/lesson-planner/references/plan-structure.md +94 -0
  396. package/payload/platform/plugins/teaching/skills/study-pack-builder/SKILL.md +52 -0
  397. package/payload/platform/plugins/teaching/skills/study-pack-builder/references/disaggregation.md +49 -0
  398. package/payload/platform/plugins/teaching/skills/study-pack-builder/references/materials.md +116 -0
  399. package/payload/platform/plugins/vendors/.claude-plugin/plugin.json +8 -0
  400. package/payload/platform/plugins/vendors/PLUGIN.md +34 -0
  401. package/payload/platform/plugins/vendors/skills/vendor-communication/SKILL.md +42 -0
  402. package/payload/platform/plugins/vendors/skills/vendor-communication/references/fee-protection-and-agenda.md +28 -0
  403. package/payload/platform/plugins/vendors/skills/vendor-communication/references/listing-scripts.md +44 -0
  404. package/payload/platform/plugins/vendors/skills/vendor-communication/references/negotiation-deep-guide.md +70 -0
  405. package/payload/platform/plugins/vendors/skills/vendor-communication/references/price-alignment-scripts.md +33 -0
  406. package/payload/platform/plugins/vendors/skills/vendor-communication/references/price-alignment.md +34 -0
  407. package/payload/platform/plugins/vendors/skills/vendor-communication/references/scenario-scripts.md +38 -0
  408. package/payload/platform/plugins/vendors/skills/vendor-communication/references/seller-engagement.md +51 -0
  409. package/payload/platform/plugins/vendors/skills/vendor-communication/references/valuation-booking.md +76 -0
  410. package/payload/platform/plugins/vendors/skills/vendor-communication/references/vendor-scripts.md +63 -0
  411. package/payload/platform/plugins/vendors/skills/vendor-communication/references/vendor-updates.md +41 -0
  412. package/payload/platform/plugins/vendors/skills/vendor-updates/SKILL.md +153 -0
  413. package/payload/platform/plugins/waitlist/PLUGIN.md +12 -6
  414. package/payload/platform/plugins/whatsapp/PLUGIN.md +25 -13
  415. package/payload/platform/plugins/workflows/PLUGIN.md +16 -8
  416. package/payload/platform/plugins/writer-craft/.claude-plugin/plugin.json +8 -0
  417. package/payload/platform/plugins/writer-craft/PLUGIN.md +87 -0
  418. package/payload/platform/plugins/writer-craft/agents/writer-craft--manuscript-reviewer.md +92 -0
  419. package/payload/platform/plugins/writer-craft/skills/citation-style/SKILL.md +94 -0
  420. package/payload/platform/plugins/writer-craft/skills/citation-style/references/book-and-chapter-models.md +77 -0
  421. package/payload/platform/plugins/writer-craft/skills/citation-style/references/citation-rules.md +103 -0
  422. package/payload/platform/plugins/writer-craft/skills/citation-style/references/journal-article-models.md +74 -0
  423. package/payload/platform/plugins/writer-craft/skills/citation-style/references/other-source-models.md +146 -0
  424. package/payload/platform/plugins/writer-craft/skills/citation-style/references/reference-list-rules.md +70 -0
  425. package/payload/platform/plugins/writer-craft/skills/editorial-practice/SKILL.md +108 -0
  426. package/payload/platform/plugins/writer-craft/skills/editorial-practice/references/copyediting.md +73 -0
  427. package/payload/platform/plugins/writer-craft/skills/editorial-practice/references/developmental-editing.md +85 -0
  428. package/payload/platform/plugins/writer-craft/skills/editorial-practice/references/genre-specific-editing.md +78 -0
  429. package/payload/platform/plugins/writer-craft/skills/editorial-practice/references/line-editing.md +55 -0
  430. package/payload/platform/plugins/writer-craft/skills/editorial-practice/references/self-editing.md +89 -0
  431. package/payload/platform/plugins/writer-craft/skills/persuasive-storytelling/SKILL.md +114 -0
  432. package/payload/platform/plugins/writer-craft/skills/persuasive-storytelling/references/audience-analysis.md +73 -0
  433. package/payload/platform/plugins/writer-craft/skills/persuasive-storytelling/references/crafting-persuasive-story.md +76 -0
  434. package/payload/platform/plugins/writer-craft/skills/persuasive-storytelling/references/persuasion-case-studies.md +67 -0
  435. package/payload/platform/plugins/writer-craft/skills/persuasive-storytelling/references/transformation-framework.md +86 -0
  436. package/payload/platform/plugins/writer-craft/skills/point-of-view/SKILL.md +97 -0
  437. package/payload/platform/plugins/writer-craft/skills/point-of-view/references/indirect-narration.md +72 -0
  438. package/payload/platform/plugins/writer-craft/skills/point-of-view/references/pov-types-and-voice.md +91 -0
  439. package/payload/platform/plugins/writer-craft/skills/point-of-view/references/protagonist-filter.md +71 -0
  440. package/payload/platform/plugins/writer-craft/skills/point-of-view/references/tense-and-person.md +85 -0
  441. package/payload/platform/plugins/writer-craft/skills/prose-craft/SKILL.md +100 -0
  442. package/payload/platform/plugins/writer-craft/skills/prose-craft/references/punctuation-and-grammar.md +72 -0
  443. package/payload/platform/plugins/writer-craft/skills/prose-craft/references/repetition.md +71 -0
  444. package/payload/platform/plugins/writer-craft/skills/prose-craft/references/sound-and-rhythm.md +64 -0
  445. package/payload/platform/plugins/writer-craft/skills/prose-craft/references/word-economy.md +93 -0
  446. package/payload/platform/plugins/writer-craft/skills/reader-engagement/SKILL.md +100 -0
  447. package/payload/platform/plugins/writer-craft/skills/reader-engagement/references/cause-effect-setup-payoff.md +79 -0
  448. package/payload/platform/plugins/writer-craft/skills/reader-engagement/references/conflict-escalation.md +81 -0
  449. package/payload/platform/plugins/writer-craft/skills/reader-engagement/references/hooking-readers.md +67 -0
  450. package/payload/platform/plugins/writer-craft/skills/reader-engagement/references/neurochemistry-of-engagement.md +94 -0
  451. package/payload/platform/plugins/writer-craft/skills/review-manuscript/SKILL.md +111 -0
  452. package/payload/platform/plugins/writer-craft/skills/review-manuscript/references/review-manuscript-checklist.md +119 -0
  453. package/payload/platform/plugins/writer-craft/skills/review-prose/SKILL.md +99 -0
  454. package/payload/platform/plugins/writer-craft/skills/review-prose/references/prose-review-checklist.md +112 -0
  455. package/payload/platform/plugins/writer-craft/skills/review-scene/SKILL.md +99 -0
  456. package/payload/platform/plugins/writer-craft/skills/review-scene/references/scene-analysis-framework.md +95 -0
  457. package/payload/platform/plugins/writer-craft/skills/story-architecture/SKILL.md +106 -0
  458. package/payload/platform/plugins/writer-craft/skills/story-architecture/references/blueprinting-and-scene-cards.md +118 -0
  459. package/payload/platform/plugins/writer-craft/skills/story-architecture/references/inner-issue-and-protagonist-goal.md +66 -0
  460. package/payload/platform/plugins/writer-craft/skills/story-architecture/references/misbelief-desire-worldview.md +87 -0
  461. package/payload/platform/plugins/writer-craft/skills/story-architecture/references/origin-scenes-and-escalation.md +82 -0
  462. package/payload/platform/plugins/writer-craft/skills/story-blueprint/SKILL.md +133 -0
  463. package/payload/platform/plugins/writer-craft/skills/story-blueprint/references/blueprinting-exercises.md +118 -0
  464. package/payload/platform/plugins/writer-craft/skills/story-blueprint/references/blueprinting-process.md +128 -0
  465. package/payload/platform/scripts/conversation-id-allowlist.txt +0 -1
  466. package/payload/platform/services/claude-session-manager/dist/config.d.ts +6 -0
  467. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  468. package/payload/platform/services/claude-session-manager/dist/config.js +60 -1
  469. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  470. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +9 -0
  471. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  472. package/payload/platform/services/claude-session-manager/dist/http-server.js +48 -2
  473. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  474. package/payload/platform/services/claude-session-manager/dist/index.js +39 -0
  475. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  476. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +22 -0
  477. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  478. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +32 -1
  479. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  480. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.d.ts +33 -0
  481. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.d.ts.map +1 -0
  482. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.js +149 -0
  483. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.js.map +1 -0
  484. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.d.ts +28 -0
  485. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.d.ts.map +1 -0
  486. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.js +77 -0
  487. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.js.map +1 -0
  488. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +25 -0
  489. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -0
  490. package/payload/platform/services/claude-session-manager/dist/tool-surface.js +149 -0
  491. package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -0
  492. package/payload/premium-plugins/real-agency/plugins/estate-business/PLUGIN.md +15 -0
  493. package/payload/premium-plugins/real-agency/plugins/estate-sales/PLUGIN.md +5 -0
  494. package/payload/premium-plugins/real-agency/plugins/leads/PLUGIN.md +16 -0
  495. package/payload/premium-plugins/real-agency/plugins/listings/PLUGIN.md +39 -0
  496. package/payload/premium-plugins/real-agency/plugins/loop/PLUGIN.md +15 -0
  497. package/payload/server/{chunk-2ZNKHCQB.js → chunk-2MRZBQMH.js} +1 -1
  498. package/payload/server/{chunk-GPUCA2RQ.js → chunk-NL7QLVAD.js} +0 -192
  499. package/payload/server/{chunk-IDKWGLM5.js → chunk-YPZFYTYP.js} +1 -247
  500. package/payload/server/{cloudflare-task-tracker-LYI5BTYI.js → cloudflare-task-tracker-QVOGHKWV.js} +2 -2
  501. package/payload/server/maxy-edge.js +2 -2
  502. package/payload/server/package.json +0 -2
  503. package/payload/server/public/assets/{Checkbox-D1OQD43b.js → Checkbox-YIF0payo.js} +1 -1
  504. package/payload/server/public/assets/{admin-czNBxWor.js → admin-DW8IJcLc.js} +1 -1
  505. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-BcwgT80u.js → architectureDiagram-Q4EWVU46-Bz8mlxZZ.js} +1 -1
  506. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BMSyZUQA.js → blockDiagram-DXYQGD6D-DwV8Z8-i.js} +1 -1
  507. package/payload/server/public/assets/{brand-2cku8WFs.css → brand-DqiRNMlu.css} +1 -1
  508. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DPRGY1jJ.js → c4Diagram-AHTNJAMY-DiUTejMp.js} +1 -1
  509. package/payload/server/public/assets/channel-PtVtoBEL.js +1 -0
  510. package/payload/server/public/assets/{chunk-336JU56O-B7oQ3g1c.js → chunk-336JU56O-4mHZpBXe.js} +2 -2
  511. package/payload/server/public/assets/{chunk-426QAEUC-C1P0yFXw.js → chunk-426QAEUC-Cbv0vrN9.js} +1 -1
  512. package/payload/server/public/assets/{chunk-4TB4RGXK-LI7kOJd0.js → chunk-4TB4RGXK-BvLhId_2.js} +1 -1
  513. package/payload/server/public/assets/{chunk-5FUZZQ4R-CXQRGTQE.js → chunk-5FUZZQ4R-bBafOTkw.js} +1 -1
  514. package/payload/server/public/assets/{chunk-5PVQY5BW-NSyzpXRy.js → chunk-5PVQY5BW-B0NqBKVy.js} +1 -1
  515. package/payload/server/public/assets/{chunk-EDXVE4YY-voNwxbDs.js → chunk-EDXVE4YY-CFd4SqI6.js} +1 -1
  516. package/payload/server/public/assets/{chunk-ENJZ2VHE-CMEMPzYY.js → chunk-ENJZ2VHE-ajf2sb6c.js} +1 -1
  517. package/payload/server/public/assets/{chunk-ICPOFSXX-hEbwu-pe.js → chunk-ICPOFSXX-pWg6bug7.js} +1 -1
  518. package/payload/server/public/assets/{chunk-OYMX7WX6-DxskDrLs.js → chunk-OYMX7WX6-OjEd-17c.js} +1 -1
  519. package/payload/server/public/assets/{chunk-U2HBQHQK-D7TKgUo0.js → chunk-U2HBQHQK-DbEFSPoh.js} +1 -1
  520. package/payload/server/public/assets/{chunk-X2U36JSP-BvPUQEPm.js → chunk-X2U36JSP-COdNwrBb.js} +1 -1
  521. package/payload/server/public/assets/{chunk-YZCP3GAM-BY-RWQUW.js → chunk-YZCP3GAM-CHMWuY9B.js} +1 -1
  522. package/payload/server/public/assets/{chunk-ZZ45TVLE-DZvOYDY6.js → chunk-ZZ45TVLE-B-uDLQOB.js} +1 -1
  523. package/payload/server/public/assets/classDiagram-6PBFFD2Q-RVH_SEhY.js +1 -0
  524. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Cm3rAb93.js +1 -0
  525. package/payload/server/public/assets/clone-BjY0Wzht.js +1 -0
  526. package/payload/server/public/assets/{dagre-KV5264BT-Cnj0mUZl.js → dagre-KV5264BT-CMEzmhIL.js} +1 -1
  527. package/payload/server/public/assets/{dagre-Bt-fpckL.js → dagre-bhIG_KnW.js} +1 -1
  528. package/payload/server/public/assets/data-K_kS__sL.js +1 -0
  529. package/payload/server/public/assets/{device-url-actions-Bjz3Xzbm.js → device-url-actions-AcOyLSeF.js} +1 -1
  530. package/payload/server/public/assets/{diagram-5BDNPKRD-DjLzvOlx.js → diagram-5BDNPKRD-6RIoQhIL.js} +1 -1
  531. package/payload/server/public/assets/{diagram-G4DWMVQ6-DTfuRd-T.js → diagram-G4DWMVQ6-BSp36TVv.js} +1 -1
  532. package/payload/server/public/assets/{diagram-MMDJMWI5-BaL2mCnx.js → diagram-MMDJMWI5-D54fo52D.js} +1 -1
  533. package/payload/server/public/assets/{diagram-TYMM5635-C5InWY5R.js → diagram-TYMM5635-CWL8z-Pq.js} +1 -1
  534. package/payload/server/public/assets/{erDiagram-SMLLAGMA-DO7BXTpn.js → erDiagram-SMLLAGMA-AnnHBo3z.js} +1 -1
  535. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-DDdAKfLf.js → flowDiagram-DWJPFMVM-laWmBl5o.js} +1 -1
  536. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-arJD8Utm.js → ganttDiagram-T4ZO3ILL-B94ko8ie.js} +1 -1
  537. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C55GH-OS.js → gitGraphDiagram-UUTBAWPF-DxzL1fxZ.js} +1 -1
  538. package/payload/server/public/assets/graph-DeEigyO_.js +1 -0
  539. package/payload/server/public/assets/graph-labels-C7I5QvNv.js +1 -0
  540. package/payload/server/public/assets/{graphlib-DL9PM7Ex.js → graphlib-CY-zIElM.js} +1 -1
  541. package/payload/server/public/assets/{infoDiagram-42DDH7IO-BMSGqUbG.js → infoDiagram-42DDH7IO-BMTajIIr.js} +1 -1
  542. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-Dw6BZ6BG.js → ishikawaDiagram-UXIWVN3A-B_QauE5O.js} +1 -1
  543. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DrywUGXw.js → journeyDiagram-VCZTEJTY-DmlqSIih.js} +1 -1
  544. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DuwtVBBc.js → kanban-definition-6JOO6SKY-ZGDQT7xB.js} +1 -1
  545. package/payload/server/public/assets/{line-JAksyKHj.js → line-D13opgep.js} +1 -1
  546. package/payload/server/public/assets/{mermaid-parser.core-BMq-ApBW.js → mermaid-parser.core-C650Sual.js} +1 -1
  547. package/payload/server/public/assets/{mermaid.core-tH4oX0Kh.js → mermaid.core-BqnQoXTp.js} +3 -3
  548. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-D1OiiJga.js → mindmap-definition-QFDTVHPH-BS_8y-tY.js} +1 -1
  549. package/payload/server/public/assets/{page-BZpoS7iR.js → page-B_rpjIRr.js} +1 -1
  550. package/payload/server/public/assets/{page-CkvBvezS.js → page-qSH972X0.js} +1 -1
  551. package/payload/server/public/assets/{pieDiagram-DEJITSTG-Ckwm69PW.js → pieDiagram-DEJITSTG-B5OmNvBO.js} +1 -1
  552. package/payload/server/public/assets/{public-C-dTMgXu.js → public-DDsYgotk.js} +3 -3
  553. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-COw3yZ1j.js → quadrantDiagram-34T5L4WZ-DTYITdNo.js} +1 -1
  554. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DqGzM4K-.js → requirementDiagram-MS252O5E-CRZWxH06.js} +1 -1
  555. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-D-l1c_Pl.js → sankeyDiagram-XADWPNL6-DazRENhe.js} +1 -1
  556. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BeIi0DtJ.js → sequenceDiagram-FGHM5R23-BcHTxmPy.js} +1 -1
  557. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-C-jgegLk.js → stateDiagram-FHFEXIEX-DYU7nbqg.js} +1 -1
  558. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BgljVtlp.js +1 -0
  559. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BGFKkYmi.js → timeline-definition-GMOUNBTQ-BKGmqkST.js} +1 -1
  560. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-5NuIhJLS.js → vennDiagram-DHZGUBPP-BXvLPmX7.js} +1 -1
  561. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Be9ytVut.js → wardleyDiagram-NUSXRM2D-BCclUa3Z.js} +1 -1
  562. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DCyHg41R.js → xychartDiagram-5P7HB3ND-C-Xp-Eoc.js} +1 -1
  563. package/payload/server/public/data.html +5 -5
  564. package/payload/server/public/graph.html +6 -6
  565. package/payload/server/public/index.html +8 -8
  566. package/payload/server/public/public.html +5 -5
  567. package/payload/server/server.js +1024 -2347
  568. package/payload/platform/scripts/check-sdk-oauth.mjs +0 -185
  569. package/payload/server/public/assets/channel-fxEghWew.js +0 -1
  570. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BsWzGW0N.js +0 -1
  571. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BGVa3h90.js +0 -1
  572. package/payload/server/public/assets/clone-Khvocke2.js +0 -1
  573. package/payload/server/public/assets/data-DBd-Buhp.js +0 -1
  574. package/payload/server/public/assets/graph-DUtVdnZ6.js +0 -1
  575. package/payload/server/public/assets/graph-labels-Dxfue-fP.js +0 -1
  576. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BaMs8Znv.js +0 -1
  577. /package/payload/server/public/assets/{brand-CSQuxS9w.js → brand-Bm671owU.js} +0 -0
@@ -0,0 +1,1288 @@
1
+ <!--
2
+ ════════════════════════════════════════════════════════════════════════════
3
+ COMPANION LANDING PAGE — index.html · canonical reference template
4
+ ════════════════════════════════════════════════════════════════════════════
5
+
6
+ This file is the canonical starting point for the property micro-site that
7
+ ships inside <property>/output/web/ alongside brochure.html. Every property
8
+ brochure run that produces a web bundle MUST start by copying this file —
9
+ do NOT rebuild it from scratch from the SKILL.md prose. The prose
10
+ describes the spec; this file IS the spec.
11
+
12
+ SUBSTITUTION CONTRACT
13
+ ─────────────────────
14
+ Every property-specific value in this file is a {{ token }} placeholder.
15
+ There is no exemplar copy left to accidentally inherit. After substitution,
16
+ `grep "{{" output/web/index.html` must return ZERO matches — any remaining
17
+ {{ x }} is a bug.
18
+
19
+ The full token list (with source field, format, length, voice) lives in
20
+ references/placeholders.md, shared with brochure.html. Each <!- - REPLACE: - ->
21
+ inline annotation here gives the short version (what fills the token, how
22
+ long, what voice). Style guidance per section is in references/copy.md.
23
+
24
+ Contract:
25
+
26
+ 1. Copy this file to <property>/output/web/index.html.
27
+ 2. Substitute every {{ placeholder }} token from the master placeholders.md.
28
+ 3. Update <title>, meta description, OG/Twitter image refs.
29
+ 4. If a section does not apply (e.g. property has no garden complex), follow
30
+ the SKILL's "Page-count expansion / repurposing" guidance — repurpose the
31
+ section title and copy. Do NOT delete sections; the layout assumes the
32
+ full set.
33
+
34
+ Editorial decisions baked into this file (KEEP, do not re-derive):
35
+ - Drop cap: .body-block p:first-of-type::first-letter (Cormorant ink, 3.6em
36
+ float-left). Every body-block opens with one. Mirrors the brochure's
37
+ opener treatment.
38
+ - Hero: 3-slide Ken-Burns rotator on an 18s cycle, pure CSS, with reduced-
39
+ motion fallback. See .hero-stage / .hero-slide CSS comments.
40
+ - Mobile collapse: top-nav → hamburger drawer at ≤960px; hero stacks at
41
+ ≤760px; hero aspect 5/4 at ≤440px.
42
+ - Type system: Cormorant Garamond (display) + Lora (body serif) + Inter
43
+ (UI labels). DO NOT swap these per-brand — the index.html register is
44
+ tuned to the canonical premium tier; brand identity lives in the logo,
45
+ copy and brand-specific colour accents that may be added via :root
46
+ overrides if needed (rare).
47
+
48
+ Authoring note — keep the body of this docstring free of inner HTML
49
+ comment delimiters. HTML does not allow nested comments: an inner "- - >"
50
+ would terminate this outer comment early and the rest of these
51
+ instructions would render as visible text on the live page (the bug that
52
+ prompted this note). When referring to the inline REPLACE markers, use
53
+ prose ("REPLACE comment block") not the literal delimiter pair.
54
+ ════════════════════════════════════════════════════════════════════════════
55
+ -->"
56
+ would terminate this outer comment early and the rest of these
57
+ instructions would render as visible text on the live page (the bug that
58
+ prompted this note). When referring to the inline REPLACE markers, use
59
+ prose ("REPLACE: comment block") not the literal "<!- - REPLACE: ... - ->"
60
+ delimiter pair.
61
+ ════════════════════════════════════════════════════════════════════════════
62
+ -->
63
+ <html lang="en-GB">
64
+ <head>
65
+ <meta charset="UTF-8">
66
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
67
+ <!-- REPLACE {{ page_title }}: "<Property name> · <street>, <locality> · For Sale".
68
+ Used as the browser tab title and search-result link. -->
69
+ <title>{{ page_title }}</title>
70
+ <!-- REPLACE {{ meta_description }}: single-sentence elevator pitch (25-45 words).
71
+ Same content as {{ backpage_tagline }} in the brochure; the two should mirror
72
+ each other. Used by social previews and search. -->
73
+ <meta name="description" content="{{ meta_description }}">
74
+ <link rel="preconnect" href="https://fonts.googleapis.com">
75
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
76
+ <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Lora:ital,wght@0,400;0,500;1,400&family=Inter:wght@400;500&display=swap" rel="stylesheet">
77
+ <style>
78
+ :root {
79
+ --paper: #FBF9F4;
80
+ --paper-2: #F4EFE5;
81
+ --ink: #0E1418;
82
+ --ink-2: #2A3036;
83
+ --slate: #5C6470;
84
+ --rule: rgba(14,20,24,0.14);
85
+ --rule-fine: #E2D5BD;
86
+ --gold: #7A6235;
87
+ --gold-soft: #A4884C;
88
+
89
+ --serif: 'Cormorant Garamond', 'EB Garamond', Garamond, serif;
90
+ --body-serif: 'Lora', 'Source Serif Pro', Georgia, serif;
91
+ --sans: 'Inter', system-ui, -apple-system, sans-serif;
92
+ }
93
+
94
+ * { margin: 0; padding: 0; box-sizing: border-box; }
95
+ html { font-size: 16px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; scroll-behavior: smooth; }
96
+ body {
97
+ font-family: var(--body-serif);
98
+ background: var(--paper);
99
+ color: var(--ink);
100
+ line-height: 1.65;
101
+ }
102
+ img { display: block; max-width: 100%; height: auto; }
103
+ a { color: inherit; }
104
+
105
+ /* ───────── TOP NAV ───────── */
106
+ .topnav {
107
+ position: relative;
108
+ z-index: 50;
109
+ height: 60px;
110
+ display: flex; align-items: center; justify-content: space-between;
111
+ padding: 0 32px;
112
+ background: var(--paper);
113
+ border-bottom: 1px solid var(--rule);
114
+ }
115
+
116
+ /* Hamburger button — hidden on desktop, visible at ≤ 960px */
117
+ .burger {
118
+ display: none;
119
+ background: transparent;
120
+ border: none;
121
+ padding: 10px;
122
+ cursor: pointer;
123
+ margin-left: -10px;
124
+ }
125
+ .burger span {
126
+ display: block;
127
+ width: 22px;
128
+ height: 1.5px;
129
+ background: var(--ink);
130
+ margin: 4px 0;
131
+ transition: transform 250ms ease, opacity 250ms ease;
132
+ }
133
+ .burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
134
+ .burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
135
+ .burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }
136
+
137
+ /* Drawer overlay — hidden by default, slides in from the right when opened */
138
+ .drawer {
139
+ position: fixed;
140
+ top: 0; right: 0; bottom: 0;
141
+ width: min(360px, 86vw);
142
+ background: var(--paper);
143
+ box-shadow: -2px 0 36px rgba(14,20,24,0.18);
144
+ transform: translateX(100%);
145
+ transition: transform 320ms ease;
146
+ z-index: 60;
147
+ padding: 64px 28px 28px;
148
+ display: flex; flex-direction: column; gap: 18px;
149
+ overflow-y: auto;
150
+ }
151
+ .drawer.open { transform: translateX(0); }
152
+ .drawer-close {
153
+ position: absolute;
154
+ top: 16px; right: 18px;
155
+ width: 36px; height: 36px;
156
+ background: transparent;
157
+ border: none;
158
+ font-size: 32px; line-height: 1;
159
+ color: var(--ink);
160
+ cursor: pointer;
161
+ }
162
+ .drawer-nav {
163
+ display: flex; flex-direction: column;
164
+ gap: 4px;
165
+ }
166
+ .drawer-nav a {
167
+ font-family: var(--sans);
168
+ font-size: 12px; font-weight: 500;
169
+ letter-spacing: 0.18em; text-transform: uppercase;
170
+ color: var(--ink-2);
171
+ text-decoration: none;
172
+ padding: 14px 0;
173
+ border-bottom: 1px solid var(--rule);
174
+ }
175
+ .drawer-nav a:hover { color: var(--gold); }
176
+ .drawer-nav a.drawer-cta {
177
+ margin-top: 12px;
178
+ padding: 14px 18px;
179
+ background: var(--ink);
180
+ color: var(--paper);
181
+ text-align: center;
182
+ border-bottom: none;
183
+ }
184
+ .drawer-nav a.drawer-cta:hover { background: var(--gold); color: var(--paper); }
185
+ .drawer-foot {
186
+ margin-top: auto;
187
+ padding-top: 24px;
188
+ border-top: 1px solid var(--rule);
189
+ font-family: var(--body-serif);
190
+ font-size: 13px;
191
+ color: var(--slate);
192
+ line-height: 1.55;
193
+ }
194
+ .drawer-foot a {
195
+ color: var(--ink-2);
196
+ text-decoration: underline;
197
+ text-decoration-color: rgba(122, 98, 53, 0.4);
198
+ text-underline-offset: 3px;
199
+ font-variant-numeric: tabular-nums;
200
+ }
201
+
202
+ /* Backdrop behind the drawer */
203
+ .drawer-backdrop {
204
+ position: fixed; inset: 0;
205
+ background: rgba(14,20,24,0.45);
206
+ opacity: 0;
207
+ pointer-events: none;
208
+ transition: opacity 320ms ease;
209
+ z-index: 55;
210
+ }
211
+ .drawer-backdrop.open {
212
+ opacity: 1;
213
+ pointer-events: auto;
214
+ }
215
+ body.drawer-open { overflow: hidden; }
216
+ .topnav .left, .topnav .right {
217
+ display: flex; align-items: center; gap: 28px;
218
+ font-family: var(--sans);
219
+ font-size: 11px;
220
+ font-weight: 500;
221
+ letter-spacing: 0.18em;
222
+ text-transform: uppercase;
223
+ color: var(--ink-2);
224
+ }
225
+ .topnav .left a, .topnav .right a { text-decoration: none; }
226
+ .topnav .left a:hover, .topnav .right a:hover { color: var(--gold); }
227
+ .topnav .center {
228
+ position: absolute; left: 50%; top: 50%;
229
+ transform: translate(-50%, -50%);
230
+ display: flex; align-items: center;
231
+ }
232
+ .topnav .center img { height: 18px; width: auto; }
233
+
234
+ /* ───────── HERO — rotating Ken-Burns stage ─────────
235
+ Three slides cross-fade on an 18s cycle (each visible ~5.5s,
236
+ ~0.5s crossfade), each with a slow Ken-Burns pan/zoom on its
237
+ <img> so the camera "moves" while the slide is visible. Pure
238
+ CSS — no JS dependency, no layout reflow. */
239
+ .hero {
240
+ position: relative;
241
+ width: 100%;
242
+ height: 78vh;
243
+ min-height: 560px;
244
+ overflow: hidden;
245
+ background: var(--ink);
246
+ }
247
+ .hero-stage {
248
+ position: absolute; inset: 0;
249
+ overflow: hidden;
250
+ }
251
+ .hero-slide {
252
+ position: absolute; inset: 0;
253
+ opacity: 0;
254
+ will-change: opacity;
255
+ }
256
+ .hero-slide img {
257
+ width: 100%; height: 100%;
258
+ object-fit: cover;
259
+ object-position: 50% 50%;
260
+ transform-origin: 50% 50%;
261
+ will-change: transform;
262
+ }
263
+
264
+ /* Stagger: each slide's animation starts 6s apart so they
265
+ never overlap except during the 0.5s crossfade. */
266
+ .hero-slide.s1 { animation: heroFade 18s 0s infinite; }
267
+ .hero-slide.s2 { animation: heroFade 18s 6s infinite; }
268
+ .hero-slide.s3 { animation: heroFade 18s 12s infinite; }
269
+ .hero-slide.s1 img { animation: heroKb1 18s 0s infinite ease-out; }
270
+ .hero-slide.s2 img { animation: heroKb2 18s 6s infinite ease-out; }
271
+ .hero-slide.s3 img { animation: heroKb3 18s 12s infinite ease-out; }
272
+
273
+ @keyframes heroFade {
274
+ 0% { opacity: 0; }
275
+ 3% { opacity: 1; } /* fade in over ~540ms */
276
+ 33% { opacity: 1; } /* hold visible ~5.4s out of the 6s window */
277
+ 36% { opacity: 0; } /* fade out over ~540ms */
278
+ 100% { opacity: 0; }
279
+ }
280
+
281
+ /* Slide 1 — main exterior. Slow push-in from a slight pull-back. */
282
+ @keyframes heroKb1 {
283
+ 0% { transform: scale(1.04) translate(0%, 0%); }
284
+ 36% { transform: scale(1.16) translate(-1.2%, 0.4%); }
285
+ 100% { transform: scale(1.16) translate(-1.2%, 0.4%); }
286
+ }
287
+ /* Slide 2 — interior moment. Pan right while pushing in. */
288
+ @keyframes heroKb2 {
289
+ 0% { transform: scale(1.06) translate(1.5%, 0%); }
290
+ 36% { transform: scale(1.18) translate(-1%, -0.8%); }
291
+ 100% { transform: scale(1.18) translate(-1%, -0.8%); }
292
+ }
293
+ /* Slide 3 — garden / outdoor. Tilt up while pushing in. */
294
+ @keyframes heroKb3 {
295
+ 0% { transform: scale(1.05) translate(0%, 1%); }
296
+ 36% { transform: scale(1.18) translate(0.8%, -1.4%); }
297
+ 100% { transform: scale(1.18) translate(0.8%, -1.4%); }
298
+ }
299
+
300
+ /* Reduced-motion users: hold slide 1, no crossfade, no zoom. */
301
+ @media (prefers-reduced-motion: reduce) {
302
+ .hero-slide.s1 { opacity: 1; animation: none; }
303
+ .hero-slide.s2, .hero-slide.s3 { opacity: 0; animation: none; }
304
+ .hero-slide img { animation: none; transform: none; }
305
+ }
306
+
307
+ .info-card {
308
+ position: absolute;
309
+ left: 6vw; bottom: 6vh;
310
+ background: rgba(252, 250, 246, 0.97);
311
+ padding: 20px 26px 22px;
312
+ width: 380px;
313
+ border-top: 1px solid var(--gold-soft);
314
+ box-shadow: 0 8px 36px rgba(14,20,24,0.14);
315
+ }
316
+ .info-card .tag {
317
+ display: inline-block;
318
+ font-family: var(--sans);
319
+ font-size: 9px; font-weight: 600;
320
+ letter-spacing: 0.32em; text-transform: uppercase;
321
+ color: var(--gold);
322
+ margin-bottom: 12px;
323
+ }
324
+ .info-card .title {
325
+ font-family: var(--serif);
326
+ font-style: italic;
327
+ font-weight: 400;
328
+ font-size: 32px;
329
+ line-height: 1.1;
330
+ color: var(--ink);
331
+ margin-bottom: 8px;
332
+ }
333
+ .info-card .address {
334
+ font-family: var(--body-serif);
335
+ font-size: 14px;
336
+ color: var(--ink-2);
337
+ line-height: 1.45;
338
+ margin-bottom: 14px;
339
+ }
340
+ .info-card .price {
341
+ font-family: var(--serif);
342
+ font-size: 19px;
343
+ color: var(--ink);
344
+ margin-bottom: 4px;
345
+ letter-spacing: 0.005em;
346
+ }
347
+ .info-card .price em { font-style: italic; color: var(--gold); }
348
+ .info-card .meta {
349
+ font-family: var(--body-serif);
350
+ font-size: 12.5px;
351
+ color: var(--slate);
352
+ line-height: 1.55;
353
+ margin-bottom: 14px;
354
+ }
355
+ .info-card .specs {
356
+ display: flex; flex-wrap: nowrap;
357
+ gap: 0;
358
+ padding: 10px 0;
359
+ margin-bottom: 14px;
360
+ border-top: 1px solid var(--rule);
361
+ border-bottom: 1px solid var(--rule);
362
+ font-family: var(--sans);
363
+ font-size: 9.5px; font-weight: 500;
364
+ letter-spacing: 0.10em; text-transform: uppercase;
365
+ color: var(--ink-2);
366
+ font-variant-numeric: tabular-nums;
367
+ justify-content: space-between;
368
+ align-items: baseline;
369
+ }
370
+ .info-card .specs span { white-space: nowrap; flex: 0 0 auto; }
371
+ .info-card .specs span + span::before {
372
+ content: "·";
373
+ color: var(--gold-soft);
374
+ margin: 0 8px;
375
+ }
376
+ .info-card .links {
377
+ display: flex; flex-wrap: nowrap; gap: 16px;
378
+ font-family: var(--sans);
379
+ font-size: 9.5px; font-weight: 500;
380
+ letter-spacing: 0.14em; text-transform: uppercase;
381
+ color: var(--ink-2);
382
+ margin-bottom: 16px;
383
+ }
384
+ .info-card .links a {
385
+ text-decoration: none;
386
+ border-bottom: 1px solid var(--gold-soft);
387
+ padding-bottom: 2px;
388
+ white-space: nowrap;
389
+ transition: color 200ms;
390
+ }
391
+ .info-card .links a:hover { color: var(--gold); }
392
+ .info-card .cta {
393
+ display: block;
394
+ width: 100%;
395
+ padding: 12px 16px;
396
+ background: var(--ink);
397
+ color: var(--paper);
398
+ font-family: var(--sans);
399
+ font-size: 11px; font-weight: 500;
400
+ letter-spacing: 0.28em; text-transform: uppercase;
401
+ text-align: center;
402
+ text-decoration: none;
403
+ border: none;
404
+ cursor: pointer;
405
+ transition: background 200ms;
406
+ }
407
+ .info-card .cta:hover { background: var(--gold); }
408
+
409
+ /* ───────── STICKY SUB-NAV (after scroll) ───────── */
410
+ .subnav {
411
+ position: sticky;
412
+ top: 0;
413
+ z-index: 40;
414
+ background: var(--paper);
415
+ border-bottom: 1px solid var(--rule);
416
+ padding: 14px 32px;
417
+ display: flex; align-items: center; justify-content: space-between;
418
+ transform: translateY(-100%);
419
+ transition: transform 300ms ease;
420
+ }
421
+ .subnav.visible { transform: translateY(0); }
422
+ .subnav .left {
423
+ font-family: var(--serif);
424
+ font-size: 17px;
425
+ color: var(--ink);
426
+ }
427
+ .subnav .left .price {
428
+ color: var(--slate);
429
+ font-size: 12px;
430
+ font-family: var(--sans);
431
+ letter-spacing: 0.12em;
432
+ margin-left: 14px;
433
+ font-variant-numeric: tabular-nums;
434
+ }
435
+ .subnav .right {
436
+ display: flex; align-items: center; gap: 16px;
437
+ }
438
+ .subnav .right a {
439
+ font-family: var(--sans);
440
+ font-size: 10px; font-weight: 500;
441
+ letter-spacing: 0.22em; text-transform: uppercase;
442
+ color: var(--ink-2);
443
+ text-decoration: none;
444
+ padding: 6px 10px;
445
+ border: 1px solid var(--rule);
446
+ }
447
+ .subnav .right a:hover { background: var(--paper-2); }
448
+ .subnav .right a.cta {
449
+ background: var(--ink);
450
+ color: var(--paper);
451
+ border-color: var(--ink);
452
+ }
453
+ .subnav .right a.cta:hover { background: var(--gold); border-color: var(--gold); }
454
+
455
+ /* ───────── BODY SECTIONS ───────── */
456
+ main {
457
+ padding: 0;
458
+ }
459
+ .body-block {
460
+ max-width: 720px;
461
+ margin: 0 auto;
462
+ padding: 64px 32px 32px;
463
+ }
464
+ .body-block.short { padding-bottom: 16px; }
465
+ .body-block h2 {
466
+ font-family: var(--serif);
467
+ font-style: italic;
468
+ font-weight: 400;
469
+ font-size: 22px;
470
+ color: var(--ink);
471
+ margin-bottom: 18px;
472
+ letter-spacing: -0.005em;
473
+ }
474
+ .body-block h2::before {
475
+ content: '';
476
+ display: block;
477
+ width: 36px;
478
+ height: 1px;
479
+ background: var(--gold-soft);
480
+ margin-bottom: 16px;
481
+ }
482
+ .body-block p {
483
+ font-family: var(--body-serif);
484
+ font-size: 15.5px;
485
+ line-height: 1.7;
486
+ color: var(--ink-2);
487
+ letter-spacing: 0.005em;
488
+ }
489
+ .body-block p + p { margin-top: 16px; }
490
+ .body-block p strong { color: var(--ink); font-weight: 500; }
491
+ .body-block p em { color: var(--gold); font-style: italic; }
492
+
493
+ /* Drop cap on the first paragraph of each body-block. Cormorant Garamond
494
+ to echo the section h2 voice; ink rather than gold so the existing gold
495
+ accent (eyebrows, em-text, hairlines) stays the only chromatic editorial
496
+ note on the page. KEEP — this is the signature editorial detail of the
497
+ landing page, mirroring the brochure's opener treatment. */
498
+ .body-block p:first-of-type::first-letter {
499
+ font-family: var(--serif);
500
+ font-weight: 400;
501
+ font-size: 3.6em;
502
+ line-height: 0.85;
503
+ float: left;
504
+ margin: 0.08em 0.12em -0.04em 0;
505
+ color: var(--ink);
506
+ letter-spacing: -0.02em;
507
+ }
508
+
509
+ .section-eyebrow {
510
+ font-family: var(--sans);
511
+ font-size: 10px; font-weight: 600;
512
+ letter-spacing: 0.36em; text-transform: uppercase;
513
+ color: var(--gold);
514
+ margin-bottom: 14px;
515
+ }
516
+
517
+ /* ───────── PHOTO GRID ───────── */
518
+ .photo-grid {
519
+ max-width: 1100px;
520
+ margin: 32px auto;
521
+ padding: 0 32px;
522
+ display: grid;
523
+ grid-template-columns: 1fr 1fr;
524
+ gap: 16px;
525
+ }
526
+ .photo-grid .cell {
527
+ position: relative;
528
+ overflow: hidden;
529
+ aspect-ratio: 4/3;
530
+ background: var(--paper-2);
531
+ }
532
+ .photo-grid .cell img {
533
+ width: 100%; height: 100%;
534
+ object-fit: cover;
535
+ transition: transform 600ms ease;
536
+ }
537
+ .photo-grid .cell:hover img { transform: scale(1.02); }
538
+
539
+ .photo-grid.tall .cell {
540
+ aspect-ratio: 4/5;
541
+ }
542
+
543
+ /* Wider single full-width image for atmospheric breaks */
544
+ .photo-full {
545
+ margin: 32px 0;
546
+ }
547
+ .photo-full img {
548
+ width: 100%;
549
+ height: auto;
550
+ max-height: 80vh;
551
+ object-fit: cover;
552
+ }
553
+
554
+ /* ───────── FLOOR PLAN ───────── */
555
+ .floorplan-section {
556
+ background: var(--paper-2);
557
+ padding: 80px 32px;
558
+ margin-top: 32px;
559
+ }
560
+ .floorplan-section .inner {
561
+ max-width: 1100px;
562
+ margin: 0 auto;
563
+ display: grid;
564
+ grid-template-columns: 1.3fr 1fr;
565
+ gap: 48px;
566
+ align-items: start;
567
+ }
568
+ .floorplan-section img {
569
+ width: 100%;
570
+ height: auto;
571
+ background: white;
572
+ padding: 16px;
573
+ }
574
+ .floorplan-section .meta h2 {
575
+ font-family: var(--serif);
576
+ font-style: italic;
577
+ font-weight: 400;
578
+ font-size: 26px;
579
+ color: var(--ink);
580
+ margin-bottom: 8px;
581
+ }
582
+ .floorplan-section .meta .lead {
583
+ font-family: var(--body-serif);
584
+ font-size: 14px;
585
+ color: var(--ink-2);
586
+ margin-bottom: 24px;
587
+ line-height: 1.6;
588
+ }
589
+ .floorplan-section .areas {
590
+ display: grid;
591
+ grid-template-columns: 1fr 1fr;
592
+ gap: 12px 18px;
593
+ border-top: 1px solid var(--rule);
594
+ padding-top: 20px;
595
+ font-variant-numeric: tabular-nums;
596
+ }
597
+ .floorplan-section .areas .row .k {
598
+ display: block;
599
+ font-family: var(--sans);
600
+ font-size: 9px; font-weight: 600;
601
+ letter-spacing: 0.28em; text-transform: uppercase;
602
+ color: var(--slate);
603
+ margin-bottom: 4px;
604
+ }
605
+ .floorplan-section .areas .row .v {
606
+ font-family: var(--serif);
607
+ font-size: 17px;
608
+ color: var(--ink);
609
+ }
610
+ .floorplan-section .areas .row .v em { font-style: italic; color: var(--gold); }
611
+
612
+ /* ───────── KEY FACTS / MATERIAL INFO ───────── */
613
+ .key-facts {
614
+ max-width: 1100px;
615
+ margin: 64px auto 32px;
616
+ padding: 0 32px;
617
+ }
618
+ .key-facts h2 {
619
+ font-family: var(--serif);
620
+ font-style: italic;
621
+ font-size: 22px;
622
+ color: var(--ink);
623
+ margin-bottom: 24px;
624
+ text-align: center;
625
+ }
626
+ .key-facts h2::after {
627
+ content: '';
628
+ display: block;
629
+ width: 36px;
630
+ height: 1px;
631
+ background: var(--gold-soft);
632
+ margin: 12px auto 0;
633
+ }
634
+ .key-facts .grid {
635
+ display: grid;
636
+ grid-template-columns: repeat(3, 1fr);
637
+ gap: 18px 36px;
638
+ font-variant-numeric: tabular-nums;
639
+ }
640
+ .key-facts .row {
641
+ border-bottom: 1px solid var(--rule);
642
+ padding: 12px 0 14px;
643
+ }
644
+ .key-facts .row .k {
645
+ font-family: var(--sans);
646
+ font-size: 9px; font-weight: 600;
647
+ letter-spacing: 0.28em; text-transform: uppercase;
648
+ color: var(--slate);
649
+ margin-bottom: 5px;
650
+ }
651
+ .key-facts .row .v {
652
+ font-family: var(--body-serif);
653
+ font-size: 14px;
654
+ color: var(--ink);
655
+ }
656
+ .key-facts .footnote {
657
+ grid-column: 1 / -1;
658
+ margin-top: 18px;
659
+ font-family: var(--body-serif);
660
+ font-style: italic;
661
+ font-size: 12px;
662
+ color: var(--slate);
663
+ text-align: center;
664
+ }
665
+
666
+ /* ───────── CTA STRIP ───────── */
667
+ .cta-strip {
668
+ background: var(--ink);
669
+ color: var(--paper);
670
+ text-align: center;
671
+ padding: 64px 32px;
672
+ margin-top: 64px;
673
+ }
674
+ .cta-strip h2 {
675
+ font-family: var(--serif);
676
+ font-style: italic;
677
+ font-weight: 400;
678
+ font-size: 32px;
679
+ margin-bottom: 28px;
680
+ color: var(--paper);
681
+ }
682
+ .cta-strip .cta-row {
683
+ display: flex; gap: 32px; justify-content: center; align-items: center;
684
+ flex-wrap: wrap;
685
+ }
686
+ .cta-strip .cta-row a {
687
+ font-family: var(--sans);
688
+ font-size: 11px; font-weight: 500;
689
+ letter-spacing: 0.28em; text-transform: uppercase;
690
+ color: var(--paper);
691
+ text-decoration: none;
692
+ padding: 12px 22px;
693
+ border: 1px solid rgba(252,250,246,0.32);
694
+ transition: background 200ms, border-color 200ms;
695
+ }
696
+ .cta-strip .cta-row a:hover {
697
+ background: var(--gold);
698
+ border-color: var(--gold);
699
+ }
700
+ .cta-strip .cta-row a.solid {
701
+ background: var(--paper);
702
+ color: var(--ink);
703
+ border-color: var(--paper);
704
+ }
705
+ .cta-strip .cta-row a.solid:hover {
706
+ background: var(--gold);
707
+ color: var(--paper);
708
+ border-color: var(--gold);
709
+ }
710
+
711
+ /* ───────── FOOTER ───────── */
712
+ footer {
713
+ background: var(--paper);
714
+ padding: 48px 32px 32px;
715
+ border-top: 1px solid var(--rule);
716
+ }
717
+ footer .inner {
718
+ max-width: 1100px;
719
+ margin: 0 auto;
720
+ display: flex;
721
+ justify-content: space-between;
722
+ align-items: flex-start;
723
+ flex-wrap: wrap;
724
+ gap: 32px;
725
+ }
726
+ footer .agent {
727
+ font-family: var(--body-serif);
728
+ font-size: 13px;
729
+ color: var(--ink-2);
730
+ line-height: 1.6;
731
+ max-width: 320px;
732
+ }
733
+ footer .agent .name {
734
+ font-family: var(--serif);
735
+ font-size: 17px;
736
+ color: var(--ink);
737
+ margin-bottom: 4px;
738
+ }
739
+ footer .agent .name em { font-style: italic; color: var(--gold); }
740
+ footer .agent .label {
741
+ font-family: var(--sans);
742
+ font-size: 9px; font-weight: 600;
743
+ letter-spacing: 0.32em; text-transform: uppercase;
744
+ color: var(--slate);
745
+ margin-bottom: 8px;
746
+ }
747
+ footer .legal {
748
+ font-family: var(--body-serif);
749
+ font-style: italic;
750
+ font-size: 11px;
751
+ color: var(--slate);
752
+ line-height: 1.55;
753
+ max-width: 600px;
754
+ }
755
+ footer .colophon {
756
+ width: 100%;
757
+ border-top: 1px solid var(--rule);
758
+ padding-top: 18px;
759
+ margin-top: 24px;
760
+ display: flex;
761
+ justify-content: space-between;
762
+ align-items: center;
763
+ font-family: var(--sans);
764
+ font-size: 10px; font-weight: 500;
765
+ letter-spacing: 0.22em; text-transform: uppercase;
766
+ color: var(--slate);
767
+ }
768
+ footer .colophon img { height: 14px; width: auto; opacity: 0.75; }
769
+
770
+ /* ───────── RESPONSIVE ─────────
771
+ The desktop top-nav (deep-section links + centred logo +
772
+ utility links) needs ~1100 px to breathe. Below 960 px the
773
+ deep-section labels overlap the centred logo, so we collapse
774
+ the entire desktop nav into a hamburger-revealed drawer.
775
+
776
+ The hero overlay → vertical-stack rule kicks in slightly later
777
+ at 760 px (where the floating info-card starts to occlude
778
+ the rotator). */
779
+
780
+ @media (max-width: 960px) {
781
+ .burger { display: block; }
782
+ .topnav .left, .topnav .right { display: none; }
783
+ /* The centred logo stays — it's the only element left on the bar */
784
+ .topnav .center { left: auto; right: auto; transform: none; position: static; margin-left: auto; margin-right: auto; }
785
+ }
786
+
787
+ @media (max-width: 760px) {
788
+ .hero {
789
+ height: auto;
790
+ min-height: 0;
791
+ display: flex;
792
+ flex-direction: column;
793
+ background: var(--paper);
794
+ }
795
+ .hero-stage {
796
+ position: relative;
797
+ width: 100%;
798
+ aspect-ratio: 4/3;
799
+ flex: 0 0 auto;
800
+ background: var(--ink);
801
+ }
802
+ .info-card {
803
+ position: static;
804
+ left: auto; right: auto; bottom: auto;
805
+ width: auto;
806
+ margin: 0;
807
+ padding: 24px 24px 28px;
808
+ box-shadow: none;
809
+ border-top: 1px solid var(--rule);
810
+ background: var(--paper);
811
+ }
812
+ .info-card .title { font-size: 30px; }
813
+ .info-card .specs { font-size: 10px; }
814
+ .info-card .links { font-size: 10px; }
815
+
816
+ .photo-grid { grid-template-columns: 1fr; gap: 12px; }
817
+ .floorplan-section .inner { grid-template-columns: 1fr; gap: 28px; }
818
+ .key-facts .grid { grid-template-columns: 1fr 1fr; }
819
+ .subnav .right a:not(.cta) { display: none; }
820
+ .body-block { padding: 48px 24px 24px; }
821
+ .topnav { padding: 0 18px; }
822
+ /* Footer colophon stacks on mobile: property line on its own row,
823
+ copyright on its own row beneath. Matches the rest of the mobile
824
+ stack pattern (every multi-column block becomes single-column). */
825
+ footer .colophon {
826
+ flex-direction: column;
827
+ align-items: flex-start;
828
+ gap: 8px;
829
+ }
830
+ }
831
+
832
+ @media (max-width: 440px) {
833
+ .hero-stage { aspect-ratio: 5/4; }
834
+ .key-facts .grid { grid-template-columns: 1fr; }
835
+ .subnav .left .price { display: none; }
836
+ }
837
+ </style>
838
+ </head>
839
+ <body>
840
+
841
+ <!-- ════════════════ TOP NAV ════════════════ -->
842
+ <nav class="topnav">
843
+ <button class="burger" aria-label="Open menu" aria-expanded="false" aria-controls="drawer">
844
+ <span></span><span></span><span></span>
845
+ </button>
846
+ <!-- REPLACE: Deep-section links — section names + #anchor IDs that match the
847
+ <article id="..."> blocks below. Keep the four-link rhythm; rename only
848
+ if the property's narrative arc differs from the canonical
849
+ (Story / The Home / The Garden / The Area). All four anchors are also
850
+ used in the drawer + sub-nav below. -->
851
+ <div class="left">
852
+ <a href="#story">{{ nav_section_1 }}</a>
853
+ <a href="#home">{{ nav_section_2 }}</a>
854
+ <a href="#garden">{{ nav_section_3 }}</a>
855
+ <a href="#area">{{ nav_section_4 }}</a>
856
+ </div>
857
+ <div class="center">
858
+ <!-- The brand DARK-art logo (placed on the warm-paper top-nav).
859
+ {{ brand_slug }} resolves to the agent's brand slug; the file is
860
+ <brand>-logo-dark.png per the brand-design SKILL convention. -->
861
+ <img src="images/{{ brand_slug }}-logo-dark.png" alt="{{ brand_name }}">
862
+ </div>
863
+ <!-- REPLACE: Utility links — Brochure (downloads the in-bundle PDF, named
864
+ {{ property_slug }}-brochure.pdf), Listing (the agent's live listing
865
+ URL), Enquire (mailto: agent). Three links, in that order. -->
866
+ <div class="right">
867
+ <a href="{{ property_slug }}-brochure.pdf" download>Brochure</a>
868
+ <a href="{{ listing_url }}" target="_blank">Listing</a>
869
+ <a href="mailto:{{ office_email }}">Enquire</a>
870
+ </div>
871
+ </nav>
872
+
873
+ <!-- Mobile drawer (revealed by the hamburger).
874
+ IMPORTANT: drawer must contain EVERY nav link the desktop has, PLUS the
875
+ extra utility links (Floor plan, Key facts, Watch video tour) and a CTA.
876
+ Mobile users get more navigation, not less. Order is: deep sections,
877
+ then utility links, then a closing CTA. -->
878
+ <div class="drawer" id="drawer" aria-hidden="true">
879
+ <button class="drawer-close" aria-label="Close menu">&times;</button>
880
+ <!-- REPLACE: Drawer nav — same anchors as the desktop deep-links plus
881
+ the utility links + a closing CTA. Mobile users get MORE navigation,
882
+ not less. The "View on Brand" label uses the brand's name verbatim
883
+ ("View on Beacons", "View on Muvin", etc.). -->
884
+ <nav class="drawer-nav">
885
+ <a href="#story">{{ nav_section_1 }}</a>
886
+ <a href="#home">{{ nav_section_2 }}</a>
887
+ <a href="#garden">{{ nav_section_3 }}</a>
888
+ <a href="#area">{{ nav_section_4 }}</a>
889
+ <a href="#floorplan">Floor plan</a>
890
+ <a href="#facts">Key facts</a>
891
+ <a href="{{ property_slug }}-brochure.pdf" download>Download brochure</a>
892
+ <a href="{{ video_url }}" target="_blank">Watch video tour</a>
893
+ <a href="{{ listing_url }}" target="_blank">View on {{ brand_name }}</a>
894
+ <a href="mailto:{{ office_email }}?subject={{ email_subject_enquiry }}" class="drawer-cta">Enquire</a>
895
+ </nav>
896
+ <!-- REPLACE: Drawer foot — agent name, agency, branch, plus a tel: link.
897
+ {{ office_phone_tel }} is the international-format dialer link (e.g.
898
+ "+441873377575"); {{ office_phone }} is the display format. -->
899
+ <div class="drawer-foot">
900
+ {{ agent_first_name }} {{ agent_surname }} · {{ brand_name }} · {{ brand_town }}<br>
901
+ <a href="tel:{{ office_phone_tel }}">{{ office_phone }}</a>
902
+ </div>
903
+ </div>
904
+
905
+ <!-- ════════════════ STICKY SUB-NAV ════════════════ -->
906
+ <!-- Revealed by the JS at the bottom of the page once the hero scrolls past.
907
+ Mirrors the hero info-card's three utility links plus a Request-viewing CTA. -->
908
+ <nav class="subnav" id="subnav">
909
+ <!-- REPLACE: Sub-nav left — property name + price + postcode (compressed
910
+ summary of the hero info-card for the scrolled state). -->
911
+ <div class="left">
912
+ {{ property_name }}
913
+ <span class="price">{{ price_formatted }} · {{ postcode }}</span>
914
+ </div>
915
+ <!-- REPLACE: Sub-nav right — same utility links as the hero info-card.
916
+ Keep "Request viewing" as the rightmost CTA in solid ink. -->
917
+ <div class="right">
918
+ <a href="#floorplan">Floor plan</a>
919
+ <a href="{{ property_slug }}-brochure.pdf" download>Brochure</a>
920
+ <a href="{{ video_url }}" target="_blank">Video tour</a>
921
+ <a href="mailto:{{ office_email }}?subject={{ email_subject_viewing }}" class="cta">Request viewing</a>
922
+ </div>
923
+ </nav>
924
+
925
+ <!-- ════════════════ HERO ════════════════ -->
926
+ <!-- 3-slide Ken-Burns rotator. Image filenames follow the convention
927
+ PROPERTY-SLUG-hero-N-<role>.webp (source-resolution, q88 — see SKILL
928
+ "Hero — rotating Ken-Burns stage"). Pick three different MOMENTS, not
929
+ three angles of the same shot:
930
+ Slide 1: main exterior (often the cover image — golden hour preferred)
931
+ Slide 2: principal interior (kitchen-dining, hearth, principal sitting)
932
+ Slide 3: garden / outdoor / aerial (different from slide 1 in subject) -->
933
+ <section class="hero">
934
+ <!-- REPLACE three hero slides. Filename pattern:
935
+ {{ property_slug }}-hero-N-<role>.webp
936
+ Three DIFFERENT MOMENTS, not three angles of the same shot:
937
+ Slide 1: main exterior (often golden hour; usually the cover image)
938
+ Slide 2: principal interior (kitchen-dining, hearth, principal sitting)
939
+ Slide 3: garden / outdoor / aerial (different subject from slide 1)
940
+ Alt: property name + the moment captured. -->
941
+ <div class="hero-stage" aria-label="{{ property_name }} — three views" role="img">
942
+ <div class="hero-slide s1"><img src="images/{{ hero_1_src }}" alt="{{ hero_1_alt }}"></div>
943
+ <div class="hero-slide s2"><img src="images/{{ hero_2_src }}" alt="{{ hero_2_alt }}"></div>
944
+ <div class="hero-slide s3"><img src="images/{{ hero_3_src }}" alt="{{ hero_3_alt }}"></div>
945
+ </div>
946
+ <!-- REPLACE: Info-card — sits over the hero (desktop) or stacks under
947
+ (mobile). Substitute the title, address (two lines via <br>), price
948
+ (qualifier + amount), meta (tenure · year), four spec cells, three
949
+ utility links, and the request-viewing CTA. The specs row + links row
950
+ each MUST stay single-line — see copy.md "Stats rows". -->
951
+ <div class="info-card">
952
+ <span class="tag">{{ hero_tag }}</span>
953
+ <h1 class="title">{{ property_name }}</h1>
954
+ <div class="address">{{ address_line_1 }},<br>{{ locality }}, {{ county }} {{ postcode }}</div>
955
+ <div class="price">{{ price_qualifier }} <em>{{ price_formatted }}</em></div>
956
+ <div class="meta">{{ tenure }} · c.&nbsp;{{ year_built }}</div>
957
+ <div class="specs">
958
+ <span>{{ spec_beds }}</span>
959
+ <span>{{ spec_baths }}</span>
960
+ <span>{{ spec_area }}</span>
961
+ <span>{{ spec_plot }}</span>
962
+ </div>
963
+ <div class="links">
964
+ <a href="#floorplan">Floor plan</a>
965
+ <a href="{{ property_slug }}-brochure.pdf" download>Brochure</a>
966
+ <a href="{{ video_url }}" target="_blank">Video tour</a>
967
+ </div>
968
+ <a href="mailto:{{ office_email }}?subject={{ email_subject_viewing }}" class="cta">Request viewing</a>
969
+ </div>
970
+ </section>
971
+
972
+ <!-- ════════════════ MAIN BODY ════════════════ -->
973
+ <main>
974
+
975
+ <!-- INTRO BLOCK -->
976
+ <!-- REPLACE: Story / "Of place & pedigree" section.
977
+ eyebrow → fixed phrase or property-specific synonym for the chapter
978
+ h2 → italic editorial headline summarising what this home is
979
+ (15-25 words; one declarative sentence; place + character)
980
+ p1, p2 → two paragraphs of opening editorial. Distil from seller
981
+ brief Q1/Q3/Q5/Q19/Q20. Para 1 short (3-4 sentences) so the
982
+ dropcap reads cleanly; para 2 longer (4-6 sentences). Close
983
+ para 2 with an italic phrase wrapped in <em>. -->
984
+ <article class="body-block" id="story">
985
+ <div class="section-eyebrow">{{ landing_story_eyebrow }}</div>
986
+ <h2>{{ landing_story_headline }}</h2>
987
+ <p>
988
+ {{ landing_story_para_1 }}
989
+ </p>
990
+ <p>
991
+ {{ landing_story_para_2 }}
992
+ </p>
993
+ </article>
994
+
995
+ <!-- PHOTO GRID 1 — Establishing exterior + drone -->
996
+ <!-- REPLACE four establishing cells — front elevation, drone aerial,
997
+ atmospheric exterior, garden-with-home-context. These set scale
998
+ before the body copy goes inside. -->
999
+ <div class="photo-grid">
1000
+ <div class="cell"><img src="images/{{ landing_grid_1_src_a }}" alt="{{ landing_grid_1_alt_a }}"></div>
1001
+ <div class="cell"><img src="images/{{ landing_grid_1_src_b }}" alt="{{ landing_grid_1_alt_b }}"></div>
1002
+ <div class="cell"><img src="images/{{ landing_grid_1_src_c }}" alt="{{ landing_grid_1_alt_c }}"></div>
1003
+ <div class="cell"><img src="images/{{ landing_grid_1_src_d }}" alt="{{ landing_grid_1_alt_d }}"></div>
1004
+ </div>
1005
+
1006
+ <!-- THE HOME -->
1007
+ <!-- REPLACE: The Home / "A home at ease" section.
1008
+ Three paragraphs (each 4-6 sentences) covering:
1009
+ (1) entrance hall + how the ground-floor plan opens / divides
1010
+ (2) kitchen-dining detail — cabinetry, worksurfaces, appliances,
1011
+ connection to utility / outdoor
1012
+ (3) sitting room(s) + any signature interior feature (hearth,
1013
+ orangery, conservatory, garden room). Use <strong> sparingly
1014
+ for the two or three most distinctive features. Em-dashes
1015
+ rare. Distil from seller brief Q5-Q7. -->
1016
+ <article class="body-block" id="home">
1017
+ <div class="section-eyebrow">{{ landing_home_eyebrow }}</div>
1018
+ <h2>{{ landing_home_headline }}</h2>
1019
+ <p>
1020
+ {{ landing_home_para_1 }}
1021
+ </p>
1022
+ <p>
1023
+ {{ landing_home_para_2 }}
1024
+ </p>
1025
+ <p>
1026
+ {{ landing_home_para_3 }}
1027
+ </p>
1028
+ </article>
1029
+
1030
+ <!-- PHOTO GRID 2 — Kitchen & dining. REPLACE four cells from the
1031
+ kitchen-breakfast-dining narrative: wide shot, island detail,
1032
+ range/appliances, dining end. -->
1033
+ <div class="photo-grid">
1034
+ <div class="cell"><img src="images/{{ landing_grid_2_src_a }}" alt="{{ landing_grid_2_alt_a }}"></div>
1035
+ <div class="cell"><img src="images/{{ landing_grid_2_src_b }}" alt="{{ landing_grid_2_alt_b }}"></div>
1036
+ <div class="cell"><img src="images/{{ landing_grid_2_src_c }}" alt="{{ landing_grid_2_alt_c }}"></div>
1037
+ <div class="cell"><img src="images/{{ landing_grid_2_src_d }}" alt="{{ landing_grid_2_alt_d }}"></div>
1038
+ </div>
1039
+
1040
+ <!-- PHOTO GRID 3 — Reception & living. REPLACE four cells from the
1041
+ reception narrative: signature hearth/sitting room, second reception,
1042
+ hallway, third reception (orangery / day room / garden room). -->
1043
+ <div class="photo-grid">
1044
+ <div class="cell"><img src="images/{{ landing_grid_3_src_a }}" alt="{{ landing_grid_3_alt_a }}"></div>
1045
+ <div class="cell"><img src="images/{{ landing_grid_3_src_b }}" alt="{{ landing_grid_3_alt_b }}"></div>
1046
+ <div class="cell"><img src="images/{{ landing_grid_3_src_c }}" alt="{{ landing_grid_3_alt_c }}"></div>
1047
+ <div class="cell"><img src="images/{{ landing_grid_3_src_d }}" alt="{{ landing_grid_3_alt_d }}"></div>
1048
+ </div>
1049
+
1050
+ <!-- THE BEDROOMS -->
1051
+ <!-- REPLACE: Bedrooms & baths section. Two paragraphs:
1052
+ (1) the sleeping floor's character + the bedroom sequence (count,
1053
+ layout, light, view)
1054
+ (2) the principal suite + family bath split, and any standout
1055
+ bathroom feature.
1056
+ Distil from seller brief Q6/Q10. Avoid "house" — use "home". -->
1057
+ <article class="body-block" id="bedrooms">
1058
+ <div class="section-eyebrow">{{ landing_bedrooms_eyebrow }}</div>
1059
+ <h2>{{ landing_bedrooms_headline }}</h2>
1060
+ <p>
1061
+ {{ landing_bedrooms_para_1 }}
1062
+ </p>
1063
+ <p>
1064
+ {{ landing_bedrooms_para_2 }}
1065
+ </p>
1066
+ </article>
1067
+
1068
+ <!-- PHOTO GRID 4 — Bedrooms & baths. REPLACE four cells, mixing
1069
+ bedrooms and bathrooms so the grid reads as the floor as a whole:
1070
+ principal bedroom (hero), second/third double, family bathroom,
1071
+ secondary bathroom. -->
1072
+ <div class="photo-grid">
1073
+ <div class="cell"><img src="images/{{ landing_grid_4_src_a }}" alt="{{ landing_grid_4_alt_a }}"></div>
1074
+ <div class="cell"><img src="images/{{ landing_grid_4_src_b }}" alt="{{ landing_grid_4_alt_b }}"></div>
1075
+ <div class="cell"><img src="images/{{ landing_grid_4_src_c }}" alt="{{ landing_grid_4_alt_c }}"></div>
1076
+ <div class="cell"><img src="images/{{ landing_grid_4_src_d }}" alt="{{ landing_grid_4_alt_d }}"></div>
1077
+ </div>
1078
+
1079
+ <!-- THE GARDEN -->
1080
+ <!-- REPLACE: Garden / outdoor section. Two paragraphs:
1081
+ (1) the principal outdoor features (terrace, pool, outdoor kitchen,
1082
+ pergola, summerhouse — whatever the property actually has;
1083
+ see structure.md "Distinguishing features clearly")
1084
+ (2) the wider garden — lawns, planting, paddocks, screening, outlook.
1085
+ Close para 2 with a one-clause italic if the brief supports one.
1086
+ For properties without a garden complex, repurpose this section as
1087
+ the property's single most distinctive outdoor feature page — keep
1088
+ the eyebrow tied to the actual feature names, never "garden complex". -->
1089
+ <article class="body-block" id="garden">
1090
+ <div class="section-eyebrow">{{ landing_garden_eyebrow }}</div>
1091
+ <h2>{{ landing_garden_headline }}</h2>
1092
+ <p>
1093
+ {{ landing_garden_para_1 }}
1094
+ </p>
1095
+ <p>
1096
+ {{ landing_garden_para_2 }}
1097
+ </p>
1098
+ </article>
1099
+
1100
+ <!-- PHOTO GRID 5 — Garden complex. REPLACE four cells. For properties
1101
+ without a true garden complex, use atmospheric shots: rear elevation,
1102
+ garden-from-distance, twilight exterior, drone aerial of the plot. -->
1103
+ <div class="photo-grid">
1104
+ <div class="cell"><img src="images/{{ landing_grid_5_src_a }}" alt="{{ landing_grid_5_alt_a }}"></div>
1105
+ <div class="cell"><img src="images/{{ landing_grid_5_src_b }}" alt="{{ landing_grid_5_alt_b }}"></div>
1106
+ <div class="cell"><img src="images/{{ landing_grid_5_src_c }}" alt="{{ landing_grid_5_alt_c }}"></div>
1107
+ <div class="cell"><img src="images/{{ landing_grid_5_src_d }}" alt="{{ landing_grid_5_alt_d }}"></div>
1108
+ </div>
1109
+
1110
+ <!-- THE AREA -->
1111
+ <!-- REPLACE: The Area section. Two paragraphs:
1112
+ (1) administrative + transport + nearest amenities (LA, nearest
1113
+ town, train/airport, schools)
1114
+ (2) the qualitative setting — open countryside / village vibe /
1115
+ urban edge / coastal — and signature walks/landmarks.
1116
+ Distil from seller brief Q11-Q14. -->
1117
+ <article class="body-block" id="area">
1118
+ <div class="section-eyebrow">{{ landing_area_eyebrow }}</div>
1119
+ <h2>{{ landing_area_headline }}</h2>
1120
+ <p>
1121
+ {{ landing_area_para_1 }}
1122
+ </p>
1123
+ <p>
1124
+ {{ landing_area_para_2 }}
1125
+ </p>
1126
+ </article>
1127
+
1128
+ <!-- PHOTO GRID 6 — Closing photographic narrative. REPLACE four cells —
1129
+ a wider aerial, an additional internal moment, an open-plan view,
1130
+ and an atmospheric closing shot (often the cover hero re-used here
1131
+ as a book-end). -->
1132
+ <div class="photo-grid">
1133
+ <div class="cell"><img src="images/{{ landing_grid_6_src_a }}" alt="{{ landing_grid_6_alt_a }}"></div>
1134
+ <div class="cell"><img src="images/{{ landing_grid_6_src_b }}" alt="{{ landing_grid_6_alt_b }}"></div>
1135
+ <div class="cell"><img src="images/{{ landing_grid_6_src_c }}" alt="{{ landing_grid_6_alt_c }}"></div>
1136
+ <div class="cell"><img src="images/{{ landing_grid_6_src_d }}" alt="{{ landing_grid_6_alt_d }}"></div>
1137
+ </div>
1138
+
1139
+ <!-- ════════════════ FLOOR PLAN ════════════════ -->
1140
+ <section class="floorplan-section" id="floorplan">
1141
+ <div class="inner">
1142
+ <!-- Floor plan PNG — line-art, copied unchanged from the canonical
1143
+ ({{ property_slug }}-floorplan.png). -->
1144
+ <img src="images/{{ property_slug }}-floorplan.png" alt="The composite floor plan for {{ property_name }}">
1145
+ <!-- REPLACE Floor plan meta — italic h2, lead sentence (total area +
1146
+ plot), and the .areas grid. Six rows MAX. Drop any row that
1147
+ doesn't apply (no acreage → drop Plot; no outbuildings → drop
1148
+ those rows). Excluded outbuildings MUST be listed separately,
1149
+ never folded into the principal home's sq ft. -->
1150
+ <div class="meta">
1151
+ <h2>{{ landing_floorplan_heading }}</h2>
1152
+ <p class="lead">{{ landing_floorplan_lead }}</p>
1153
+ <div class="areas">
1154
+ <div class="row"><span class="k">{{ landing_floorplan_row_1_k }}</span><span class="v">{{ landing_floorplan_row_1_v }}</span></div>
1155
+ <div class="row"><span class="k">{{ landing_floorplan_row_2_k }}</span><span class="v">{{ landing_floorplan_row_2_v }}</span></div>
1156
+ <div class="row"><span class="k">{{ landing_floorplan_row_3_k }}</span><span class="v">{{ landing_floorplan_row_3_v }}</span></div>
1157
+ <div class="row"><span class="k">{{ landing_floorplan_row_4_k }}</span><span class="v">{{ landing_floorplan_row_4_v }}</span></div>
1158
+ <div class="row"><span class="k">{{ landing_floorplan_row_5_k }}</span><span class="v">{{ landing_floorplan_row_5_v }}</span></div>
1159
+ <div class="row"><span class="k">EPC</span><span class="v">{{ epc_rating }}</span></div>
1160
+ </div>
1161
+ </div>
1162
+ </div>
1163
+ </section>
1164
+
1165
+ <!-- ════════════════ KEY FACTS ════════════════ -->
1166
+ <!-- REPLACE Key facts — 15-row three-column grid mirroring the brochure's
1167
+ Material Information Part A. Mark unknowns "TBC"; never invent. The
1168
+ footnote is fixed boilerplate (DMCCA 2024 + CPR 2008) — keep. The
1169
+ keys below match the brochure's mi-rows by intent; substitute the
1170
+ values from property.json. -->
1171
+ <section class="key-facts" id="facts">
1172
+ <h2>Key facts</h2>
1173
+ <div class="grid">
1174
+ <div class="row"><div class="k">Tenure</div><div class="v">{{ mi_tenure }}</div></div>
1175
+ <div class="row"><div class="k">Title</div><div class="v">{{ mi_title_number }}</div></div>
1176
+ <div class="row"><div class="k">Council Tax</div><div class="v">{{ mi_council_tax }}</div></div>
1177
+ <div class="row"><div class="k">Local Authority</div><div class="v">{{ mi_local_authority }}</div></div>
1178
+ <div class="row"><div class="k">Heating</div><div class="v">{{ mi_heating }}</div></div>
1179
+ <div class="row"><div class="k">Electricity</div><div class="v">{{ mi_electricity }}</div></div>
1180
+ <div class="row"><div class="k">Water</div><div class="v">{{ mi_water }}</div></div>
1181
+ <div class="row"><div class="k">Sewerage</div><div class="v">{{ mi_sewerage }}</div></div>
1182
+ <div class="row"><div class="k">Broadband</div><div class="v">{{ mi_broadband }}</div></div>
1183
+ <div class="row"><div class="k">Mobile</div><div class="v">{{ mi_mobile }}</div></div>
1184
+ <div class="row"><div class="k">Flood Risk</div><div class="v">{{ landing_flood_summary }}</div></div>
1185
+ <div class="row"><div class="k">Construction</div><div class="v">{{ mi_construction }}</div></div>
1186
+ <div class="row"><div class="k">Conservation Area</div><div class="v">{{ mi_conservation }}</div></div>
1187
+ <div class="row"><div class="k">Listed Building</div><div class="v">{{ mi_listed }}</div></div>
1188
+ <div class="row"><div class="k">UPRN</div><div class="v">{{ mi_uprn }}</div></div>
1189
+ <div class="footnote">Material information provided in accordance with the Consumer Protection from Unfair Trading Regulations 2008 and the Digital Markets, Competition and Consumers Act 2024.</div>
1190
+ </div>
1191
+ </section>
1192
+
1193
+ </main>
1194
+
1195
+ <!-- ════════════════ CTA STRIP ════════════════ -->
1196
+ <!-- REPLACE CTA strip — italic h2 (canonical "Interested? Let's talk." or
1197
+ property-specific variant), three CTAs in order: tel:, mailto: enquiry,
1198
+ mailto: request-viewing (the rightmost, .solid). Drop the tel: only if
1199
+ the agent's number isn't published. -->
1200
+ <section class="cta-strip">
1201
+ <h2>{{ landing_cta_headline }}</h2>
1202
+ <div class="cta-row">
1203
+ <a href="tel:{{ office_phone_tel }}">{{ office_phone }}</a>
1204
+ <a href="mailto:{{ office_email }}?subject={{ email_subject_enquiry }}">{{ office_email }}</a>
1205
+ <a href="mailto:{{ office_email }}?subject={{ email_subject_viewing }}" class="solid">Request viewing</a>
1206
+ </div>
1207
+ </section>
1208
+
1209
+ <!-- ════════════════ FOOTER ════════════════ -->
1210
+ <!-- REPLACE Footer — agent block (label, name with first name in <em>,
1211
+ agency · branch + address + tel/email), legal disclaimer, colophon.
1212
+ Disclaimer is mostly boilerplate; keep the CGI/AI sentence if any
1213
+ image in the brochure was AI-staged. -->
1214
+ <footer>
1215
+ <div class="inner">
1216
+ <div class="agent">
1217
+ <div class="label">The Agent</div>
1218
+ <div class="name"><em>{{ agent_first_name }}</em> {{ agent_surname }}</div>
1219
+ {{ brand_name }} · {{ brand_town }}<br>
1220
+ {{ office_address_line_1 }}<br>
1221
+ {{ office_address_line_2 }}<br>
1222
+ {{ office_phone }} · {{ office_email }}
1223
+ </div>
1224
+ <p class="legal">
1225
+ These particulars, whilst believed to be accurate, are set out as a general outline only for guidance and do not constitute any part of an offer or contract. Intending purchasers should not rely on them as statements or representations of fact, but must satisfy themselves by inspection or otherwise as to their accuracy. All measurements are approximate and floor plans are drawn to indicative scale. Some images may include CGI or AI enhancements for illustrative purposes.
1226
+ </p>
1227
+ <div class="colophon">
1228
+ <span>{{ property_name }} · {{ address_line_1 }}, {{ locality }}</span>
1229
+ <span>© {{ brand_year }} {{ brand_name }}</span>
1230
+ </div>
1231
+ </div>
1232
+ </footer>
1233
+
1234
+ <script>
1235
+ // Show sticky sub-nav after scrolling past the hero
1236
+ (function() {
1237
+ const subnav = document.getElementById('subnav');
1238
+ const hero = document.querySelector('.hero');
1239
+ function update() {
1240
+ const heroBottom = hero.getBoundingClientRect().bottom;
1241
+ if (heroBottom < 0) subnav.classList.add('visible');
1242
+ else subnav.classList.remove('visible');
1243
+ }
1244
+ window.addEventListener('scroll', update, { passive: true });
1245
+ update();
1246
+ })();
1247
+
1248
+ // Hamburger / drawer
1249
+ (function() {
1250
+ const burger = document.querySelector('.burger');
1251
+ const drawer = document.getElementById('drawer');
1252
+ if (!burger || !drawer) return;
1253
+
1254
+ // Inject backdrop sibling (created lazily so the markup stays clean)
1255
+ const backdrop = document.createElement('div');
1256
+ backdrop.className = 'drawer-backdrop';
1257
+ document.body.appendChild(backdrop);
1258
+
1259
+ function open() {
1260
+ drawer.classList.add('open');
1261
+ backdrop.classList.add('open');
1262
+ document.body.classList.add('drawer-open');
1263
+ burger.setAttribute('aria-expanded', 'true');
1264
+ drawer.setAttribute('aria-hidden', 'false');
1265
+ }
1266
+ function close() {
1267
+ drawer.classList.remove('open');
1268
+ backdrop.classList.remove('open');
1269
+ document.body.classList.remove('drawer-open');
1270
+ burger.setAttribute('aria-expanded', 'false');
1271
+ drawer.setAttribute('aria-hidden', 'true');
1272
+ }
1273
+ burger.addEventListener('click', () => {
1274
+ drawer.classList.contains('open') ? close() : open();
1275
+ });
1276
+ backdrop.addEventListener('click', close);
1277
+ document.querySelector('.drawer-close').addEventListener('click', close);
1278
+ // Close on link click (so clicking a section link also closes the drawer)
1279
+ drawer.querySelectorAll('a').forEach(a => a.addEventListener('click', close));
1280
+ // Close on Escape
1281
+ document.addEventListener('keydown', e => {
1282
+ if (e.key === 'Escape' && drawer.classList.contains('open')) close();
1283
+ });
1284
+ })();
1285
+ </script>
1286
+
1287
+ </body>
1288
+ </html>