# Integration Notes — CFS Homepage

Technical notes for the Drupal 10 theme developer integrating the HTML/Tailwind components.

---

## 1. Blocks vs Paragraphs vs Views — Decision Guide

### Use Blocks for:
- **Utility Bar** (01) — site-wide secondary navigation, managed as a menu block
- **Main Navigation** (02) — Drupal core menu block + custom CTA block
- **CTA Action Buttons** (10) — static 3-link row, custom block type
- **Callback Form** (14) — Webform block placed in content or sidebar region
- **Sticky Bar** (16) — fixed-position custom block in `page_bottom` region

**Rationale:** These sections are either site-wide (not page-specific) or are simple enough that a Block type with a few link/text fields is sufficient. They do not require per-item content management.

### Use Paragraphs for:
- **Hero Banner** (03) — complex layout with multiple field types (text, image, stats repeater, form reference)
- **Specialities Tabs** (05) — tab items vary per installation; Paragraph repeater gives editors control
- **Why Us** (07) — mixed content (stat items + images) best modeled as a Paragraph with nested items
- **Journey Timeline** (08) — milestone items are a classic Paragraph repeater use case
- **International Patients** (11) — split-content layout; image + rich text as a reusable Paragraph type
- **Accreditations** (12) — if not enough items to justify a content type, use Paragraph repeater

**Rationale:** Paragraphs are ideal for page-specific, editorially controlled sections that need flexible field structures. They attach to the Homepage node and render in order.

### Use Views for:
- **Centres Listing** (04) — Centre nodes filtered/sorted dynamically
- **Doctor Cards** (06) — Doctor nodes; two View displays (featured + row)
- **Testimonials** (09) — Testimonial nodes with possible taxonomy filtering
- **Blogs** (13) — Article/Blog nodes, standard teaser grid

**Rationale:** Content types that will be managed independently, require filtering/sorting, or will appear on multiple pages should be Views-driven. This decouples content entry from layout.

---

## 2. JS Interaction Hooks (Data Attributes)

The following `data-*` attributes are used as JS hooks. Do not remove them when porting to Twig templates.

| Attribute | Component | Behaviour |
|---|---|---|
| `data-tab` | 05-specialities | Identifies tab trigger buttons; value matches `data-panel` on content panels |
| `data-panel` | 05-specialities | Content panel toggled by matching `data-tab` value |
| `data-accordion` | 05-specialities (mobile) | Accordion trigger for mobile specialty items |
| `data-slider` | 06-doctor-cards, 09-testimonials | Marks slider containers; JS initialises scroll/carousel behaviour |
| `data-slide-prev` / `data-slide-next` | 06-doctor-cards, 09-testimonials | Navigation arrow buttons for sliders |
| `data-menu-toggle` | 02-main-nav | Hamburger button that toggles the mobile menu open/close |
| `data-sticky` | 16-sticky-bar | Root element of the sticky bar; JS may add/remove classes based on scroll position |

**Note:** All JS is vanilla (no jQuery, no external library dependency). Scripts are self-contained in each component's `<script>` block. When porting to Drupal, consolidate these scripts into the theme's JS file (e.g., `js/cfs-homepage.js`) and attach via `hook_page_attachments` or a Drupal library definition.

---

## 3. Special Twig Handling

### Menu rendering (02-main-nav)
- Replace the static `<ul>` nav with `{{ menus.main }}` rendered via `menu.html.twig`.
- The CTA "Book Appointment" button is a separate block; pass it as a Twig variable or place it as a block in the header region template.

### Dynamic field loops (04, 05, 06, 08, 09, 12, 13)
- Static `<div>` card/item repetitions must be replaced with `{% for item in items %}` loops.
- Use Drupal's field template system (`field--*.html.twig`) or Views row templates (`views-view-fields--*.html.twig`) for output.

### Image handling
- All `<img src="...">` tags should use `{{ file_url(node.field_image.entity.uri.value) }}` or the equivalent responsive image style function.
- Use Drupal's Responsive Image module with image styles matching the breakpoints listed in Section 6.

### Forms (14-callback-form)
- Replace the static HTML form with `{{ drupal_entity('webform', 'callback_form') }}` or the Webform block render.
- Preserve the surrounding wrapper `<div>` classes for layout; only the inner `<form>` element changes.

### Sticky bar visibility (16-sticky-bar)
- The sticky bar has two visual states: desktop (chat bubble icon) and mobile (action task bar).
- Both states are in the same template; visibility is controlled by Tailwind's `hidden md:flex` / `flex md:hidden` pattern — no Twig conditionals needed.

---

## 4. Font Loading Requirements

The design uses the following fonts, loaded via Google Fonts:

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,300;0,400;0,700;0,900;1,700&family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
```

- **Poppins** (CSS var: `--font-heading`) — section headings, navigation, buttons (weights: 300, 400, 500, 600, 700)
- **Lato** (CSS var: `--font-body`) — body text, form labels, descriptions (weights: 300, 400, 700, 900; italic 700)

**Drupal integration:** Add the Google Fonts `<link>` tags to the theme's `html.html.twig` template, or declare them in `THEMENAME.libraries.yml` as an external CSS library attached to all pages:

```yaml
global-fonts:
  css:
    theme:
      'https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,300;0,400;0,700;0,900;1,700&family=Poppins:wght@300;400;500;600;700&display=swap': { type: external, minified: true }
```

---

## 5. Tailwind Usage (CDN — no build step, no config)

The project uses the **Tailwind Play CDN** (`https://cdn.tailwindcss.com/3.4.16`), loaded in each
page's `<head>`. Classes resolve in-browser at runtime — **there is no build step, no
`tailwind.config.js`, and no compiled CSS**. This reflects the client's request to drop the
Tailwind config (see `docs/homepage-deliverables-amendment.md`, which amends spec §3).

Design values are written as **arbitrary-value utility classes** directly in the markup rather
than via configured theme tokens. Common values used across the page:

| Design value | Class example |
|---|---|
| Primary navy `#2b286f` | `bg-[#2b286f]`, `text-[#2b286f]` |
| Accent yellow `#ffcb05` | `bg-[#ffcb05]` |
| Body text `#1a1a1a` / dark `#434343` / strip gray `#d9d9d9` | `text-[#1a1a1a]`, `text-[#434343]`, `bg-[#d9d9d9]` |
| Section title 69px / line-height 81px | `text-[69px] leading-[81px]` |
| Card heading 29px, subtitle 21px, nav 15px | `text-[29px]`, `text-[21px]`, `text-[15px]` |
| Radii: 7px card, 13px lg, 17px card-lg, 30px section | `rounded-[7px]`, `rounded-[13px]`, `rounded-[17px]`, `rounded-[30px]` |
| Heading / body fonts | `font-['Poppins',sans-serif]` / `font-['Lato',sans-serif]` |

Rules that can't be expressed as utilities (the CMS-friendly `cms-*` classes, accordion/slider
animation, hover states, etc.) live in **`css/custom.css`**, linked from every page. That file
also defines the two layout-container CSS variables, used across the markup via
`max-w-[var(--container-site)]` / `max-w-[var(--container-inner)]`:

```css
:root {
  --container-site: 1440px;   /* outer page max-width */
  --container-inner: 1380px;  /* inner content max-width */
}
```

> **For the Drupal theme:** there is nothing to compile. Either keep the same arbitrary-value
> approach, or (if the theme prefers tokens) port these values into the theme's own
> `theme.extend` / SCSS token set. The legacy `css/input.css` and `css/output.css` (an old
> Tailwind v4 `@theme` + `@tailwindcss/cli` build) are **dead artifacts** — no page links them
> and they can be deleted.

---

## 6. Responsive Breakpoint Strategy

All components are built mobile-first. The breakpoint strategy follows Tailwind's defaults with the following usage conventions:

| Breakpoint | Tailwind Prefix | Viewport | Usage in this project |
|---|---|---|---|
| Mobile (base) | (none) | < 640px | Single column, stacked layout, accordion menus |
| Small | `sm:` | >= 640px | Slight padding/font adjustments |
| Medium | `md:` | >= 768px | Two-column layouts begin, hamburger hides |
| Large | `lg:` | >= 1024px | Full desktop grid, utility bar visible, multi-column |
| XL | `xl:` | >= 1280px | Max-width container locks at 1280px |

**Key patterns used:**
- Navigation: hamburger at mobile → full horizontal menu at `md:`
- Hero: stacked (image below text) at mobile → side-by-side at `lg:`
- Centres grid: 1 col → 2 col (`sm:`) → 3 col (`lg:`) → 4 col (`xl:`)
- Blogs: compact list at mobile → card grid at `md:`
- Utility bar: `hidden lg:flex` — not rendered in mobile DOM flow
- Sticky bar: separate layout per breakpoint in same element using `hidden`/`flex` pairs

---

## 7. Deviations from Figma Design

The following intentional deviations were made during implementation:

| Section | Figma Spec | Implementation | Reason |
|---|---|---|---|
| 02-main-nav | Mega-dropdown on hover | Simple dropdown via CSS + JS toggle | Mega-menu requires content data not available at HTML prototype stage; structure is in place for Drupal menu blocks |
| 03-hero-banner | Animated counter for stats | Static numbers | Animation can be added via IntersectionObserver in production; kept static for prototype clarity |
| 05-specialities | Figma shows desktop-only tabs | Mobile accordion added | Accessibility and UX requirement; accordion mirrors tab content, no data duplication |
| 06-doctor-cards | Custom carousel library implied | Vanilla JS scroll-snap slider | Avoids external dependency; Swiper.js can replace if richer features needed |
| 09-testimonials | Auto-advancing carousel | Manual navigation only | Auto-advance can cause accessibility issues; manual is WCAG-safer default |
| 13-blogs | Figma shows 3-col grid only | 1-col list on mobile added | Responsive requirement not in Figma; list layout derived from design system patterns |
| 15-footer | Single footer layout | Sub-regions split into logical blocks | Drupal region architecture requires this split; visual output matches Figma |
