BhargavMN commited on
Commit
64cf79d
Β·
1 Parent(s): 4c6c6bd

Enhance lobby UI with new styles: remove outer screen background, add room-code hint, copy-to-clipboard button, team-pick button states, and progress bar. Center prep status and improve host/guest instructions. Update pill styles for better visibility.

Browse files
Files changed (3) hide show
  1. app.py +94 -19
  2. app/data/sessions_store.json +1 -1
  3. app/ui/theme.py +70 -1
app.py CHANGED
@@ -698,15 +698,52 @@ def code_html(session_id: str) -> str:
698
  code = s.get("room_code", "β€”β€”β€”β€”β€”β€”")
699
  return (
700
  "<div style='text-align:center'>"
701
- "<div class='section-label' style='justify-content:center'>Share this room code</div>"
702
  f"<div class='cq-code'>{code}</div></div>"
703
  )
704
 
705
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
706
  def roster_html(session_id: str, me: str = "") -> str:
707
  s = SESSION_STORE.get(session_id) or {}
708
  host = s.get("host_name", "")
 
 
709
  parts = ["<div style='display:flex;flex-direction:column;gap:14px'>"]
 
 
 
 
 
 
710
  for t in s.get("teams", []):
711
  members = [p for p in s.get("players", []) if p["team_id"] == t["id"]]
712
  if members:
@@ -862,16 +899,26 @@ POLL_SLOW = 3.0
862
  POLL_IDLE_LIMIT = 4 # identical ticks before easing off
863
 
864
 
865
- def poll_tick(session_id, screen, team_id, player_name, poll_state):
866
  nav = [gr.update()] * 7
867
  new_screen = screen
868
  lobby_code = lobby_roster = play_timer = play_status = wait_status = win_score = gr.update()
 
869
 
870
  if session_id:
871
  status = rooms.session_status(session_id)
872
  if screen == "lobby":
873
  lobby_code = code_html(session_id)
874
  lobby_roster = roster_html(session_id, player_name)
 
 
 
 
 
 
 
 
 
875
  if status == "playing":
876
  new_screen = "play"
877
  nav = list(vis("play"))
@@ -903,7 +950,7 @@ def poll_tick(session_id, screen, team_id, player_name, poll_state):
903
  timer_update = gr.Timer(target_iv) if target_iv != cur_iv else gr.update()
904
  new_state = (sig, idle, target_iv)
905
 
906
- return (*nav, new_screen, lobby_code, lobby_roster,
907
  play_timer, play_status, wait_status, win_score, timer_update, new_state)
908
 
909
 
@@ -915,6 +962,27 @@ def wall_tick(session_id, screen, team_id, taskids):
915
 
916
 
917
  # ── Screen-action handlers ────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
918
  def do_create(name, gtype, city, area, duration, teams_n, head_start,
919
  difficulty, age_group, energy, players_n):
920
  name = (name or "Host").strip() or "Host"
@@ -935,11 +1003,11 @@ def do_create(name, gtype, city, area, duration, teams_n, head_start,
935
  }
936
  rooms.create_room(name, config, session_id)
937
  teams = rooms.list_teams(session_id)
938
- tb = [gr.update(value=f"{t['name']} Β· {t['role']}", visible=True) for t in teams]
939
- tb += [gr.update(visible=False)] * (4 - len(teams))
940
  return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], True,
941
  code_html(session_id), roster_html(session_id, name),
942
- gr.update(visible=True), *tb)
 
943
 
944
 
945
  def do_join(code, name):
@@ -948,25 +1016,27 @@ def do_join(code, name):
948
  gr.Warning(msg)
949
  return (*vis("join"), "join", "", "", "", False, f"⚠ {msg}",
950
  gr.update(), gr.update(), gr.update(visible=False),
 
951
  *([gr.update(visible=False)] * 4))
952
  gr.Info(f"Joined room β€” {msg}")
953
  name = (name or "").strip()
954
  teams = rooms.list_teams(session_id)
955
- tb = [gr.update(value=f"{t['name']} Β· {t['role']}", visible=True) for t in teams]
956
- tb += [gr.update(visible=False)] * (4 - len(teams))
957
  return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], False, f"βœ… {msg}",
958
  code_html(session_id), roster_html(session_id, name),
959
- gr.update(visible=False), *tb)
 
960
 
961
 
962
  def make_pick(idx):
963
  def _pick(session_id, player):
964
  teams = rooms.list_teams(session_id)
965
  if idx >= len(teams):
966
- return gr.update(), gr.update()
967
  tid = teams[idx]["id"]
968
  rooms.pick_team(session_id, player, tid)
969
- return tid, roster_html(session_id, player)
 
970
  return _pick
971
 
972
 
@@ -1401,18 +1471,20 @@ with gr.Blocks(title="CityQuest Β· AI") as demo:
1401
  with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_lobby:
1402
  with gr.Column(elem_classes=["cq-card"]):
1403
  lobby_code = gr.HTML("")
 
1404
  gr.HTML("<div class='section-label'>Pick your team</div>")
1405
  with gr.Row():
1406
  team_btn = [gr.Button("", variant="secondary", visible=False,
1407
  elem_classes=["team-pick"]) for _ in range(4)]
1408
  gr.HTML("<div class='section-label' style='margin-top:18px'>Who's here</div>")
1409
  lobby_roster = gr.HTML("")
1410
- lobby_prep = gr.HTML("")
1411
- gr.Markdown("*The host starts the game once everyone's in.*")
1412
  with gr.Row():
1413
  lobby_leave = gr.Button("Leave", variant="secondary", elem_id="lobby-leave")
1414
  lobby_start = gr.Button("Start the adventure β†’", variant="primary",
1415
- visible=False, elem_id="lobby-start")
 
1416
 
1417
  # ── SCREEN: PLAY ──────────────────────────────────────────────────────
1418
  with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_play:
@@ -1503,8 +1575,8 @@ with gr.Blocks(title="CityQuest Β· AI") as demo:
1503
  # ── Shared poll timer ─────────────────────────────────────────────────
1504
  poll = gr.Timer(1.5)
1505
  nav_groups = [g_home, g_create, g_join, g_lobby, g_play, g_wait, g_win]
1506
- poll.tick(poll_tick, inputs=[s_session, s_screen, s_team, s_player, s_poll_state],
1507
- outputs=nav_groups + [s_screen, lobby_code, lobby_roster,
1508
  play_timer, play_status, wait_status, win_scoreboard,
1509
  poll, s_poll_state])
1510
  poll.tick(wall_tick, inputs=[s_session, s_screen, s_team, s_taskids],
@@ -1537,17 +1609,20 @@ with gr.Blocks(title="CityQuest Β· AI") as demo:
1537
  inputs=[c_name, c_type, c_city, c_area, c_duration, c_teams, c_headstart,
1538
  c_diff, c_age, c_energy, c_players],
1539
  outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
1540
- lobby_code, lobby_roster, lobby_start] + team_btn,
 
1541
  ).then(prepare_game, inputs=[s_session], outputs=[lobby_prep]
1542
  ).then(_btn_on, None, [create_submit])
1543
  join_submit.click(
1544
  do_join, inputs=[j_code, j_name],
1545
  outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
1546
- join_feedback, lobby_code, lobby_roster, lobby_start] + team_btn,
 
1547
  )
1548
 
1549
  for i, tb in enumerate(team_btn):
1550
- tb.click(make_pick(i), inputs=[s_session, s_player], outputs=[s_team, lobby_roster])
 
1551
 
1552
  lobby_leave.click(do_leave, outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host])
1553
  lobby_start.click(_btn_off, None, [lobby_start]).then(
 
698
  code = s.get("room_code", "β€”β€”β€”β€”β€”β€”")
699
  return (
700
  "<div style='text-align:center'>"
701
+ "<div class='cq-code-hint'>Share this code with your friends to join</div>"
702
  f"<div class='cq-code'>{code}</div></div>"
703
  )
704
 
705
 
706
+ def copy_btn_html(session_id: str) -> str:
707
+ """A clipboard button beside the room code. Kept in its own (non-polled)
708
+ HTML component so the 'Copied!' state isn't reset by the 1.5s lobby poll.
709
+ Pure inline JS β€” Gradio can't reach the clipboard from Python."""
710
+ s = SESSION_STORE.get(session_id) or {}
711
+ code = s.get("room_code", "")
712
+ js = (
713
+ "var b=this;navigator.clipboard.writeText('" + code + "').then(function(){"
714
+ "b.classList.add('copied');var l=b.querySelector('.cq-copy-label');"
715
+ "if(l)l.textContent='βœ“ Copied!';"
716
+ "setTimeout(function(){b.classList.remove('copied');"
717
+ "if(l)l.textContent='πŸ“‹ Copy';},2000);});"
718
+ )
719
+ return (
720
+ "<div class='cq-copy-wrap'>"
721
+ f"<button type='button' class='cq-copy-btn' onclick=\"{js}\">"
722
+ "<span class='cq-copy-label'>πŸ“‹ Copy</span></button></div>"
723
+ )
724
+
725
+
726
+ def _teams_ready(session_id: str):
727
+ """(teams_with_at_least_one_player, total_teams) for the lobby."""
728
+ s = SESSION_STORE.get(session_id) or {}
729
+ teams = s.get("teams", [])
730
+ have = {p["team_id"] for p in s.get("players", [])}
731
+ ready = sum(1 for t in teams if t["id"] in have)
732
+ return ready, len(teams)
733
+
734
+
735
  def roster_html(session_id: str, me: str = "") -> str:
736
  s = SESSION_STORE.get(session_id) or {}
737
  host = s.get("host_name", "")
738
+ ready, total = _teams_ready(session_id)
739
+ pct = int(round(100 * ready / total)) if total else 0
740
  parts = ["<div style='display:flex;flex-direction:column;gap:14px'>"]
741
+ parts.append(
742
+ "<div class='cq-progress'>"
743
+ f"<div class='cq-progress-label'>{ready} / {total} teams ready</div>"
744
+ "<div class='cq-progress-track'>"
745
+ f"<div class='cq-progress-fill' style='width:{pct}%'></div></div></div>"
746
+ )
747
  for t in s.get("teams", []):
748
  members = [p for p in s.get("players", []) if p["team_id"] == t["id"]]
749
  if members:
 
899
  POLL_IDLE_LIMIT = 4 # identical ticks before easing off
900
 
901
 
902
+ def poll_tick(session_id, screen, team_id, player_name, is_host, poll_state):
903
  nav = [gr.update()] * 7
904
  new_screen = screen
905
  lobby_code = lobby_roster = play_timer = play_status = wait_status = win_score = gr.update()
906
+ lobby_start = lobby_hint = gr.update()
907
 
908
  if session_id:
909
  status = rooms.session_status(session_id)
910
  if screen == "lobby":
911
  lobby_code = code_html(session_id)
912
  lobby_roster = roster_html(session_id, player_name)
913
+ # Keep Start enabled only once every team has a player, and keep the
914
+ # instruction line in sync with who's waiting on whom.
915
+ ready, total = _teams_ready(session_id)
916
+ all_ready = total > 0 and ready == total
917
+ lobby_start = gr.update(interactive=all_ready)
918
+ if is_host:
919
+ lobby_hint = HINT_HOST_READY if all_ready else HINT_HOST_WAIT
920
+ else:
921
+ lobby_hint = HINT_GUEST
922
  if status == "playing":
923
  new_screen = "play"
924
  nav = list(vis("play"))
 
950
  timer_update = gr.Timer(target_iv) if target_iv != cur_iv else gr.update()
951
  new_state = (sig, idle, target_iv)
952
 
953
+ return (*nav, new_screen, lobby_code, lobby_roster, lobby_start, lobby_hint,
954
  play_timer, play_status, wait_status, win_score, timer_update, new_state)
955
 
956
 
 
962
 
963
 
964
  # ── Screen-action handlers ────────────────────────────────────────────────
965
+ # Lobby instruction copy β€” differs for the host vs. everyone else.
966
+ HINT_HOST_WAIT = "⏳ Waiting for every team to have at least one player…"
967
+ HINT_HOST_READY = "βœ… Everyone's in β€” start the adventure whenever you're ready."
968
+ HINT_GUEST = "⏳ Waiting for the host to start the adventure…"
969
+
970
+
971
+ def _team_btn_updates(session_id, selected_id):
972
+ """Button updates for the 4 team-pick slots: label + visibility, with the
973
+ player's current team flagged 'selected' so it reads as chosen (green)."""
974
+ teams = rooms.list_teams(session_id)
975
+ ups = []
976
+ for i in range(4):
977
+ if i < len(teams):
978
+ cls = ["team-pick", "selected"] if teams[i]["id"] == selected_id else ["team-pick"]
979
+ ups.append(gr.update(value=f"{teams[i]['name']} Β· {teams[i]['role']}",
980
+ visible=True, elem_classes=cls))
981
+ else:
982
+ ups.append(gr.update(visible=False))
983
+ return ups
984
+
985
+
986
  def do_create(name, gtype, city, area, duration, teams_n, head_start,
987
  difficulty, age_group, energy, players_n):
988
  name = (name or "Host").strip() or "Host"
 
1003
  }
1004
  rooms.create_room(name, config, session_id)
1005
  teams = rooms.list_teams(session_id)
1006
+ tb = _team_btn_updates(session_id, teams[0]["id"])
 
1007
  return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], True,
1008
  code_html(session_id), roster_html(session_id, name),
1009
+ gr.update(visible=True, interactive=False),
1010
+ copy_btn_html(session_id), HINT_HOST_WAIT, *tb)
1011
 
1012
 
1013
  def do_join(code, name):
 
1016
  gr.Warning(msg)
1017
  return (*vis("join"), "join", "", "", "", False, f"⚠ {msg}",
1018
  gr.update(), gr.update(), gr.update(visible=False),
1019
+ gr.update(), gr.update(),
1020
  *([gr.update(visible=False)] * 4))
1021
  gr.Info(f"Joined room β€” {msg}")
1022
  name = (name or "").strip()
1023
  teams = rooms.list_teams(session_id)
1024
+ tb = _team_btn_updates(session_id, teams[0]["id"])
 
1025
  return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], False, f"βœ… {msg}",
1026
  code_html(session_id), roster_html(session_id, name),
1027
+ gr.update(visible=False),
1028
+ copy_btn_html(session_id), HINT_GUEST, *tb)
1029
 
1030
 
1031
  def make_pick(idx):
1032
  def _pick(session_id, player):
1033
  teams = rooms.list_teams(session_id)
1034
  if idx >= len(teams):
1035
+ return (gr.update(), gr.update(), *([gr.update()] * 4))
1036
  tid = teams[idx]["id"]
1037
  rooms.pick_team(session_id, player, tid)
1038
+ return (tid, roster_html(session_id, player),
1039
+ *_team_btn_updates(session_id, tid))
1040
  return _pick
1041
 
1042
 
 
1471
  with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_lobby:
1472
  with gr.Column(elem_classes=["cq-card"]):
1473
  lobby_code = gr.HTML("")
1474
+ lobby_copy = gr.HTML("")
1475
  gr.HTML("<div class='section-label'>Pick your team</div>")
1476
  with gr.Row():
1477
  team_btn = [gr.Button("", variant="secondary", visible=False,
1478
  elem_classes=["team-pick"]) for _ in range(4)]
1479
  gr.HTML("<div class='section-label' style='margin-top:18px'>Who's here</div>")
1480
  lobby_roster = gr.HTML("")
1481
+ lobby_prep = gr.HTML("", elem_classes=["lobby-prep"])
1482
+ lobby_hint = gr.Markdown(HINT_GUEST, elem_classes=["lobby-hint"])
1483
  with gr.Row():
1484
  lobby_leave = gr.Button("Leave", variant="secondary", elem_id="lobby-leave")
1485
  lobby_start = gr.Button("Start the adventure β†’", variant="primary",
1486
+ visible=False, interactive=False,
1487
+ elem_id="lobby-start", elem_classes=["lobby-start-btn"])
1488
 
1489
  # ── SCREEN: PLAY ──────────────────────────────────────────────────────
1490
  with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_play:
 
1575
  # ── Shared poll timer ─────────────────────────────────────────────────
1576
  poll = gr.Timer(1.5)
1577
  nav_groups = [g_home, g_create, g_join, g_lobby, g_play, g_wait, g_win]
1578
+ poll.tick(poll_tick, inputs=[s_session, s_screen, s_team, s_player, s_host, s_poll_state],
1579
+ outputs=nav_groups + [s_screen, lobby_code, lobby_roster, lobby_start, lobby_hint,
1580
  play_timer, play_status, wait_status, win_scoreboard,
1581
  poll, s_poll_state])
1582
  poll.tick(wall_tick, inputs=[s_session, s_screen, s_team, s_taskids],
 
1609
  inputs=[c_name, c_type, c_city, c_area, c_duration, c_teams, c_headstart,
1610
  c_diff, c_age, c_energy, c_players],
1611
  outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
1612
+ lobby_code, lobby_roster, lobby_start,
1613
+ lobby_copy, lobby_hint] + team_btn,
1614
  ).then(prepare_game, inputs=[s_session], outputs=[lobby_prep]
1615
  ).then(_btn_on, None, [create_submit])
1616
  join_submit.click(
1617
  do_join, inputs=[j_code, j_name],
1618
  outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
1619
+ join_feedback, lobby_code, lobby_roster, lobby_start,
1620
+ lobby_copy, lobby_hint] + team_btn,
1621
  )
1622
 
1623
  for i, tb in enumerate(team_btn):
1624
+ tb.click(make_pick(i), inputs=[s_session, s_player],
1625
+ outputs=[s_team, lobby_roster] + team_btn)
1626
 
1627
  lobby_leave.click(do_leave, outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host])
1628
  lobby_start.click(_btn_off, None, [lobby_start]).then(
app/data/sessions_store.json CHANGED
@@ -1 +1 @@
1
- {"codes": {"75ZKFE": "9fcb0953-4e36-4485-9bbe-fad577de31fa", "JWR5RV": "6b1af473-b00b-44ae-bffc-7b8e93616767", "NKPZKT": "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550", "NXWHQK": "4b03fbfc-4326-4325-8975-e4216c44e03e", "VMJVMF": "2cfd0fef-a118-4044-a9bd-2583e60b56e1", "EHPYXY": "720ab67a-9428-4c7b-a01e-de3d393d6a96", "Y3ZTX5": "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d", "GY4QMQ": "b56f7a32-961f-4001-be35-503866b95227", "HZWQB4": "a549cbe3-e796-4ca5-9f00-78ea47eb9704", "FHGKNU": "e1e90fde-7eb5-4a56-a2ee-edd451b3c099", "P4XT35": "136f317b-5d93-4b30-aa0a-7a8f501dde2f", "QN4J62": "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164", "EHSFKC": "f02216a5-19f8-46cf-8d52-7dd74eeafb65", "5VDVSH": "26e9880a-4d33-4e4a-a773-a00f097c9c83", "QVTJKG": "70959adc-6172-41e6-ae4f-ef8f90772dba"}, "sessions": {"9fcb0953-4e36-4485-9bbe-fad577de31fa": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}, {"name": "play 2", "team_id": "team-b"}, {"name": "hola", "team_id": "team-b"}], "game": {"game_id": "mock-8506e14a", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": [{"photo_id": "photo-71c44ee8", "photo_name": "", "caption": "", "task_id": "t1"}]}, "6b1af473-b00b-44ae-bffc-7b8e93616767": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}], "game": {"game_id": "mock-6d6ab9cf", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Scavenger Hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No proximity to water, traffic, or rail lines", "No interacting with strangers", "All tasks must be observed, no purchases"], "tasks": [{"task_id": "t1", "title": "Historic Fountain", "description": "Observe the historic fountain at Place des Vosges.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the historic fountain", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t2", "title": "Colorful Door", "description": "Observe the colorful door on Rue des Rosiers.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the colorful door", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t3", "title": "Task 3", "description": "Explore and discover something interesting in the area", "location_hint": "Look around the central area", "points": 25, "time_limit_minutes": null, "proof_type": "text", "hint": "Check visible landmarks and signs for clues", "safety_note": "Stay on public paths and respect local rules"}], "global_hints": ["Le Marais is a historic district", "All tasks are observation-based"], "score_rules": ["Higher points win", "Tie broken by total points"], "tie_breaker": "Highest total points wins", "safety": {"allowed_zone": "Le Marais public streets and parks", "forbidden_behaviors": ["Entering buildings or private property", "Proximity to water, traffic, or rail lines", "Interacting with strangers", "Purchasing items"], "adult_supervision": false, "stop_conditions": ["All tasks completed", "Time limit 60 minutes reached", "Any rule violation"]}, "story_seed": {"tone": "playful", "motifs": ["historic architecture", "urban exploration"], "recap_style": "Summarize each player's observations and points"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "4b03fbfc-4326-4325-8975-e4216c44e03e": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Observational scavenger hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No crossing traffic or water", "No interacting with strangers", "No purchases", "All tasks are observation only"], "tasks": [{"task_id": "t1", "title": "Vosges View", "description": "Find the historic square Place des Vosges and note its symmetrical layout.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the central fountain", "safety_note": "Stay on pavement, no building entry"}, {"task_id": "t2", "title": "Rue des Rosiers", "description": "Observe the vibrant street market stalls and colorful awnings.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Notice the flower displays", "safety_note": "No entering stalls"}, {"task_id": "t3", "title": "H\u00f4tel de Ville View", "description": "Observe the fa\u00e7ade of the H\u00f4tel de Ville from the street.", "location_hint": "Place des Vosges near H\u00f4tel de Ville", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the clock tower", "safety_note": "No entering building"}], "global_hints": ["Stay within Le Marais", "Use observation only", "No purchases"], "score_rules": ["Highest points wins", "All tasks completed for bonus"], "tie_breaker": "First player to reach 50 points wins", "safety": {"allowed_zone": "Le Marais streets and public squares", "forbidden_behaviors": ["Entering buildings", "Crossing traffic", "Approaching water", "Interacting with strangers", "Purchasing items"], "adult_supervision": true, "stop_conditions": ["Time limit 60 minutes", "Safety breach", "All tasks completed"]}, "story_seed": {"tone": "playful", "motifs": ["hidden clues", "Parisian charm", "observation"], "recap_style": "Gather at the meeting point for a recap of findings."}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "2cfd0fef-a118-4044-a9bd-2583e60b56e1": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "VMJVMF", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-50dd0c65", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "720ab67a-9428-4c7b-a01e-de3d393d6a96": {"config": {"game_type": "hide_and_seek", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHPYXY", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Hiders"}, {"id": "team-b", "name": "Meadow", "role": "Seekers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-15f50146", "game_type": "hide_and_seek", "title": "Hide_And_Seek in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d": {"config": {"game_type": "tag", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "Y3ZTX5", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Runners"}, {"id": "team-b", "name": "Meadow", "role": "Chasers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "jkjlkj", "team_id": "team-b"}], "game": {"game_id": "mock-f949048c", "game_type": "tag", "title": "Tag in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:03:57.108418+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-b": "2026-06-12T16:05:24.467878+00:00", "team-a": "2026-06-12T16:05:31.049593+00:00"}, "photos": []}, "b56f7a32-961f-4001-be35-503866b95227": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "GY4QMQ", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "a549cbe3-e796-4ca5-9f00-78ea47eb9704": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "HZWQB4", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-eb9ec682", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:59:08.914806+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "e1e90fde-7eb5-4a56-a2ee-edd451b3c099": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "FHGKNU", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "136f317b-5d93-4b30-aa0a-7a8f501dde2f": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 2, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "P4XT35", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "Hope", "team_id": "team-b"}], "game": {"game_id": "mock-ef48dd67", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 2}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:29:30.570903+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 15, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QN4J62", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-b"}, {"name": "Priyasha", "team_id": "team-a"}], "game": {"game_id": "mock-47326f6b", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 15, "num_players": 4}, "rules": ["Complete as many tasks as possible within 15 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "f02216a5-19f8-46cf-8d52-7dd74eeafb65": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHSFKC", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-d3ae7576", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "26e9880a-4d33-4e4a-a773-a00f097c9c83": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "5VDVSH", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-9108f87e", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:44:34.248892+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-a": "2026-06-12T17:44:40.426298+00:00"}, "photos": []}, "70959adc-6172-41e6-ae4f-ef8f90772dba": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QVTJKG", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}}}
 
1
+ {"codes": {"75ZKFE": "9fcb0953-4e36-4485-9bbe-fad577de31fa", "JWR5RV": "6b1af473-b00b-44ae-bffc-7b8e93616767", "NKPZKT": "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550", "NXWHQK": "4b03fbfc-4326-4325-8975-e4216c44e03e", "VMJVMF": "2cfd0fef-a118-4044-a9bd-2583e60b56e1", "EHPYXY": "720ab67a-9428-4c7b-a01e-de3d393d6a96", "Y3ZTX5": "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d", "GY4QMQ": "b56f7a32-961f-4001-be35-503866b95227", "HZWQB4": "a549cbe3-e796-4ca5-9f00-78ea47eb9704", "FHGKNU": "e1e90fde-7eb5-4a56-a2ee-edd451b3c099", "P4XT35": "136f317b-5d93-4b30-aa0a-7a8f501dde2f", "QN4J62": "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164", "EHSFKC": "f02216a5-19f8-46cf-8d52-7dd74eeafb65", "5VDVSH": "26e9880a-4d33-4e4a-a773-a00f097c9c83", "QVTJKG": "70959adc-6172-41e6-ae4f-ef8f90772dba", "NCVFAZ": "8e04b90f-baa6-45a6-9a8b-21d91a4b4d8a", "9F2X98": "bc218c4b-3b0d-4f33-b91a-8b10500ea29e", "AFV67H": "29725220-ef25-499f-9ef3-47f4afacbff4", "WQ799U": "9c9f53d7-5b26-4d11-be5a-eb6b657b63c2", "CUJCK3": "c4f53a5f-6e23-4030-a2e7-a04a47fe14f5", "8MRZWG": "03491a8c-e9ad-47fe-810e-10acbf649270", "FAUV65": "1959d776-cd89-4aa9-82b1-4922f4d5e37f"}, "sessions": {"9fcb0953-4e36-4485-9bbe-fad577de31fa": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}, {"name": "play 2", "team_id": "team-b"}, {"name": "hola", "team_id": "team-b"}], "game": {"game_id": "mock-8506e14a", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": [{"photo_id": "photo-71c44ee8", "photo_name": "", "caption": "", "task_id": "t1"}]}, "6b1af473-b00b-44ae-bffc-7b8e93616767": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}], "game": {"game_id": "mock-6d6ab9cf", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Scavenger Hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No proximity to water, traffic, or rail lines", "No interacting with strangers", "All tasks must be observed, no purchases"], "tasks": [{"task_id": "t1", "title": "Historic Fountain", "description": "Observe the historic fountain at Place des Vosges.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the historic fountain", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t2", "title": "Colorful Door", "description": "Observe the colorful door on Rue des Rosiers.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the colorful door", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t3", "title": "Task 3", "description": "Explore and discover something interesting in the area", "location_hint": "Look around the central area", "points": 25, "time_limit_minutes": null, "proof_type": "text", "hint": "Check visible landmarks and signs for clues", "safety_note": "Stay on public paths and respect local rules"}], "global_hints": ["Le Marais is a historic district", "All tasks are observation-based"], "score_rules": ["Higher points win", "Tie broken by total points"], "tie_breaker": "Highest total points wins", "safety": {"allowed_zone": "Le Marais public streets and parks", "forbidden_behaviors": ["Entering buildings or private property", "Proximity to water, traffic, or rail lines", "Interacting with strangers", "Purchasing items"], "adult_supervision": false, "stop_conditions": ["All tasks completed", "Time limit 60 minutes reached", "Any rule violation"]}, "story_seed": {"tone": "playful", "motifs": ["historic architecture", "urban exploration"], "recap_style": "Summarize each player's observations and points"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "4b03fbfc-4326-4325-8975-e4216c44e03e": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Observational scavenger hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No crossing traffic or water", "No interacting with strangers", "No purchases", "All tasks are observation only"], "tasks": [{"task_id": "t1", "title": "Vosges View", "description": "Find the historic square Place des Vosges and note its symmetrical layout.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the central fountain", "safety_note": "Stay on pavement, no building entry"}, {"task_id": "t2", "title": "Rue des Rosiers", "description": "Observe the vibrant street market stalls and colorful awnings.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Notice the flower displays", "safety_note": "No entering stalls"}, {"task_id": "t3", "title": "H\u00f4tel de Ville View", "description": "Observe the fa\u00e7ade of the H\u00f4tel de Ville from the street.", "location_hint": "Place des Vosges near H\u00f4tel de Ville", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the clock tower", "safety_note": "No entering building"}], "global_hints": ["Stay within Le Marais", "Use observation only", "No purchases"], "score_rules": ["Highest points wins", "All tasks completed for bonus"], "tie_breaker": "First player to reach 50 points wins", "safety": {"allowed_zone": "Le Marais streets and public squares", "forbidden_behaviors": ["Entering buildings", "Crossing traffic", "Approaching water", "Interacting with strangers", "Purchasing items"], "adult_supervision": true, "stop_conditions": ["Time limit 60 minutes", "Safety breach", "All tasks completed"]}, "story_seed": {"tone": "playful", "motifs": ["hidden clues", "Parisian charm", "observation"], "recap_style": "Gather at the meeting point for a recap of findings."}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "2cfd0fef-a118-4044-a9bd-2583e60b56e1": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "VMJVMF", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-50dd0c65", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "720ab67a-9428-4c7b-a01e-de3d393d6a96": {"config": {"game_type": "hide_and_seek", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHPYXY", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Hiders"}, {"id": "team-b", "name": "Meadow", "role": "Seekers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-15f50146", "game_type": "hide_and_seek", "title": "Hide_And_Seek in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d": {"config": {"game_type": "tag", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "Y3ZTX5", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Runners"}, {"id": "team-b", "name": "Meadow", "role": "Chasers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "jkjlkj", "team_id": "team-b"}], "game": {"game_id": "mock-f949048c", "game_type": "tag", "title": "Tag in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:03:57.108418+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-b": "2026-06-12T16:05:24.467878+00:00", "team-a": "2026-06-12T16:05:31.049593+00:00"}, "photos": []}, "b56f7a32-961f-4001-be35-503866b95227": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "GY4QMQ", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "a549cbe3-e796-4ca5-9f00-78ea47eb9704": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "HZWQB4", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-eb9ec682", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:59:08.914806+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "e1e90fde-7eb5-4a56-a2ee-edd451b3c099": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "FHGKNU", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "136f317b-5d93-4b30-aa0a-7a8f501dde2f": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 2, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "P4XT35", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "Hope", "team_id": "team-b"}], "game": {"game_id": "mock-ef48dd67", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 2}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:29:30.570903+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 15, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QN4J62", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-b"}, {"name": "Priyasha", "team_id": "team-a"}], "game": {"game_id": "mock-47326f6b", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 15, "num_players": 4}, "rules": ["Complete as many tasks as possible within 15 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "f02216a5-19f8-46cf-8d52-7dd74eeafb65": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHSFKC", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-d3ae7576", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "26e9880a-4d33-4e4a-a773-a00f097c9c83": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "5VDVSH", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-9108f87e", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:44:34.248892+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-a": "2026-06-12T17:44:40.426298+00:00"}, "photos": []}, "70959adc-6172-41e6-ae4f-ef8f90772dba": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QVTJKG", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "8e04b90f-baa6-45a6-9a8b-21d91a4b4d8a": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "NCVFAZ", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "bc218c4b-3b0d-4f33-b91a-8b10500ea29e": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "9F2X98", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "29725220-ef25-499f-9ef3-47f4afacbff4": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "AFV67H", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "hola", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "9c9f53d7-5b26-4d11-be5a-eb6b657b63c2": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "WQ799U", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "lkjdfsdf", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "c4f53a5f-6e23-4030-a2e7-a04a47fe14f5": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "CUJCK3", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "holakdf", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "03491a8c-e9ad-47fe-810e-10acbf649270": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "8MRZWG", "host_name": "Player", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Player", "team_id": "team-a"}, {"name": "kljdfi", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "1959d776-cd89-4aa9-82b1-4922f4d5e37f": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "FAUV65", "host_name": "kljsdf", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "kljsdf", "team_id": "team-a"}, {"name": "kljdfi", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}}}
app/ui/theme.py CHANGED
@@ -196,6 +196,20 @@ footer { display: none !important; }
196
  }
197
 
198
  /* ── Create screen refinements (scoped to .cq-create only) ── */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  /* CHANGE 1: Give the dropdown fields (game type, difficulty, age group, energy)
200
  the same grey opaque input box as the textbox fields. Gradio renders a
201
  dropdown's display element as .wrap (not a typed <input>), so it never picked
@@ -359,6 +373,60 @@ ul.options[role="listbox"] li {
359
  padding: 14px 26px; display: inline-block;
360
  }
361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  /* ── Task wall ── */
363
  .cq-wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px,1fr)); gap: 14px; }
364
  .cq-tcard {
@@ -381,7 +449,8 @@ ul.options[role="listbox"] li {
381
  fragments that re-render every poll tick β€” it won't re-trigger/flicker. */
382
  .cq-pill { transition: background .35s ease, border-color .35s ease, color .35s ease; }
383
  .cq-pill.live { border-color: var(--teal); color: var(--teal-dk); }
384
- .cq-pill.wait { border-color: var(--clay); color: var(--clay-dk); }
 
385
  .cq-pill.done { background: var(--teal); color:#0A1F0A; border-color: var(--teal); }
386
  .cq-pill.alert { border-color: var(--red); color: #FF8A80; background: rgba(244,67,54,0.18); }
387
  .cq-timer { font-family:'Fraunces',serif; font-weight:700; font-size: clamp(1.6rem,5vw,2.4rem);
 
196
  }
197
 
198
  /* ── Create screen refinements (scoped to .cq-create only) ── */
199
+ /* Remove the outer grey rectangle around the whole screen. Each screen's own
200
+ gr.Group (.cq-screen) renders Gradio's default card chrome; strip it so the
201
+ inner .cq-card floats against the animated background. Scoped to the group's
202
+ own wrapper layers so the inner .cq-card keeps its border/fill. Applies to
203
+ every screen (create, join, lobby, play, wait, win). */
204
+ .cq-screen,
205
+ .cq-screen > .block,
206
+ .cq-screen > div:not(.cq-card),
207
+ .cq-screen > .block > div:not(.cq-card) {
208
+ background: transparent !important;
209
+ border: none !important;
210
+ box-shadow: none !important;
211
+ backdrop-filter: none !important;
212
+ }
213
  /* CHANGE 1: Give the dropdown fields (game type, difficulty, age group, energy)
214
  the same grey opaque input box as the textbox fields. Gradio renders a
215
  dropdown's display element as .wrap (not a typed <input>), so it never picked
 
373
  padding: 14px 26px; display: inline-block;
374
  }
375
 
376
+ /* ── Lobby: room-code hint (replaces the redundant "SHARE…" label) ── */
377
+ .cq-code-hint {
378
+ text-align: center; color: var(--muted);
379
+ font-size: 0.95rem; margin-bottom: 10px;
380
+ }
381
+
382
+ /* ── Lobby: copy-to-clipboard button beside the room code ── */
383
+ .cq-copy-wrap { display: flex; justify-content: center; margin-top: 12px; }
384
+ .cq-copy-btn {
385
+ background: var(--paper-2); color: var(--ink);
386
+ border: 1px solid var(--line); border-radius: 999px;
387
+ padding: 8px 20px; font-size: 0.95rem; font-family: 'Inter', sans-serif;
388
+ font-weight: 600; cursor: pointer; transition: all 0.2s ease;
389
+ }
390
+ .cq-copy-btn:hover {
391
+ background: #4A4A4A; border-color: var(--green); transform: scale(1.03);
392
+ }
393
+ .cq-copy-btn.copied {
394
+ background: rgba(76,175,80,0.22); border-color: var(--green); color: var(--ink);
395
+ transform: scale(1.0);
396
+ }
397
+
398
+ /* ── Lobby: team-pick buttons β€” selected state ── */
399
+ .team-pick.selected button {
400
+ background: rgba(76,175,80,0.20) !important;
401
+ border: 2px solid var(--green) !important;
402
+ color: var(--ink) !important; font-weight: 700 !important;
403
+ box-shadow: 0 0 12px rgba(76,175,80,0.3) !important;
404
+ }
405
+
406
+ /* ── Lobby: "N / M teams ready" progress bar ── */
407
+ .cq-progress { margin: 2px 0 6px 0; }
408
+ .cq-progress-label {
409
+ font-size: 0.85rem; color: var(--muted); margin-bottom: 6px; display: block;
410
+ }
411
+ .cq-progress-track {
412
+ height: 6px; background: var(--paper-2); border-radius: 3px; overflow: hidden;
413
+ }
414
+ .cq-progress-fill {
415
+ height: 100%; background: var(--green); border-radius: 3px;
416
+ transition: width 0.4s ease;
417
+ }
418
+
419
+ /* ── Lobby: center the prep status pill (loading / ready) ── */
420
+ .lobby-prep { text-align: center; }
421
+
422
+ /* ── Lobby: host/guest instruction line ── */
423
+ .lobby-hint, .lobby-hint p {
424
+ text-align: center; color: var(--clay-dk) !important;
425
+ font-size: 1rem !important; font-weight: 500 !important;
426
+ background: rgba(255,193,7,0.08); border-radius: 8px;
427
+ padding: 8px 16px; margin: 8px 0 !important;
428
+ }
429
+
430
  /* ── Task wall ── */
431
  .cq-wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px,1fr)); gap: 14px; }
432
  .cq-tcard {
 
449
  fragments that re-render every poll tick β€” it won't re-trigger/flicker. */
450
  .cq-pill { transition: background .35s ease, border-color .35s ease, color .35s ease; }
451
  .cq-pill.live { border-color: var(--teal); color: var(--teal-dk); }
452
+ .cq-pill.wait { border-color: var(--clay); color: var(--clay-dk);
453
+ background: rgba(255,193,7,0.15); }
454
  .cq-pill.done { background: var(--teal); color:#0A1F0A; border-color: var(--teal); }
455
  .cq-pill.alert { border-color: var(--red); color: #FF8A80; background: rgba(244,67,54,0.18); }
456
  .cq-timer { font-family:'Fraunces',serif; font-weight:700; font-size: clamp(1.6rem,5vw,2.4rem);