"""Entry point for the Tiny Court of Everyday Crimes Gradio app. Run locally with: uv run python main.py On Hugging Face Spaces this file is the ``app_file``. We expose a module-level ``demo`` (Gradio's launcher looks for it) and launch unconditionally so the app starts whether the Space runs the file or imports it. Theme/CSS/head are applied via ``launch()`` (Gradio 6 ignores them on the Blocks constructor). Backend selection (docs/adr/0002) is via env var: TINYCOURT_BACKEND=fake (default) canned text, no GPU — great for the UI demo TINYCOURT_BACKEND=local load a downloaded model (Qwen3 via @spaces.GPU) TINYCOURT_BACKEND=remote use Modal llama.cpp; auto-selected when TINYCOURT_MODAL_CHAT_URL is set """ from tinycourt.app import build_demo, launch_kwargs, warm_backend warm_backend() demo = build_demo() # Launch unconditionally (not under an `if __name__` guard) so it runs even when # the Space imports this module. launch() normally blocks; on some Space setups # it returns instead, so hold the main thread afterwards — the server it started # keeps serving and the container stays alive. demo.launch(**launch_kwargs()) print("[tinycourt] launch() returned — holding main thread", flush=True) demo.block_thread()