diff --git a/migrations/006_missing_columns.sql b/migrations/006_missing_columns.sql
new file mode 100644
index 0000000..f44759a
--- /dev/null
+++ b/migrations/006_missing_columns.sql
@@ -0,0 +1,22 @@
+-- Migration 006: Add columns and tables present in the live DB but missing from migrations
+-- These were added via direct ALTER TABLE after the v0.8.5 baseline was written.
+
+-- date_posted: used for ghost-post shadow-score detection
+ALTER TABLE jobs ADD COLUMN date_posted TEXT;
+
+-- hired_feedback: JSON blob saved when a job reaches the 'hired' outcome
+ALTER TABLE jobs ADD COLUMN hired_feedback TEXT;
+
+-- references_ table: contacts who can provide references for applications
+CREATE TABLE IF NOT EXISTS references_ (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ relationship TEXT,
+ company TEXT,
+ email TEXT,
+ phone TEXT,
+ notes TEXT,
+ tags TEXT,
+ prep_email TEXT,
+ role TEXT
+);
diff --git a/web/src/components/DemoBanner.vue b/web/src/components/DemoBanner.vue
new file mode 100644
index 0000000..93162cd
--- /dev/null
+++ b/web/src/components/DemoBanner.vue
@@ -0,0 +1,79 @@
+
+
+
👁 Demo mode — changes are not saved
+
+
+
+
+
+
+
diff --git a/web/src/components/HintChip.vue b/web/src/components/HintChip.vue
index bc8960b..dc1621e 100644
--- a/web/src/components/HintChip.vue
+++ b/web/src/components/HintChip.vue
@@ -44,7 +44,7 @@ function dismiss(): void {
.hint-chip__message {
flex: 1;
font-size: 0.85rem;
- color: var(--app-primary-light, #68A8D8);
+ color: var(--color-text, #1a202c);
line-height: 1.4;
}
diff --git a/web/src/components/JobCardStack.vue b/web/src/components/JobCardStack.vue
index 6335fce..27e407e 100644
--- a/web/src/components/JobCardStack.vue
+++ b/web/src/components/JobCardStack.vue
@@ -216,7 +216,23 @@ watch(() => props.job.id, () => {
}
})
-defineExpose({ dismissApprove, dismissReject, dismissSkip })
+/** Restore card to its neutral state — used when an action is blocked (e.g. demo guard). */
+function resetCard() {
+ dx.value = 0
+ dy.value = 0
+ isExiting.value = false
+ isHeld.value = false
+ if (wrapperEl.value) {
+ wrapperEl.value.style.transition = 'none'
+ wrapperEl.value.style.transform = ''
+ wrapperEl.value.style.opacity = ''
+ requestAnimationFrame(() => {
+ if (wrapperEl.value) wrapperEl.value.style.transition = ''
+ })
+ }
+}
+
+defineExpose({ dismissApprove, dismissReject, dismissSkip, resetCard })