diff --git a/games/age-of-dwarves/guide/src/pages/BiomeBrowserPage.tsx b/games/age-of-dwarves/guide/src/pages/BiomeBrowserPage.tsx
deleted file mode 100644
index 4771f92a..00000000
--- a/games/age-of-dwarves/guide/src/pages/BiomeBrowserPage.tsx
+++ /dev/null
@@ -1,351 +0,0 @@
-import { useState, useMemo, type ReactElement } from 'react'
-import styled from 'styled-components'
-import { FadeIn, PageTitle, Section, SectionHeading, Prose, FilterRow, FilterChip } from '@magic-civ/guide-engine'
-import { Heading, Text } from '@lilith/ui-typography'
-import { ALL_BIOMES, BIOME_CATEGORIES, QUALITY_COLORS, QUALITY_LABELS } from '@/data/ecology'
-import type { BiomeDisplay } from '@/data/ecology'
-
-function BiomePieChart({ biomes }: { biomes: BiomeDisplay[] }): ReactElement {
- const total = biomes.length
- let currentAngle = 0
-
- const slices = biomes.map((biome) => {
- const fraction = 1 / total
- const startAngle = currentAngle
- const endAngle = currentAngle + fraction * 360
- currentAngle = endAngle
-
- const startRad = (startAngle - 90) * (Math.PI / 180)
- const endRad = (endAngle - 90) * (Math.PI / 180)
- const largeArc = fraction > 0.5 ? 1 : 0
- const x1 = 50 + 45 * Math.cos(startRad)
- const y1 = 50 + 45 * Math.sin(startRad)
- const x2 = 50 + 45 * Math.cos(endRad)
- const y2 = 50 + 45 * Math.sin(endRad)
-
- return {
- biome,
- d: `M 50 50 L ${x1} ${y1} A 45 45 0 ${largeArc} 1 ${x2} ${y2} Z`,
- }
- })
-
- return (
-
-
-
- {BIOME_CATEGORIES.map(cat => {
- const count = biomes.filter(b => b.category === cat.id).length
- if (count === 0) return null
- return (
-
-
- {cat.label} ({count})
-
- )
- })}
-
-
- )
-}
-
-function BiomeCard({ biome }: { biome: BiomeDisplay }): ReactElement {
- return (
-
-
-
- {biome.name}
- {biome.category}
-
-
-
- Quality Range
-
- {Array.from({ length: biome.quality_range[1] - biome.quality_range[0] + 1 }, (_, i) => {
- const q = biome.quality_range[0] + i
- return (
-
- {q}
-
- )
- })}
-
-
-
- Temperature
- {biome.temp_range[0].toFixed(2)} - {biome.temp_range[1].toFixed(2)}
-
-
- Moisture
- {biome.moisture_range[0].toFixed(2)} - {biome.moisture_range[1].toFixed(2)}
-
-
- Fauna Capacity
- {biome.fauna_capacity}
-
-
-
-
-
-
-
- Canopy {biome.flora_climax.canopy}
- Undergrowth {biome.flora_climax.undergrowth}
- Fungi {biome.flora_climax.fungi}
-
-
-
- )
-}
-
-export default function BiomeBrowserPage(): ReactElement {
- const [categoryFilter, setCategoryFilter] = useState('all')
-
- const filtered = useMemo(() => {
- if (categoryFilter === 'all') return ALL_BIOMES
- return ALL_BIOMES.filter(b => b.category === categoryFilter)
- }, [categoryFilter])
-
- return (
-
-
- Biome Browser
-
- {ALL_BIOMES.length} biomes across aquatic, tropical, temperate, cold, elevation, and
- special categories. Each biome defines climate ranges, flora climax values, and fauna capacity.
-
-
-
-
- Distribution
-
- Biomes emerge from substrate type, temperature, moisture, and canopy state.
- The BiomeClassifier reclassifies tiles each turn when conditions change significantly.
-
-
-
-
-
- All Biomes
-
- setCategoryFilter('all')}>
- All ({ALL_BIOMES.length})
-
- {BIOME_CATEGORIES.map(cat => {
- const count = ALL_BIOMES.filter(b => b.category === cat.id).length
- return (
- setCategoryFilter(cat.id)}
- >
- {cat.label} ({count})
-
- )
- })}
-
-
- {filtered.map(biome => (
-
- ))}
-
-
-
-
- Color Legend
-
- {ALL_BIOMES.map(biome => (
-
-
- {biome.name}
-
- ))}
-
-
-
- )
-}
-
-// ---------------------------------------------------------------------------
-// Styled components
-// ---------------------------------------------------------------------------
-
-const PieContainer = styled.div`
- display: flex;
- align-items: center;
- gap: 2rem;
- margin-top: 1rem;
- flex-wrap: wrap;
-`
-
-const PieLegend = styled.div`
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-`
-
-const PieLegendItem = styled.div`
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-size: 0.8125rem;
- color: ${({ theme }) => theme.colors.text.secondary};
-`
-
-const PieLegendDot = styled.span`
- width: 0.75rem;
- height: 0.75rem;
- border-radius: 50%;
- flex-shrink: 0;
-`
-
-const BiomeGrid = styled.div`
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
- gap: 1rem;
- margin-top: 1rem;
-`
-
-const Card = styled.div`
- background: ${({ theme }) => theme.colors.surface};
- border: 1px solid ${({ theme }) => theme.colors.border.default};
- border-radius: 6px;
- overflow: hidden;
-`
-
-const CardHeader = styled.div`
- display: flex;
- align-items: center;
- gap: 0.75rem;
- padding: 0.75rem 1rem;
- border-bottom: 1px solid ${({ theme }) => theme.colors.border.default};
-`
-
-const BiomeSwatch = styled.span`
- width: 1.25rem;
- height: 1.25rem;
- border-radius: 4px;
- flex-shrink: 0;
-`
-
-const CardTitle = styled.span`
- font-weight: 600;
- font-size: 0.9375rem;
- color: ${({ theme }) => theme.colors.text.primary};
- flex: 1;
-`
-
-const CategoryTag = styled.span`
- font-size: 0.6875rem;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- color: ${({ theme }) => theme.colors.text.muted};
- padding: 0.125rem 0.375rem;
- border: 1px solid ${({ theme }) => theme.colors.border.default};
- border-radius: 3px;
-`
-
-const CardBody = styled.div`
- padding: 0.75rem 1rem;
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-`
-
-const StatRow = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
- font-size: 0.8125rem;
-`
-
-const StatLabel = styled.span`
- color: ${({ theme }) => theme.colors.text.muted};
-`
-
-const StatValue = styled.span`
- font-family: monospace;
- font-weight: 600;
- color: ${({ theme }) => theme.colors.text.primary};
-`
-
-const QualityRange = styled.div`
- display: flex;
- gap: 0.25rem;
-`
-
-const QualityDot = styled.span`
- width: 1.5rem;
- height: 1.5rem;
- border-radius: 4px;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 0.6875rem;
- font-weight: 700;
- font-family: monospace;
- color: #fff;
-`
-
-const FloraBar = styled.div`
- display: flex;
- height: 0.375rem;
- border-radius: 3px;
- overflow: hidden;
- background: ${({ theme }) => theme.colors.border.default};
- margin-top: 0.25rem;
-`
-
-const FloraSegment = styled.div`
- height: 100%;
- min-width: 1px;
-`
-
-const FloraLabels = styled.div`
- display: flex;
- gap: 0.75rem;
- font-size: 0.6875rem;
- font-family: monospace;
- color: ${({ theme }) => theme.colors.text.muted};
-`
-
-const ColorLegend = styled.div`
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
- gap: 0.375rem;
- margin-top: 0.5rem;
-`
-
-const LegendEntry = styled.div`
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-size: 0.8125rem;
- color: ${({ theme }) => theme.colors.text.secondary};
-`
-
-const LegendSwatch = styled.span`
- width: 1rem;
- height: 1rem;
- border-radius: 3px;
- flex-shrink: 0;
-`
-
-const LegendName = styled.span`
- white-space: nowrap;
-`