diff --git a/fusion_plating/fusion_plating/data/fp_landing_data.xml b/fusion_plating/fusion_plating/data/fp_landing_data.xml
index e26af20b..f823df61 100644
--- a/fusion_plating/fusion_plating/data/fp_landing_data.xml
+++ b/fusion_plating/fusion_plating/data/fp_landing_data.xml
@@ -24,15 +24,37 @@
code
1:
+ return _('Due %s · %dd') % (base, days)
+ return _('Due %s · %dd late') % (base, -days)
+
+
+def _icons(job, step):
+ """Compact icon row at the card footer."""
+ icons = []
+ if step:
+ if step.requires_signoff and not step.signoff_user_id:
+ icons.append('🔏')
+ if step.recipe_node_id \
+ and step.recipe_node_id.default_kind == 'bake':
+ icons.append('🔥')
+ if job.card_state == 'bake_due':
+ icons.append('⏰')
+ if job.card_state == 'no_parts':
+ icons.append('🚚')
+ if job.card_state == 'on_hold':
+ icons.append('💬')
+ if job.card_state == 'predecessor_locked':
+ icons.append('🔒')
+ if job.card_state == 'done':
+ icons.append('📜')
+ return icons
+
+
+def _initials_for(user):
+ if not user or not user.name:
+ return ''
+ parts = user.name.strip().split()
+ if len(parts) == 1:
+ return parts[0][:2].upper()
+ return (parts[0][0] + parts[-1][0]).upper()
+
+
+def _sort_key(card):
+ """Sort within a column: overdue first, then by state priority,
+ then by due date (earlier = higher priority)."""
+ return (
+ 0 if card['is_overdue'] else 1,
+ _SORT_PRIORITY.get(card['card_state'], 99),
+ card['due_date'] or '9999-12-31',
+ )
diff --git a/fusion_plating/fusion_plating_shopfloor/views/fp_plant_overview_views.xml b/fusion_plating/fusion_plating_shopfloor/views/fp_plant_overview_views.xml
index 6a7b0b7a..0d838433 100644
--- a/fusion_plating/fusion_plating_shopfloor/views/fp_plant_overview_views.xml
+++ b/fusion_plating/fusion_plating_shopfloor/views/fp_plant_overview_views.xml
@@ -28,4 +28,18 @@
fp_process_tree
+
+
+
+
+
+
+
+
+
+ Shop Floor
+ fp_plant_kanban
+ main
+
+