All brand colors are CSS custom properties defined at the top of assets/css/style.css:
:root{
--primary:#315C45;
--primary-dark:#214334;
--secondary:#A47C52;
--accent:#C9824B;
--sage:#A9B9A2;
--cream:#F7F3EA;
--sand:#E8DDCB;
--text:#243129;
--muted:#6F786F;
--border:#DCD8CE;
}
Dark mode overrides live in the same file under [data-bs-theme="dark"], plus refinements in assets/css/dark-mode.css. Change a variable once and it updates every component site-wide.
Two font families are loaded from Google Fonts in each page's <head>: Playfair Display (headings, --font-display) and Manrope (body/UI, --font-body). To swap a typeface, update the Google Fonts <link> and the corresponding CSS variable in style.css.
Handled by assets/js/main.js (ThemeManager). It stores the choice (light / dark / system) under the localStorage key ayurveda-theme and sets data-bs-theme on <html>.
Toggled the same way via DirectionManager, storing ltr/rtl under the localStorage key ayurveda-dir and setting the dir attribute on <html>. Component-level RTL overrides live in assets/css/rtl.css; most spacing already uses logical CSS properties (margin-inline, inset-inline) so it mirrors automatically.
Each product card in shop.html is a self-contained block with data-category, data-name, data-price, data-rating and data-instock attributes that shop.js reads for filtering/sorting. Duplicate a card block, edit its content and data attributes, and it's automatically included in filtering.
Duplicate a .journal-card block in blog.html, update the image, category, title and meta line, then create a matching blog-details.html copy for the full article.
The booking form in consultation.html is plain HTML with client-side validation only. Connect it to a real scheduling backend by replacing the TODO comment in assets/js/booking.js and main.js's FormValidation.handleSubmit with a real API call.
Every form has data-validate and a plain action="#". To use Formspree, set action to your form endpoint and add method="POST". For Netlify Forms, add data-netlify="true" and a hidden form-name input matching the form's name attribute.
The map on contact.html is a placeholder block. Replace it with an embedded iframe using your Google Maps API key, or a static map image.
Newsletter forms (homepage, blog article, coming-soon page) are Mailchimp/ConvertKit-ready: set the form's action to your provider's POST endpoint and match input name attributes to their expected fields.
Add-to-cart and buy-now buttons currently update a demo localStorage cart and show a toast. Replace CommerceState.addToCart in main.js with calls to your checkout/payment provider (Stripe, Razorpay, etc.).