/* global window */
/* ============================================================
   PRACTICE_CONTENT — detailed write-ups for each agronomic
   practice across the 9 phenological stages. Each entry has:
   - problem: 1-3 sentences on what happens without precision
   - method: array of steps (the Revolute approach)
   - imagery: array of {src, caption, type} — type is 'photo' or
     'data' or 'placeholder'. Placeholders include a label that
     describes the missing photo so the grower knows what to send.
   - timing: when in the season this happens (text)
   - services: array of service ids that deliver this practice
   - density: 'short' | 'medium' — controls how much copy renders
   ============================================================ */
(function () {

  // Helper: build a placeholder spec
  const ph = (label, ratio = '16/10') => ({
    src: null,
    placeholder: label,
    ratio,
    type: 'placeholder',
  });

  // Helper: real image
  const img = (src, caption, ratio = '16/10', type = 'photo') => ({
    src: 'assets/' + src,
    caption,
    ratio,
    type,
    imgFile: 'assets/' + src,
  });

  // ============================================================
  // The full practice content map.
  // Keys match PRACTICES in page-optimize.jsx.
  // ============================================================
  window.PRACTICE_CONTENT = {

    // ================= DORMANCY =================
    'Block development': {
      density: 'medium',
      timing: 'Before the cycle begins — site selection through the first two establishment years.',
      problem:
        'Most of a block\u2019s yield ceiling is set before the first season ever starts. Pick the wrong ' +
        'rootstock for the soil, run rows across a drainage line, or skip the structural lime and gypsum ' +
        'at planting depth, and you spend the next twenty years managing around a mistake that a soil scan ' +
        'would have caught in an afternoon.',
      method: [
        { h: 'Site selection — EMI before you plant', t: 'Scan the candidate soil first. The EC map shows soil class, depth and drainage at 5\u00d75 m before a single tree goes in — so you know exactly what you\u2019re planting into.' },
        { h: 'Soil prep — lime, gypsum, drainage', t: 'Correct pH and structure at depth while the machinery can still reach it. Variable-rate lime and gypsum go in by zone, and drainage is cut where the deep-EC layer calls for it — not blanket across the block.' },
        { h: 'Cultivar / rootstock to soil class', t: 'Match vigour to the soil. Heavier high-EC zones and lighter sandy zones each get the rootstock that suits them, instead of one choice fighting the soil for half the block.' },
        { h: 'Planting & trellis — row direction by EC', t: 'Lay rows and irrigation blocks along the grain of the soil and drainage, so each row sits in as consistent a soil class as possible and water moves the way you want it to.' },
        { h: 'First two years — establish, monitor, refine', t: 'Track canopy establishment on satellite from year one. Catch the slow corners early and refine irrigation and nutrition before the block locks into its mature pattern.' },
      ],
      imagery: [
        img('dormancy-emi-scan-zones.png', 'EMI soil scan of candidate soil before planting — soil class and drainage mapped at 5\u00d75 m so site selection, rootstock and row direction are decided from data, not guesswork.', '16/9', 'data'),
        img('practice-establishment-trench.jpg', 'Drainage trenching at establishment, cut along the lines the soil scan flagged — fixing structure while the machinery can still move freely through the block.', '16/10'),
        img('dormancy-gypsum-prescription-new.png', 'Variable-rate gypsum prescription for a new development block — structural correction applied by zone at planting prep, from near-adequate soil up to severely sodic patches.', '16/9', 'data'),
      ],
      services: ['emi', 'toolbox'],
    },

    'EMI soil scan': {
      density: 'medium',
      timing: 'Late winter, before bud break — the orchard is dormant and accessible.',
      problem:
        'Soil variability under your trees is invisible from the surface. Two trees ten metres apart ' +
        'can be sitting on completely different soil types — different pH, different clay content, ' +
        'different water-holding capacity. Treating them the same means you never fix the limiting ' +
        'factors that restrict nutrition uptake and hold yield back every season.',
      method: [
        { h: 'Pull the rig', t: 'A vehicle-mounted Electromagnetic Induction probe is towed across the block once, recording readings every half-second.' },
        { h: 'Three depths at once', t: 'EMI captures conductivity at 25 cm, 50 cm and 90 cm — root-zone, mid-zone and deep restrictions, in a single pass.' },
        { h: '5×5 m resolution', t: 'The output is a soil map at 5-metre grid resolution — the exact scale at which orchard variability lives.' },
        { h: 'Define management zones', t: 'Raw EC values are classified into 3–5 management zones: where the soil is sandy, where it is heavy, where pH and limiting-factor remediation will need different rates.' },
      ],
      imagery: [
        img('dormancy-emi-scan-zones.png', 'EMI soil scan output — farm-level EC map (orange–brown palette, light = sandy/low EC, dark = clay/high EC). Blue lines are block boundaries; red lines are management zone divisions derived from the scan. A single tractor pass captures all of this.', '16/9', 'data'),
        img('dormancy-emi-scan-sample-points.png', 'The same EC scan with zonal soil sample points overlaid (coloured dots). Each dot is a GPS-tagged sampling location placed within its EC zone — the next step after the scan.', '16/9', 'data'),
      ],
      services: ['emi', 'toolbox'],
    },

    'Zonal soil sampling': {
      density: 'medium',
      timing: 'Right after the EMI scan — late winter / dormant period, before any inputs are applied.',
      problem:
        'Grid sampling takes too many samples in uniform areas and misses the zones that actually ' +
        'differ in pH, phosphate, and mineral availability — and a grid point can land right on the ' +
        'border between two soils, one meaningless sample that represents neither. The result is a lab ' +
        'report that averages out the variability, and a lime or gypsum prescription that under-fixes ' +
        'problem zones and over-applies where the soil was already adequate.',
      method: [
        { h: 'Sample by zone, not by grid', t: 'EMI zones define where the samples land — each soil class gets its own readings, placed well inside the zone rather than on an arbitrary grid point that might straddle two soils. Several sub-samples are composited per zone, so the result describes that soil honestly, never a blur of two.' },
        { h: 'Fewer samples, sharper answers', t: 'Typically a third of the samples a grid would require. Every sample answers a real question about a specific zone — pH, P, K, Ca, Mg, micronutrients.' },
        { h: 'Focus on pH and limiting factors', t: 'The primary dormancy goal is identifying which zones need lime (to lift pH), gypsum (to improve Ca:Mg ratio and structure), and phosphate (to unlock uptake). These are the limiting factors that hold back the whole growing season.' },
        { h: 'Lab results back to the zone map', t: 'Lab values are joined to their zones in RevToolbox — chemistry on top of physics — creating the prescription inputs for VRA lime, gypsum, and phosphate.' },
        { h: 'Corrected to the soil boundary', t: 'Because the chemistry is tied to real zones, the VRA spreader applies the right rate right up to the edge of each soil — not feathered across an interpolated 50×50 m grid that ignores where the boundary actually is.' },
      ],
      imagery: [
        img('emi-ec-vs-ndvi.png', 'EC soil conductivity (left) beside canopy NDVI (right) for the same block. Where the soil layer and the canopy agree on a transition, the management zone is real — and that is exactly where the composite sample points are placed, never on a blind 50×50 m grid.', '1368/550', 'data'),
        img('emi-ec-vs-yield.png', 'EC (left) against the measured yield map (right). The high-EC, high-vigour core reads low on the yield map — excess vigour suppressing fruit set — so neighbouring zones carry opposite prescriptions. Sampling by zone captures that difference; a grid averages it away.', '1368/550', 'data'),
        img('dormancy-zonal-ndvi-1.png', 'NDVI vigour map — first date. Canopy variability across the same farm footprint without zone boundaries. The light patches and dark patches are the signal that, combined with the EC scan, defines the sampling zones.', '16/9', 'data'),
        img('dormancy-zonal-ndvi-2.png', 'NDVI second date with zone boundaries (red lines) overlaid. The zones are drawn where both NDVI and EC agree on a transition — not arbitrary grid lines.', '16/9', 'data'),
        img('dormancy-zonal-ec-no-points.png', 'EC scan with zone boundaries — same zones as the NDVI view, now on the soil conductivity layer. Light = sandy/low EC, dark orange = clay/high EC. Zones follow the soil physics.', '16/9', 'data'),
        img('dormancy-zonal-ec-points-labeled.png', 'EC zones with sample point locations and IDs (1A_A, 2A_B, 3B_C etc.). Each coloured dot is one composite sample placed within its zone — the lab will return one result per zone per block.', '16/9', 'data'),
        img('dormancy-zonal-satellite-points.png', 'Satellite basemap with sample points and IDs only — no EC overlay. Field-ready navigation view: the sampling team moves down rows to each labelled point in sequence. No lab data wasted on areas already covered.', '16/9', 'photo'),
      ],
      services: ['emi', 'toolbox'],
    },

    'Drainage / structure decisions': {
      density: 'medium',
      timing: 'Dormancy — when machinery can move and you can intervene before the next season.',
      problem:
        'Drainage problems hide. They cost you yield every year and you blame it on weather. ' +
        'High-EC zones reveal where water sits at depth; cross-referencing with the NDVI vigour map ' +
        'shows the real cost — the same zones that read dark on the EC scan consistently ' +
        'underperform on the vigour and yield maps.',
      method: [
        { h: 'Read the EC–vigour correlation', t: 'Overlay the EC scan against the end-of-season NDVI in RevToolbox. Zones with high EC and low vigour — or high EC and low yield — are where soil physical limitations drive under-performance.' },
        { h: 'Read the deep channel', t: 'The 90 cm EC layer reveals subsoil moisture pooling and clay barriers. Dark conductive zones at depth mark where the water sits — and where the drain needs to go.' },
        { h: 'Plan the cut', t: 'You see the drain path before you cut a trench, not after. Infrastructure follows the data, not the guess.' },
        { h: 'Re-scan to verify', t: 'A post-intervention re-scan confirms the fix worked — the conductive plume should clear in the season following a correctly placed drain.' },
      ],
      imagery: [
        img('emi-ndvi-vs-ec-drainage.png', 'Canopy NDVI (left) beside deep EC (right) across two strips. The conductive sub-soil maps where water and clay sit at depth — read the 90 cm EC and the drain path is visible before a trench is ever cut.', '1369/552', 'data'),
        img('practice-establishment-trench.jpg', 'Trenching along lines the soil scan flagged — drainage infrastructure cut where the deep-EC layer calls for it.', '16/10'),
        img('dormancy-drainage-yield-ec-1.png', 'RevToolbox dual map — fruit count/yield zones (left, red–green, Zone 1: 58–71 through Zone 8: 145–157 fruit) vs EC 25 cm (right, orange–white, Zone 1: 14.7–15.97 through Zone 8: 23.57–24.83 mS/m). The low-yield zones (red, left) align directly with high-EC zones (dark orange, right).', '16/9', 'data'),
        img('dormancy-drainage-yield-ec-2.png', 'Same dual map, second block set. High-EC patches consistently correspond to depressed yield. These are the zones where drainage or soil structure intervention will recover performance.', '16/9', 'data'),
      ],
      services: ['emi', 'toolbox'],
    },

    'Replant planning · rootstock': {
      density: 'short',
      timing: 'Pre-planting — the EMI scan should happen BEFORE you commit to a layout.',
      problem:
        'Most orchards are planted with a single rootstock per block. But the soil under the block ' +
        'varies. Match the rootstock to the soil class and you save a decade of fighting it.',
      method: [
        { h: 'Map first, plant second', t: 'EMI before planting reveals soil zones at the scale of individual rows.' },
        { h: 'Vary rootstock by zone', t: 'Vigorous rootstocks for sandy / low-EC zones; controlled rootstocks for high-EC heavy soils.' },
        { h: 'Match row direction to drainage', t: 'Run rows along contour lines suggested by the deep-EC layer.' },
      ],
      imagery: [
        img('emi-management-zones.png', 'Three soil classes within a single block. Three different planting decisions.'),
        img('practice-new-orchard.jpg', 'A newly established block — rows and infrastructure laid out across the mapped soil zones.'),
      ],
      services: ['emi'],
    },

    'Probe placement plan': {
      density: 'medium',
      timing: 'After EMI scan, before installing in-ground probes.',
      problem:
        'Probes are expensive and they only tell you about the soil they sit in. One probe in the ' +
        'wrong spot measures the wrong zone all season. The EC map solves this: it shows exactly ' +
        'where each distinct soil class sits and how large each representative area is — making ' +
        'the best probe location obvious.',
      method: [
        { h: 'Read the zone structure, not the sample points', t: 'The EC–vigour dual map without sample overlays shows the continuous zone structure: sandy zones (light EC), medium zones, and heavy clay zones (dark EC). Each is a distinct irrigation and moisture behaviour unit.' },
        { h: 'One probe per zone', t: 'Each distinct EC zone gets its own probe — you measure the variability instead of averaging it away.' },
        { h: 'Maximise representable area', t: 'Place each probe at the centroid of its zone — the point that represents the largest area of that soil class. A probe at the centroid of a 4-hectare sandy zone reads for all 4 hectares; a probe at the edge reads for almost nothing.' },
        { h: 'Schedules follow the zones', t: 'Sandy low-EC zones get shorter, more frequent irrigation cycles. Clay high-EC zones get longer pulses with more recovery time. Each probe drives its own schedule.' },
      ],
      imagery: [
        img('dormancy-probe-ec-zones.png', 'EC soil zone map — zones defined by soil conductivity (light = sandy/low EC, dark orange = clay/high EC). The largest zone per block is the one that drives irrigation behaviour for the most area — that is where the probe goes.', '16/9', 'data'),
        img('dormancy-probe-photo.png', 'Soil moisture probe ready for installation — placed at the centroid of the dominant zone, it monitors the soil class that represents the most hectares in the block.', '3/4', 'photo'),
      ],
      services: ['emi', 'probe'],
    },

    'Variable-rate lime / gypsum': {
      density: 'medium',
      timing: 'Dormancy, before the season begins — ideally on a 3-year cycle. For new developments, at planting preparation.',
      problem:
        'pH and soil chemistry vary zone by zone across every block. Spreading lime, gypsum, or ' +
        'phosphate at a flat rate across a block where the limiting factors differ between zones is the ' +
        'most expensive way to fix nothing. You over-apply where the soil is already adequate and ' +
        'under-apply in the zones where the crop cannot access the nutrients it needs.',
      method: [
        { h: 'Lab results per zone → prescription per zone', t: 'Soil pH, Ca:Mg ratio, and P values from zonal samples directly drive per-zone application rates — not block averages.' },
        { h: 'Calcitic lime by zone', t: 'Zones with low pH get the highest lime rate. Zones at target pH get zero or a maintenance rate. The lime map shows this range across the block — from 3 000 kg/ha to 12 500 kg/ha depending on zone deficiency.' },
        { h: 'Gypsum for structure and Ca:Mg', t: 'Gypsum is applied where Ca:Mg ratios need correction and where soil structure benefits from calcium. Per-zone gypsum rates are tighter (1 680–2 019 kg/ha) — the soil needs precision, not volume.' },
        { h: 'Phosphate where uptake is locked', t: 'Zones with low available P get a targeted phosphate application — unlocking the nutrient uptake that drives root establishment and early-season growth.' },
        { h: 'Export to variable-rate spreader', t: 'All prescription maps export to ISO-XML or shapefile. One GPS-guided pass applies the right rate to every zone.' },
      ],
      imagery: [
        img('dormancy-calcitic-lime-prescription.png', 'Calcitic lime VRA prescription — new development block. Zones from 1 000 kg/ha (white, already near target pH) to 12 500 kg/ha (deep red, highest deficiency). Zone boundaries driven by EC scan and zonal soil pH lab results.', '16/9', 'data'),
        img('dormancy-gypsum-prescription-new.png', 'Gypsum VRA prescription for the same development area. Rates from 300 kg/ha (near-adequate Ca:Mg zones) to 12 500 kg/ha (zones with severe structural and calcium deficiency). Wider spread than lime — gypsum addresses both chemistry and physical soil structure.', '16/9', 'data'),
        img('dormancy-phosphate-prescription-new.png', 'Phosphate VRA prescription. Near-uniform 1 710–1 740 kg/ha across most zones with one high-deficiency zone at 2 019 kg/ha (red). P availability is the most uniform limiting factor — the one outlier zone is the critical fix.', '16/9', 'data'),
      ],
      services: ['emi', 'toolbox'],
    },

    // ================= BUD BREAK =================
    'Bud-break uniformity check': {
      density: 'short',
      timing: 'First 2–3 weeks after bud break.',
      problem:
        'If your block breaks bud unevenly, the yield gap is already locked in. The trees that ' +
        'started slow will never catch up — but you cannot see this from the road.',
      method: [
        { h: 'Capture an early NDVI scene', t: 'Sentinel-derived NDVI at 10 m every 5 days — the first scene after bud break is your baseline, across every block on the farm.' },
        { h: 'Flag the slow zones', t: 'Patches of the block at lower NDVI than the average get flagged for inspection.' },
        { h: 'Download the 5-zone KMZ', t: 'Export each block as a 5-zone NDVI KMZ and open it in Google Earth on your phone — walk straight to the flagged points instead of the whole 50 hectares.' },
      ],
      imagery: [
        img('budbreak-ndvi-farm.png', 'Early-season NDVI across the whole farm in RevToolbox — vigour painted block by block in the first weeks after bud break.', '16/10', 'data'),
        img('budbreak-ndvi-kmz-googleearth.jpg', 'The same blocks downloaded as a 5-zone NDVI KMZ and opened in Google Earth — field inspection in the palm of your hand.', '16/10', 'data'),
      ],
      services: ['ndvi'],
    },

    'Early canopy vigour read': {
      density: 'short',
      timing: 'Weeks 2–6 after bud break.',
      problem:
        'Vigour is your honest read on what the orchard thinks about this season. Soil, weather, ' +
        'last year\'s crop load — all of it shows up in the early canopy. Skip the read and you fly blind.',
      method: [
        { h: 'Run the 5-day cadence', t: 'NDVI scenes come in every 5 days through the early season.' },
        { h: 'Compare to last year', t: 'Same block, same week, last year vs. this year — instant signal on whether this season is ahead or behind.' },
        { h: 'Trigger early actions', t: 'A weak start triggers a foliar plan; a strong start triggers a thinning conversation.' },
      ],
      imagery: [
        img('budbreak-vigour-2024-vs-2025.png', 'The same block, 2024 vs 2025 at the start of the season — dual vigour maps with the time series zoomed into the bud-break window. Instantly shows whether this season is ahead or behind.', '16/10', 'data'),
      ],
      services: ['ndvi'],
    },

    'Bud-break VRA mapping': {
      density: 'short',
      timing: 'Bud break, before the first fertiliser pass.',
      problem:
        'Zones that ended last season low on reserves break bud behind — and a flat fertiliser ' +
        'rate leaves them short exactly where they need the most help. The gap widens before the ' +
        'season has really started.',
      method: [
        { h: 'Start from last season’s end map', t: 'The end-of-season vigour map shows which zones closed the year weak — low on the reserves that drive next spring’s growth.' },
        { h: 'Write the VRA prescription', t: 'Weak zones get a higher rate, strong zones less — a variable-rate fertiliser map that adds extra early-growth potential exactly where reserves ran short.' },
        { h: 'Send it to the spreader', t: 'Export the prescription (Standard or RedAnt) to the GPS spreader; the bud-break pass evens the block out from the first flush.' },
      ],
      imagery: [
        img('budbreak-vra-map.png', 'A bud-break VRA fertiliser prescription in RevToolbox — heavier rates on the zones that closed last season low on reserves, with per-zone totals.', '16/10', 'data'),
      ],
      services: ['ndvi', 'toolbox'],
    },

    'First-pass irrigation tuning': {
      density: 'short',
      timing: 'First weeks of active growth.',
      problem:
        'A single irrigation schedule for a varied block over-waters the heavy soil and ' +
        'under-waters the sandy patch. Both ends lose yield.',
      method: [
        { h: 'Schedule by zone', t: 'Each EMI zone gets its own irrigation schedule, informed by its probe.' },
        { h: 'Verify with NDVI response', t: 'NDVI tracks the canopy\'s response — if the schedule is right, vigour evens out.' },
      ],
      imagery: [
        img('budbreak-soil-vs-vigour.png', 'Canopy vigour (left) vs. soil EC (right) for the same block — where the two disagree, irrigation and soil have the work to do.', '16/9', 'data'),
      ],
      services: ['probe', 'ndvi'],
    },

    // ================= FLOWERING =================
    'Canopy uniformity check': {
      density: 'short',
      timing: 'Through bloom and into petal fall.',
      problem:
        'Flowering on an uneven canopy is uneven yield, full stop. You cannot fix the trees ' +
        'mid-bloom, but you CAN identify the patches and adjust pollination + thinning plans.',
      method: [
        { h: 'NDVI through bloom', t: 'Capture 2–3 scenes across the bloom window.' },
        { h: 'Flag the laggards', t: 'Persistently low-NDVI patches go on the priority list for ground inspection.' },
      ],
      imagery: [
        img('ndvi-mosaic.png', 'A bloom-window NDVI mosaic — uniformity is the goal; deviations are the work.'),
      ],
      services: ['ndvi'],
    },

    'Anomaly flagging (stress patches)': {
      density: 'short',
      timing: 'Through the bloom and early-set window.',
      problem:
        'Stress shows up in NDVI before it shows up to the eye. By the time you see the leaves ' +
        'curl from the road, the damage is already in the fruit set.',
      method: [
        { h: 'Compare to historical', t: 'Each new scene gets compared against the 3-year mean for the same week.' },
        { h: 'Drop a pin', t: 'Anomalies become field pins in the portal — the agronomist walks straight to them.' },
      ],
      imagery: [
        img('ndvi-mosaic.png', 'Anomalies stand out as patches that lag the rest of the mosaic.'),
        ph('Portal screenshot showing flagged anomalies as pins on the map'),
      ],
      services: ['ndvi'],
    },

    'Pollination block condition': {
      density: 'short',
      timing: 'Bloom window.',
      problem:
        'A weak block at bloom will not respond to extra hives. Better to know which blocks ' +
        'deserve the bee resources and which need a different plan.',
      method: [
        { h: 'Rank blocks by canopy', t: 'NDVI ranks blocks from strongest to weakest at bloom.' },
        { h: 'Allocate hives', t: 'Bees go to the blocks where they will actually move yield.' },
      ],
      imagery: [
        ph('Photo of a beehive in a strong-canopy block at peak bloom'),
      ],
      services: ['ndvi'],
    },

    'Blossom density mapping': {
      density: 'medium',
      timing: 'Full bloom — drive the block the same week the flowers open.',
      problem:
        'Flower load is never uniform across a block. A heavy patch that sets every blossom ' +
        'becomes an over-cropped zone by fruitset; a sparse patch may need to be left alone. ' +
        'Without a density map you apply the same rate everywhere and get the worst of both outcomes.',
      method: [
        { h: 'Drive at full bloom', t: 'RevScout S counts blossoms per tree as it moves — same hardware, same row-drive workflow as the fruit-count survey. Both sides of every tree in a single pass at 30 ha/day.' },
        { h: '5-zone density raster', t: 'Flower counts per tree interpolate into a continuous block raster and are auto-classified into 5 density bands: near-white (sparse) through to deep magenta (peak blossom load).' },
        { h: 'Ready in RevToolbox', t: 'The raster lands in RevToolbox on the same day as the drive — zone legend, per-zone statistics, and ready for export or VRA prescription generation.' },
      ],
      imagery: [
        img('blossom-density-map.png', 'RevToolbox · Block E2 · blossom density raster — 5 zones from near-white (15 flowers/tree) to deep magenta (354 flowers/tree). Selected date: 2023-10-13.', '16/9', 'data'),
      ],
      services: ['scout', 'toolbox'],
    },

    'Google Earth field calibration': {
      density: 'medium',
      timing: 'Immediately after the blossom density map is generated — while still at full bloom.',
      problem:
        'A density map without ground truth is just a colour pattern. The agronomist needs to ' +
        'stand in the block and cross-check what the camera counted against what they see on the ' +
        'tree. That calibration step is what turns a map into a confident prescription.',
      method: [
        { h: 'One-click KML export', t: 'Export the 5-zone blossom raster from RevToolbox as a KML overlay. No special app required — it opens directly in Google Earth on any phone.' },
        { h: 'Walk the block', t: 'The agronomist or scout walks the block with the density overlay live on the phone. Zone boundaries appear in the context of real satellite imagery — not an abstract data grid.' },
        { h: 'Calibrate dosages', t: 'Compare the zone colours to what is visible on the tree. Adjust the spray rates for each zone before the VRA prescription is finalised and sent to the sprayer.' },
      ],
      imagery: [
        img('blossom-googleearth-phone.jpg', 'Google Earth on phone with the KML blossom overlay open — "E2 – Blossom". The agronomist sees the density map in the field and calibrates prescription dosages against what the trees are showing.', '9/16', 'photo'),
      ],
      services: ['scout', 'toolbox'],
    },

    'VRA flower-thinning spray': {
      density: 'medium',
      timing: 'Immediately after the blossom density map is confirmed — at full bloom.',
      problem:
        'A blanket thinning application wastes chemical on lightly-loaded patches and under-applies ' +
        'on the heavy ones. The trees that need the most thinning get the same rate as trees ' +
        'that barely need any. Zone-targeted application is the only way to balance crop load from the start.',
      method: [
        { h: 'Blossom map → source raster', t: 'The 5-zone blossom-density raster becomes the input for a Variable Rate Application prescription — the same VRA engine used for fertiliser and vigour maps.' },
        { h: 'Assign rate per zone', t: 'Set a thinning agent rate (kg/ha or L/ha) per density zone. Low-density zones: zero or reduced rate to preserve fruitset. High-density zones: full rate. The portal shows per-zone area and total product before you commit.' },
        { h: 'Export to the sprayer', t: 'Download Standard (SHP), RedAnt, Trimble, John Deere or AGCO format. One click — the spray map is in the machine.' },
      ],
      imagery: [
        img('blossom-vra-map.png', 'RevToolbox · VRA Mapping tab · flower-thinning prescription for Block E2. Zone 4 tooltip: 75 kg/ha · 0.05 ha · 3.9 kg. Settings panel shows 5 zones, rate inputs 0 / 25 / 50 / 75 / 100 kg/ha.', '16/9', 'data'),
        img('blossom-density-map.png', 'The source raster: blossom density map that feeds directly into the VRA prescription engine.', '16/9', 'data'),
      ],
      services: ['scout', 'toolbox'],
    },

    // ================= FRUIT SET =================
    'Early counts + thinning guidance': {
      density: 'medium',
      timing: 'Just after fruit set — once fruit reaches ~20 mm, RevScout S can see it. RevField counts can start even earlier.',
      problem:
        'RevScout S only detects fruit reliably from around 20 mm. In the weeks before the camera ' +
        'can run, crop load is already being set. Early random counts with RevField — guided by the ' +
        'flower density map from bloom — give thinning teams actionable direction before the first camera pass.',
      method: [
        { h: 'RevField random counts', t: 'Scouts use the RevField app to record fruit counts across the block — either as random samples or targeted to zones identified on the blossom density map from flowering.' },
        { h: 'Flower-map-guided sampling', t: 'The blossom density zones (white to magenta) tell you exactly where to focus: sample the heavy zones first. RevField pins each count to GPS so the data maps back to the zone structure.' },
        { h: 'First RevScout S pass from 20 mm', t: 'Once fruit reaches 20 mm the camera can run. The RevScout S pass produces a per-tree count map across the whole block — the RevField early counts calibrate it immediately.' },
        { h: 'Guide the thinning teams', t: 'Heavy-zone trees get more time per tree. Light-zone trees are left or passed quickly. The zone map routes the teams — no more guessing which rows to prioritise.' },
      ],
      imagery: [
        img('revscout-step-4-zone-map.png', 'Early RevScout S 5-zone fruit-count map from the first camera pass at ~20 mm. Heavy zones (dark) direct thinning teams; light zones (pale) are left alone.', '16/9', 'data'),
        img('blossom-density-map.png', 'The blossom density map from flowering — used to guide RevField sampling points before the RevScout S camera can run.', '16/9', 'data'),
      ],
      services: ['scout', 'revfield'],
    },

    'In-season NDVI VRA mapping': {
      density: 'medium',
      timing: 'From fruit set onwards — using in-season vigour scenes, not end-of-last-season maps.',
      problem:
        'A VRA prescription built from last season\'s NDVI is already 6–9 months out of date ' +
        'by fruit set. This season\'s blocks may have shifted — strong blocks can weaken, ' +
        'weak blocks recover. Only an in-season vigour map reflects current reality.',
      method: [
        { h: 'Pull the current-season scene', t: 'RevToolbox\'s dual-map view shows two vigour layers side by side — or left layer vigour vs. right layer EC. Select in-season dates from the current year, not last season\'s archive.' },
        { h: 'Compare blocks in the same window', t: 'The dual map and time series confirm which blocks are performing above or below their own historical range right now — giving you a live zone picture for prescription writing.' },
        { h: 'Write the VRA prescription', t: 'From the Vigour Time Series tab, switch to VRA Mapping. Assign fertiliser or spray rates per zone based on current-season NDVI — high-vigour zones get less, low-vigour zones get more.' },
        { h: 'Export and apply', t: 'Download Standard, RedAnt or tractor-format shapefile. The in-season prescription corrects exactly where the block is now, not where it was.' },
      ],
      imagery: [
        img('fruitset-ndvi-dual-map.png', 'RevToolbox dual-map view · Block 6G3, Paul Cluver · Left: NDVI 2025-11-25 vs Right: NDVI 2024-11-25. In-season vigour comparison drives the VRA prescription — not last year\'s archive. Time series below shows 2-year seasonal trend with range and StDev.', '16/9', 'data'),
        img('vra-single-result.png', 'The resulting in-season VRA prescription map — zones driven by this season\'s canopy, not historical averages.', '16/9', 'data'),
      ],
      services: ['ndvi', 'toolbox'],
    },

    'Irrigation block monitoring': {
      density: 'medium',
      timing: 'From fruit set through cell division — when water stress costs the most.',
      problem:
        'A single irrigation schedule for a block with varied soil rarely fits all of it. ' +
        'Sandy northern sub-blocks dry out faster; heavy southern soils hold water longer. ' +
        'The mismatch shows in NDVI within days of a stress event — but only if you are looking ' +
        'at irrigation blocks separately, not averaging them into a single block number.',
      method: [
        { h: 'Enable irrigation blocks', t: 'In RevToolbox Block Inspector, tick "Show Irrigation Blocks". The block splits into its irrigation sub-units — each tracked independently.' },
        { h: 'NDVI vs. EC split view', t: 'Set the dual map to Left: Vigour, Right: 50 EC. The EC map reveals soil type; the NDVI map shows canopy response. Where they diverge — sandy EC + low NDVI — water management is the culprit.' },
        { h: 'Time series per irrigation block', t: 'The Block Timeseries tab separates the North and South (or other) irrigation blocks onto the same chart. An early dip in the North line on sandy soil identifies the irrigation schedule mismatch before it costs size.' },
        { h: 'Adjust schedules by soil zone', t: 'Sandy sub-blocks need shorter, more frequent irrigation; heavier soils need longer pulses. The diverging time series lines tell you which sub-block to adjust and when.' },
      ],
      imagery: [
        img('fruitset-irrigation-ndvi-ec.png', 'RevToolbox · Block 204 BBN, Ouplaas · Left: NDVI vigour (5 zones, green palette) · Right: 50 cm EC (5 zones, orange–brown palette) · Irrigation blocks enabled. Time series: 204 North (blue) vs 204 South (purple) — the northern block on sandy soil lags behind from early in the season, revealing the irrigation schedule mismatch.', '16/9', 'data'),
      ],
      services: ['ndvi', 'probe'],
    },

    // ── old fruitset entries kept for reference (no longer in PRACTICES) ──

    'Per-tree fruit count': {
      density: 'medium',
      timing: 'Just after fruit set, before the first thinning pass — typically 4–6 weeks after bloom.',
      problem:
        'You are about to make crop-load decisions for an entire block based on a walk-through of ' +
        'a few rows. The trees you walked might be the average; they might be the outliers. ' +
        'Either way, the actual count per tree across the whole block is invisible.',
      method: [
        { h: 'Drive the orchard', t: 'RevScout — a vehicle-mounted camera unit — drives every row, capturing imagery on both sides of the tree.' },
        { h: 'Count every tree', t: 'Computer vision counts visible fruit per tree, with on-board GPS tagging each tree\'s position.' },
        { h: 'Calibrate by zone', t: 'The block is split into 5 calibration zones; ground-truth counts in each zone correct the computer-vision estimate.' },
        { h: 'Output per-tree map', t: 'The block becomes a per-tree count map — one number per tree, visible in the portal.' },
      ],
      imagery: [
        img('revscout-orchard-pov.png', 'RevScout in the orchard — drives 4–8 km/h between rows.'),
        img('revscout-detection-real.png', 'Computer vision detects individual fruit on the canopy.', '16/10', 'data'),
        img('portal-block-nf16-targeted-calibration.png', 'Portal view: per-tree fruit count clustered into 5 zones, with targeted calibration points overlaid.', '16/10', 'data'),
      ],
      services: ['scout'],
    },

    '5-zone density mapping': {
      density: 'short',
      timing: 'Right after the RevScout pass.',
      problem:
        'A single average for a block is a useful number for accountants. For agronomists, it ' +
        'hides the entire reason your block is uneven.',
      method: [
        { h: 'Cluster the per-tree counts', t: 'We split the block into 5 density zones based on the actual count distribution.' },
        { h: 'Map to soil zones', t: 'Cross-referenced against EMI zones — does fruit-set track soil class? Almost always yes.' },
      ],
      imagery: [
        img('portal-block-pko04-random-calibration.png', 'Per-tree counts clustered into 5 density zones — the prescription input for thinning.', '16/10', 'data'),
        img('portal-farm-yield-paardekloof.png', 'Same logic, whole-farm: every block, every zone, in a single view.', '16/9', 'data'),
      ],
      services: ['scout', 'toolbox'],
    },

    'Early thinning prescription': {
      density: 'medium',
      timing: 'Within 2 weeks of the RevScout pass.',
      problem:
        'Thinning by feel — "this row looks heavy" — leaves money on the table. You over-thin ' +
        'the average rows and under-thin the heavy ones. Variable-rate thinning is the only way ' +
        'to actually balance crop load.',
      method: [
        { h: 'Per-zone thinning targets', t: 'For each of the 5 density zones, we compute how many fruit per tree to drop.' },
        { h: 'Hand-team route', t: 'The hand-thinning team gets a per-zone instruction — heavy-zone passes get more time per tree.' },
        { h: 'Verify with a re-scan', t: 'A RevScout pass after thinning shows whether the targets were hit.' },
      ],
      imagery: [
        img('portal-block-m12-targeted-calibration.png', 'Thinning prescription written onto the per-zone count map.', '16/10', 'data'),
        ph('Photo of a thinning team at work in a flagged heavy-density zone'),
      ],
      services: ['scout', 'toolbox'],
    },

    'Calibration of yield prediction': {
      density: 'short',
      timing: 'Through fruit set.',
      problem:
        'Yield predictions made before fruit set are guesses. Made after, with real per-tree counts, ' +
        'they become numbers you can sell against.',
      method: [
        { h: 'Plug counts into the model', t: 'Per-tree counts × estimated final fruit weight = first credible yield prediction.' },
        { h: 'Refine through the season', t: 'As Rev-Sizer measurements come in, the prediction tightens.' },
      ],
      imagery: [
        img('portal-farm-yield-paardekloof.png', 'Block-by-block yield calibration across a whole farm.', '16/9', 'data'),
        img('portal-block-pko10b-random-calibration.png', 'Per-block calibration view — ground-truth points plug into the model and tighten the prediction.', '16/10', 'data'),
      ],
      services: ['scout', 'toolbox'],
    },

    // ================= CELL DIVISION =================
    'Fruit size monitoring': {
      density: 'medium',
      timing: 'Cell division window — digital caliper from 12 mm, RevScout-S from 15–20 mm.',
      problem:
        'Fruit size during cell division sets the ceiling for final pack grade. Most growers don\'t ' +
        'start measuring until cell expansion — by which time the cell count is already locked in. ' +
        'Early spatial size data tells you which zones are behind before the window closes.',
      method: [
        { h: 'Digital caliper from 12 mm', t: 'The Rev-Sizer digital caliper can start logging measurements from 12 mm fruit — capturing the earliest size data in the block, zone by zone.' },
        { h: 'RevScout-S from 15–20 mm', t: 'Once fruit reaches 15–20 mm, the RevScout-S camera can run a sizing pass, producing a per-tree fruit size map across the entire block in a single drive.' },
        { h: 'Build the spatial size map', t: 'Measurements are interpolated into a 5-zone size raster in RevToolbox — immediately showing which zones are ahead and which lag, at a scale the grower can act on.' },
      ],
      imagery: [
        Object.assign(img('celldiv-fruit-size-camera-early.png', 'Early-season fruit size map from camera only — RevScout-S sizing pass at the start of cell division. Spatial size distribution visible across the block before manual calipers are even needed.', '16/9', 'data'), { objectPos: 'left center' }),
      ],
      services: ['scout', 'sizer'],
    },

    'Fruit size growth increments': {
      density: 'medium',
      timing: 'Weekly through cell division — tracking mm of growth per week per variety.',
      problem:
        'A single size measurement tells you where the fruit is. Weekly increments tell you ' +
        'whether the growth rate is on track — and flag a slowdown before it costs you a count grade. ' +
        'A dip in growth rate during cell division is almost always water or nutrition, and both can be fixed if you catch them early.',
      method: [
        { h: 'Measure on a weekly cadence', t: 'Run the caliper or RevScout-S weekly to build a per-block, per-variety growth increment curve (mm/week) across the season.' },
        { h: 'Track against the standard curve', t: 'The RevSizing platform plots your measured increments against standard growth benchmarks — showing whether each variety is above, on, or below expected weekly growth for the days-after-bloom moment.' },
        { h: 'Cross-reference soil moisture probes', t: 'A dip in weekly increment, confirmed by a dry reading on the probe, points directly at irrigation as the constraint. The increment chart is your early warning; the probe tells you why.' },
        { h: 'Act before the window closes', t: 'Water stress at cell division permanently reduces fruit cell count — the ceiling is set and cannot be recovered. Catching the slowdown here, not at harvest, is where size gains are made.' },
      ],
      imagery: [
        Object.assign(img('celldiv-fruit-size-increments.png', 'Variety fruit size growth increments (mm/week) across multiple farms and blocks — plotted against the standard growth curve. A dip below the standard band during cell division is the trigger to interrogate irrigation and nutrition.', '16/9', 'data'), { objectPos: 'center bottom' }),
      ],
      services: ['sizer', 'probe'],
    },

    'Variable-rate K application': {
      density: 'medium',
      timing: 'Cell division — the K window is early; potassium drives cell expansion from the start.',
      problem:
        'Potassium drives fruit size at cell division. A flat K rate ignores two independent sources of ' +
        'variability: crop load (high-yielding zones need more K per hectare) and soil texture ' +
        '(sandy, low-EC soils leach K easily and need higher doses; clay, high-EC soils retain K and ' +
        'need less). Applying one rate everywhere means under-feeding the heavy leachy zones and ' +
        'wasting expensive K on soils that don\'t need it.',
      method: [
        { h: 'Start from the calibrated yield map', t: 'Use the calibrated yield map (T/ha) from RevToolbox as the primary driver — zones producing more fruit need proportionally more K per hectare. This is the left-raster input.' },
        { h: 'Add the Soil EC adjustment', t: 'Layer the Soil EC map as the right raster to apply a percentage adjustment per zone. Low EC (sandy, easily leachable) = higher dose %. High EC (clay, good retention) = lower dose %. The two inputs combine into one prescription.' },
        { h: 'Set rates per zone in RevToolbox', t: 'In the VRA Mapping tab, enter Kg/ha per yield zone in the left raster, and the EC-driven % modifier per zone in the right raster. RevToolbox shows per-zone area, total product, and the combined output map before you commit.' },
        { h: 'Export and apply', t: 'Download in Standard, RedAnt, or tractor format. A single GPS-guided pass delivers the right rate to each zone.' },
      ],
      imagery: [
        img('celldiv-vra-k-toolbox.png', 'RevToolbox · VRA Mapping tab — K prescription combining yield map (left raster, Kg/ha by zone) with Soil EC adjustment (right raster, % modifier: Zone 1 low-EC sandy soils at 120%, Zone 5 high-EC clay at 70%). Dual map shows yield zone vs EC zone side by side.', '16/9', 'data'),
      ],
      services: ['toolbox', 'emi'],
    },

    'Targeted leaf sampling': {
      density: 'medium',
      timing: 'By cell division — enough satellite images have accumulated for reliable zone classification.',
      problem:
        'Not all parts of a block grow the same way, season after season. Identifying zones that ' +
        'consistently track together — and those that consistently diverge — is the foundation for ' +
        'targeted foliar sampling. A single satellite image won\'t reveal this; you need the stack ' +
        'of images from across the season, combined with what the soil tells you.',
      method: [
        { h: 'Select the first images of the season', t: 'In RevToolbox Zonal Reporting, select the first several satellite vigour images from the current season\'s list — typically the images collected from bud break through to now.' },
        { h: 'Combine with the soil scan', t: 'Layer the Soil EC data alongside the satellite stack. Zones are classified using both canopy behaviour AND underlying soil physics — not just surface greenness.' },
        { h: 'Generate the zonal report', t: 'The tool classifies the block into zones of consistent growing behaviour — areas that grow together through the season. Each zone represents a distinct management unit with its own vigour signature.' },
        { h: 'Target foliar sampling per zone', t: 'Send a scout to collect one foliar sample per zone, not random samples across the block. Zone-targeted sampling tells you exactly which management unit is deficient and where in the block to act.' },
      ],
      imagery: [
        img('celldiv-zonal-report.png', 'RevToolbox zonal report — first satellite vigour images of the season (2025-11-10, 2025-11-15, 2025-11-20) combined with 25 cm EC soil scan. Zones of consistent canopy behaviour identify where to collect targeted foliar samples.', '16/9', 'data'),
      ],
      services: ['ndvi', 'toolbox'],
    },

    // ================= CELL EXPANSION =================
    'Weekly fruit size measurements': {
      density: 'medium',
      timing: 'Weekly through cell expansion — measuring growth increments per variety and per block.',
      problem:
        'Fruit size at harvest is built week by week during cell expansion. A growth rate on track ' +
        'one week can stall the next — and if you are not measuring, you will not see it until the ' +
        'packhouse. Weekly increments reveal in real time whether your irrigation and nutrition ' +
        'program is translating into actual size gain.',
      method: [
        { h: 'Track weekly growth increments', t: 'Using the Rev-Sizer or RevScout-S, measure the same trees every week. The bar chart in the RevSizing Platform shows growth increment (mm/week) per date — immediately flagging whether the week\'s growth rate is above or below the previous period.' },
        { h: 'Cross-reference the EC map', t: 'Overlay weekly size data against the Soil EC dual map. The side-by-side view (fruit size left, EC right) shows whether sandy low-EC zones and clay high-EC zones are diverging in growth — pointing at irrigation management as the driver.' },
        { h: 'Compare two seasons on the same axis', t: 'RevToolbox Fruitsize tab lets you overlay Season 2025 and Season 2026 on the same DAFB curve. Seeing both lines instantly shows whether this season is ahead or behind — and from which stage the gap opened.' },
        { h: 'Act before the window closes', t: 'A stall in weekly increment, cross-checked against probe data, tells you whether to adjust irrigation frequency, apply a precision foliar, or trigger a late thinning pass on the heavy zones.' },
      ],
      imagery: [
        img('cellexp-fruit-size-increments-bar.png', 'Variety fruit size growth increments (mm/week) as a bar chart — two varieties (green vs red) plotted across DAFB. Week-on-week divergence points directly at irrigation or nutrition as the constraint.', '16/9', 'data'),
        img('cellexp-fruit-size-vs-ec-dual.png', 'Dual map: fruit size raster (left, 8-zone colour scale) vs soil EC raster (right) for the same block. Zones where size and EC diverge reveal where soil texture is driving size variation.', '16/9', 'data'),
        img('cellexp-fruit-size-timeseries.png', 'RevToolbox Fruitsize tab — Block OUPLAAS_401_RSG, Rosy Glow apples. Season 2025 (blue) vs Season 2026 (green) on the same DAFB axis, with block-level projections as dashed lines.', '16/9', 'data'),
      ],
      services: ['sizer', 'probe'],
    },

    'Canopy stress monitoring': {
      density: 'medium',
      timing: 'Through cell expansion — continuous satellite cadence tracking EVI and moisture stress per irrigation block.',
      problem:
        'Canopy stress during cell expansion costs fruit size permanently. But stress events rarely ' +
        'hit the whole block uniformly — irrigation sub-blocks respond differently depending on soil ' +
        'type. A single block average hides the signal. You need per-irrigation-block tracking, ' +
        'across multiple seasons, to separate structural problems from one-off events.',
      method: [
        { h: 'Track EVI per irrigation block', t: 'RevToolbox Vigour Time Series separates each irrigation sub-block as its own line — North and South tracked independently. EVI values per block through the season show relative canopy performance at the sub-block level.' },
        { h: 'Moisture stress index per block', t: 'The same time series plots moisture stress index data alongside EVI per irrigation block — showing periods where canopy behaviour diverged from what the irrigation inputs should have produced.' },
        { h: 'Four seasons on one interface', t: 'Pull four full seasons of the same block onto the chart. Patterns that repeat at the same DAFB window — a dip in February, a divergence between North and South from December — identify structural irrigation mismatches, not random events.' },
        { h: 'Diagnose by pattern type', t: 'A sharp dip in both irrigation blocks simultaneously points to a systemic event (heat, drought). A dip in one block only points to an irrigation mismatch or soil difference — the fix is targeted to that sub-block.' },
      ],
      imagery: [
        img('cellexp-evi-season-2223.png', 'Block 204 BBN — EVI Vigour Time Series, Season 2022/23. 204 North (blue) and 204 South (purple) tracked separately across the full season.', '16/9', 'data'),
        img('cellexp-evi-season-2324.png', 'Same block, Season 2023/24 — higher peak EVI, more pronounced seasonal decline, both irrigation blocks closely aligned.', '16/9', 'data'),
        img('cellexp-evi-season-2425.png', 'Season 2024/25 — sharp EVI dip in the North block (blue) in late February, while South (purple) holds steady. Classic single-block stress event.', '16/9', 'data'),
        img('cellexp-evi-season-2526.png', 'Season 2025/26 — four seasons of context now available. Recurring patterns across years identify the irrigation and soil issues worth addressing structurally.', '16/9', 'data'),
      ],
      services: ['ndvi', 'probe'],
    },

    'Late thinning correction': {
      density: 'medium',
      timing: 'Mid cell expansion — once the camera can see enough fruit to generate accurate load maps.',
      problem:
        'Early in the season, leaf cover obscures most fruit and camera counts underestimate crop ' +
        'load. By mid cell expansion, fruit is large enough and visible enough for RevScout S to ' +
        'produce accurate fruit load maps. This is the window where over-cropped zones become ' +
        'visible — and where a targeted late thin can still recover final size.',
      method: [
        { h: 'Accurate yield maps from camera', t: 'By mid cell expansion, RevScout S can see enough fruit relative to leaf area to generate reliable fruit load maps. The 5-zone yield raster shows which areas of the block are carrying above-target crop load.' },
        { h: 'Correlate with field hand counts', t: 'In the Yield Prediction tab, field hand counts from the thinning team are loaded as calibration points and correlated against camera counts. The R² value on the correlation plot confirms model accuracy — when it\'s tight, the yield estimate is credible.' },
        { h: 'Identify over-yielding zones', t: 'The zone table (Low through High) shows predicted Ton/ha per zone. Zones running significantly above target yield are flagged for a late thinning pass.' },
        { h: 'Targeted thinning only where needed', t: 'Only the over-cropped zones get the pass — the rest of the block is untouched. A blunt blanket correction costs volume you did not need to lose.' },
      ],
      imagery: [
        img('cellexp-yield-prediction-late-thin.png', 'RevToolbox Yield Prediction tab — Block VB07, fruit load map (5 zones, 17–190 fruit/tree). Yield Samples Correlation: field hand counts vs camera counts, R²=0.62. Zone table: Low (12.99 T/ha) through High (84.44 T/ha) — over-yielding zones flagged for late thinning.', '16/9', 'data'),
      ],
      services: ['scout', 'toolbox'],
    },

    // ================= VERAISON =================
    'Sugar / colour development': {
      density: 'medium',
      timing: 'Veraison through pre-harvest — combining end-of-season NDVI with the yield layer.',
      problem:
        'Ripeness is never uniform across a block. Areas carrying heavier crop loads ripen ' +
        'differently from lighter zones; areas with more vigorous canopy may hold colour back. ' +
        'Treating the whole block as one unit at harvest risks picking slow zones too early and ' +
        'fast zones too late — costing both quality and storage life.',
      method: [
        { h: 'Open Zonal Reporting at season end', t: 'In RevToolbox, navigate to Zonal Reporting and select the late-season NDVI images — the scenes from the veraison window through to now.' },
        { h: 'Add the yield layer', t: 'Layer the calibrated RevScout yield map (raw counts) alongside the late-season NDVI scenes. The combination reveals which areas carry heavy crop loads AND which are still actively green — the areas slowest to ripen.' },
        { h: 'Generate ripeness zones', t: 'The tool classifies the block into zones of consistent ripening behaviour — areas that track together through the senescence window. Each zone is a distinct monitoring unit with its own harvest timing signature.' },
        { h: 'Sample per zone at harvest', t: 'Maturity samples — starch, firmness, Brix — are taken per ripeness zone, not randomly across the block. Zone-targeted sampling gives the most accurate signal for pick timing per area.' },
      ],
      imagery: [
        img('veraison-ripeness-zones.png', 'RevToolbox zonal report — yield layer (top left, raw counts 31–89) combined with three late-season vigour images (Feb–Mar 2026). Four panels showing the spatial consistency of ripeness behaviour across the block.', '16/9', 'data'),
      ],
      services: ['ndvi', 'toolbox'],
    },

    'Harvest planning': {
      density: 'medium',
      timing: 'From veraison through to the harvest window — building the pick sequence and forward position.',
      problem:
        'Planning harvest across many blocks — each with different varieties, yield levels, fruit ' +
        'sizes and pick windows — requires all the data in one place, filterable by what matters ' +
        'right now. Separate spreadsheets and reports slow decisions and lose the connections ' +
        'between volume, size, and timing.',
      method: [
        { h: 'Farm Yield Summary Report', t: 'RevToolbox Yield Prediction Report puts every block on the farm in a single filterable table — Block name, Variety, Yield (T), Yield (T/Ha), Avg fruit weight, Area (Ha), sample count, and model accuracy. Filter by tag, variety or crop type. Download as CSV for the marketer or packhouse.' },
        { h: 'Fruit size distributions per block', t: 'In the Fruit Sizing App, the Fruit Distributions view shows the mm histogram and predicted count-grade distribution (4 through >1xxx) for any variety, season, farm, and block. Final measurement week distributions are shown per block and summarised as a total — exactly the format a packhouse needs to plan line settings.' },
        { h: 'Sequence the pick order', t: 'Cross-reference the yield table with the size distributions to sequence pick order — heaviest loaded, smallest fruit blocks first; lightest loaded, largest fruit last. The sequence comes from data, not from walking the block.' },
      ],
      imagery: [
        img('veraison-yield-summary-report.png', 'RevToolbox Farm Yield Summary Report — 101 blocks filterable by Block Name, Crop Type, Date, Tag, Variety. Columns: Yield T, T/Ha, Avg Fruit Weight, Area Ha, Samples, Accuracy. Downloadable for packhouse and marketing.', '16/9', 'data'),
        img('veraison-fruit-distributions.png', 'Fruit Sizing App — Fruit Distributions view. Variety: Nadorcott · Season 2026 · Mos Plaas. Left: mm size histogram. Right: predicted count grade distribution. Table: per-block count breakdown (4 through >1xxx) by count and percentage.', '16/9', 'data'),
      ],
      services: ['toolbox', 'sizer'],
    },

    'Precision sprays': {
      density: 'medium',
      timing: 'Veraison — targeting zones for retention, size gain, or colour response before harvest.',
      problem:
        'Late-season spray interventions — retention agents, colour promoters, size boosters — work ' +
        'best applied where the canopy actually needs them. A blanket application wastes product on ' +
        'zones already performing and misses zones that are behind. At veraison you have three maps ' +
        'that can drive a precision prescription: vigour, yield load, and fruit size.',
      method: [
        { h: 'Choose your source layer', t: 'In RevToolbox VRA Mapping, select the layer that best matches the problem: Vigour for canopy-driven interventions; Yield for crop-load-driven decisions; Fruit size raster for size-targeted applications.' },
        { h: 'Combine layers if needed', t: 'Use Map Combine Settings to blend two layers — e.g. yield map as primary driver with vigour as a percentage modifier. High-vigour + high-yield zones get a different rate from low-vigour + low-yield zones.' },
        { h: 'Set rates per zone', t: 'Assign the spray rate (L/ha or g/ha) per zone. Per-zone area and total product volume are calculated before you export — no surprises at the mixing shed.' },
        { h: 'Export to the sprayer', t: 'Download Standard, RedAnt, or tractor format. GPS-guided precision pass applies exactly the right rate in each zone.' },
      ],
      imagery: [
        img('veraison-vra-yield-vigour-dual.png', 'RevToolbox dual map — left: yield/fruit count raster (2026-01-22, 5 zones red–green, 7–288 fruit); right: vigour NDVI raster (2026-05-16, 5 zones, 0.34–0.54 index). The two layers are the inputs to a combined late-season VRA prescription.', '16/9', 'data'),
      ],
      services: ['toolbox', 'ndvi'],
    },

    // ================= HARVEST & POST-HARVEST =================
    'Zonal harvesting': {
      density: 'medium',
      timing: 'At harvest — combining NDVI and yield maps to guide pick sequencing and storage allocation.',
      problem:
        'Not all fruit in a block is the same quality at harvest. Over-vigorous zones in apples ' +
        'carry higher bitterpit and storage disorder risk; in wine and table grapes the same zones ' +
        'show differences in sugar and flavour. Picking the block as one unit misses these ' +
        'differences — which only show up post-storage. Zonal maps make them visible before the bins leave the farm.',
      method: [
        { h: 'Farm-level NDVI view', t: 'Start with the farm-level vigour map to compare blocks and identify which are carrying the highest end-of-season canopy load — the first signal of over-vigour risk.' },
        { h: 'Layer yield + vigour per block', t: 'In RevToolbox, combine the yield map (raw counts from RevScout) with the late-season NDVI vigour map. Zones with high vigour AND high yield load are the highest bitterpit and storage risk for apples; in other crops, these zones drive ripeness and taste differences.' },
        { h: 'Compare seasons year-on-year', t: 'Run the 2025 vs 2026 yield + vigour comparison on the same block. Zones that are consistently over-loaded are a structural issue — addressable with targeted pruning, irrigation adjustment, or VRA nutrition — not just a harvest decision.' },
        { h: 'Separate or prioritise', t: 'High-risk zones can be picked first, stored separately, or prioritised for CA storage. The zonal map gives the picker team and packhouse the information they need before the bins are filled.' },
      ],
      imagery: [
        img('harvest-farm-ndvi.png', 'Farm-level NDVI vigour map — 2026-01-29. Blocks at different vigour levels across the farm, with individual variation within each block visible at 10 m resolution.', '16/9', 'data'),
        img('harvest-vra-input-dual.png', 'RevToolbox dual map — post-harvest vigour (left, 2026-05-16, 5 zones 0.35–0.54) and yield/fruit count (right, 2025-12-01, 5 zones 3.9–108 fruit). High-vigour + high-yield zones are the bitterpit and storage risk areas.', '16/9', 'data'),
      ],
      services: ['ndvi', 'toolbox'],
    },

    'Pre-harvest scan for bin planning': {
      density: 'medium',
      timing: '2–4 weeks before pick — enough lead time to plan bin and storage allocation.',
      problem:
        'Bin and coolstore allocation is usually decided after harvest, when it is too late to ' +
        'optimise. Knowing the fruit size distribution of each block before it is picked lets you ' +
        'pre-plan which blocks go to which storage destination, and predict packout by count grade ' +
        'per bin before the first apple is off the tree.',
      method: [
        { h: 'Drive the RevScout-S sizing pass', t: 'Run the RevScout-S 2–4 weeks before pick. The onboard processor generates per-block size histograms immediately — no portal upload needed for a first-cut read.' },
        { h: 'Read the distribution per block', t: 'Each block’s histogram shows the mm distribution with a density curve overlay. Mean, median, and standard deviation per block show at a glance whether the size profile is tight or spread, and where the peak grade lands.' },
        { h: 'Pre-plan storage and bin routing', t: 'Blocks peaking at 65–68 mm go to one destination; those peaking at 57–60 mm with a spread distribution to another. The decision is made using data from the field, not estimated at packhouse intake.' },
      ],
      imagery: [
        img('harvest-revscout-histograms.png', 'RevScout-S processor output — size histograms for 5 blocks (204 BBN, 205, 210, 211, 212). Each histogram shows count frequency and density curve. Mean/median/Std/n stats per block. Size range 52–70 mm depending on block.', '16/9', 'data'),
      ],
      services: ['scout', 'toolbox'],
    },

    'Post-harvest VRA N & K': {
      density: 'medium',
      timing: 'Immediately after harvest — the most critical nutrition window of the year.',
      problem:
        'Post-harvest is when the tree rebuilds the reserves it will use next season. Trees that ' +
        'came off a heavy crop are depleted; trees that carried a light load have more left. A flat ' +
        'rate across the block ignores this and risks driving yield zones to flip through crop ' +
        'alternation. Zone-targeted post-harvest N and K is how you keep the block on a consistent trajectory year-on-year.',
      method: [
        { h: 'Read yield + post-harvest vigour together', t: 'The yield map shows which zones were over-worked this season. The post-harvest vigour map shows which zones ended the season depleted. Zones that are both high-yield AND low-post-harvest-vigour need the most N and K.' },
        { h: 'Build the VRA prescription', t: 'In RevToolbox VRA Mapping, set the yield map as the left raster (primary driver) and post-harvest vigour as the right raster (percentage modifier). Heavy-yield + weak-vigour zones get the highest rates; light-yield + strong-vigour get the lowest.' },
        { h: 'Prevent the alternation flip', t: 'Year-on-year comparison of yield zones shows the classic alternation pattern — the zones that over-yielded in 2025 under-yield in 2026. Post-harvest zone-targeted fertiliser is the primary intervention to prevent the flip before it locks in for the next season.' },
      ],
      imagery: [
        img('harvest-yield-vigour-2026.png', 'Block-level dual map 2026 — yield raster (left, 8 zones, 5–148 raw counts) vs vigour NDVI (right, 8 zones, 0.39–0.48 index). Zones that over-yielded and stayed vigorous are first candidates for post-harvest N & K.', '16/9', 'data'),
        img('harvest-yield-vigour-2025.png', 'Same block, 2025 — year-on-year yield and vigour compared. Zones that repeat the same pattern confirm structural imbalances the post-harvest prescription needs to correct.', '16/9', 'data'),
      ],
      services: ['toolbox', 'ndvi'],
    },
  };
})();
