diff --git a/docs/plans/20260506-1300-radio-info-display/plan.md b/docs/plans/20260506-1300-radio-info-display/plan.md
new file mode 100644
index 0000000..9bd8edf
--- /dev/null
+++ b/docs/plans/20260506-1300-radio-info-display/plan.md
@@ -0,0 +1,260 @@
+# Plan: Radio Info Tile Display — Homepage Network Info Panel Overhaul
+
+**Date**: 2026-05-06
+**Status**: Draft
+
+---
+
+## Summary
+
+Replace the flat label:value list in the **Network Info** panel on the home page (`/`) with a **3×2 grid of compact tiles**. Each tile represents one radio configuration parameter and displays an icon, a label, and the value. The design uses subtle colour, rounded borders, and a clear visual hierarchy (icon → label → value).
+
+---
+
+## Current State
+
+### UI
+
+The Network Info panel at `home.js:204–215` renders radio config parameters as a simple two-column flex list inside a `card bg-base-100 shadow-xl`:
+
+```
+┌──────────────────────────────┐
+│ ℹ Network Info │
+│ │
+│ Profile: EU/UK Narrow │
+│ Frequency: 869.618MHz │
+│ Bandwidth: 62.5kHz │
+│ Spreading Factor: 8 │
+│ Coding Rate: 8 │
+│ TX Power: 22dBm │
+└──────────────────────────────┘
+```
+
+The `renderRadioConfig()` function at `home.js:11–28` maps the 6 `RadioConfig` fields to a flat array of label+value pairs, rendered with `
` rows.
+
+### Data Source
+
+Radio config is injected server-side via `window.__APP_CONFIG__.network_radio_config` (not an API endpoint). The `RadioConfig` Pydantic model (`common/schemas/network.py`) parses a comma-delimited string into:
+- `profile` (str) — e.g. `"EU/UK Narrow"`
+- `frequency` (str) — e.g. `"869.618MHz"`
+- `bandwidth` (str) — e.g. `"62.5kHz"`
+- `spreading_factor` (int) — e.g. `8`
+- `coding_rate` (int) — e.g. `8`
+- `tx_power` (str) — e.g. `"22dBm"`
+
+Any field can be `None`/`null` (partial configs are supported).
+
+### Key Files
+
+| File | Role |
+|------|------|
+| `src/meshcore_hub/web/static/js/spa/pages/home.js` | Home page render; `renderRadioConfig()` at lines 11–28; panel layout at lines 204–215 |
+| `src/meshcore_hub/web/static/css/app.css` | Custom styles; color palette at lines 21–29; panel utilities at lines 88–113 |
+| `src/meshcore_hub/web/static/js/spa/components.js` | Shared component imports; `t()`, `html`, `litRender`, `pageColors` |
+| `src/meshcore_hub/web/static/js/spa/icons.js` | SVG icon functions (`iconAntenna`, `iconChart`, etc.) |
+| `src/meshcore_hub/web/static/locales/en.json` | i18n keys: `links.profile`, `home.frequency`, `home.bandwidth`, `home.spreading_factor`, `home.coding_rate`, `home.tx_power`, `home.network_info` |
+| `src/meshcore_hub/common/schemas/network.py` | `RadioConfig` Pydantic model (data structure validation) |
+| `src/meshcore_hub/web/app.py` | Server-side config injection into `__APP_CONFIG__` (line 237–272) |
+
+---
+
+## Target State
+
+### UI
+
+Replace the flat label:value list with a **3-column × 2-row grid** of compact tiles. Each tile has this structure:
+
+```
+┌──────────────────────┐
+│ │
+│ [icon] │ ← higher-contrast colour
+│ │
+│ Label │ ← medium-contrast font (e.g. "Frequency")
+│ 869.618MHz │ ← white (dark theme) / black (light theme)
+│ │
+└──────────────────────┘
+```
+
+**6 tiles**: Profile, Frequency, Bandwidth, Spreading Factor, Coding Rate, TX Power.
+
+**Grid layout**:
+
+```
+┌────────────┬────────────┬────────────┐
+│ Profile │ Frequency │ Bandwidth │
+│ EU/UK... │ 869.618MHz │ 62.5kHz │
+├────────────┼────────────┼────────────┤
+│ Spreading │ Coding │ TX Power │
+│ Factor 8 │ Rate 8 │ 22dBm │
+└────────────┴────────────┴────────────┘
+```
+
+**Responsive behaviour**: On small screens (`md` breakpoint and below), collapse to 2 columns. No single-column fallback — 2 columns minimum ensures tiles remain compact even on phones.
+
+**Missing fields**: If a radio parameter is `null`/`undefined`, the entire tile for that parameter is hidden (same as current behaviour where empty values are filtered out).
+
+### Visual Design
+
+| Element | Dark Theme | Light Theme |
+|---------|-----------|-------------|
+| **Tile background** | `transparent` (no fill) | Same |
+| **Tile border** | `border border-base-content/10 rounded-box` | Same |
+| **Icon colour** | `var(--color-radio)` — new cyan accent (`oklch(0.75 0.15 210)`) | `var(--color-radio)` — darker variant (`oklch(0.55 0.15 210)`) |
+| **Label** | `opacity-70` on `text-base-content` (medium contrast) | Same |
+| **Value** | `text-base-content` (white in dark, black in light) with `font-semibold` | Same |
+
+Tiles use a transparent background — no fill, no `panel-glow`. The rounded border alone provides visual separation, keeping tiles compact and lightweight.
+
+### Icon Selection
+
+Create new SVG icon functions in `icons.js` for radio-specific concepts, OR reuse existing Heroicons:
+
+| Parameter | Icon Concept | Source |
+|-----------|-------------|--------|
+| Profile | Cog/gear (settings profile) | Existing `iconSettings` or new cog variant |
+| Frequency | Waveform/sine wave | New SVG — sine wave icon |
+| Bandwidth | Sliders/adjust | New SVG — horizontal sliders |
+| Spreading Factor | Arrows expanding outward | New SVG — expand arrows |
+| Coding Rate | Shield with check | New SVG — shield-check |
+| TX Power | Bolt/power | New SVG — bolt |
+
+Each new icon follows the existing pattern: a function exporting a `lit-html` template with a `cls` parameter for CSS sizing, using Heroicons outline style (24×24 viewBox, `stroke="currentColor"` with `stroke-width="2"`, `stroke-linecap="round"`, `stroke-linejoin="round"`).
+
+---
+
+## Implementation Plan
+
+### 1. Add Radio Parameter Icons (`icons.js`)
+
+Add 5–6 new icon functions in `icons.js`. Where an adequate existing icon exists, reuse it. For the rest, create new Heroicons-style SVG icons.
+
+Icons needed (at minimum 5 — `iconSettings` already exists for Profile):
+- `iconFrequency` — waveform/sine (new)
+- `iconBandwidth` — horizontal sliders (new)
+- `iconSpreadingFactor` — expand arrows (new)
+- `iconCodingRate` — shield-check (new)
+- `iconTxPower` — bolt/lightning (new)
+
+### 2. Rewrite `renderRadioConfig()` → `renderRadioTiles()` (`home.js`)
+
+Replace the current `renderRadioConfig()` function (lines 11–28) with a new `renderRadioTiles()` function that:
+
+1. Maps each parameter to a tile definition: `{ icon, label, value }`
+2. Filters out tiles with no value
+3. Renders a CSS Grid (3 columns, responsive) of tiles
+4. Each tile is a `