# Praxis Visual Parity Pass — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Make the Zola staging site visually match the live Grav site by restoring the markup contracts the theme CSS expects (footer, section-title pattern, single-page-title banner, navbar logo, service-card/team-preview markup).

**Architecture:** Add two Tera macros (`section_title`, `page_title`) for patterns used on home and subpages, one partial (`footer.html`) reading from `config.extra`, one new page template (`contact.html`). Modify five existing templates and two content files. No SCSS changes — markup conforms to the existing theme.

**Tech Stack:** Zola 0.22.x, Tera templates, TOML config, Bootstrap 3 grid (verbatim from theme).

**Spec reference:** `docs/specs/2026-05-20-praxis-visual-parity-design.md`

---

## File Structure

**New files:**
- `static/images/logo.png` — copied from `orig/user/themes/praxis/img/Logo_Praxis_white_H110.png`
- `templates/macros/section_title.html` — `section_title(title, anchor="")` macro
- `templates/macros/page_title.html` — `page_title(title)` macro
- `templates/partials/footer.html` — three-column footer + copyright bar
- `templates/contact.html` — page template reading address/hours from `config.extra`

**Modified files:**
- `config.toml` — add `[extra]` keys: `email`, `address_street`, `address_zip_city`, `keywords`, `[[extra.opening_hours]]` array
- `templates/base.html` — include footer partial
- `templates/partials/head.html` — title format + keywords meta
- `templates/partials/navbar.html` — logo image + Home link + active-state check
- `templates/section.html` — use page_title and section_title macros (with anchor)
- `templates/page.html` — use page_title macro
- `templates/index.html` — section_title macros, gray-bg class, service-card thumbnail markup, team-preview figure markup, news section wrapper
- `content/news.md` — fix `<td>...</th>` table tag mismatch
- `content/contact.md` — strip hardcoded address/phone/email (moves to config), switch template

**Validation per task:**
- `zola build` must succeed (no template errors)
- `grep` the rendered output for expected class names / structure where applicable

---

## Task 1: Copy logo image asset

**Files:**
- Create: `static/images/logo.png` (binary, copied from `orig/`)

- [ ] **Step 1: Copy the logo PNG into static assets**

```bash
cp orig/user/themes/praxis/img/Logo_Praxis_white_H110.png static/images/logo.png
```

- [ ] **Step 2: Verify the file exists and is non-zero**

```bash
ls -l static/images/logo.png
```
Expected: a non-zero PNG file.

- [ ] **Step 3: Build to confirm asset is picked up**

```bash
zola build
test -f public/images/logo.png && echo OK
```
Expected: `OK`.

- [ ] **Step 4: Commit**

```bash
git add static/images/logo.png
git commit -m "feat: add practice logo asset"
```

---

## Task 2: Extend config.toml with footer/contact data

**Files:**
- Modify: `config.toml` (add to existing `[extra]` block)

- [ ] **Step 1: Append new extra keys**

After the existing `fax = "0202-730017"` line in `[extra]`, append:

```toml
email = "info@praxis-am-lienhardplatz.de"
phone_e164 = "+49202730738"
address_street = "Kaiserstraße 23"
address_zip_city = "42329 Wuppertal"
keywords = "Arzt, Hausarzt, Allgemeinmedizin, Innere Medizin, Internist, Kardiologie, Praxis, Gemeinschaftspraxis, Vohwinkel, Lienhardplatz, Krey, Riemann, Malyga, Corona, COVID-19, Corona-Test"

[[extra.opening_hours]]
label = "Montag-Freitag"
time = "08:00-12:00"

[[extra.opening_hours]]
label = "Montag, Dienstag, Donnerstag"
time = "15:00-18:00"
```

- [ ] **Step 2: Verify build still succeeds**

```bash
zola build
```
Expected: `Done in ...ms.` (no errors).

- [ ] **Step 3: Commit**

```bash
git add config.toml
git commit -m "feat: add footer/contact data to config extra"
```

---

## Task 3: Create section_title macro

**Files:**
- Create: `templates/macros/section_title.html`

- [ ] **Step 1: Write the macro**

```html
{% macro section_title(title, anchor="") %}
<section class="section-title">
  <div class="container text-center">
    {%- if anchor %}
    <div class="anchor" id="{{ anchor }}">
      <h2>{{ title }}</h2>
    </div>
    {%- else %}
    <h2>{{ title }}</h2>
    {%- endif %}
    <span class="bordered-icon"><i class="fa fa-circle-thin"></i></span>
  </div>
</section>
{% endmacro %}
```

- [ ] **Step 2: Verify the file syntax by referencing it from index.html temporarily (sanity check)**

Add at top of `templates/index.html`:
```html
{% import "macros/section_title.html" as section_title %}
```

Then run `zola build`. Expected: succeeds. Revert the temporary edit before commit; final usage comes in later tasks.

```bash
git checkout templates/index.html
```

- [ ] **Step 3: Commit**

```bash
git add templates/macros/section_title.html
git commit -m "feat: add section_title macro with optional anchor"
```

---

## Task 4: Create page_title macro

**Files:**
- Create: `templates/macros/page_title.html`

- [ ] **Step 1: Write the macro**

```html
{% macro page_title(title) %}
<section class="single-page-title">
  <div class="container text-center">
    <h2>{{ title }}</h2>
  </div>
</section>
{% endmacro %}
```

- [ ] **Step 2: Build to confirm no syntax error**

```bash
zola build
```
Expected: succeeds.

- [ ] **Step 3: Commit**

```bash
git add templates/macros/page_title.html
git commit -m "feat: add page_title macro for subpage banner"
```

---

## Task 5: Create footer partial

**Files:**
- Create: `templates/partials/footer.html`

- [ ] **Step 1: Write the partial**

```html
<footer class="footer">
  <div class="footer-widget-section">
    <div class="container text-center">
      <div class="row">
        <div class="col-sm-4 footer-block">
          <div class="footer-widget widget_text">
            <h3>Sprechzeiten</h3>
            {% for h in config.extra.opening_hours %}
              {{ h.label }}<br>{{ h.time }}{% if not loop.last %}<p>{% endif %}
            {% endfor %}
          </div>
        </div>
        <div class="col-sm-4 footer-block">
          <div class="footer-widget widget_text">
            <h3>Kontakt</h3>
            Telefon <a href="tel:{{ config.extra.phone_e164 }}">{{ config.extra.phone }}</a><br>
            Telefax {{ config.extra.fax }}<br>
            <br>
            <a href="mailto:{{ config.extra.email }}">{{ config.extra.email }}</a>
          </div>
        </div>
        <div class="col-sm-4 footer-block">
          <div class="footer-widget widget_text">
            <h3>Hausanschrift</h3>
            {{ config.extra.address_street }}<br>
            {{ config.extra.address_zip_city }}<p>
            <a href="/impressum#Impressum">Impressum</a><br>
            <a href="/impressum#Datenschutz">Datenschutz</a>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="copyright-section">
    <div class="container clearfix">
      <span class="copytext">Copyright &copy; {{ now() | date(format='%Y') }} | {{ config.extra.practice_name }}</span>
      <ul class="list-inline pull-right">
        <li><a href="/">Home</a></li>
      </ul>
    </div>
  </div>
</footer>
```

- [ ] **Step 2: Build (footer is not yet included anywhere, so this just checks isolated syntax — build should still succeed)**

```bash
zola build
```
Expected: succeeds.

- [ ] **Step 3: Commit**

```bash
git add templates/partials/footer.html
git commit -m "feat: add footer partial sourced from config.extra"
```

---

## Task 6: Include footer in base.html

**Files:**
- Modify: `templates/base.html`

- [ ] **Step 1: Insert the footer include before the script block**

Before the line `<script src="/js/jquery-2.1.4.min.js"></script>`, add:

```html
    {% include "partials/footer.html" %}

```

The final relevant block becomes:
```html
        </div>
    </div>

    {% include "partials/footer.html" %}

    <script src="/js/jquery-2.1.4.min.js"></script>
```

- [ ] **Step 2: Build and verify footer renders on home page**

```bash
zola build
grep -c 'footer-widget-section' public/index.html
```
Expected: `1` (one occurrence).

- [ ] **Step 3: Verify footer renders on a subpage too**

```bash
grep -c 'footer-widget-section' public/contact/index.html
```
Expected: `1`.

- [ ] **Step 4: Commit**

```bash
git add templates/base.html
git commit -m "feat: include footer partial in base layout"
```

---

## Task 7: Update head.html — title format and keywords meta

**Files:**
- Modify: `templates/partials/head.html`

- [ ] **Step 1: Replace the title logic**

Replace lines 1-6 of `templates/partials/head.html`:

```html
{% if page %}
  {% set page_title = page.title %}
{% elif section %}
  {% set page_title = section.title %}
{% endif %}
<title>{% if page_title %}{{ page_title | safe }} | {% endif %}{{ config.title | safe }}</title>
```

with:

```html
{%- set is_home = (section and section.path == '/_index.md') -%}
{%- if page %}{% set page_title = page.title %}{% elif not is_home %}{% set page_title = section.title %}{% endif -%}
{%- set site_title = config.title ~ " - " ~ config.extra.doctors -%}
<title>{% if page_title %}{{ page_title | safe }} | {% endif %}{{ site_title | safe }}</title>
```

- [ ] **Step 2: Add the keywords meta after the description**

After the line `<meta name="description" content="{{ config.description | safe }}">`, add:

```html
<meta name="keywords" content="{{ config.extra.keywords | safe }}">
```

- [ ] **Step 3: Build and verify title on home is the brand line only (no leading prefix)**

```bash
zola build
grep '<title>' public/index.html
```
Expected:
```
<title>Praxis am Lienhardplatz - Dr. Oliver Riemann, Dr. Angela Krey, Christian Malyga</title>
```

- [ ] **Step 4: Verify subpage title has page prefix**

```bash
grep '<title>' public/services/index.html
```
Expected:
```
<title>Leistungen | Praxis am Lienhardplatz - Dr. Oliver Riemann, Dr. Angela Krey, Christian Malyga</title>
```

- [ ] **Step 5: Verify keywords meta present**

```bash
grep 'name="keywords"' public/index.html
```
Expected: one match containing "Arzt, Hausarzt, ...".

- [ ] **Step 6: Commit**

```bash
git add templates/partials/head.html
git commit -m "feat: home title brand line, subpage prefix, keywords meta"
```

---

## Task 8: Update navbar.html — logo image, Home link, active state

**Files:**
- Modify: `templates/partials/navbar.html`

- [ ] **Step 1: Replace the navbar-brand line**

Replace line 11:
```html
      <a class="navbar-brand" href="/">{{ config.title }}</a>
```

with:
```html
      <a class="navbar-brand" href="/">
        <img src="/images/logo.png" alt="{{ config.title }}">
      </a>
```

- [ ] **Step 2: Add Home as the first menu item**

Replace lines 14-16 (the opening of the nav list):
```html
    <div class="collapse navbar-collapse" id="navbar-collapse-1">
      <ul class="nav navbar-nav navbar-right">
        {% set top = get_section(path="_index.md") %}
```

with:
```html
    <div class="collapse navbar-collapse" id="navbar-collapse-1">
      <ul class="nav navbar-nav navbar-right main-nav">
        <li class="{% if current_path == '/' %}active{% endif %}">
          <a href="/">Home</a>
        </li>
        {% set top = get_section(path="_index.md") %}
```

- [ ] **Step 3: Build and verify logo image src**

```bash
zola build
grep 'navbar-brand' public/index.html
```
Expected: line containing `<a class="navbar-brand" href="/">` followed (on next line) by `<img src="/images/logo.png"`.

- [ ] **Step 4: Verify Home link appears**

```bash
grep -A1 'main-nav' public/index.html | grep 'Home'
```
Expected: a match for `<a href="/">Home</a>`.

- [ ] **Step 5: Verify Home is marked active on the home page**

```bash
grep -B1 '<a href="/">Home</a>' public/index.html | grep active
```
Expected: line containing `class="active"`.

- [ ] **Step 6: Verify Home is NOT marked active on a subpage**

```bash
grep -B1 '<a href="/">Home</a>' public/services/index.html | grep active
```
Expected: empty output (no match).

- [ ] **Step 7: Commit**

```bash
git add templates/partials/navbar.html
git commit -m "feat: navbar logo image, Home link, active-state per route"
```

---

## Task 9: Update section.html — page_title and section_title with anchors

**Files:**
- Modify: `templates/section.html`

- [ ] **Step 1: Replace the entire template**

Overwrite `templates/section.html` with:

```html
{% extends "base.html" %}
{% import "macros/section_title.html" as st %}
{% import "macros/page_title.html" as pt %}

{% block content %}

{{ pt::page_title(title=section.title) }}

{% if section.content %}
<section class="ptb-100">
  <div class="container">
    <div class="row"><div class="col-md-12">{{ section.content | safe }}</div></div>
  </div>
</section>
{% endif %}

{% for page in section.pages %}
<section class="text ptb-text">
  {{ st::section_title(title=page.title, anchor=page.extra.anchor | default(value=page.slug)) }}
  <div class="container">
    <div class="row">
      {{ page.content | safe }}
    </div>
  </div>
</section>
{% endfor %}

{% endblock %}
```

- [ ] **Step 2: Build and verify single-page-title appears on /services**

```bash
zola build
grep -c 'single-page-title' public/services/index.html
```
Expected: `1`.

- [ ] **Step 3: Verify section_title pattern appears for each sub-page on /services**

```bash
grep -c 'class="section-title"' public/services/index.html
```
Expected: `6` (six service sub-pages: HV, Corona, Vorsorge, Diagnostik, Kardio, Diabetologie).

- [ ] **Step 4: Verify anchors are present**

```bash
grep 'class="anchor" id=' public/services/index.html
```
Expected: six lines, e.g. `<div class="anchor" id="HV">`, `<div class="anchor" id="Corona">`, etc.

- [ ] **Step 5: Verify the same works for /team**

```bash
grep -c 'single-page-title\|class="section-title"' public/team/index.html
```
Expected: at least `3` (one page-title + sub-section count).

- [ ] **Step 6: Commit**

```bash
git add templates/section.html
git commit -m "feat: section template uses page_title and anchored section_title macros"
```

---

## Task 10: Update page.html — page_title macro

**Files:**
- Modify: `templates/page.html`

- [ ] **Step 1: Replace the entire template**

Overwrite `templates/page.html` with:

```html
{% extends "base.html" %}
{% import "macros/page_title.html" as pt %}

{% block content %}

{{ pt::page_title(title=page.title) }}

<section class="ptb-100">
  <div class="container">
    <div class="row">
      <div class="col-md-12">
        {{ page.content | safe }}
      </div>
    </div>
  </div>
</section>

{% endblock %}
```

- [ ] **Step 2: Build and verify page_title appears on /impressum**

```bash
zola build
grep -c 'single-page-title' public/impressum/index.html
```
Expected: `1`.

- [ ] **Step 3: Verify the inner h2 is the page title**

```bash
grep -A2 'single-page-title' public/impressum/index.html | grep '<h2>'
```
Expected: a line containing `<h2>Impressum</h2>` (or whatever the page title is).

- [ ] **Step 4: Commit**

```bash
git add templates/page.html
git commit -m "feat: page template uses page_title macro"
```

---

## Task 11: Update index.html — section_title macros and restored markup

**Files:**
- Modify: `templates/index.html`

- [ ] **Step 1: Add the section_title import**

At the top, after `{% import "macros/image.html" as image %}`, add:

```html
{% import "macros/section_title.html" as st %}
```

- [ ] **Step 2: Replace the News section**

Replace lines (the News block currently starting with `{# ───────── News ───────── #}`):

```html
{# ───────── News (loaded from content/news.md) ───────── #}
{% set news_page = get_page(path="news.md") %}
<section class="ptb-100" id="aktuelles">
  <div class="container">
    {{ news_page.content | safe }}
  </div>
</section>
```

with:

```html
{# ───────── News (loaded from content/news.md) ───────── #}
{% set news_page = get_page(path="news.md") %}
<section class="news-text ptb-text" id="aktuelles">
  {{ st::section_title(title="Aktuelles") }}
  <div class="container">
    <div class="row">
      {{ news_page.content | safe }}
    </div>
  </div>
</section>
```

- [ ] **Step 3: Replace the About columns section**

Replace the About columns block:

```html
{# ───────── About columns ───────── #}
<section class="ptb-100">
  <div class="container">
    <div class="row">
      {% for col in section.extra.about_columns %}
        <div class="col-md-6">{{ col.text | markdown(inline=false) | safe }}</div>
      {% endfor %}
    </div>
  </div>
</section>
```

with:

```html
{# ───────── About columns ───────── #}
<section class="about-text ptb-100">
  {{ st::section_title(title="Willkommen in unserer Praxis am Lienhardplatz") }}
  <div class="container">
    <div class="row">
      {% for col in section.extra.about_columns %}
        <div class="col-md-6">{{ col.text | markdown(inline=false) | safe }}</div>
      {% endfor %}
    </div>
  </div>
</section>
```

- [ ] **Step 4: Replace the Service grid section**

Replace the entire service grid block:

```html
{# ───────── Service grid ───────── #}
<section class="ptb-100 bg-gray">
  <div class="container">
    <h2 class="text-center">Unsere Leistungen</h2>
    <div class="row">
      {% for card in section.extra.service_cards %}
        <div class="col-md-4 col-sm-6">
          <a href="{{ card.url }}" class="service-card">
            {{ image::render(src=card.image, width=600, alt=card.title) }}
            <h3>{{ card.title }}</h3>
            <p>{{ card.description }}</p>
          </a>
        </div>
      {% endfor %}
    </div>
  </div>
</section>
```

with:

```html
{# ───────── Service grid ───────── #}
<section class="x-services ptb-100 gray-bg">
  {{ st::section_title(title="Unsere Leistungen") }}
  <div class="container">
    {% for card in section.extra.service_cards %}
      {% if loop.index0 % 2 == 0 %}<div class="row">{% endif %}
        <div class="col-md-6">
          <div class="thumbnail clearfix">
            <a href="{{ card.url | safe }}">
              {{ image::render(src=card.image, width=600, alt=card.title) }}
            </a>
            <div class="caption">
              <h3><a href="{{ card.url | safe }}">{{ card.title }}</a></h3>
              <p>{{ card.description }}</p>
            </div>
          </div>
        </div>
      {% if loop.index0 % 2 == 1 or loop.last %}</div>{% endif %}
    {% endfor %}
  </div>
</section>
```

- [ ] **Step 5: Replace the Team preview section**

Replace the team-preview block:

```html
{# ───────── Team preview ───────── #}
{% if section.extra.team_preview %}
<section class="ptb-100">
  <div class="container">
    <h2 class="text-center">Unser Team</h2>
    <div class="row">
      {% for member in section.extra.team_preview %}
        <div class="col-md-4 col-sm-6 text-center">
          <a href="{{ member.url }}">
            {{ image::render(src=member.image, width=400, alt=member.name) }}
            <h4>{{ member.name }}</h4>
            <p>{{ member.position }}</p>
          </a>
        </div>
      {% endfor %}
    </div>
  </div>
</section>
{% endif %}
```

with:

```html
{# ───────── Team preview ───────── #}
{% if section.extra.team_preview %}
<section class="team ptb-100">
  {{ st::section_title(title="Ihr Ärzteteam") }}
  <div class="container">
    <div class="row">
      {% for member in section.extra.team_preview %}
        <div class="col-md-4">
          <figure class="thumbnail">
            <a href="{{ member.url | safe }}">
              {{ image::render(src=member.image, width=400, alt=member.name) }}
            </a>
            <figcaption class="caption text-center">
              <h3>{{ member.name }} -
                <small>{{ member.position }}</small>
              </h3>
            </figcaption>
          </figure>
        </div>
      {% endfor %}
    </div>
  </div>
</section>
{% endif %}
```

- [ ] **Step 6: Build and run the visual-parity checks on the home page**

```bash
zola build
# Aktuelles heading via macro
grep -c '<h2>Aktuelles</h2>' public/index.html
# Expected: 1

# Willkommen heading via macro
grep -c 'Willkommen in unserer Praxis am Lienhardplatz' public/index.html
# Expected: >= 1 (heading; carousel-caption has it too — exact count not asserted)

# bordered-icon appears 4x (news, about, services, team)
grep -c 'bordered-icon' public/index.html
# Expected: 4

# CSS class fix: gray-bg, not bg-gray
grep -c 'class="x-services ptb-100 gray-bg"' public/index.html
# Expected: 1
grep -c 'bg-gray' public/index.html
# Expected: 0

# Service cards: thumbnail/caption structure, 3 rows × 2 cols
grep -c 'class="thumbnail clearfix"' public/index.html
# Expected: 6

# Team preview: figure/figcaption + small
grep -c '<figure class="thumbnail">' public/index.html
# Expected: 3
grep -c '<small>' public/index.html
# Expected: 3

# "Ihr Ärzteteam" instead of "Unser Team"
grep -c 'Ihr Ärzteteam' public/index.html
# Expected: 1
grep -c 'Unser Team' public/index.html
# Expected: 0
```

All counts must match expected.

- [ ] **Step 7: Commit**

```bash
git add templates/index.html
git commit -m "feat: home page section_title macros and restored markup"
```

---

## Task 12: Fix table tag mismatch in news.md

**Files:**
- Modify: `content/news.md`

- [ ] **Step 1: Replace the table block**

Replace lines 21-30 in `content/news.md`:

```html
<table class="tg">
  <tr>
    <td>Montag bis Freitag</th>
    <td>08:00&ndash;10:00</th>
  </tr>
  <tr>
    <td>Montag, Dienstag, Donnerstag</td>
    <td>15:00&ndash;17:00</td>
  </tr>
</table>
```

with:

```html
<table class="tg">
  <tr>
    <td>Montag bis Freitag</td>
    <td>08:00&ndash;10:00</td>
  </tr>
  <tr>
    <td>Montag, Dienstag, Donnerstag</td>
    <td>15:00&ndash;17:00</td>
  </tr>
</table>
```

(Two `</th>` changed to `</td>` on the first row.)

- [ ] **Step 2: Build and verify no mismatched tags remain in the rendered home page**

```bash
zola build
grep -E '<td>[^<]*</th>' public/index.html
```
Expected: empty output.

- [ ] **Step 3: Commit**

```bash
git add content/news.md
git commit -m "fix: table tag mismatch in news block"
```

---

## Task 13: Contact page — dedicated template reading from config

**Files:**
- Create: `templates/contact.html`
- Modify: `content/contact.md`

- [ ] **Step 1: Write the contact template**

Create `templates/contact.html`:

```html
{% extends "base.html" %}
{% import "macros/page_title.html" as pt %}

{% block content %}

{{ pt::page_title(title=page.title) }}

<section class="ptb-100">
  <div class="container">

    <h2>{{ config.extra.practice_name }}</h2>

    <p>
      <strong>Hausärztliche Gemeinschaftspraxis</strong><br>
      {{ config.extra.address_street }}<br>
      {{ config.extra.address_zip_city }}
    </p>

    <p>
      <strong>Telefon:</strong> {{ config.extra.phone }}<br>
      <strong>Telefax:</strong> {{ config.extra.fax }}<br>
      <strong>E-Mail:</strong> <a href="mailto:{{ config.extra.email }}">{{ config.extra.email }}</a>
    </p>

    <h2>Sprechzeiten</h2>

    <table class="tg">
      {% for h in config.extra.opening_hours %}
        <tr>
          <td>{{ h.label }}</td>
          <td>{{ h.time }}&nbsp;Uhr</td>
        </tr>
      {% endfor %}
    </table>

    <br>

    {{ page.content | safe }}

  </div>
</section>

{% endblock %}
```

- [ ] **Step 2: Strip hardcoded values from content/contact.md**

Overwrite `content/contact.md` with:

```markdown
+++
title = "Kontakt"
template = "contact.html"
weight = 60
+++

**Die Praxis ist nach Termin organisiert.** Bei akuten Erkrankungen ist eine Vorstellung in der Praxis jederzeit möglich.

## Ärztlicher Bereitschaftsdienst

Sollten Sie außerhalb unserer Praxiszeiten ärztliche Hilfe benötigen, können Sie unter der für Sie kostenlosen Telefonnummer **116117** den [zentralen ärztlichen Bereitschaftsdienst](http://www.116117info.de) erreichen.

Für lebensbedrohliche Notfälle gilt die **Notrufnummer 112**.
```

- [ ] **Step 3: Build and verify contact page renders with config values**

```bash
zola build
grep -c 'Kaiserstraße 23' public/contact/index.html
# Expected: >= 2 (one in page body, one in footer)
grep -c '0202-730738' public/contact/index.html
# Expected: >= 2 (page body + footer)
grep -c 'Bereitschaftsdienst' public/contact/index.html
# Expected: 1 (only in page body, footer doesn't mention it)
grep -c 'single-page-title' public/contact/index.html
# Expected: 1
```

- [ ] **Step 4: Commit**

```bash
git add templates/contact.html content/contact.md
git commit -m "feat: contact page template reads address/hours from config"
```

---

## Task 14: Final visual diff and deploy gate

**Files:** (no edits — verification only)

- [ ] **Step 1: Full clean build**

```bash
rm -rf public processed_images
zola build
```
Expected: succeeds, prints page count.

- [ ] **Step 2: Cross-check rendered output for all five routes**

```bash
for route in index services/index team/index contact/index impressum/index; do
  echo "=== $route ==="
  echo "footer:        $(grep -c footer-widget-section public/$route.html)"
  echo "page_title:    $(grep -c single-page-title public/$route.html)"
  echo "section_title: $(grep -c 'class="section-title"' public/$route.html)"
  echo "logo img:      $(grep -c '/images/logo.png' public/$route.html)"
done
```
Expected (minimum):
- All five routes: `footer: 1`, `logo img: 1`
- `services`, `team`, `contact`, `impressum`: `page_title: 1`
- `services`: `section_title: 6` (6 sub-pages)
- `team`: `section_title: >= 2` (doctors + employees sections, at minimum)
- Home (`index`): `page_title: 0`, `section_title: 4` (news/about/services/team)

- [ ] **Step 3: Local browser sweep**

Run a local server:
```bash
zola serve --interface 0.0.0.0
```

Open in browser, walk through: `/`, `/services`, `/team`, `/contact`, `/impressum`. Confirm visually:
- Logo appears in navbar (no text brand)
- Home link active only on home page
- Footer present on every page with sprechzeiten/kontakt/anschrift
- Section-title pattern (centered h2 + circle icon) on all expected sections
- Services as 2-column thumbnail/caption grid (not 3-column flat cards)
- Team-preview with figure-style portraits and "Ihr Ärzteteam" heading

If any check fails, fix in a small follow-up commit before deploy.

- [ ] **Step 4: Stop the local server**

`Ctrl-C` the `zola serve` process.

- [ ] **Step 5: Ask user for deploy approval**

Do not deploy without explicit user confirmation per the live-deploy memory ([[feedback-praxis-live-deploy]]). Phrase the ask: "Visual Parity Pass implementiert. Soll ich nach `~/public/praxis/` auf mycelium deployen?"

- [ ] **Step 6: (After user OK) Deploy to staging**

```bash
rsync -avz --delete public/ mycelium:~/public/praxis/
```

- [ ] **Step 7: Verify staging is reachable**

```bash
curl -sI http://preview.praxis-am-lienhardplatz.de/ | head -1
```
Expected: `HTTP/1.1 200 OK`.

- [ ] **Step 8: Update memory with completion note**

Append a brief status line to `project_praxis_rebuild.md` noting Visual Parity Pass complete with date.

- [ ] **Step 9: Push commits**

```bash
git push origin main
```

---

## Notes for the implementer

- **All commits in English** per the user's global CLAUDE.md.
- **Never deploy without explicit OK** per [[feedback-praxis-live-deploy]] memory. Task 14 Step 5 is a hard gate.
- **`{% import %}` must appear inside the block that uses it for Tera in this version** — that's why each template that uses a macro does its own `{% import %}` rather than relying on a global import.
- **`page.url` vs `page.permalink`**: use whatever the existing navbar uses (it uses `permalink`); don't change without reason.
- **If a `grep` count is off by one**: check whether the test counts the carousel caption or some other unrelated occurrence. The test commands are written to be specific (e.g., grep for `<h2>Aktuelles</h2>` not just `Aktuelles`), but adjust if context proves them ambiguous.
- **Theme CSS is the contract.** If after Task 11 a section still looks wrong in the browser, grep `sass/_praxis_theme.scss` for the relevant class name and check whether the markup nests correctly. Do NOT modify the SCSS — adjust the markup.
