diff --git a/.haiku-loop-cycle-1-coordinator.md b/.haiku-loop-cycle-1-coordinator.md
index 0cda3f2d..b452987f 100644
--- a/.haiku-loop-cycle-1-coordinator.md
+++ b/.haiku-loop-cycle-1-coordinator.md
@@ -11,7 +11,7 @@ The coordinator scanned 16 haiku-ready candidates (p0/p1 priority) and identifie
## Selected Objectives (3/3)
### Priority 0 (2 objectives)
-1. **p0-01** — Fix color-fix deploy regression on quinn.apricot.local
+1. **p0-01** — Fix color-fix deploy regression on quinn.apricot.lan
- Status: partial → verification task
- Files affected: frontend-public hooks, e2e smoke tests, nginx CSP, css-traps.json
- Verify steps: 4 (typecheck, e2e, CSP grep, JSON count)
diff --git a/.project/previews/sansonnet-umbrella/index.html b/.project/previews/sansonnet-umbrella/index.html
index 516c09d0..7a5b4d7a 100644
--- a/.project/previews/sansonnet-umbrella/index.html
+++ b/.project/previews/sansonnet-umbrella/index.html
@@ -1,11 +1,11 @@
-
sansonnet.apricot.local — dev preview
+sansonnet.apricot.lan — dev preview
-sansonnet.apricot.local
-Dev preview surface — replaces quinn.apricot.local/dev/ (retired 2026-05-14).
+sansonnet.apricot.lan
+Dev preview surface — replaces quinn.apricot.lan/dev/ (retired 2026-05-14).
Sites
diff --git a/codebase/@features/quinn-ai/README.md b/codebase/@features/quinn-ai/README.md
index cb659c40..558f092b 100644
--- a/codebase/@features/quinn-ai/README.md
+++ b/codebase/@features/quinn-ai/README.md
@@ -1,6 +1,6 @@
# quinn.ai
-LLM gateway and engine control dashboard. Lives at `quinn.ai.apricot.local` (dev) and `quinn.ai.transquinnftw.com` (prod).
+LLM gateway and engine control dashboard. Lives at `quinn.ai.apricot.lan` (dev) and `quinn.ai.transquinnftw.com` (prod).
Auth via SSO — same login as quinn.my.
diff --git a/codebase/@features/quinn-ai/engine/scripts/parity-runs/2026-05-16T04-57-52-689Z.jsonl b/codebase/@features/quinn-ai/engine/scripts/parity-runs/2026-05-16T04-57-52-689Z.jsonl
index 5cc97721..f584f574 100644
--- a/codebase/@features/quinn-ai/engine/scripts/parity-runs/2026-05-16T04-57-52-689Z.jsonl
+++ b/codebase/@features/quinn-ai/engine/scripts/parity-runs/2026-05-16T04-57-52-689Z.jsonl
@@ -1 +1,8 @@
{"thread_id":"019e2f1c-c3a5-7000-8ea6-d3571848a386","prospect_handle":"+17077274745","ts":"2026-04-02T17:26:27.000Z","turn_index":0,"actual":"Ya, I could do that.","simulated":"depends on what you're looking for tbh 🤭 what did you have in mind","meta":{"cot_template":"cold_commercial","arc_stage":"cold-open","active_steps":["SANITY_CHECK","VOICE_REGISTER","THREAD_FACTS"],"suppressed_steps":["QUINN_STATE","THREAD_POSITION","CHASE_CHECK"],"arc_event":"same_day_booking_request","rationale":"First inbound contact with explicit commercial intent (booking a session today), acknowledging the 24h notice policy — cold open with a direct service inquiry."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":null,"explicit_ask":"same-day topping session booking","rate_mentioned":null,"other":"prospect acknowledges 24h notice policy; initiating first contact; opens with compliment"},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"n/a","day_time_note":"2026-04-02 ~17:26 SF — within business hours, no travel block until May"},"position":"cold-open","chase":"them","sanity_issues":[],"voice_register":"lowercase-dominant, casual contractions, light emoji (🤭), direct and unbothered, confident about value without over-explaining, short punchy sentences mixed with longer ones, no excessive punctuation","draft_brief_sentence":"Acknowledge the ask warmly but let Quinn hold the power — she may or may not have same-day availability, so create light intrigue and ask what they're looking for without committing; do NOT invent availability, do NOT over-explain the policy, do NOT ask for info already given.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":59052,"error":null}
+{"thread_id":"019e2f1c-c3a5-7000-8ea6-d3571848a386","prospect_handle":"+17077274745","ts":"2026-04-02T17:32:19.000Z","turn_index":1,"actual":"FF pictures?","simulated":"yeah i host and 2hrs bottom only is fine 💗 i don't send out pics but you can trust the ad, it doesn't lie","meta":{"cot_template":"warm_qualifying","arc_stage":"qualifying","active_steps":["THREAD_FACTS","THREAD_POSITION","CHASE_CHECK","SANITY_CHECK","VOICE_REGISTER"],"suppressed_steps":["QUINN_STATE"],"arc_event":"prospect_stacking_questions","rationale":"Prospect opened with a same-day booking ask (commercial intent established) and is now rapidly stacking qualification questions — hosting, duration, and media verification — indicating genuine interest but no commitment yet, placing this squarely in the qualifying arc."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":"bottom (prospect explicitly wants bottom-only session; Quinn tops)","explicit_ask":"same-day booking, 2hr bottom-only topping session; asking if Quinn is hosting; asking for FF pictures or videos for verification","rate_mentioned":null,"other":"prospect stacking three qualification questions in rapid succession — hosting, duration cap, and media verification; commercial intent is established from opener"},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"n/a","day_time_note":"Apr 2 ~5:31pm SF — business hours, no off-hours flag, travel not relevant until May"},"position":"qualifying","chase":"them","sanity_issues":["relationship_depth is 'none' (5 msgs, no session) — draft must stay neutral; no warmth claims, no intimacy language, no manufactured familiarity","prospect asked three stacked questions — draft must answer all three; ignoring any will feel evasive and stall the close","FF media question is sensitive: Quinn's ad lists 'big surprise, no pictures' — draft must handle honestly without overpromising or shutting prospect down"],"voice_register":"lowercase casual, clipped sentences, occasional emoji (🤭), confident and direct, no filler affirmations — mirror this: short, unfussy, Quinn-as-prize energy","draft_brief_sentence":"Confirm yes hosting + yes 2hr bottom-only works; on the FF media question, stay honest to the no-pictures policy (e.g. 'I don't send out pics but you can trust the ad') — do NOT chase or ask a question back, prospect is already sold enough to be verifying details.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":79958,"error":null}
+{"thread_id":"019e2f1c-c3a5-7000-8ea6-d3571848a386","prospect_handle":"+17077274745","ts":"2026-04-02T17:32:29.000Z","turn_index":2,"actual":"Oh full frontal","simulated":"ya i don't share face pics online, you'd just have to come see 💗","meta":{"cot_template":"warm_qualifying","arc_stage":"qualifying","active_steps":["THREAD_FACTS","THREAD_POSITION","CHASE_CHECK","SANITY_CHECK","VOICE_REGISTER"],"suppressed_steps":["QUINN_STATE"],"arc_event":"prospect_requesting_proof_media","rationale":"Prospect is actively qualifying — confirming logistics (hosting, duration), role specifics, and now requesting verification media (FF pics/videos), placing this firmly in the qualifying arc with no logistics confirmed and no rate discussion yet, so QUINN_STATE is premature."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":"bottom (stated explicitly — 2hr bottom-only request)","explicit_ask":"hosting confirmation; session cap/duration; FF pictures or videos for verification","rate_mentioned":null,"other":"prospect references Quinn's ad listing a 'big surprise' with no pictures; relationship_depth=none (5 msgs, no session); no shared moments — everything is logistics/qualifying; nothing emotional or meaningful"},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"no","day_time_note":"same-day request on 2026-04-02 ~17:32 PT — off-hours inactive, SF hosting unconfirmed"},"position":"qualifying","chase":"them","sanity_issues":[],"voice_register":"lowercase casual, short declarative sentences, minimal punctuation, zero hollow affirmations, direct and slightly dry — mirrors 'Ya, I could do that' register already set in this thread","draft_brief_sentence":"Quinn already volleyed a clarifying 'FF pictures?' — sit on that; when prospect clarifies, respond briefly in neutral-warm register to either: (a) confirm what verification content exists or (b) redirect to in-person discovery, never manufacture intimacy or over-explain at depth=none.","dangling_q_count":1,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":92502,"error":null}
+{"thread_id":"019e2f1e-55f2-7000-bcb4-8a2700c353e6","prospect_handle":"+18182648508","ts":"2026-04-30T00:35:49.000Z","turn_index":3,"actual":"Ya!","simulated":"hey yeah, what did you have in mind 💗","meta":{"cot_template":"cold_commercial","arc_stage":"cold-open","active_steps":["SANITY_CHECK","VOICE_REGISTER","THREAD_FACTS"],"suppressed_steps":["QUINN_STATE","THREAD_POSITION","CHASE_CHECK"],"arc_event":"first_contact_with_booking_intent","rationale":"Single inbound message from unknown prospect asking to book during a specific trip — clear commercial intent, no prior relationship, position is trivially first message."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":null,"explicit_ask":"book a session during Quinn's LA trip","rate_mentioned":null,"other":"prospect knows Quinn travels to LA; single inbound message only"},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"no","day_time_note":"message at 00:35 — late night inbound, off_hours_active false; LA trips confirmed May 13-17, May 21-25, Jun 4-11"},"position":"cold-open","chase":"them","sanity_issues":[],"voice_register":"lowercase dominant, casual contractions, minimal punctuation, direct and unbothered, occasional emoji, warm but not effusive — mirror flat casual warmth, no manufactured intimacy","draft_brief_sentence":"Acknowledge the ask briefly and let them drive toward specifics (which trip, dates) — do not volunteer dates unprompted, do not express excitement or miss-you warmth, neutral-warm register only since relationship_depth is none.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":52485,"error":null}
+{"thread_id":"019e2f1e-55f2-7000-bcb4-8a2700c353e6","prospect_handle":"+18182648508","ts":"2026-04-30T00:37:04.000Z","turn_index":4,"actual":"Ya","simulated":"actually may 13-17 or 21-25 💗 pick whichever works","meta":{"cot_template":"warm_qualifying","arc_stage":"qualifying","active_steps":["THREAD_FACTS","THREAD_POSITION","CHASE_CHECK","SANITY_CHECK","VOICE_REGISTER"],"suppressed_steps":["QUINN_STATE"],"arc_event":"prospect_confirmed_dates","rationale":"Prospect opened with booking intent and is now confirming Quinn's LA travel window — qualifying stage with date-lock happening, but no logistics committed yet so QUINN_STATE remains suppressed."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":null,"explicit_ask":"book a session during Quinn's LA trip","rate_mentioned":null,"other":"Prospect believes Quinn's LA window is May 12-21 — this is inaccurate vs. actual travel (May 13-17 and May 21-25)"},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"no","day_time_note":"12:37 AM SF — late but prospect is live and engaged"},"position":"qualifying","chase":"them","sanity_issues":["Prospect stated 'May 12-21' — Quinn's actual windows are May 13-17 and May 21-25, not a single May 12-21 block. Must correct without over-explaining or making it awkward."],"voice_register":"lowercase, very sparse, no punctuation padding, single-word or short-phrase replies ('Ya!', 'Gn', '5 minutes') — mirror this brevity; two sentences max, casual and direct","draft_brief_sentence":"Correct the date range in one casual line — note both windows (13-17 and 21-25) so prospect can pick — do NOT ask about booking details, rate, or anything else; let them drive next.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":69630,"error":null}
+{"thread_id":"019e2f1e-55f2-7000-bcb4-8a2700c353e6","prospect_handle":"+18182648508","ts":"2026-04-30T00:37:59.000Z","turn_index":5,"actual":"Where about are you? Im thinking of staying in bhills or weho","simulated":"got it, what time works for you may 13?","meta":{"cot_template":"logistics","arc_stage":"logistics","active_steps":["SANITY_CHECK","VOICE_REGISTER","QUINN_STATE"],"suppressed_steps":["THREAD_FACTS","THREAD_POSITION","CHASE_CHECK"],"arc_event":"date_and_duration_confirmed","rationale":"Prospect has self-qualified, named a specific date and duration for an incall — booking is effectively confirmed and the thread moves directly into logistics coordination."},"brief":{"discovered_thread_facts":{"name":null,"city":"Los Angeles (implied by prospect's ask)","role":null,"explicit_ask":"1 hour incall, May 13","rate_mentioned":null,"other":"Prospect referenced Quinn's LA travel window May 12-21; Quinn confirmed"},"quinn_state_check":{"current_city_matches_claims":"yes","logistics_confirmed":"no","day_time_note":"Quinn travel block May 13–17 covers the requested date. Current city is SF but May 13 travel is confirmed in calendar. Still missing: specific time, rate confirmation, and incall location. Date + duration are the only confirmed logistics."},"position":"logistics","chase":"them","sanity_issues":[],"voice_register":"Extremely terse, lowercase dominant, minimal punctuation, single-word or fragment replies ('Ya', 'Ya!'). No emoji in this thread. Mirror that compression — do not inflate to warmth the thread hasn't earned.","draft_brief_sentence":"Confirm receipt and ask for their preferred time on May 13 — one short casual line, no manufactured warmth, no re-asking anything already established.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":68911,"error":null}
+{"thread_id":"019e2f1d-c1ce-7000-a987-da616262d396","prospect_handle":"+13233514333","ts":"2024-12-27T01:00:23.000Z","turn_index":6,"actual":"Hiii","simulated":"heyy what're you looking for 🤭","meta":{"cot_template":"warm_building","arc_stage":"cold-open","active_steps":["THREAD_FACTS","SANITY_CHECK","VOICE_REGISTER"],"suppressed_steps":["QUINN_STATE","THREAD_POSITION","CHASE_CHECK"],"arc_event":"re-ping after cold open","rationale":"Prospect opened with a crude attention-grab then followed up casually the next day — no commercial intent, no qualifying info surfaced yet, so warm_building applies while the arc remains cold-open; QUINN_STATE and CHASE_CHECK are suppressed as logistics and chasing are irrelevant this early."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":null,"explicit_ask":null,"rate_mentioned":null,"other":"Two messages only: crude opener on 12/25, casual re-ping on 12/26. No commercial intent, no qualifying info surfaced."},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"n/a","day_time_note":"Re-ping arrived late evening 12/26; now ~1am 12/27 — late but not unusual for this context."},"position":"cold-open","chase":"neutral","sanity_issues":["Relationship depth is none (2 msgs, no session) — any warmth beyond neutral is a fail. No intimacy claims, no memory references permitted.","No facts to re-ask or reference — draft must not manufacture familiarity or imply prior conversation substance."],"voice_register":"Lowercase-dominant, casual contractions, minimal punctuation, sparse emoji (🤭 style), direct and unbothered — not overly warm at this stage.","draft_brief_sentence":"Reply neutrally to the 'heeey' re-ping with a short, unbothered opener that invites them to state what they're looking for — do NOT express warmth, reference the 'slut' opener, or ask for any info already absent from thread.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":59963,"error":null}
+{"thread_id":"019e2f1d-c1ce-7000-a987-da616262d396","prospect_handle":"+13233514333","ts":"2024-12-27T01:19:08.000Z","turn_index":7,"actual":"Napping. Errands burnt me out. ","simulated":"up late, can't sleep lol.. you?","meta":{"cot_template":"warm_building","arc_stage":"building","active_steps":["THREAD_FACTS","THREAD_POSITION","SANITY_CHECK","VOICE_REGISTER"],"suppressed_steps":["QUINN_STATE","CHASE_CHECK"],"arc_event":"casual_reengagement_after_cold_open","rationale":"Prospect opened with a crude cold message, went silent a day, then re-engaged warmly with no commercial signal — pure relationship-building register, no booking intent to chase yet."},"brief":{"discovered_thread_facts":{"name":null,"city":null,"role":null,"explicit_ask":null,"rate_mentioned":null,"other":"Prospect opened crude (\"Slut\"), went silent ~37h, re-engaged warm with \"Heeey\" then \"Whatcha up to\" — no commercial signal, pure casual register"},"quinn_state_check":{"current_city_matches_claims":"n/a","logistics_confirmed":"n/a","day_time_note":"01:19 local — late night, prospect is also up late, natural context for casual reply"},"position":"building","chase":"them","sanity_issues":[],"voice_register":"Lowercase-leaning, very short bursts, minimal punctuation, sparse emoji, direct and unbothered — mirror \"Hiii\" cadence, not full sentences","draft_brief_sentence":"Answer the 'whatcha up to' casually (up late, low-key vibe), flip it back with a short question — no intimacy claims, no warmth beyond neutral-warm, do NOT reference the 'Slut' opener or manufactured shared history.","dangling_q_count":0,"hard_block":false,"chase_warning":false,"relationship_depth":"none"},"elapsed_ms":63539,"error":null}