diff --git a/docs/superpowers/plans/2026-05-31-bloombase-redesign.md b/docs/superpowers/plans/2026-05-31-bloombase-redesign.md
new file mode 100644
index 0000000..c1e4b91
--- /dev/null
+++ b/docs/superpowers/plans/2026-05-31-bloombase-redesign.md
@@ -0,0 +1,1613 @@
+# BloomBase UI Redesign — 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:** Replace Bootstrap 5 with Tailwind CSS, add a 5-tab bottom navigation, extend `Location` with a cover photo field, restyle all existing screens, and add a new Area Detail page — producing the vibrant organic aesthetic from Naomi's mockup.
+
+**Architecture:** New `bloombase.css` holds fonts + CSS blob/flower decorations; `base.html` is fully rewritten with Tailwind CDN + bottom nav; all child templates are rewritten to use Tailwind utilities; one new view + template (`location_detail`) handles the Area Detail screen; `Location` model gains a nullable `cover_photo` ImageField with its own migration.
+
+**Tech Stack:** Django 5.x, HTMX 1.9, Tailwind CSS Play CDN (development), Google Fonts (Great Vibes + Nunito + Pacifico), SQLite
+
+---
+
+## File Map
+
+| File | Action |
+|---|---|
+| `plants/static/plants/css/bloombase.css` | **Create** — fonts, blob shapes, canvas flowers |
+| `plants/templates/plants/base.html` | **Rewrite** — Tailwind, bottom nav, decorations |
+| `plants/models.py` | **Modify** — add `cover_photo` to `Location` |
+| `plants/migrations/XXXX_location_cover_photo.py` | **Create** via `makemigrations` |
+| `plants/forms.py` | **Modify** — add `LocationForm` with `cover_photo` |
+| `plants/views/locations.py` | **Modify** — use `LocationForm`; add `location_detail` view |
+| `plants/urls.py` | **Modify** — add `location_detail` URL |
+| `plants/templates/plants/locations.html` | **Rewrite** — My Garden screen |
+| `plants/templates/plants/location_detail.html` | **Create** — Area Detail screen |
+| `plants/templates/plants/location_edit.html` | **Rewrite** — add cover photo field |
+| `plants/templates/plants/dashboard.html` | **Rewrite** — camera-first Home screen |
+| `plants/templates/plants/plant_list.html` | **Rewrite** — search + filter chips |
+| `plants/templates/plants/plant_detail.html` | **Rewrite** — hero + care + CTA |
+| `plants/templates/plants/identify_upload.html` | **Rewrite** — viewfinder camera UI |
+| `plants/templates/plants/identify_confirm.html` | **Rewrite** — match list restyle |
+| `plants/tests/test_location_redesign.py` | **Create** — model + view tests |
+
+---
+
+## Task 1: Static CSS — bloombase.css
+
+Creates the custom stylesheet: Google Fonts import, CSS blob background shapes, and fixed-position SVG flower decorations.
+
+**Files:**
+- Create: `plants/static/plants/css/bloombase.css`
+
+- [ ] **Step 1.1: Create the static directory and file**
+
+```bash
+mkdir -p plants/static/plants/css
+```
+
+- [ ] **Step 1.2: Write bloombase.css**
+
+```css
+/* plants/static/plants/css/bloombase.css */
+
+@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&family=Great+Vibes&family=Pacifico&display=swap');
+
+/* ── Body canvas ── */
+body {
+ background-color: #FFF8F2;
+ font-family: 'Nunito', sans-serif;
+ min-height: 100vh;
+ position: relative;
+ overflow-x: hidden;
+}
+
+/* ── Background blob shapes ── */
+.bb-blob-tl {
+ position: fixed; top: -100px; left: -80px;
+ width: 380px; height: 380px;
+ background: radial-gradient(ellipse at 45% 45%, #F9C090 0%, #F07040 55%, #E05020 100%);
+ border-radius: 62% 38% 54% 46% / 58% 44% 56% 42%;
+ opacity: 0.18;
+ pointer-events: none; z-index: 0;
+}
+.bb-blob-br {
+ position: fixed; bottom: -80px; right: -60px;
+ width: 340px; height: 340px;
+ background: radial-gradient(ellipse at 55% 55%, #FFD080 0%, #F8A040 60%, #F07040 100%);
+ border-radius: 44% 56% 38% 62% / 52% 48% 52% 48%;
+ opacity: 0.16;
+ pointer-events: none; z-index: 0;
+}
+
+/* ── Canvas SVG flowers ── */
+.bb-flower { position: fixed; pointer-events: none; z-index: 0; }
+.bb-flower-tr { top: 16px; right: 24px; }
+.bb-flower-ml { top: 38%; left: -4px; }
+.bb-flower-br { bottom: 72px; right: 48px; }
+.bb-flower-bl { bottom: 88px; left: 32px; }
+
+/* ── Brand fonts ── */
+.font-script { font-family: 'Great Vibes', cursive; }
+.font-pacifico { font-family: 'Pacifico', cursive; }
+.font-nunito { font-family: 'Nunito', sans-serif; }
+
+/* ── Bottom nav stays above content ── */
+#bottom-nav {
+ position: fixed; bottom: 0; left: 0; right: 0;
+ background: #fff;
+ border-top: 1px solid #F0E8DF;
+ height: 62px;
+ display: flex; align-items: center; justify-content: space-around;
+ z-index: 50;
+ padding-bottom: env(safe-area-inset-bottom, 0);
+}
+
+/* ── FAB inside nav ── */
+.bb-fab {
+ width: 44px; height: 44px; border-radius: 50%;
+ background: linear-gradient(145deg, #F58040, #E84020);
+ box-shadow: 0 4px 16px rgba(240, 80, 40, 0.5);
+ display: flex; align-items: center; justify-content: center;
+ color: #fff; font-size: 24px; line-height: 1; font-weight: 300;
+ flex-shrink: 0;
+}
+
+/* ── Gradient CTA button ── */
+.btn-bloom {
+ display: block; width: 100%;
+ background: linear-gradient(135deg, #F58040, #E84020);
+ color: #fff; border: none; border-radius: 50px;
+ padding: 12px 24px; font-family: 'Nunito', sans-serif;
+ font-weight: 800; font-size: 15px; text-align: center;
+ box-shadow: 0 4px 14px rgba(240,80,40,0.4); cursor: pointer;
+ text-decoration: none;
+}
+.btn-bloom-outline {
+ display: block; width: 100%;
+ background: transparent; color: #1A1208;
+ border: 1.5px solid #E0D4C8; border-radius: 50px;
+ padding: 11px 24px; font-family: 'Nunito', sans-serif;
+ font-weight: 700; font-size: 15px; text-align: center;
+ cursor: pointer; text-decoration: none;
+}
+
+/* ── White pill button (hero overlays) ── */
+.btn-pill {
+ background: rgba(255,255,255,0.88);
+ border: none; border-radius: 50px;
+ padding: 6px 14px; font-size: 13px; font-weight: 700;
+ color: #1A1208; backdrop-filter: blur(4px); cursor: pointer;
+ text-decoration: none;
+}
+
+/* ── Confidence bar ── */
+.conf-track { height: 5px; background: #F0E4D8; border-radius: 3px; overflow: hidden; }
+.conf-fill { height: 100%; background: linear-gradient(90deg, #F8A060, #E84020); border-radius: 3px; }
+
+/* ── Area thumbnail gradient placeholders ── */
+.at-placeholder-1 { background: linear-gradient(135deg, #88C860, #E85878, #A0D060); }
+.at-placeholder-2 { background: linear-gradient(150deg, #B8E060, #F0A840, #E87830); }
+.at-placeholder-3 { background: linear-gradient(120deg, #F8B840, #88C060, #F0C860); }
+.at-placeholder-4 { background: linear-gradient(140deg, #D0A8E8, #68B858, #C888E0); }
+.at-placeholder-5 { background: linear-gradient(130deg, #78D8C8, #E8F0A0, #60C8A8); }
+.at-placeholder-6 { background: linear-gradient(125deg, #F8A0B0, #B8E060, #F09060); }
+
+/* ── Viewfinder corners ── */
+.vf-corner { position: absolute; width: 18px; height: 18px; border-color: rgba(255,255,255,0.9); border-style: solid; }
+.vf-tl { top: 10px; left: 10px; border-width: 2.5px 0 0 2.5px; border-radius: 2px 0 0 0; }
+.vf-tr { top: 10px; right: 10px; border-width: 2.5px 2.5px 0 0; border-radius: 0 2px 0 0; }
+.vf-bl { bottom: 10px; left: 10px; border-width: 0 0 2.5px 2.5px; border-radius: 0 0 0 2px; }
+.vf-br { bottom: 10px; right: 10px; border-width: 0 2.5px 2.5px 0; border-radius: 0 0 2px 0; }
+```
+
+- [ ] **Step 1.3: Commit**
+
+```bash
+git add plants/static/plants/css/bloombase.css
+git commit -m "feat: add bloombase.css — fonts, blobs, canvas flowers, shared components"
+```
+
+---
+
+## Task 2: Rewrite base.html
+
+Full replacement of the Bootstrap top-nav shell with Tailwind CDN + 5-tab bottom nav + background canvas decorations.
+
+**Files:**
+- Modify: `plants/templates/plants/base.html`
+
+- [ ] **Step 2.1: Replace base.html**
+
+```html
+{# plants/templates/plants/base.html #}
+
+
+
+
+
+ {% block title %}BloomBase{% endblock %}
+ {% load static %}
+
+
+
+
+ {% block extra_head %}{% endblock %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% block content %}{% endblock %}
+
+
+
+
+
+
+
+```
+
+- [ ] **Step 2.2: Verify the app still loads (no crash)**
+
+```bash
+cd /home/stephan/devel/python/plantdb
+python manage.py check
+```
+
+Expected: `System check identified no issues (0 silenced).`
+
+- [ ] **Step 2.3: Commit**
+
+```bash
+git add plants/templates/plants/base.html
+git commit -m "feat: rewrite base.html — Tailwind CDN, 5-tab bottom nav, canvas decorations"
+```
+
+---
+
+## Task 3: Location model — add cover_photo + migration
+
+**Files:**
+- Modify: `plants/models.py`
+- Create: migration (via `makemigrations`)
+- Create: `plants/tests/test_location_redesign.py`
+
+- [ ] **Step 3.1: Write failing test first**
+
+```python
+# plants/tests/test_location_redesign.py
+import pytest
+from django.core.files.uploadedfile import SimpleUploadedFile
+from plants.models import Location
+
+
+@pytest.mark.django_db
+def test_location_cover_photo_field_exists():
+ """Location can be saved with and without a cover_photo."""
+ loc = Location.objects.create(name='Test Garden')
+ assert loc.cover_photo.name == '' or loc.cover_photo.name is None
+
+ fake_img = SimpleUploadedFile('cover.jpg', b'fake-image-data', content_type='image/jpeg')
+ loc.cover_photo = fake_img
+ loc.save()
+ loc.refresh_from_db()
+ assert loc.cover_photo.name.startswith('locations/')
+```
+
+- [ ] **Step 3.2: Run test — expect failure**
+
+```bash
+python -m pytest plants/tests/test_location_redesign.py::test_location_cover_photo_field_exists -v
+```
+
+Expected: `FAILED` — `AttributeError: 'Location' object has no attribute 'cover_photo'`
+
+- [ ] **Step 3.3: Add cover_photo to Location model**
+
+In `plants/models.py`, change:
+
+```python
+class Location(models.Model):
+ name = models.CharField(max_length=200, unique=True)
+```
+
+to:
+
+```python
+class Location(models.Model):
+ name = models.CharField(max_length=200, unique=True)
+ cover_photo = models.ImageField(upload_to='locations/', blank=True, null=True)
+```
+
+- [ ] **Step 3.4: Create migration**
+
+```bash
+python manage.py makemigrations plants --name location_cover_photo
+```
+
+Expected output: `Migrations for 'plants': plants/migrations/XXXX_location_cover_photo.py`
+
+- [ ] **Step 3.5: Apply migration**
+
+```bash
+python manage.py migrate
+```
+
+Expected: `Applying plants.XXXX_location_cover_photo... OK`
+
+- [ ] **Step 3.6: Run test — expect pass**
+
+```bash
+python -m pytest plants/tests/test_location_redesign.py::test_location_cover_photo_field_exists -v
+```
+
+Expected: `PASSED`
+
+- [ ] **Step 3.7: Commit**
+
+```bash
+git add plants/models.py plants/migrations/ plants/tests/test_location_redesign.py
+git commit -m "feat: add Location.cover_photo ImageField + migration + test"
+```
+
+---
+
+## Task 4: LocationForm + updated views + new location_detail + URL
+
+**Files:**
+- Modify: `plants/forms.py`
+- Modify: `plants/views/locations.py`
+- Modify: `plants/urls.py`
+- Modify: `plants/tests/test_location_redesign.py`
+
+- [ ] **Step 4.1: Write failing tests**
+
+Append to `plants/tests/test_location_redesign.py`:
+
+```python
+from django.test import Client
+from django.urls import reverse
+
+
+@pytest.fixture
+def client():
+ return Client()
+
+
+@pytest.mark.django_db
+def test_location_detail_view_returns_200(client):
+ loc = Location.objects.create(name='My Terrace')
+ resp = client.get(reverse('location_detail', kwargs={'pk': loc.pk}))
+ assert resp.status_code == 200
+ assert b'My Terrace' in resp.content
+
+
+@pytest.mark.django_db
+def test_location_edit_with_cover_photo(client):
+ loc = Location.objects.create(name='Balcony')
+ fake_img = SimpleUploadedFile('cover.jpg', b'data', content_type='image/jpeg')
+ resp = client.post(
+ reverse('location_edit', kwargs={'pk': loc.pk}),
+ {'name': 'Balcony Updated', 'cover_photo': fake_img},
+ )
+ assert resp.status_code == 302
+ loc.refresh_from_db()
+ assert loc.name == 'Balcony Updated'
+ assert loc.cover_photo.name.startswith('locations/')
+```
+
+- [ ] **Step 4.2: Run tests — expect failure**
+
+```bash
+python -m pytest plants/tests/test_location_redesign.py -v -k "detail or edit_with_cover"
+```
+
+Expected: `FAILED` — `NoReverseMatch: location_detail` and related errors.
+
+- [ ] **Step 4.3: Add LocationForm to forms.py**
+
+Append to `plants/forms.py`:
+
+```python
+class LocationForm(forms.ModelForm):
+ class Meta:
+ model = Location
+ fields = ['name', 'cover_photo']
+```
+
+- [ ] **Step 4.4: Rewrite views/locations.py**
+
+```python
+# plants/views/locations.py
+from django.shortcuts import render, get_object_or_404, redirect
+from django.views.decorators.http import require_POST
+from django.db.models import Count
+from plants.models import Location, Plant
+from plants.forms import LocationForm
+
+
+def location_list(request):
+ if request.method == 'POST':
+ name = request.POST.get('name', '').strip()
+ if name:
+ Location.objects.get_or_create(name=name)
+ return redirect('location_list')
+
+ locations = Location.objects.annotate(plant_count=Count('plants'))
+ return render(request, 'plants/locations.html', {
+ 'locations': locations,
+ 'active_tab': 'garden',
+ })
+
+
+def location_detail(request, pk):
+ location = get_object_or_404(Location, pk=pk)
+ plants = location.plants.select_related('species').prefetch_related('photos').all()
+ return render(request, 'plants/location_detail.html', {
+ 'location': location,
+ 'plants': plants,
+ 'active_tab': 'garden',
+ })
+
+
+def location_edit(request, pk):
+ location = get_object_or_404(Location, pk=pk)
+ if request.method == 'POST':
+ form = LocationForm(request.POST, request.FILES, instance=location)
+ if form.is_valid():
+ form.save()
+ return redirect('location_list')
+ else:
+ form = LocationForm(instance=location)
+ return render(request, 'plants/location_edit.html', {
+ 'location': location,
+ 'form': form,
+ 'active_tab': 'garden',
+ })
+
+
+@require_POST
+def location_delete(request, pk):
+ location = get_object_or_404(Location, pk=pk)
+ Plant.objects.filter(location=location).update(location=None)
+ location.delete()
+ return redirect('location_list')
+```
+
+- [ ] **Step 4.5: Add location_detail URL**
+
+In `plants/urls.py`, add after the existing `locations/` URL:
+
+```python
+path('locations//', locations.location_detail, name='location_detail'),
+```
+
+The full relevant section of urlpatterns should look like:
+
+```python
+path('locations/', locations.location_list, name='location_list'),
+path('locations//', locations.location_detail, name='location_detail'),
+path('locations//edit/', locations.location_edit, name='location_edit'),
+path('locations//delete/', locations.location_delete, name='location_delete'),
+```
+
+- [ ] **Step 4.6: Run tests — expect pass**
+
+```bash
+python -m pytest plants/tests/test_location_redesign.py -v
+```
+
+Expected: all `PASSED`
+
+- [ ] **Step 4.7: Commit**
+
+```bash
+git add plants/forms.py plants/views/locations.py plants/urls.py plants/tests/test_location_redesign.py
+git commit -m "feat: add LocationForm with cover_photo, location_detail view, update location_edit"
+```
+
+---
+
+## Task 5: locations.html — My Garden screen
+
+**Files:**
+- Modify: `plants/templates/plants/locations.html`
+
+- [ ] **Step 5.1: Rewrite locations.html**
+
+```html
+{# plants/templates/plants/locations.html #}
+{% extends "plants/base.html" %}
+{% block title %}My Garden — BloomBase{% endblock %}
+{% block content %}
+{% load static %}
+
+
+
+
+
+
+
+
+
+
Search plants or areas
+
+
+
+
+
+
+
+
+
+{% endblock %}
+```
+
+- [ ] **Step 5.2: Verify page renders**
+
+```bash
+python manage.py runserver 0.0.0.0:8000
+```
+
+Open http://localhost:8000/locations/ — expect My Garden screen with area rows and + form.
+
+- [ ] **Step 5.3: Commit**
+
+```bash
+git add plants/templates/plants/locations.html
+git commit -m "feat: restyle locations.html as My Garden screen with cover photo thumbnails"
+```
+
+---
+
+## Task 6: location_detail.html — Area Detail screen
+
+**Files:**
+- Create: `plants/templates/plants/location_detail.html`
+
+- [ ] **Step 6.1: Create location_detail.html**
+
+```html
+{# plants/templates/plants/location_detail.html #}
+{% extends "plants/base.html" %}
+{% block title %}{{ location.name }} — BloomBase{% endblock %}
+{% block content %}
+
+
+
+ {% if location.cover_photo %}
+

+ {% else %}
+
+ {% endif %}
+
+
+
+
← Back
+
+
Edit
+
+
+
+
+
+
{{ location.name }}
+
+ {{ plants.count }} plant{{ plants.count|pluralize }}
+
+
+
+ {% if plants %}
+
+ {% else %}
+
+
+
🪴
+
No plants here yet.
+
Identify a plant
+
+ {% endif %}
+
+
+{% endblock %}
+```
+
+- [ ] **Step 6.2: Verify page renders**
+
+Open http://localhost:8000/locations/1/ (replace 1 with a real pk) — expect hero + plant grid.
+
+- [ ] **Step 6.3: Commit**
+
+```bash
+git add plants/templates/plants/location_detail.html
+git commit -m "feat: add location_detail.html — area detail with cover photo header + plant grid"
+```
+
+---
+
+## Task 7: location_edit.html — add cover photo upload
+
+**Files:**
+- Modify: `plants/templates/plants/location_edit.html`
+
+- [ ] **Step 7.1: Rewrite location_edit.html**
+
+```html
+{# plants/templates/plants/location_edit.html #}
+{% extends "plants/base.html" %}
+{% block title %}Edit Area — BloomBase{% endblock %}
+{% block content %}
+
+
+{% endblock %}
+```
+
+- [ ] **Step 7.2: Verify form submits with photo**
+
+Open http://localhost:8000/locations/1/edit/ — fill name, attach image, save. Confirm redirect to /locations/ with updated thumbnail.
+
+- [ ] **Step 7.3: Commit**
+
+```bash
+git add plants/templates/plants/location_edit.html
+git commit -m "feat: restyle location_edit.html with cover photo upload field"
+```
+
+---
+
+## Task 8: dashboard.html — camera-first Home screen
+
+Also update `dashboard` view to pass `active_tab`.
+
+**Files:**
+- Modify: `plants/views/dashboard.py`
+- Modify: `plants/templates/plants/dashboard.html`
+
+- [ ] **Step 8.1: Update dashboard view to pass active_tab and location count**
+
+```python
+# plants/views/dashboard.py
+from datetime import date
+from django.shortcuts import render
+from plants.models import Plant, Location
+
+
+def dashboard(request):
+ today = date.today()
+ all_plants = list(Plant.objects.select_related('species').all())
+ blooming_now = [p for p in all_plants if today.month in (p.bloom_months or [])]
+ latest_plants = Plant.objects.select_related('species', 'location').prefetch_related('photos').order_by('-pk')[:6]
+ location_count = Location.objects.count()
+
+ return render(request, 'plants/dashboard.html', {
+ 'total_plants': len(all_plants),
+ 'blooming_now': blooming_now,
+ 'blooming_now_count': len(blooming_now),
+ 'today': today,
+ 'latest_plants': latest_plants,
+ 'location_count': location_count,
+ 'active_tab': 'home',
+ })
+```
+
+- [ ] **Step 8.2: Rewrite dashboard.html**
+
+```html
+{# plants/templates/plants/dashboard.html #}
+{% extends "plants/base.html" %}
+{% load plant_extras %}
+{% block title %}BloomBase{% endblock %}
+{% block content %}
+
+
+
+
+
+{% endblock %}
+```
+
+- [ ] **Step 8.3: Verify home screen**
+
+Open http://localhost:8000/ — expect camera viewfinder + My Garden pill + recent plants.
+
+- [ ] **Step 8.4: Commit**
+
+```bash
+git add plants/views/dashboard.py plants/templates/plants/dashboard.html
+git commit -m "feat: restyle dashboard as camera-first Home screen"
+```
+
+---
+
+## Task 9: plant_list.html — search + location filter chips
+
+Also update the `plant_list` view to pass `active_tab`.
+
+**Files:**
+- Modify: `plants/views/plants.py` (just add `active_tab` to plant_list context)
+- Modify: `plants/templates/plants/plant_list.html`
+
+- [ ] **Step 9.1: Add active_tab to plant_list view**
+
+In `plants/views/plants.py`, find the `plant_list` view and add `'active_tab': 'garden'` to the context dict it passes to `render`. (Check the current return statement and add the key alongside existing context keys.)
+
+- [ ] **Step 9.2: Rewrite plant_list.html**
+
+```html
+{# plants/templates/plants/plant_list.html #}
+{% extends "plants/base.html" %}
+{% block title %}Plants — BloomBase{% endblock %}
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% include "plants/partials/plant_list_results.html" %}
+
+
+
+{% endblock %}
+```
+
+- [ ] **Step 9.3: Update plant_list_results partial**
+
+Open `plants/templates/plants/partials/plant_list_results.html` and check its current content. Update it to use Tailwind card style:
+
+```html
+{# plants/templates/plants/partials/plant_list_results.html #}
+{% for plant in plants %}
+
+ {% if plant.species and plant.species.api_image_url %}
+
+ {% elif plant.thumbnail_url %}
+
+ {% else %}
+ 🌿
+ {% endif %}
+
+
+ {% if plant.location %}
+
+ {{ plant.location.name }}
+
+ {% endif %}
+
+ ›
+
+{% empty %}
+No plants found.
+{% endfor %}
+```
+
+- [ ] **Step 9.4: Verify plant list**
+
+Open http://localhost:8000/plants/ — expect search + chips + card list.
+
+- [ ] **Step 9.5: Commit**
+
+```bash
+git add plants/views/plants.py plants/templates/plants/plant_list.html plants/templates/plants/partials/plant_list_results.html
+git commit -m "feat: restyle plant_list with Tailwind — search, filter chips, plant cards"
+```
+
+---
+
+## Task 10: plant_detail.html — hero + care + CTA
+
+Also add `active_tab` to the `plant_detail` view.
+
+**Files:**
+- Modify: `plants/views/plants.py` (add `active_tab` to plant_detail context)
+- Modify: `plants/templates/plants/plant_detail.html`
+
+- [ ] **Step 10.1: Add active_tab to plant_detail view context**
+
+In `plants/views/plants.py`, find the `plant_detail` view and add `'active_tab': 'garden'` to the context.
+
+- [ ] **Step 10.2: Rewrite plant_detail.html**
+
+```html
+{# plants/templates/plants/plant_detail.html #}
+{% extends "plants/base.html" %}
+{% load plant_extras %}
+{% block title %}{{ plant.name }} — BloomBase{% endblock %}
+{% block content %}
+
+
+
+ {% if plant.species and plant.species.api_image_url %}
+

+ {% elif plant.thumbnail_url %}
+

+ {% else %}
+
🌿
+ {% endif %}
+
+
+
← Back
+
+
Edit
+
+
+
+
+
+
+
+
{{ plant.name }}
+ {% if plant.species %}
+
+
{{ plant.species.scientific_name }}
+
+
+
+
+ {% endif %}
+
+ {% if plant.location %}
+
+ 📍 {{ plant.location.name }}
+
+ {% endif %}
+
+
+ {% if plant.watering or plant.sunlight or plant.species %}
+
+ {% if plant.watering %}
+
+ 💧
+ {{ plant.get_watering_display }}
+
+ {% elif plant.species and plant.species.watering %}
+
+ 💧
+ {{ plant.species.watering }}
+
+ {% endif %}
+ {% if plant.sunlight %}
+
+ ☀️
+ {{ plant.get_sunlight_display }}
+
+ {% elif plant.species and plant.species.sunlight %}
+
+ ☀️
+ {{ plant.species.sunlight }}
+
+ {% endif %}
+ {% if plant.species and plant.species.frost_hardiness_c is not None %}
+
+ 🌡️
+ {{ plant.species.frost_hardiness_c }}°C min
+
+ {% endif %}
+ {% if plant.species and plant.species.max_height_cm %}
+
+ 📏
+ {{ plant.species.max_height_cm }} cm
+
+ {% endif %}
+
+ {% endif %}
+
+
+ {% if plant.bloom_months %}
+
+
🌸 Bloom months
+ {% month_strip plant.bloom_months %}
+
+ {% endif %}
+
+
+ {% if plant.notes %}
+
+
{{ plant.notes|linebreaksbr }}
+
+ {% endif %}
+
+
+ {% if plant.pruning_months %}
+ {% include "plants/partials/pruning_strip.html" %}
+ {% endif %}
+
+
+
+ {% include "plants/partials/photo_gallery.html" %}
+
+
+
+
+
+
+{% endblock %}
+```
+
+- [ ] **Step 10.3: Verify plant detail**
+
+Open http://localhost:8000/plants/1/ — expect hero + care row + CTA buttons.
+
+- [ ] **Step 10.4: Commit**
+
+```bash
+git add plants/views/plants.py plants/templates/plants/plant_detail.html
+git commit -m "feat: restyle plant_detail — hero, care row, gradient CTA buttons"
+```
+
+---
+
+## Task 11: identify_upload.html — viewfinder camera UI
+
+Also add `active_tab` to `identify_upload` view.
+
+**Files:**
+- Modify: `plants/views/identify.py` (add `active_tab`)
+- Modify: `plants/templates/plants/identify_upload.html`
+
+- [ ] **Step 11.1: Add active_tab to identify_upload view**
+
+In `plants/views/identify.py`, find the `identify_upload` view. Add `'active_tab': 'home'` to the context dict passed to render (for the GET response).
+
+- [ ] **Step 11.2: Rewrite identify_upload.html**
+
+```html
+{# plants/templates/plants/identify_upload.html #}
+{% extends "plants/base.html" %}
+{% block title %}Identify plant — BloomBase{% endblock %}
+{% block content %}
+
+
+
+
+
+
+
+ Add one or more photos, tag what each shows, then tap Identify.
+
+
+ {% if error %}
+
+ {{ error }}
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+```
+
+- [ ] **Step 11.3: Verify identify screen**
+
+Open http://localhost:8000/identify/ — expect viewfinder box + shutter button + organ tags.
+
+- [ ] **Step 11.4: Commit**
+
+```bash
+git add plants/views/identify.py plants/templates/plants/identify_upload.html
+git commit -m "feat: restyle identify_upload as camera-first viewfinder screen"
+```
+
+---
+
+## Task 12: identify_confirm.html — match list restyle
+
+**Files:**
+- Modify: `plants/templates/plants/identify_confirm.html`
+
+- [ ] **Step 12.1: Rewrite identify_confirm.html**
+
+```html
+{# plants/templates/plants/identify_confirm.html #}
+{% extends "plants/base.html" %}
+{% block title %}Confirm species — BloomBase{% endblock %}
+{% block content %}
+
+
+
+
+
←
+
Is this your plant?
+
+
+ Tap the correct species, then confirm.
+
+
+
+
+
+
+
+{% endblock %}
+```
+
+- [ ] **Step 12.2: Verify identify confirm**
+
+Run a real identification or view the confirm page directly — expect match cards with confidence badges and gradient confirm button.
+
+- [ ] **Step 12.3: Commit**
+
+```bash
+git add plants/templates/plants/identify_confirm.html
+git commit -m "feat: restyle identify_confirm — match cards with confidence badges"
+```
+
+---
+
+## Self-Review
+
+**Spec coverage check:**
+
+| Spec item | Task |
+|---|---|
+| Replace Bootstrap 5 with Tailwind CSS | Task 2 (base.html) |
+| 5-tab bottom nav (Home, Garden, +, Care, Profile) | Task 2 |
+| `Location.cover_photo` + migration | Task 3 |
+| `LocationForm` with cover_photo | Task 4 |
+| `location_detail` view + URL | Task 4 |
+| locations.html My Garden screen | Task 5 |
+| location_detail.html Area Detail | Task 6 |
+| location_edit.html with cover photo | Task 7 |
+| dashboard.html camera-first | Task 8 |
+| plant_list.html | Task 9 |
+| plant_detail.html | Task 10 |
+| identify_upload.html | Task 11 |
+| identify_confirm.html | Task 12 |
+| Canvas blob decorations + SVG flowers | Task 1 + Task 2 |
+| Great Vibes + Nunito + Pacifico fonts | Task 1 |
+| Gradient CTA buttons | Task 1 (.btn-bloom) |
+| `active_tab` nav active state | Tasks 4, 8, 9, 10, 11 |
+| Care + Profile stubs | Task 2 (href="#") |
+
+**Gaps identified and resolved:**
+- `plant_list_results.html` partial was missing — added in Task 9.3
+- `plant_list` and `plant_detail` views need `active_tab` in context — noted in Tasks 9 and 10
+- `identify_upload` view needs `active_tab` — noted in Task 11
+
+**Type/name consistency:**
+- `active_tab` values: `'home'` (dashboard, identify), `'garden'` (locations, plant_list, plant_detail, location_detail, location_edit)
+- CSS class names used consistently: `.btn-bloom`, `.btn-bloom-outline`, `.btn-pill`, `.bb-fab`, `.vf-corner .vf-tl/tr/bl/br`
+- `at-placeholder-N` classes 1–6 defined in bloombase.css and used in locations.html + location_detail.html
+
+**No placeholders:** All template code is complete. All CSS is complete.