Single-use to
reusable, decoded.
An operational map of packaging replacements under EU Regulation 2025/40. Filter by deadline, PPWR status, CapEx band, and complexity to find which transitions to prioritise.
<div id="rotion-navigator-root"></div> <style> @import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,700&family=JetBrains+Mono:wght@400;500;600&family=Inter:wght@300;400;500;600;700&display=swap'); #rotion-navigator-root { --bg: #f5f2ec; --fg: #1a1a1a; --accent: #d4ff3a; --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; --font-display: 'Fraunces', Georgia, serif; --font-mono: 'JetBrains Mono', 'Courier New', monospace; background: var(--bg); color: var(--fg); font-family: var(--font-body); width: 100%; box-sizing: border-box; } #rotion-navigator-root *, #rotion-navigator-root *::before, #rotion-navigator-root *::after { box-sizing: border-box; } .rn-container { max-width: 1600px; margin: 0 auto; padding: 0 32px; } .rn-horizon-bar { background: linear-gradient(to bottom, rgba(26,26,26,0.02), transparent); padding: 24px 0; } .rn-horizon-inner { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; } .rn-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(26,26,26,0.5); } .rn-label-medium { color: rgba(26,26,26,0.6); } .rn-segmented { display: inline-flex; align-items: center; background: rgba(26,26,26,0.05); padding: 4px; } .rn-segmented button { padding: 8px 20px; font-size: 12px; font-weight: 500; background: transparent; color: rgba(26,26,26,0.7); border: none; cursor: pointer; font-family: var(--font-body); transition: all 0.15s; } .rn-segmented button.active { background: var(--fg); color: var(--accent); } .rn-horizon-caption { font-size: 12px; color: rgba(26,26,26,0.6); font-style: italic; font-family: var(--font-display); } .rn-controls { border-top: 1px solid rgba(26,26,26,0.2); border-bottom: 1px solid rgba(26,26,26,0.2); padding: 20px 0; } .rn-controls-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; } .rn-search-wrapper { position: relative; flex: 1; min-width: 260px; max-width: 380px; } .rn-search-wrapper svg.search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: rgba(26,26,26,0.4); pointer-events: none; } .rn-search-wrapper input { width: 100%; background: transparent; border: 1px solid rgba(26,26,26,0.3); padding: 10px 40px 10px 40px; font-size: 14px; color: var(--fg); font-family: var(--font-body); } .rn-search-wrapper input:focus { outline: none; border-color: var(--fg); } .rn-search-clear { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); background: transparent; border: none; cursor: pointer; color: rgba(26,26,26,0.4); font-size: 18px; line-height: 1; padding: 0; } .rn-search-clear:hover { color: var(--fg); } .rn-filter-group { display: flex; align-items: center; gap: 8px; } .rn-filter-btn { padding: 6px 12px; font-size: 12px; font-weight: 500; background: transparent; color: var(--fg); border: none; cursor: pointer; font-family: var(--font-body); transition: all 0.15s; } .rn-filter-btn:hover:not(.active) { background: rgba(26,26,26,0.05); } .rn-filter-btn.active { background: var(--fg); color: var(--accent); } .rn-count { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: rgba(26,26,26,0.6); } .rn-count-total { opacity: 0.5; } .rn-table-wrap { padding: 32px 0; overflow-x: auto; } .rn-table { width: 100%; border-collapse: collapse; min-width: 900px; } .rn-table thead tr { border-bottom: 2px solid var(--fg); } .rn-table th { text-align: left; padding: 12px 12px 12px 0; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(26,26,26,0.5); font-weight: 400; } .rn-sort-btn { display: inline-flex; align-items: center; gap: 4px; background: transparent; border: none; padding: 0; cursor: pointer; font-family: inherit; font-size: inherit; letter-spacing: inherit; text-transform: inherit; color: rgba(26,26,26,0.5); font-weight: 400; } .rn-sort-btn.active { color: var(--fg); font-weight: 600; } .rn-sort-arrow { font-size: 8px; } .rn-table tbody tr.rn-data-row { border-bottom: 1px solid rgba(26,26,26,0.1); cursor: pointer; transition: background 0.15s; } .rn-data-row:hover { background: rgba(212,255,58,0.08); } .rn-data-row.expanded { background: rgba(26,26,26,0.05); } .rn-table td { padding: 16px 12px 16px 0; vertical-align: top; } .rn-row-num-wrap { display: flex; align-items: center; gap: 8px; } .rn-row-num { font-family: var(--font-mono); font-size: 10px; color: rgba(26,26,26,0.4); } .rn-chevron { font-size: 12px; color: rgba(26,26,26,0.4); } .rn-category { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase; color: rgba(26,26,26,0.6); line-height: 1.3; max-width: 130px; } .rn-single-use { font-size: 13px; line-height: 1.4; color: rgba(26,26,26,0.7); max-width: 320px; text-decoration: line-through; text-decoration-color: rgba(26,26,26,0.3); } .rn-reusable { font-size: 13px; line-height: 1.4; font-weight: 500; max-width: 320px; } .rn-status-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; font-size: 11px; font-weight: 500; letter-spacing: 0.03em; text-transform: uppercase; font-family: var(--font-body); white-space: nowrap; } .rn-status-badge.mandatory { background: var(--fg); color: var(--accent); } .rn-status-badge.recommended { background: transparent; color: var(--fg); border: 1px solid var(--fg); } .rn-status-dot { width: 6px; height: 6px; border-radius: 50%; } .rn-status-badge.mandatory .rn-status-dot { background: var(--accent); } .rn-status-badge.recommended .rn-status-dot { background: var(--fg); } .rn-num-display { font-family: var(--font-display); font-size: 20px; font-weight: 500; line-height: 1; } .rn-capex-wrap { display: flex; align-items: center; gap: 6px; } .rn-capex-symbol { font-family: var(--font-display); font-size: 18px; font-weight: 500; line-height: 1; letter-spacing: -0.02em; } .rn-capex-tier { font-family: var(--font-mono); font-size: 10px; color: rgba(26,26,26,0.4); letter-spacing: 0.05em; } .rn-complexity-wrap { display: flex; align-items: center; gap: 8px; } .rn-complexity-bars { display: flex; gap: 2px; } .rn-complexity-bar { height: 16px; width: 6px; background: rgba(26,26,26,0.15); } .rn-complexity-bar.filled { background: var(--fg); } .rn-complexity-label { font-size: 12px; font-weight: 500; color: var(--fg); } .rn-expanded-row { background: var(--fg); color: var(--bg); } .rn-expanded-content { padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 32px; animation: rnSlideDown 0.2s ease-out; } @keyframes rnSlideDown { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } .rn-exp-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(245,242,236,0.5); margin-bottom: 12px; } .rn-exp-label.accent { color: var(--accent); margin-bottom: 4px; } .rn-exp-text { font-size: 13px; line-height: 1.6; color: rgba(245,242,236,0.9); margin: 0; } .rn-exp-text.muted { color: rgba(245,242,236,0.8); font-size: 12px; } .rn-exp-divider { border-top: 1px solid rgba(245,242,236,0.15); padding-top: 12px; margin-top: 12px; } .rn-exp-divider.big { padding-top: 16px; margin-top: 16px; } .rn-capex-big { font-family: var(--font-display); font-size: 32px; font-weight: 500; line-height: 1; } .rn-capex-range { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(245,242,236,0.5); margin-top: 4px; } .rn-payback-num { font-family: var(--font-display); font-size: 28px; font-weight: 500; line-height: 1; } .rn-payback-unit { font-size: 14px; font-family: var(--font-mono); font-weight: 400; color: rgba(245,242,236,0.5); letter-spacing: 0.05em; } .rn-empty { padding: 80px 0; text-align: center; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(26,26,26,0.4); } .rn-legend { padding: 0 0 32px; border-top: 1px solid rgba(26,26,26,0.1); padding-top: 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; } .rn-legend-item > div + div { margin-top: 8px; } .rn-legend-row { display: flex; align-items: center; gap: 12px; } .rn-legend-text { font-size: 12px; color: rgba(26,26,26,0.7); } .rn-legend-symbol { font-family: var(--font-display); font-size: 15px; font-weight: 500; color: var(--fg); margin-right: 10px; } .rn-methodology { border-top: 1px solid rgba(26,26,26,0.1); padding: 24px 0 32px; } .rn-methodology p { font-size: 12px; line-height: 1.7; color: rgba(26,26,26,0.6); max-width: 960px; margin: 0; } </style> <script> (function() { 'use strict'; var data = [ { id: 1, category: "Transport & Logistics", singleUse: "Cardboard shipping boxes (B2B transport)", reusable: "Foldable/nestable plastic crates or totes", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "40% transport reuse target by 2030, 70% by 2040", ppwrDetail: "Art. 29 transport packaging reuse target: 40% by 2030, 70% by 2040 (indicative). Applies to B2B shipments between sites or partner enterprises (100% target).", roi: "8-14", complexity: "Low", capex: "€€", capexNote: "Per-crate unit cost moderate; scales with fleet size. Tracking layer adds per-asset cost.", complexityNote: "Drop-in replacement. Only process change is return logistics. Compatible with existing conveyors, WMS, forklifts.", sector: "Cross-sector" }, { id: 2, category: "Transport & Logistics", singleUse: "Stretch wrap / pallet film (LDPE)", reusable: "Reusable pallet covers (Bearhug, Return2Sender, elastic nets)", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Supports 2030 transport reuse and 2030 waste reduction targets", ppwrDetail: "Counts toward Art. 29 transport reuse target. Reduces plastic waste footprint under Art. 43 waste reduction targets (-5% by 2030, -15% by 2040).", roi: "6-12", complexity: "Low", capex: "€", capexNote: "Low per-unit cost. No equipment changes. Scales incrementally with pallet volume.", complexityNote: "Minimal operational change. Requires stock of covers and return loop. No equipment changes.", sector: "Cross-sector" }, { id: 3, category: "Transport & Logistics", singleUse: "Single-use wooden pallets (one-way)", reusable: "Pooled standardised pallets (EUR/EPAL, CHEP-style)", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Supports Art. 29 B2B transport target 100% by 2030", ppwrDetail: "Already mature pooling model; reinforced by Art. 29 B2B transport targets. EPR eco-modulation will penalise single-use alternatives.", roi: "4-10", complexity: "Low", capex: "€", capexNote: "Operational expense via pooling service; no ownership CapEx.", complexityNote: "Mature pooling ecosystem exists. Main change is service contract vs. purchasing.", sector: "Cross-sector" }, { id: 4, category: "Transport & Logistics", singleUse: "Big bags / FIBCs for bulk goods", reusable: "Reusable palletboxes or reusable IBCs", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 transport reuse 40% by 2030; 70% by 2040", ppwrDetail: "Falls under Art. 29 transport reuse targets where applicable. Bulk contact packaging has conditional exemptions depending on product (food/chemical).", roi: "18-30", complexity: "High", capex: "€€€", capexNote: "Palletbox unit cost €100 to €800+ plus filling/discharge stations, dust management, cleaning infrastructure. Significant fleet investment.", complexityNote: "Unloading paradigm shift: from cut-and-dump to tilt/vacuum extraction. Often requires new filling and discharge stations, dust management, cleaning infrastructure.", sector: "Chemicals, food ingredients, agriculture" }, { id: 5, category: "Transport & Logistics", singleUse: "Corrugated trays for grouped transport", reusable: "Returnable Plastic Containers (RPCs), stackable trays", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Grouped packaging (non-cardboard) 10% reuse by 2030, 25% by 2040", ppwrDetail: "Art. 29 grouped packaging (non-cardboard) reuse target: 10% by 2030, 25% by 2040. Cardboard exempt but RPC systems count toward overall 40% transport target.", roi: "10-18", complexity: "Medium", capex: "€€", capexNote: "RPC unit cost plus pooling/wash infrastructure. Usually accessed via service model (EPS, IFCO).", complexityNote: "Needs pooling infrastructure, wash cycles, reverse logistics. Widely adopted in FMCG/produce (EPS, IFCO model).", sector: "FMCG, produce, grocery" }, { id: 6, category: "Fresh Produce & Retail", singleUse: "Plastic trays, nets, bags for fresh fruit & veg <1.5kg", reusable: "Reusable retail crates, open display in bulk bins", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Hard EU-wide ban from 1 Jan 2030", ppwrDetail: "Art. 25 + Annex V: EU-wide BAN from 1 Jan 2030 on single-use plastic packaging for unprocessed fresh produce under 1.5kg (limited safety exceptions).", roi: "12-20", complexity: "Medium", capex: "€€", capexNote: "Shelf and merchandising redesign, crate fleet, checkout process changes. Store-level rollout cost.", complexityNote: "Shelf and merchandising redesign. Hygiene and shrinkage concerns. Checkout process may need SKU identifiers on crates, not items.", sector: "Grocery retail, produce suppliers" }, { id: 7, category: "Fresh Produce & Retail", singleUse: "Cardboard fruit crates (one-way)", reusable: "Foldable plastic fruit/veg crates (pooling)", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Supports Art. 29 transport reuse 40% by 2030", ppwrDetail: "Counts toward Art. 29 transport reuse. Well-established via EPS, Euro Pool, IFCO. Eco-modulation of EPR fees will favour reusables.", roi: "8-14", complexity: "Low", capex: "€", capexNote: "Typically accessed via pooling service (OpEx not CapEx). Pay-per-trip model.", complexityNote: "Mature pooling ecosystem. Retailer-supplier coordination needed but industry standard exists.", sector: "Grocery retail, produce" }, { id: 8, category: "Fresh Produce & Retail", singleUse: "Single-use plastic packaging for mushrooms, berries, soft fruits", reusable: "Reusable deposit-return trays (Repasys-style)", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Under Art. 25 <1.5kg produce ban from 2030", ppwrDetail: "Under the <1.5kg fresh produce ban (Art. 25 + Annex V) from 2030. Reusable deposit systems are the primary compliant replacement.", roi: "14-24", complexity: "Medium", capex: "€€", capexNote: "Deposit system infrastructure, return points, consumer-facing tracking. Proven at retailer scale in Belgian pilots.", complexityNote: "Requires deposit system, consumer education, return points at retail. Proven in Belgian pilots.", sector: "Grocery retail" }, { id: 9, category: "HORECA & Takeaway", singleUse: "Single-use plastic cups, plates, cutlery (dine-in)", reusable: "Reusable tableware, washable cups, branded mugs", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Hard EU-wide ban from 1 Jan 2030", ppwrDetail: "Art. 25 + Annex V: EU-wide BAN from 1 Jan 2030 for on-site HORECA consumption. Includes cups, plates, trays, service-ware.", roi: "6-12", complexity: "Low", capex: "€", capexNote: "Tableware restock (typically already exists in most venues). Dishwasher capacity may need upgrading.", complexityNote: "Requires dishwashing capacity. Cost savings usually rapid given per-unit price differential.", sector: "HORECA, events" }, { id: 10, category: "HORECA & Takeaway", singleUse: "Takeaway cups and containers (coffee, food-to-go)", reusable: "Reusable takeaway container systems (Vytal, Recup, Billie Cup)", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "2028 offer obligation; 10% reuse by 2030; 40% indicative by 2040", ppwrDetail: "Art. 29: from 2028 operators must offer consumer-owned container option and reusable/refill option. 10% reusable target by 2030 (endeavour), scaling toward 40% by 2040.", roi: "18-30", complexity: "High", capex: "€€", capexNote: "Deposit infrastructure, cleaning logistics, multi-venue interoperability platform, consumer-facing app.", complexityNote: "Needs deposit system, cleaning logistics, consumer adoption, multi-venue interoperability. Tracking essential.", sector: "HORECA, cafes, QSR" }, { id: 11, category: "HORECA & Takeaway", singleUse: "Single-serve sachets (sauce, sugar, creamer, seasoning)", reusable: "Bulk dispensers, refillable condiment stations", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Hard EU-wide ban from 1 Jan 2030", ppwrDetail: "Art. 25 + Annex V: BAN from 1 Jan 2030 on single-use plastic sachets in HORECA for condiments, sauces, sugar, seasoning, creamer.", roi: "8-16", complexity: "Medium", capex: "€", capexNote: "Dispenser units per venue. Low per-station cost but scales with venue count.", complexityNote: "Hygiene compliance, dispenser maintenance, portion control. Staff training required.", sector: "HORECA, QSR" }, { id: 12, category: "HORECA & Takeaway", singleUse: "Hotel miniature toiletries (shampoo, shower gel, body lotion)", reusable: "Wall-mounted refillable dispensers", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Hard EU-wide ban from 1 Jan 2030", ppwrDetail: "Art. 25 + Annex V: BAN from 1 Jan 2030 on single-use plastic packaging for cosmetics/hygiene in the accommodation sector.", roi: "12-20", complexity: "Medium", capex: "€€", capexNote: "Dispenser installation across all rooms, refilling operations, brand-compliant design. Scales with room count.", complexityNote: "Dispenser installation across rooms, refilling operations, brand experience redesign.", sector: "Hospitality, accommodation" }, { id: 13, category: "Beverage", singleUse: "Single-use PET bottles, aluminium cans (beverages)", reusable: "Refillable glass or PET bottles (deposit-return)", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "10% reuse by 2030, 40% by 2040; 90% collection SUP bottles/cans by 2029", ppwrDetail: "Art. 29 beverage reuse target: 10% by 2030, 40% by 2040 (with exceptions for wine, spirits, milk). DRS mandatory for Member States not hitting 90% collection for single-use bottles and cans by 2029.", roi: "24-48", complexity: "High", capex: "€€€", capexNote: "Bottling line adaptation, inspection systems, wash infrastructure, reverse logistics fleet. Major CapEx requiring multi-year amortisation.", complexityNote: "Major CapEx: bottling line adaptation, inspection systems, reverse logistics, wash infrastructure. Clear ROI at scale.", sector: "Beverage producers, bottlers" }, { id: 14, category: "Beverage", singleUse: "Shrink-wrap multipacks (bundled bottles/cans)", reusable: "Reusable crates, carriers, baskets", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Hard EU-wide ban on SUP grouped packaging at POS from 1 Jan 2030", ppwrDetail: "Art. 25 + Annex V: BAN from 1 Jan 2030 on single-use plastic grouped packaging at point of sale (purely promotional bundling).", roi: "10-18", complexity: "Medium", capex: "€€", capexNote: "Bottling line end-of-line changes, crate fleet, pooling infrastructure.", complexityNote: "Bottling line end-of-line changes. Crate pooling infrastructure. Retailer shelf standards.", sector: "Beverage, retail" }, { id: 15, category: "Beverage", singleUse: "Cardboard beer/soft drink multipack trays", reusable: "Returnable beverage crates", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Supports 10%/40% beverage reuse targets", ppwrDetail: "Counts toward 10%/40% beverage reuse targets. Standard practice in mature beverage markets (Germany, Belgium, Netherlands).", roi: "14-22", complexity: "Medium", capex: "€€", capexNote: "Crate fleet, deposit integration, retailer coordination.", complexityNote: "Retailer coordination critical. Industry standards exist. Deposit integration.", sector: "Beverage, brewery" }, { id: 16, category: "E-commerce", singleUse: "Single-use cardboard shipping boxes with void fill", reusable: "Reusable shipping bags/boxes (RePack, LivingPackets, Opopop)", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "40% e-commerce transport reuse by 2030, 70% by 2040; 50% empty-space cap from 2030", ppwrDetail: "Art. 29 e-commerce transport reuse target: 40% by 2030, 70% by 2040. Art. 24: 50% empty-space ratio cap from 2030 also pushes redesign.", roi: "18-36", complexity: "High", capex: "€€", capexNote: "Reusable mailer/box fleet, reverse logistics network, consumer-facing return infrastructure.", complexityNote: "Reverse logistics for B2C is the hardest variable. Works best with closed-loop retailers or subscription models. Consumer behaviour change needed.", sector: "E-commerce, D2C brands" }, { id: 17, category: "E-commerce", singleUse: "Bubble wrap, air pillows, paper void fill", reusable: "Reusable protective inserts, foam shaped inserts", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 10 minimisation from 2026; 50% empty-space cap from 2030", ppwrDetail: "Supports Art. 10 minimisation (from 2026) and 50% empty-space cap (2030). EPR eco-modulation will penalise single-use fill.", roi: "12-20", complexity: "Medium", capex: "€", capexNote: "Foam/insert tooling for standard SKUs. Low cost in closed-loop B2B, higher complexity in B2C.", complexityNote: "Works well in closed-loop B2B. More complex in open B2C. SKU-to-insert matching for multi-SKU ops.", sector: "E-commerce, electronics, fragile goods" }, { id: 18, category: "Industrial & B2B", singleUse: "Single-use plastic drums, jerrycans for chemicals/liquids", reusable: "Reusable IBCs, stainless steel drums, returnable jerrycans", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 B2B: 100% reuse target between sites of same/partner enterprises", ppwrDetail: "Art. 29 B2B transport: 100% reuse target for packaging between sites of same or partner enterprises. EPR eco-modulation penalises single-use.", roi: "14-24", complexity: "Medium", capex: "€€", capexNote: "IBC/drum fleet plus cleaning and decontamination infrastructure. Existing rental/pool market reduces CapEx exposure.", complexityNote: "Cleaning/decontamination infrastructure is the main lift (especially for chemicals). Strong existing market for IBCs.", sector: "Chemicals, lubricants, food ingredients" }, { id: 19, category: "Industrial & B2B", singleUse: "EPS foam boxes (temperature-sensitive goods)", reusable: "Insulated reusable cool boxes with phase-change materials", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Supports Art. 10 minimisation and Art. 29 transport reuse", ppwrDetail: "Supports Art. 10 minimisation and Art. 29 transport reuse. EPS increasingly restricted under national law and recyclability grade rules.", roi: "16-28", complexity: "High", capex: "€€€", capexNote: "Insulated box units are high unit-cost (€100 to €500+). Phase-change material conditioning infrastructure. Critical for pharma cold chain.", complexityNote: "CapEx on insulated boxes is significant. Reverse logistics and conditioning cycles required. Critical for pharma cold chain.", sector: "Pharma, cold chain, seafood, meal kits" }, { id: 20, category: "Industrial & B2B", singleUse: "Cardboard gaylord boxes / one-way palletboxes", reusable: "Foldable plastic palletboxes (injection-moulded)", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 B2B 100% reuse target where applicable", ppwrDetail: "Art. 29 B2B transport 100% target where applicable. Strong EPR eco-modulation incentive. Durability of HDPE/PP palletboxes gives high rotation counts.", roi: "18-30", complexity: "Medium", capex: "€€€", capexNote: "Palletbox unit cost €100 to €800 depending on design. Fleet investment significant; amortises over 50+ rotations.", complexityNote: "Handling equipment usually compatible. Folding mechanism reduces return transport cost. Initial unit cost is higher.", sector: "Manufacturing, automotive parts, industrial" }, { id: 21, category: "Automotive & Parts", singleUse: "Single-use cardboard/foam dividers for parts", reusable: "Reusable dunnage, custom-fit plastic trays", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 B2B closed-loop 100% reuse target", ppwrDetail: "Art. 29 B2B closed-loop: 100% reuse target. Automotive is already a mature reusable dunnage sector (VDA standards).", roi: "12-20", complexity: "Medium", capex: "€€", capexNote: "Custom tooling for part-specific dunnage. VDA/Odette standards reduce design cost.", complexityNote: "Tooling investment for custom dunnage. Existing industry standards (VDA, Odette) ease adoption.", sector: "Automotive, aerospace, industrial" }, { id: 22, category: "Fashion & Retail", singleUse: "Polybags / dust covers for garments in transit", reusable: "Reusable garment covers / shipping bags", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Supports Art. 29 transport reuse 40% by 2030", ppwrDetail: "Art. 29 transport reuse target 40% by 2030. Fashion industry pressure on single-use polybags accelerates voluntary adoption.", roi: "14-24", complexity: "Medium", capex: "€", capexNote: "Fabric/polymer cover unit cost is low. Scales with garment throughput.", complexityNote: "Works well in closed-loop (DC to store). Harder in open B2C e-commerce. Brand experience considerations.", sector: "Fashion, apparel retail" }, { id: 23, category: "Fashion & Retail", singleUse: "Cardboard hanger boxes, garment cartons", reusable: "Reusable hanging garment racks/containers", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 transport reuse target 40% by 2030", ppwrDetail: "Art. 29 transport target (40%/70%). Common in apparel DC-to-store (GOH, garment on hanger).", roi: "16-24", complexity: "Medium", capex: "€€", capexNote: "Rack fleet plus truck fitment. Closed-loop DC-to-store reduces reverse logistics cost.", complexityNote: "Closed-loop between DC and store works well. Requires truck fitment, rack pooling.", sector: "Fashion retail" }, { id: 24, category: "Agriculture & Horticulture", singleUse: "Single-use plastic plant trays, pots", reusable: "Reusable multi-use nursery trays", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 B2B 100% reuse target closed-loop grower-retailer", ppwrDetail: "Art. 29 B2B transport 100% target for closed-loop between grower and retailer. EPR eco-modulation favours reusables.", roi: "12-20", complexity: "Medium", capex: "€€", capexNote: "Tray fleet investment. CC Container pooling model already established for larger units.", complexityNote: "CC (Container Centralen) model well established in horticulture. Expansion to smaller trays is next step.", sector: "Horticulture, nurseries" }, { id: 25, category: "Agriculture & Horticulture", singleUse: "Single-use plastic sacks (feed, seed, fertiliser)", reusable: "Reusable FIBCs/big bags with tracking", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 B2B transport target; supports Art. 43 waste reduction", ppwrDetail: "Art. 29 B2B transport target. Supports waste reduction under Art. 43. Tracking ensures return loop integrity.", roi: "16-28", complexity: "High", capex: "€€", capexNote: "FIBC unit cost plus cleaning infrastructure and tracking layer. Reverse logistics to dispersed rural sites adds cost.", complexityNote: "Cleaning between uses (contamination risk), tracking, return logistics to rural/dispersed sites.", sector: "Agriculture, animal feed" }, { id: 26, category: "Construction", singleUse: "Plastic film wrap on building materials", reusable: "Reusable construction packaging covers", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 B2B transport; eco-modulation pressure by 2030", ppwrDetail: "Art. 29 B2B transport. Low adoption currently but eco-modulation and waste targets will push change by 2030.", roi: "18-36", complexity: "High", capex: "€€", capexNote: "Durable covers for harsh site conditions. Return logistics in fragmented construction supply chain is the main cost driver.", complexityNote: "Site-to-site coordination, durability in harsh conditions, return loops in fragmented construction supply chain.", sector: "Construction, building materials" }, { id: 27, category: "Construction", singleUse: "Cardboard boxes for fittings, fixtures, hardware", reusable: "Stackable returnable tote systems", ppwrStatus: "Mandatory", deadline: 2030, deadlineNote: "Art. 29 transport reuse 40% by 2030", ppwrDetail: "Art. 29 transport reuse target 40% by 2030. Wholesale distribution to contractors is closed-loop friendly.", roi: "10-18", complexity: "Medium", capex: "€€", capexNote: "Tote fleet via distributor network (e.g. Lecot, Gamma Wopla). Route density makes return economics favourable.", complexityNote: "Works well with distributor networks (Lecot, Gamma Wopla, etc.). Crate return via route density.", sector: "Construction, hardware wholesale" }, { id: 28, category: "Postal & Express", singleUse: "Single-use padded mailers (jiffy bags)", reusable: "Reusable padded shipping envelopes", ppwrStatus: "Recommended", deadline: 2030, deadlineNote: "Art. 29 e-commerce target 40% by 2030; Art. 10 minimisation from 2026", ppwrDetail: "Art. 29 e-commerce target 40% by 2030. Art. 10 minimisation from 2026. Low-hanging fruit for subscription and rental models.", roi: "14-24", complexity: "Medium", capex: "€", capexNote: "Mailer unit cost low. Return label and drop-off network costs via existing postal infrastructure.", complexityNote: "Strong fit for B2B or subscription B2C. Prepaid return labels, drop-off network, consumer compliance.", sector: "E-commerce, subscriptions, rental" } ]; var statusOrder = { Mandatory: 0, Recommended: 1 }; var complexityOrder = { Low: 0, Medium: 1, High: 2 }; var capexOrder = { "€": 0, "€€": 1, "€€€": 2 }; var state = { search: "", sortBy: "category", sortDir: "asc", filterStatus: "all", filterComplexity: "all", filterCapex: "all", horizon: "all", expandedRow: null }; function escapeHtml(str) { if (str == null) return ""; return String(str) .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function getFiltered() { var q = state.search.toLowerCase(); var result = data.filter(function(item) { var matchSearch = !q || item.singleUse.toLowerCase().indexOf(q) !== -1 || item.reusable.toLowerCase().indexOf(q) !== -1 || item.category.toLowerCase().indexOf(q) !== -1 || item.sector.toLowerCase().indexOf(q) !== -1; var matchStatus = state.filterStatus === "all" || item.ppwrStatus === state.filterStatus; var matchComplexity = state.filterComplexity === "all" || item.complexity === state.filterComplexity; var matchCapex = state.filterCapex === "all" || item.capex === state.filterCapex; var matchHorizon = state.horizon === "all" || (state.horizon === "2030" && item.deadline <= 2030) || (state.horizon === "2040" && item.deadline <= 2040); return matchSearch && matchStatus && matchComplexity && matchCapex && matchHorizon; }); result.sort(function(a, b) { var av, bv; if (state.sortBy === "status") { av = statusOrder[a.ppwrStatus]; bv = statusOrder[b.ppwrStatus]; } else if (state.sortBy === "complexity") { av = complexityOrder[a.complexity]; bv = complexityOrder[b.complexity]; } else if (state.sortBy === "capex") { av = capexOrder[a.capex]; bv = capexOrder[b.capex]; } else if (state.sortBy === "roi") { av = parseInt(a.roi.split("-")[0], 10); bv = parseInt(b.roi.split("-")[0], 10); } else if (state.sortBy === "deadline") { av = a.deadline; bv = b.deadline; } else { av = a[state.sortBy]; bv = b[state.sortBy]; } if (av < bv) return state.sortDir === "asc" ? -1 : 1; if (av > bv) return state.sortDir === "asc" ? 1 : -1; return 0; }); return result; } function statusBadge(status) { var cls = status === "Mandatory" ? "mandatory" : "recommended"; return '<span class="rn-status-badge ' + cls + '"><span class="rn-status-dot"></span>' + escapeHtml(status) + '</span>'; } function complexityBar(level) { var levels = { Low: 1, Medium: 2, High: 3 }; var n = levels[level] || 0; var bars = ""; for (var i = 1; i <= 3; i++) { bars += '<div class="rn-complexity-bar' + (i <= n ? ' filled' : '') + '"></div>'; } return '<div class="rn-complexity-wrap"><div class="rn-complexity-bars">' + bars + '</div><span class="rn-complexity-label">' + level + '</span></div>'; } function capexBadge(band) { var tier = band === "€" ? "LOW" : band === "€€" ? "MID" : "HIGH"; return '<div class="rn-capex-wrap"><span class="rn-capex-symbol">' + band + '</span><span class="rn-capex-tier">' + tier + '</span></div>'; } function sortBtn(field, label) { var active = state.sortBy === field; var arrow = active ? (state.sortDir === "asc" ? "↑" : "↓") : "↕"; return '<button class="rn-sort-btn' + (active ? ' active' : '') + '" data-sort="' + field + '">' + label + ' <span class="rn-sort-arrow">' + arrow + '</span></button>'; } function expandedContent(item) { var capexRange = item.capex === "€" ? "Low (under €50k pilot)" : item.capex === "€€" ? "Mid (€50k to €500k)" : "High (€500k+)"; return '<tr class="rn-expanded-row"><td colspan="9"><div class="rn-expanded-content">' + '<div>' + '<div class="rn-exp-label">PPWR Reference</div>' + '<p class="rn-exp-text">' + escapeHtml(item.ppwrDetail) + '</p>' + '<div class="rn-exp-divider">' + '<div class="rn-exp-label accent">Key horizon</div>' + '<p class="rn-exp-text muted">' + escapeHtml(item.deadlineNote) + '</p>' + '</div>' + '</div>' + '<div>' + '<div class="rn-exp-label">Operational lift</div>' + '<p class="rn-exp-text">' + escapeHtml(item.complexityNote) + '</p>' + '</div>' + '<div>' + '<div class="rn-exp-label">CapEx profile</div>' + '<div style="margin-bottom:12px;"><div class="rn-capex-big">' + item.capex + '</div><div class="rn-capex-range">' + capexRange + '</div></div>' + '<p class="rn-exp-text">' + escapeHtml(item.capexNote) + '</p>' + '</div>' + '<div>' + '<div class="rn-exp-label">Primary sectors</div>' + '<p class="rn-exp-text">' + escapeHtml(item.sector) + '</p>' + '<div class="rn-exp-divider big">' + '<div class="rn-exp-label">Payback window</div>' + '<div class="rn-payback-num">' + escapeHtml(item.roi) + ' <span class="rn-payback-unit">months</span></div>' + '</div>' + '</div>' + '</div></td></tr>'; } function render() { var root = document.getElementById("rotion-navigator-root"); if (!root) return; var filtered = getFiltered(); var horizonCaption = { "2030": "Showing transitions binding or in force by 1 Jan 2030", "2040": "Showing transitions binding or in force by 2040", "all": "Showing all transitions across all deadlines" }[state.horizon]; var html = ''; // HORIZON BAR html += '<div class="rn-horizon-bar"><div class="rn-container"><div class="rn-horizon-inner">'; html += '<div style="display:flex;align-items:center;gap:8px;">'; html += '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>'; html += '<span class="rn-label rn-label-medium">Compliance horizon</span>'; html += '</div>'; html += '<div class="rn-segmented">'; ['all','2030','2040'].forEach(function(h) { var labels = { all: "All horizons", "2030": "By 2030", "2040": "By 2040" }; html += '<button data-horizon="' + h + '"' + (state.horizon === h ? ' class="active"' : '') + '>' + labels[h] + '</button>'; }); html += '</div>'; html += '<div class="rn-horizon-caption">' + horizonCaption + '</div>'; html += '</div></div></div>'; // CONTROLS html += '<div class="rn-controls"><div class="rn-container"><div class="rn-controls-inner">'; html += '<div class="rn-search-wrapper">'; html += '<svg class="search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>'; html += '<input type="text" id="rn-search" placeholder="Search packaging, sector, or material..." value="' + escapeHtml(state.search) + '"/>'; if (state.search) html += '<button class="rn-search-clear" id="rn-search-clear">×</button>'; html += '</div>'; // PPWR filters html += '<div class="rn-filter-group"><span class="rn-label">PPWR</span>'; ['all','Mandatory','Recommended'].forEach(function(s) { html += '<button class="rn-filter-btn' + (state.filterStatus === s ? ' active' : '') + '" data-filter-status="' + s + '">' + (s === 'all' ? 'All' : s) + '</button>'; }); html += '</div>'; // Complexity filters html += '<div class="rn-filter-group"><span class="rn-label">Complexity</span>'; ['all','Low','Medium','High'].forEach(function(c) { html += '<button class="rn-filter-btn' + (state.filterComplexity === c ? ' active' : '') + '" data-filter-complexity="' + c + '">' + (c === 'all' ? 'All' : c) + '</button>'; }); html += '</div>'; // CapEx filters html += '<div class="rn-filter-group"><span class="rn-label">CapEx</span>'; [['all','All'],['€','€'],['€€','€€'],['€€€','€€€']].forEach(function(pair) { html += '<button class="rn-filter-btn' + (state.filterCapex === pair[0] ? ' active' : '') + '" data-filter-capex="' + pair[0] + '">' + pair[1] + '</button>'; }); html += '</div>'; html += '<div class="rn-count">' + filtered.length + ' <span class="rn-count-total">/ ' + data.length + '</span></div>'; html += '</div></div></div>'; // TABLE html += '<div class="rn-container"><div class="rn-table-wrap">'; html += '<table class="rn-table"><thead><tr>'; html += '<th style="width:48px;"></th>'; html += '<th>' + sortBtn("category", "Category") + '</th>'; html += '<th>Single-use</th>'; html += '<th>Reusable alternative</th>'; html += '<th>' + sortBtn("status", "PPWR") + '</th>'; html += '<th>' + sortBtn("deadline", "Deadline") + '</th>'; html += '<th>' + sortBtn("roi", "ROI (mo)") + '</th>'; html += '<th>' + sortBtn("capex", "CapEx") + '</th>'; html += '<th>' + sortBtn("complexity", "Complexity") + '</th>'; html += '</tr></thead><tbody>'; filtered.forEach(function(item, idx) { var isExpanded = state.expandedRow === item.id; html += '<tr class="rn-data-row' + (isExpanded ? ' expanded' : '') + '" data-row-id="' + item.id + '">'; html += '<td><div class="rn-row-num-wrap"><span class="rn-row-num">' + String(idx + 1).padStart(2, "0") + '</span><span class="rn-chevron">' + (isExpanded ? "▲" : "▼") + '</span></div></td>'; html += '<td><div class="rn-category">' + escapeHtml(item.category) + '</div></td>'; html += '<td><div class="rn-single-use">' + escapeHtml(item.singleUse) + '</div></td>'; html += '<td><div class="rn-reusable">' + escapeHtml(item.reusable) + '</div></td>'; html += '<td>' + statusBadge(item.ppwrStatus) + '</td>'; html += '<td><div class="rn-num-display">' + item.deadline + '</div></td>'; html += '<td><div class="rn-num-display">' + escapeHtml(item.roi) + '</div></td>'; html += '<td>' + capexBadge(item.capex) + '</td>'; html += '<td>' + complexityBar(item.complexity) + '</td>'; html += '</tr>'; if (isExpanded) html += expandedContent(item); }); html += '</tbody></table>'; if (filtered.length === 0) html += '<div class="rn-empty">No matches for current filters</div>'; html += '</div>'; // LEGEND html += '<div class="rn-legend">'; html += '<div class="rn-legend-item">'; html += '<div class="rn-label" style="margin-bottom:12px;">PPWR status</div>'; html += '<div class="rn-legend-row">' + statusBadge("Mandatory") + '<span class="rn-legend-text">Hard EU-wide ban or binding reuse quota under Regulation 2025/40</span></div>'; html += '<div class="rn-legend-row">' + statusBadge("Recommended") + '<span class="rn-legend-text">Strongly incentivised via reuse targets, EPR eco-modulation, waste reduction</span></div>'; html += '</div>'; html += '<div class="rn-legend-item">'; html += '<div class="rn-label" style="margin-bottom:12px;">CapEx bands</div>'; html += '<div class="rn-legend-text"><span class="rn-legend-symbol">€</span>Low: under €50k for a typical pilot deployment</div>'; html += '<div class="rn-legend-text"><span class="rn-legend-symbol">€€</span>Mid: €50k to €500k infrastructure and fleet</div>'; html += '<div class="rn-legend-text"><span class="rn-legend-symbol">€€€</span>High: €500k+ capital investment at scale</div>'; html += '</div>'; html += '<div class="rn-legend-item">'; html += '<div class="rn-label" style="margin-bottom:12px;">Complexity</div>'; html += '<div class="rn-legend-row">' + complexityBar("Low") + '<span class="rn-legend-text">Drop-in or near drop-in replacement</span></div>'; html += '<div class="rn-legend-row">' + complexityBar("Medium") + '<span class="rn-legend-text">Process changes, some infrastructure</span></div>'; html += '<div class="rn-legend-row">' + complexityBar("High") + '<span class="rn-legend-text">Major operational or supply chain redesign</span></div>'; html += '</div>'; html += '</div>'; // METHODOLOGY html += '<div class="rn-methodology">'; html += '<div class="rn-label" style="margin-bottom:8px;">Methodology note</div>'; html += '<p>ROI estimates assume tracked reusable assets with average rotation lifespans of 50 to 500+ cycles depending on format. Payback includes asset CapEx, washing/handling, reverse logistics, and tracking infrastructure, offset against avoided single-use material cost and EPR fees. Complexity scores reflect process change, CapEx, and supply-chain coordination. CapEx bands are indicative order-of-magnitude ranges for a pilot to mid-scale deployment and will vary significantly by volume and geography. Deadlines refer to the year by which an obligation becomes enforceable or practically binding, based on Regulation 2025/40 timelines (12 Aug 2026 application date, 1 Jan 2030 for key bans and reuse targets, 2040 for longer-horizon thresholds).</p>'; html += '</div>'; html += '</div>'; root.innerHTML = html; attachHandlers(); } function attachHandlers() { var root = document.getElementById("rotion-navigator-root"); if (!root) return; // Horizon root.querySelectorAll("[data-horizon]").forEach(function(btn) { btn.addEventListener("click", function() { state.horizon = btn.getAttribute("data-horizon"); render(); }); }); // Search var searchInput = root.querySelector("#rn-search"); if (searchInput) { searchInput.addEventListener("input", function(e) { state.search = e.target.value; var cursor = e.target.selectionStart; render(); var newInput = document.getElementById("rn-search"); if (newInput) { newInput.focus(); try { newInput.setSelectionRange(cursor, cursor); } catch(e) {} } }); } var searchClear = root.querySelector("#rn-search-clear"); if (searchClear) { searchClear.addEventListener("click", function() { state.search = ""; render(); }); } // Filters root.querySelectorAll("[data-filter-status]").forEach(function(btn) { btn.addEventListener("click", function() { state.filterStatus = btn.getAttribute("data-filter-status"); render(); }); }); root.querySelectorAll("[data-filter-complexity]").forEach(function(btn) { btn.addEventListener("click", function() { state.filterComplexity = btn.getAttribute("data-filter-complexity"); render(); }); }); root.querySelectorAll("[data-filter-capex]").forEach(function(btn) { btn.addEventListener("click", function() { state.filterCapex = btn.getAttribute("data-filter-capex"); render(); }); }); // Sort root.querySelectorAll("[data-sort]").forEach(function(btn) { btn.addEventListener("click", function(e) { e.stopPropagation(); var field = btn.getAttribute("data-sort"); if (state.sortBy === field) { state.sortDir = state.sortDir === "asc" ? "desc" : "asc"; } else { state.sortBy = field; state.sortDir = "asc"; } render(); }); }); // Row expand root.querySelectorAll(".rn-data-row").forEach(function(row) { row.addEventListener("click", function() { var id = parseInt(row.getAttribute("data-row-id"), 10); state.expandedRow = state.expandedRow === id ? null : id; render(); }); }); } // Polyfill padStart for older browsers if (!String.prototype.padStart) { String.prototype.padStart = function(targetLength, padString) { targetLength = targetLength >> 0; padString = String(typeof padString !== "undefined" ? padString : " "); if (this.length > targetLength) return String(this); targetLength = targetLength - this.length; if (targetLength > padString.length) { padString += padString.repeat(targetLength / padString.length); } return padString.slice(0, targetLength) + String(this); }; } render(); })(); </script>