diff --git a/docs/plans/2026-03-09-provider-pricing-reports.md b/docs/plans/2026-03-09-provider-pricing-reports.md
deleted file mode 100644
index 27471b606..000000000
--- a/docs/plans/2026-03-09-provider-pricing-reports.md
+++ /dev/null
@@ -1,621 +0,0 @@
-# Provider-Specific Pricing for Reports — Implementation Plan
-
-> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
-
-**Goal:** Replace the hard-coded 0.39 CHF/kWh electricity price with real per-provider tariffs from ELCOM, so report savings reflect each installation's actual network provider rate.
-
-**Architecture:** New `ProviderTariff` SQLite model stores ELCOM tariff data (total + breakdown) per provider per year. New `PricingService` fetches tariffs via SPARQL, caches in DB, and exposes a lookup method. All three report services (`WeeklyReportService`, `ReportAggregationService`, `ReportEmailService`) replace the hard-coded constant with a dynamic lookup using the installation's `NetworkProvider` field.
-
-**Tech Stack:** C#/.NET, SQLite-net ORM, SPARQL (ELCOM/LINDAS endpoint), Flurl HTTP
-
-**Decisions made during brainstorming:**
-- Fetch total price now, store breakdown components for future use
-- Fetch once per provider+year, store in SQLite (ELCOM tariffs are fixed per year)
-- Only new reports going forward use real tariffs (existing stored reports untouched)
-- Fallback to 0.39 CHF/kWh if provider has no tariff data
-- Scope: accurate savings only (no provider comparison or ROI features yet)
-
----
-
-## Task 1: Create ProviderTariff Data Model
-
-**Files:**
-- Create: `csharp/App/Backend/DataTypes/ProviderTariff.cs`
-
-**Step 1: Create the data model**
-
-```csharp
-using SQLite;
-
-namespace InnovEnergy.App.Backend.DataTypes;
-
-///
-/// Cached ELCOM electricity tariff for a network provider and year.
-/// Fetched from lindas.admin.ch/elcom/electricityprice via SPARQL.
-/// Tariffs are fixed per year — fetched once and stored permanently.
-///
-public class ProviderTariff
-{
- [PrimaryKey, AutoIncrement]
- public Int64 Id { get; set; }
-
- [Indexed]
- public String ProviderName { get; set; } = "";
-
- [Indexed]
- public Int32 Year { get; set; }
-
- // Total electricity price (CHF/kWh) — used for savings calculation
- public Double TotalPricePerKwh { get; set; }
-
- // Breakdown components (CHF/kWh) — stored for future use
- public Double GridUsagePerKwh { get; set; } // Netznutzung
- public Double EnergyPerKwh { get; set; } // Energielieferung
- public Double FeesPerKwh { get; set; } // Abgaben an Gemeinwesen + KEV/SDL
-
- public String FetchedAt { get; set; } = "";
-}
-```
-
-**Step 2: Register table in Db.cs**
-
-In `csharp/App/Backend/Database/Db.cs`:
-
-Add table accessor after line 39 (after TicketTimelineEvents):
-```csharp
-public static TableQuery ProviderTariffs => Connection.Table();
-```
-
-Add `CreateTable` call inside the `RunInTransaction` block (after line 77, after TicketTimelineEvent):
-```csharp
-Connection.CreateTable();
-```
-
-**Step 3: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 4: Commit**
-
-```bash
-git add csharp/App/Backend/DataTypes/ProviderTariff.cs csharp/App/Backend/Database/Db.cs
-git commit -m "feat: add ProviderTariff data model for ELCOM pricing"
-```
-
----
-
-## Task 2: Add Database Read/Create Methods for ProviderTariff
-
-**Files:**
-- Modify: `csharp/App/Backend/Database/Read.cs`
-- Modify: `csharp/App/Backend/Database/Create.cs`
-
-**Step 1: Add read method in Read.cs**
-
-Add at the end of the file (before closing brace):
-```csharp
-public static ProviderTariff? GetProviderTariff(string providerName, int year)
-{
- return ProviderTariffs
- .FirstOrDefault(t => t.ProviderName == providerName && t.Year == year);
-}
-```
-
-**Step 2: Add create method in Create.cs**
-
-Add at the end of the file (before closing brace):
-```csharp
-public static void InsertProviderTariff(ProviderTariff tariff)
-{
- Connection.Insert(tariff);
-}
-```
-
-**Step 3: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 4: Commit**
-
-```bash
-git add csharp/App/Backend/Database/Read.cs csharp/App/Backend/Database/Create.cs
-git commit -m "feat: add DB read/create methods for ProviderTariff"
-```
-
----
-
-## Task 3: Create PricingService
-
-**Files:**
-- Create: `csharp/App/Backend/Services/PricingService.cs`
-
-**Step 1: Create the service**
-
-This service:
-1. Exposes `GetElectricityPrice(providerName, year)` -> returns CHF/kWh (double)
-2. Checks SQLite cache first
-3. If not cached, fetches from ELCOM SPARQL and stores
-4. Falls back to 0.39 if provider not found or fetch fails
-
-```csharp
-using Flurl.Http;
-using InnovEnergy.App.Backend.Database;
-using InnovEnergy.App.Backend.DataTypes;
-using Newtonsoft.Json.Linq;
-
-namespace InnovEnergy.App.Backend.Services;
-
-///
-/// Provides electricity tariffs per network provider and year.
-/// Source: ELCOM/LINDAS SPARQL endpoint (Swiss electricity price database).
-/// Caches results in SQLite — tariffs are fixed per year.
-/// Falls back to 0.39 CHF/kWh if provider data is unavailable.
-///
-public static class PricingService
-{
- private const double FallbackPricePerKwh = 0.39;
- private const string SparqlEndpoint = "https://ld.admin.ch/query";
-
- ///
- /// Get the total electricity price for a provider in a given year.
- /// Returns cached value if available, otherwise fetches from ELCOM.
- /// Falls back to 0.39 CHF/kWh if data is unavailable.
- ///
- public static async Task GetElectricityPriceAsync(string providerName, int year)
- {
- if (string.IsNullOrWhiteSpace(providerName))
- return FallbackPricePerKwh;
-
- // Check DB cache first
- var cached = Db.GetProviderTariff(providerName, year);
- if (cached is not null)
- return cached.TotalPricePerKwh;
-
- // Fetch from ELCOM
- var tariff = await FetchTariffFromElcomAsync(providerName, year);
- if (tariff is null)
- {
- Console.WriteLine($"[PricingService] No ELCOM data for '{providerName}' year {year}, using fallback {FallbackPricePerKwh} CHF/kWh.");
- return FallbackPricePerKwh;
- }
-
- // Cache in DB
- Db.InsertProviderTariff(tariff);
- Console.WriteLine($"[PricingService] Cached tariff for '{providerName}' year {year}: {tariff.TotalPricePerKwh:F4} CHF/kWh.");
- return tariff.TotalPricePerKwh;
- }
-
- ///
- /// Synchronous convenience wrapper for use in report generation.
- ///
- public static double GetElectricityPrice(string providerName, int year)
- {
- return GetElectricityPriceAsync(providerName, year).GetAwaiter().GetResult();
- }
-
- private static async Task FetchTariffFromElcomAsync(string providerName, int year)
- {
- try
- {
- // ELCOM SPARQL query for H4 household profile (standard household 4500 kWh/year)
- // H4 is the most common reference category for residential installations.
- // The query fetches tariff components: gridusage, energy, charge (fees).
- // Total = gridusage + energy + charge
- var sparqlQuery = $@"
-PREFIX schema:
-PREFIX cube:
-PREFIX elcom:
-
-SELECT ?gridusage ?energy ?charge
-FROM
-WHERE {{
- ?obs a cube:Observation ;
- elcom:operator ?op ;
- elcom:period ;
- elcom:category ;
- elcom:product ;
- elcom:gridusage ?gridusage ;
- elcom:energy ?energy ;
- elcom:charge ?charge .
- ?op schema:name ""{EscapeSparql(providerName)}"" .
-}}
-LIMIT 1";
-
- var response = await SparqlEndpoint
- .WithHeader("Accept", "application/sparql-results+json")
- .PostUrlEncodedAsync(new { query = sparqlQuery });
-
- var json = await response.GetStringAsync();
- var parsed = JObject.Parse(json);
- var bindings = parsed["results"]?["bindings"];
-
- if (bindings is null || !bindings.Any())
- return null;
-
- var first = bindings.First();
- var gridUsage = ParseRpToChf(first["gridusage"]?["value"]?.ToString());
- var energy = ParseRpToChf(first["energy"]?["value"]?.ToString());
- var charge = ParseRpToChf(first["charge"]?["value"]?.ToString());
- var total = gridUsage + energy + charge;
-
- if (total <= 0)
- return null;
-
- return new ProviderTariff
- {
- ProviderName = providerName,
- Year = year,
- TotalPricePerKwh = Math.Round(total, 4),
- GridUsagePerKwh = Math.Round(gridUsage, 4),
- EnergyPerKwh = Math.Round(energy, 4),
- FeesPerKwh = Math.Round(charge, 4),
- FetchedAt = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")
- };
- }
- catch (Exception ex)
- {
- Console.Error.WriteLine($"[PricingService] ELCOM fetch failed for '{providerName}' year {year}: {ex.Message}");
- return null;
- }
- }
-
- ///
- /// ELCOM values may be in Rp./kWh (centimes) or CHF/kWh.
- /// Values > 1 are likely Rp./kWh and need /100 conversion.
- /// Values <= 1 are already CHF/kWh.
- ///
- private static double ParseRpToChf(string? value)
- {
- if (!double.TryParse(value, System.Globalization.NumberStyles.Float,
- System.Globalization.CultureInfo.InvariantCulture, out var parsed))
- return 0;
-
- // ELCOM typically returns Rp./kWh (centimes), convert to CHF
- return parsed > 1 ? parsed / 100.0 : parsed;
- }
-
- private static string EscapeSparql(string value)
- {
- return value.Replace("\\", "\\\\").Replace("\"", "\\\"");
- }
-}
-```
-
-**Important: SPARQL query validation required**
-- The exact SPARQL predicates (`elcom:gridusage`, `elcom:energy`, `elcom:charge`) need verification against the live endpoint before implementing.
-- Test manually first:
- ```bash
- curl -X POST https://ld.admin.ch/query \
- -H "Accept: application/sparql-results+json" \
- -d "query=PREFIX schema: PREFIX cube: PREFIX elcom: SELECT ?gridusage ?energy ?charge FROM WHERE { ?obs a cube:Observation ; elcom:operator ?op ; elcom:period ; elcom:category ; elcom:product ; elcom:gridusage ?gridusage ; elcom:energy ?energy ; elcom:charge ?charge . ?op schema:name \"BKW Energie AG\" . } LIMIT 1"
- ```
-- If predicates or URIs differ, adjust `PricingService.cs` accordingly.
-- The H4 category (standard household, 4500 kWh/year) is the best default for residential Sodistore installations.
-- ELCOM docs: https://www.elcom.admin.ch/elcom/en/home/open-data-api.html
-
-**Step 2: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 3: Commit**
-
-```bash
-git add csharp/App/Backend/Services/PricingService.cs
-git commit -m "feat: add PricingService for ELCOM tariff lookup with DB caching"
-```
-
----
-
-## Task 4: Verify SPARQL Query Against Live Endpoint
-
-**This is a critical validation step before integrating into reports.**
-
-**Step 1: Test the SPARQL query**
-
-Run the curl command from Task 3 notes against the live ELCOM endpoint with a known provider name (e.g., one from the existing `NetworkProviderService` list).
-
-**Step 2: Inspect the response**
-
-Check:
-- Are the predicate names correct (`elcom:gridusage`, `elcom:energy`, `elcom:charge`)?
-- What units are the values in (Rp./kWh or CHF/kWh)?
-- Does the H4 category exist?
-- Does the year URI format `` work?
-
-**Step 3: Adjust PricingService if needed**
-
-If predicates, URIs, or units differ from what's in the code, update the SPARQL query and unit conversion logic in `PricingService.cs`.
-
-**Step 4: Commit any fixes**
-
-```bash
-git add csharp/App/Backend/Services/PricingService.cs
-git commit -m "fix: adjust SPARQL query to match live ELCOM endpoint"
-```
-
----
-
-## Task 5: Integrate Pricing into WeeklyReportService
-
-**Files:**
-- Modify: `csharp/App/Backend/Services/WeeklyReportService.cs`
-
-**Step 1: Replace hard-coded price in savings calculation (around line 181)**
-
-Before:
-```csharp
-const double ElectricityPriceCHF = 0.39;
-var totalEnergySaved = Math.Round(currentSummary.TotalConsumption - currentSummary.TotalGridImport, 1);
-var totalSavingsCHF = Math.Round(totalEnergySaved * ElectricityPriceCHF, 0);
-```
-
-After:
-```csharp
-var installation = Db.GetInstallationById(installationId);
-var reportYear = DateTime.Parse(currentWeekDays.First().Date).Year;
-var electricityPrice = await PricingService.GetElectricityPriceAsync(
- installation?.NetworkProvider ?? "", reportYear);
-var totalEnergySaved = Math.Round(currentSummary.TotalConsumption - currentSummary.TotalGridImport, 1);
-var totalSavingsCHF = Math.Round(totalEnergySaved * electricityPrice, 0);
-```
-
-Note: The `installation` variable may already exist earlier in the method. If so, reuse it instead of fetching again. Check the method context.
-
-**Step 2: Replace hard-coded price in AI prompt section (around line 265)**
-
-Before:
-```csharp
-const double ElectricityPriceCHF = 0.39;
-```
-
-After: Remove this line. Use the `electricityPrice` variable from step 1 (pass it as a parameter to the AI insight method, or compute it there).
-
-The key point: wherever `ElectricityPriceCHF` appears, replace with the dynamic value.
-
-**Step 3: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 4: Commit**
-
-```bash
-git add csharp/App/Backend/Services/WeeklyReportService.cs
-git commit -m "feat: use provider-specific tariff in weekly report savings"
-```
-
----
-
-## Task 6: Integrate Pricing into ReportAggregationService
-
-**Files:**
-- Modify: `csharp/App/Backend/Services/ReportAggregationService.cs`
-
-**Step 1: Remove the class-level constant (line 14)**
-
-Before:
-```csharp
-private const Double ElectricityPriceCHF = 0.39;
-```
-
-After: Remove this line entirely.
-
-**Step 2: Update monthly aggregation (around line 366)**
-
-The method already has `installationId` and fetches the installation. Add pricing lookup:
-
-Before:
-```csharp
-var savingsCHF = Math.Round(energySaved * ElectricityPriceCHF, 0);
-```
-
-After:
-```csharp
-var electricityPrice = await PricingService.GetElectricityPriceAsync(
- installation?.NetworkProvider ?? "", year);
-var savingsCHF = Math.Round(energySaved * electricityPrice, 0);
-```
-
-Note: `installation` is already fetched at line 373 (`Db.GetInstallationById(installationId)`). Move the fetch before the savings calculation if needed, or reuse.
-
-**Step 3: Update yearly aggregation (around line 477)**
-
-Before:
-```csharp
-var savingsCHF = Math.Round(energySaved * ElectricityPriceCHF, 0);
-```
-
-After:
-```csharp
-var electricityPrice = await PricingService.GetElectricityPriceAsync(
- installation?.NetworkProvider ?? "", year);
-var savingsCHF = Math.Round(energySaved * electricityPrice, 0);
-```
-
-Note: `installation` is already fetched at line 488. Same pattern as monthly.
-
-**Step 4: Update AI prompt references**
-
-Search for any remaining `ElectricityPriceCHF` references in the file (AI prompt strings around lines 693, 728). Replace with the dynamic value passed into the AI generation methods.
-
-**Step 5: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 6: Commit**
-
-```bash
-git add csharp/App/Backend/Services/ReportAggregationService.cs
-git commit -m "feat: use provider-specific tariff in monthly/yearly report savings"
-```
-
----
-
-## Task 7: Update Email Templates with Dynamic Price
-
-**Files:**
-- Modify: `csharp/App/Backend/Services/ReportEmailService.cs`
-
-**Step 1: Make `AtRate` field dynamic**
-
-The `EmailStrings` and `AggregatedEmailStrings` records have an `AtRate` field with hard-coded "bei 0.39 CHF/kWh" / "a 0.39 CHF/kWh" / etc.
-
-Change the approach: instead of hard-coding the rate in the language strings, pass the rate as a parameter and format it dynamically.
-
-Update the `GetWeeklyStrings` method to accept a `double electricityPrice` parameter:
-
-Before (example for German, line 106):
-```csharp
-AtRate: "bei 0.39 CHF/kWh",
-```
-
-After:
-```csharp
-AtRate: $"bei {electricityPrice:F2} CHF/kWh",
-```
-
-Apply the same pattern for all 4 languages (de, fr, it, en) in both:
-- `GetWeeklyStrings()` — 4 language variants (lines ~90-200)
-- `GetAggregatedStrings()` — 8 language+type variants (lines ~524-574)
-
-The preposition varies by language:
-- German: `"bei {price:F2} CHF/kWh"`
-- French: `"a {price:F2} CHF/kWh"`
-- Italian: `"a {price:F2} CHF/kWh"`
-- English: `"at {price:F2} CHF/kWh"`
-
-**Step 2: Update callers to pass the price**
-
-Wherever `GetWeeklyStrings(language)` or `GetAggregatedStrings(language, type)` is called, pass the electricity price as an additional parameter. The price should come from the report generation context (already computed in Tasks 5-6).
-
-**Step 3: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 4: Commit**
-
-```bash
-git add csharp/App/Backend/Services/ReportEmailService.cs
-git commit -m "feat: display actual provider tariff rate in report emails"
-```
-
----
-
-## Task 8: Add GetProviderTariff API Endpoint (Optional but Recommended)
-
-**Files:**
-- Modify: `csharp/App/Backend/Controller.cs`
-
-**Step 1: Add endpoint for frontend to query tariff**
-
-This allows the frontend Information tab to display the current tariff next to the provider selector.
-
-Add in Controller.cs (near the existing `GetNetworkProviders` endpoint around line 756):
-
-```csharp
-[HttpGet(nameof(GetProviderTariff))]
-public async Task> GetProviderTariff(Token authToken, string providerName, int year)
-{
- var session = Db.GetSession(authToken);
- if (session is null)
- return Unauthorized();
-
- var price = await PricingService.GetElectricityPriceAsync(providerName, year);
- var tariff = Db.GetProviderTariff(providerName, year);
-
- return Ok(new
- {
- providerName,
- year,
- totalPricePerKwh = price,
- gridUsagePerKwh = tariff?.GridUsagePerKwh ?? 0,
- energyPerKwh = tariff?.EnergyPerKwh ?? 0,
- feesPerKwh = tariff?.FeesPerKwh ?? 0,
- isFallback = tariff is null
- });
-}
-```
-
-**Step 2: Build to verify**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds
-
-**Step 3: Commit**
-
-```bash
-git add csharp/App/Backend/Controller.cs
-git commit -m "feat: add GetProviderTariff API endpoint"
-```
-
----
-
-## Task 9: End-to-End Verification
-
-**Step 1: Full build**
-
-Run: `cd csharp/App/Backend && dotnet build`
-Expected: Build succeeds with no warnings related to our changes
-
-**Step 2: Test SPARQL query manually**
-
-Pick 2-3 known provider names from the ELCOM list and verify the pricing query returns sensible values (typical Swiss residential rates are 0.20-0.45 CHF/kWh).
-
-**Step 3: Verify fallback behavior**
-
-Test with:
-- Empty provider name -> should return 0.39
-- Unknown provider name -> should return 0.39
-- Valid provider -> should return actual ELCOM rate
-
-**Step 4: Review all changes**
-
-```bash
-git diff main --stat
-git log --oneline main..HEAD
-```
-
-Verify:
-- No remaining hard-coded 0.39 in report calculation code
-- Email templates use dynamic formatting
-- ProviderTariff table is registered in Db.cs
-- PricingService has proper error handling and fallback
-
----
-
-## Summary of All Files Changed
-
-| File | Action | Purpose |
-|------|--------|---------|
-| `DataTypes/ProviderTariff.cs` | Create | SQLite model for cached tariffs |
-| `Database/Db.cs` | Modify | Register table + accessor |
-| `Database/Read.cs` | Modify | Add `GetProviderTariff()` query |
-| `Database/Create.cs` | Modify | Add `InsertProviderTariff()` |
-| `Services/PricingService.cs` | Create | ELCOM fetch + cache + fallback logic |
-| `Services/WeeklyReportService.cs` | Modify | Use dynamic price (2 places) |
-| `Services/ReportAggregationService.cs` | Modify | Use dynamic price (monthly + yearly) |
-| `Services/ReportEmailService.cs` | Modify | Dynamic rate in 12 language strings |
-| `Controller.cs` | Modify | Optional: GetProviderTariff endpoint |
-
-## Fallback Behavior
-
-| Scenario | Behavior |
-|----------|----------|
-| No NetworkProvider set on installation | Uses 0.39 CHF/kWh |
-| Provider not found in ELCOM | Uses 0.39 CHF/kWh, logs warning |
-| ELCOM endpoint unavailable | Uses 0.39 CHF/kWh, logs error |
-| Tariff already cached in DB | Returns cached value (no network call) |
-| New year, same provider | Fetches new year's tariff from ELCOM |
-
-## Future Extensions (Not In Scope)
-
-- Provider comparison ("your rate vs. average")
-- ROI/payback calculation
-- Time-of-use / dynamic spot pricing
-- Tariff breakdown display in reports
-- Category selection (H1-H8 profiles beyond default H4)