diff --git a/DESIGN.md b/DESIGN.md index e30fba6d..86b229b6 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -15,8 +15,8 @@ colors: night-card: "#182025" night-ink: "#f2ede4" honey: "#ffcf3a" - qloo-purple: "#8C8CC8" - qloo-ink: "#5b5ba3" + slate: "#45596b" + slate-night: "#a9bccb" zone-pink: "#e0337a" destructive: "#b0152f" taste-3: "#f28644" @@ -89,7 +89,7 @@ components: - **Signal orange** (#ff5a1f by day, #ff6a2b at night): the one accent. It's for the primary action, the selected or top item, the pitch ring, and the taste cells. It is never used for body text; text in the accent tone uses **signal text** (#b13a00) for contrast. ### Secondary -- **Qloo purple** (#8C8CC8 brand bar, #5b5ba3 for text): only where Qloo is named or its data shows (the Brain page, Qloo calls, the Qloo wordmark). +- **Slate** (#45596b day, #a9bccb night): neutral ink for data from a named source (the Brain page, Qloo calls, Qloo-sourced chips), always beside the word "Qloo". No Qloo colour or logo anywhere. ### Neutral - **Paper** (#f2eee6) ground with **paper card** (#fbf9f5) surfaces; **bluestone** (#141c21) ink, rules and the night header; **muted ink** (#56606a) for secondary text; a **hairline** (#cfc7b8) for quiet dividers. diff --git a/PRODUCT.md b/PRODUCT.md index 75c4393d..ce33cd27 100644 --- a/PRODUCT.md +++ b/PRODUCT.md @@ -20,7 +20,7 @@ Taste-matched pitches: who is actually out there at that hour, and what they lik ## Operating Context -Built for the Qloo Agentic Hackathon 2026; submission is due 30 Oct. The live judge path is landing → plan a busk → the plan page → Repertoire → Brain (how Qloo powers it). +Built for the Qloo Agentic Hackathon 2026; submission is due 30 Oct. The live judge path is landing → plan a busk → the plan page → Repertoire → Brain (how Qloo taste data feeds it). ## Capabilities and Constraints @@ -34,7 +34,7 @@ Built for the Qloo Agentic Hackathon 2026; submission is due 30 Oct. The live ju - The name is Busk Map, and the visual identity is Honeycomb (the published design system is the reference; the app is the source of truth for component code). - The logo is the lockup: the hex mark beside the wordmark. -- Every Qloo logo links to qloo.com. +- Qloo is named in plain text only: no Qloo logo, no partner or sponsor wording. Busk Map is not affiliated with or endorsed by Qloo. - Busk Map never confirms a pitch is legal: it tells buskers to check their permit conditions. - No text glyphs as icons (arrows, chevrons, checks); icons are the design system's Icon set. - One keyboard focus ring, never two. diff --git a/README.md b/README.md index b6827c01..5637dc21 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ Know where to play, and what to play there. -Busk Map is an agent for street performers. Pick a city and a time slot, and it finds the pitches whose crowd matches your music, near busy places that are open at that hour. It then builds a setlist for each pitch from the songs you can play. It is built with [Qloo](https://qloo.com) for the [Qloo Agentic Hackathon](https://qloo.devpost.com/). Live at https://buskmap.app. +Busk Map is an agent for street performers. Pick a city and a time slot, and it finds the pitches whose crowd matches your music, near busy places that are open at that hour. It then builds a setlist for each pitch from the songs you can play. Taste data from the Qloo API. Built for the [Qloo Agentic Hackathon](https://qloo.devpost.com/). Live at https://buskmap.app. + +Busk Map is not affiliated with or endorsed by Qloo. ## Hive, the agent @@ -46,7 +48,7 @@ pnpm test:e2e # builds and starts an offline server, then runs the judg `pnpm purge:spotify` deletes or nulls the Spotify data stored in Postgres (cover images, Spotify years and durations, artist profile snapshots, research snapshots, learn-run steps, cached runs, Spotify pacer rows). It keeps the Spotify IDs and our own data, and it is safe to run twice. Run it once on 10 Nov 2026 against production (Spotify Developer Terms IV.3). Before that date it refuses unless you pass `--force`. It uses the same main-database guard as the other scripts. ## Data -- [Qloo](https://qloo.com) taste API (16 kinds of call, see the /brain page; a local mock without a key) +- Taste data from the Qloo API, used under Qloo's Terms of Use (18 kinds of call, see the /brain page; a local mock without a key) - OpenStreetMap public spaces and venue names (© OpenStreetMap contributors, ODbL) - City of Melbourne busking locations (CC BY) - Ticketmaster Discovery API, Last.fm, Open-Meteo diff --git a/docs/qloo-city-coverage.md b/docs/qloo-city-coverage.md index 2ed75317..cfdfd0ee 100644 --- a/docs/qloo-city-coverage.md +++ b/docs/qloo-city-coverage.md @@ -2,7 +2,7 @@ Run on 2026-10-17 against the live Qloo hackathon API (`https://hackathon.api.qloo.com`). Qloo only, no model calls. Script: `scripts/probe-qloo-cities.mjs` (re-run with `node --env-file=.env.local scripts/probe-qloo-cities.mjs`). -It prints aggregates only. Qloo responses are cached privately server-side (Qloo Support confirmed this is allowed). No Qloo response data is kept in this repo: no locality ids, counts or artist names from live responses. +It prints aggregates only. Qloo responses are cached privately server-side. No Qloo response data is kept in this repo: no locality ids, counts or artist names from live responses. ## Method diff --git a/package.json b/package.json index b22e9f83..63664b4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "busk-map", - "version": "1.2.0", + "version": "1.2.1", "private": true, "scripts": { "dev": "node scripts/copy-maplibre-worker.mjs && next dev", diff --git a/public/brand/kit/features/02-repertoire.png b/public/brand/kit/features/02-repertoire.png index 65c141aa..efdd9246 100644 Binary files a/public/brand/kit/features/02-repertoire.png and b/public/brand/kit/features/02-repertoire.png differ diff --git a/public/brand/kit/features/03-brain.png b/public/brand/kit/features/03-brain.png index 513e86f7..770f37b8 100644 Binary files a/public/brand/kit/features/03-brain.png and b/public/brand/kit/features/03-brain.png differ diff --git a/public/brand/kit/github-social-preview-1280x640.png b/public/brand/kit/github-social-preview-1280x640.png index 035763b3..532750a6 100644 Binary files a/public/brand/kit/github-social-preview-1280x640.png and b/public/brand/kit/github-social-preview-1280x640.png differ diff --git a/public/brand/kit/readme-hero-1600x640.png b/public/brand/kit/readme-hero-1600x640.png index f88f8051..9e7f5781 100644 Binary files a/public/brand/kit/readme-hero-1600x640.png and b/public/brand/kit/readme-hero-1600x640.png differ diff --git a/public/brand/kit/screenshot-desktop-1500x1000.png b/public/brand/kit/screenshot-desktop-1500x1000.png index 88622f67..ea77b7d4 100644 Binary files a/public/brand/kit/screenshot-desktop-1500x1000.png and b/public/brand/kit/screenshot-desktop-1500x1000.png differ diff --git a/public/brand/kit/video-end-1920x1080.png b/public/brand/kit/video-end-1920x1080.png index fde8f21e..d748eb9a 100644 Binary files a/public/brand/kit/video-end-1920x1080.png and b/public/brand/kit/video-end-1920x1080.png differ diff --git a/public/brand/kit/video-lower-third-1920x1080.png b/public/brand/kit/video-lower-third-1920x1080.png index 1ea51574..561197aa 100644 Binary files a/public/brand/kit/video-lower-third-1920x1080.png and b/public/brand/kit/video-lower-third-1920x1080.png differ diff --git a/public/brand/kit/video-title-1920x1080.png b/public/brand/kit/video-title-1920x1080.png index 815dcbea..d089a323 100644 Binary files a/public/brand/kit/video-title-1920x1080.png and b/public/brand/kit/video-title-1920x1080.png differ diff --git a/public/brand/social/devpost-cover-1200x800.png b/public/brand/social/devpost-cover-1200x800.png index dc8cc970..cf26632c 100644 Binary files a/public/brand/social/devpost-cover-1200x800.png and b/public/brand/social/devpost-cover-1200x800.png differ diff --git a/public/brand/social/og-image-1200x630.png b/public/brand/social/og-image-1200x630.png index 9cb71a90..9caae4c5 100644 Binary files a/public/brand/social/og-image-1200x630.png and b/public/brand/social/og-image-1200x630.png differ diff --git a/public/partners/qloo-icon-ink.svg b/public/partners/qloo-icon-ink.svg deleted file mode 100644 index 24fbc5a1..00000000 --- a/public/partners/qloo-icon-ink.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/partners/qloo-icon-white.svg b/public/partners/qloo-icon-white.svg deleted file mode 100644 index 6f8cbabf..00000000 --- a/public/partners/qloo-icon-white.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/brain/page.tsx b/src/app/brain/page.tsx index 4a7e9b04..f2723134 100644 --- a/src/app/brain/page.tsx +++ b/src/app/brain/page.tsx @@ -1,12 +1,11 @@ import type { Metadata } from "next"; import Link from "next/link"; import { BrainMap } from "@/components/brain/brain-map"; -import { QlooWordmark } from "@/components/honeycomb/logo"; import { Icon } from "@/components/honeycomb/icon"; import { MeetTheHive } from "@/components/honeycomb/meet-the-hive"; import { NoteCard } from "@/components/honeycomb/note-card"; import { StatStrip } from "@/components/honeycomb/stat-strip"; -import { callKinds, facts, next, QUOTA } from "@/lib/qloo-map"; +import { callKinds, facts, next, quotaNote } from "@/lib/qloo-map"; export const metadata: Metadata = { title: "The brain of Busk Map", @@ -27,13 +26,10 @@ export default function BrainPage() {
- - Powered by - - + Taste data from the Qloo API

- Powered by Qloo: - The brain + Taste data from the Qloo API: + The brain
of Busk Map

@@ -61,7 +57,7 @@ export default function BrainPage() {

- {`Answers are cached for ${QUOTA.cacheHours} hours. Qloo allows ${QUOTA.requestsPerSecond} calls a second; Busk Map paces itself to ${QUOTA.pacedPerSecond}, because bursts of 4 drew rate-limit errors. One key's ${QUOTA.requestsPerMonth.toLocaleString("en-AU")} calls a month cover roughly 270–360 new busks, and reruns are free.`} + {quotaNote}

diff --git a/src/app/brand/page.tsx b/src/app/brand/page.tsx index 77143f18..416dbf61 100644 --- a/src/app/brand/page.tsx +++ b/src/app/brand/page.tsx @@ -9,7 +9,7 @@ import { PhoneFold } from "@/components/brand/phone-fold"; import { HexCell } from "@/components/honeycomb/hex-cell"; import { Icon } from "@/components/honeycomb/icon"; import { Spinner } from "@/components/ui/spinner"; -import { Logo, QlooWordmark } from "@/components/honeycomb/logo"; +import { Logo } from "@/components/honeycomb/logo"; import { ScoreCell } from "@/components/honeycomb/score-cell"; import { RankTile } from "@/components/honeycomb/rank-tile"; import { DURATIONS, EASINGS, RADII, SHADOWS, SIZES, SPACE, STROKES, TOKENS, WORDS, type ScaleRow } from "@/lib/brand-data"; @@ -82,7 +82,7 @@ const PRINCIPLES = [ ["Bluestone and paper", "Bluestone is the ink and the night ground; warm paper is the day ground. Both themes pass AA everywhere."], ["Condensed caps", "Big Shoulders shouts the headings. Sentences stay in Atkinson Hyperlegible Next; data and numbers in JetBrains Mono."], ["Print texture", "2px rules instead of soft shadows, hard offsets on things that float, a halftone grain on night grounds, a stencil wordmark."], - ["Qloo, our partner", "Qloo is credited with its own wordmark wherever its data changes the answer, and has its own purple (`qloo`) only for Qloo facts and the Brain."], + ["Credit in words", "Qloo's taste data is credited in plain text wherever it changes the answer: the word Qloo, never a logo, in the neutral `slate`."], ["Honest numbers", "Every number names its source. Estimates are labelled; planned work is labelled \"Next · not built yet\"; nothing is invented."], ] as const; @@ -90,7 +90,7 @@ const VOICE = [ ["Pitch, busk", "A pitch is one place to play. A busk is the whole outing: three pitches, their suggested sets, one link."], ["Plain words", "Say what the research found, never the tool behind it."], ["Honest numbers", "Every number names its source. Estimates are labelled, and nothing is invented."], - ["Qloo first", "Taste data is the heart of every busk. Credit Qloo wherever its data changed the answer."], + ["Name the data", "Taste data is the heart of every busk. Name Qloo, in plain text, wherever its data changed the answer."], ] as const; const COLOURS = [ @@ -99,7 +99,7 @@ const COLOURS = [ ["Paper", "--card", "cards, panels"], ["Ground", "--background", "the page"], ["Honey", "--honey", "hidden gems"], - ["Qloo", "--qloo", "Qloo, our partner"], + ["Slate", "--slate", "data from a named source"], ["Event blue", "--event", "events"], ["Zone pink", "--zone-pink", "no-busking zones"], ["Footfall", "--footfall", "activity estimate"], @@ -159,7 +159,6 @@ export default function BrandPage() { {body} - {title === "Qloo, our partner" ? : null} ))} @@ -402,14 +401,8 @@ export default function BrandPage() { ))} - -
- - Qloo's own logo, shown wherever Busk Map names Qloo as its partner. It always links to qloo.com in a new tab. -
-
-

The pictures for the repository, the Devpost page and the video. Each uses the logo and Qloo's logo as drawn here; the screenshots are real captures of the app at 1440 and 390.

+

The pictures for the repository, the Devpost page and the video. Each uses the logo as drawn here and names Qloo in plain text only; the screenshots are real captures of the app at 1440 and 390.

diff --git a/src/app/globals.css b/src/app/globals.css index d849adf5..bd481f5a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -51,8 +51,8 @@ --bluestone: #141c21; --honey: #ffcf3a; --honey-deep: #d99a00; - --qloo: #5b5ba3; - --qloo-brand: #8C8CC8; + /* Slate: the neutral ink for data from a named source (a Qloo-sourced chip, tag or stat), always with the source's name in words. */ + --slate: #45596b; --signal-text: #b13a00; /* The Hive mark (Hive Identity): signal-text by day, signal at night. The day and night values and the board's day paper are the same in both themes, so a specimen can show the day mark inside a night panel. */ @@ -60,7 +60,7 @@ --hive-night: #ff6a2b; --hive-paper: #f7f3ec; --hive: var(--hive-day); - /* Source colours for the Hive mark's centre cell (single-source steps): Qloo's bluestone with a white mark, Spotify's green with a black mark, Last.fm's red with a white mark. Brand colours, the same in both themes. */ + /* Source colours for the Hive mark's centre cell (single-source steps): Qloo steps on Busk Map's own bluestone with the white neutral data glyph (no Qloo mark), Spotify's green with a black mark, Last.fm's red with a white mark. Brand colours, the same in both themes. */ --source-qloo: #141c21; --source-qloo-ink: #ffffff; --source-spotify: #1ed760; @@ -122,8 +122,7 @@ --bluestone: #141c21; --honey: #ffcf3a; --honey-deep: #d99a00; - --qloo: #8C8CC8; - --qloo-brand: #8C8CC8; + --slate: #a9bccb; --signal-text: #ff7f45; --hive: var(--hive-night); --zone-pink: #ff5c9d; @@ -180,8 +179,7 @@ --bluestone: #141c21; --honey: #ffcf3a; --honey-deep: #d99a00; - --qloo: #8C8CC8; - --qloo-brand: #8C8CC8; + --slate: #a9bccb; --signal-text: #ff7f45; --hive: var(--hive-night); --zone-pink: #ff5c9d; @@ -292,8 +290,7 @@ --color-bluestone: var(--bluestone); --color-honey: var(--honey); --color-honey-deep: var(--honey-deep); - --color-qloo: var(--qloo); - --color-qloo-brand: var(--qloo-brand); + --color-slate: var(--slate); --color-signal-text: var(--signal-text); --color-hive: var(--hive); --color-hive-paper: var(--hive-paper); @@ -440,20 +437,6 @@ html { scroll-padding-bottom: var(--bottom-nav); } @media (prefers-reduced-motion: reduce) { .hc-flow-cell, .hc-flow-link { animation: none; } } /* The landing's one pause control (MotionPause) holds every loop where it is (WCAG 2.2.2): the ticker, the hero glow, the brain pulse. */ :root[data-motion="paused"] :is(.hc-ticker, .hc-glow, .hc-flow-cell, .hc-flow-link) { animation-play-state: paused; } -/* The sponsor's Qloo wordmark assembles once, when it scrolls into view (impeccable live, 17 Oct; progressive). Paths: 1 l, 2 Q, 3 and 4 the o's, 5 the purple bar. */ -@keyframes hc-qloo-rise { 0% { opacity: 0; transform: translateY(60%) scaleY(0.6); } 100% { opacity: 1; transform: none; } } -@keyframes hc-qloo-bar { 0% { transform: scaleX(0); } 100% { transform: scaleX(1); } } -/* Progressive: with no JS (or before it runs) there is no data-inview and no animation, so the logo is always visible. InView marks an - off-screen wordmark "ready" (held at its first frame) and then "true" when it scrolls into view (it plays). */ -[data-inview] .hc-qloo-rise path { transform-box: fill-box; transform-origin: 50% 100%; animation: hc-qloo-rise 0.6s cubic-bezier(.2,.8,.2,1) both; } -[data-inview] .hc-qloo-rise path:nth-child(2) { animation-delay: 0.05s; } -[data-inview] .hc-qloo-rise path:nth-child(1) { animation-delay: 0.17s; } -[data-inview] .hc-qloo-rise path:nth-child(4) { animation-delay: 0.29s; } -[data-inview] .hc-qloo-rise path:nth-child(3) { animation-delay: 0.41s; } -[data-inview] .hc-qloo-rise path:nth-child(5) { transform-origin: 0 50%; animation: hc-qloo-bar 0.5s cubic-bezier(.2,.8,.2,1) 0.75s both; } -[data-inview="ready"] .hc-qloo-rise path { animation-play-state: paused; } -/* Reduced motion: no rise, no bar; the nth-child(5) rule is named too, or its higher specificity would keep the bar animating. */ -@media (prefers-reduced-motion: reduce) { [data-inview] .hc-qloo-rise path, [data-inview] .hc-qloo-rise path:nth-child(5) { animation: none; } } .hc-cell { transform-box: fill-box; transform-origin: center; animation: hc-cell-in 520ms var(--ease-out, ease) backwards; animation-delay: var(--d, 0ms); } .hc-cell-hot { animation: hc-cell-in 520ms var(--ease-out, ease) backwards, hc-breathe 3.6s ease-in-out infinite; animation-delay: var(--d, 0ms), calc(var(--d, 0ms) + 2400ms); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 91ca8cf7..706db2c1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,7 +16,7 @@ const mono = JetBrains_Mono({ subsets: ["latin"], weight: ["400", "500", "700"], const TITLE = "Busk Map"; const DESCRIPTION = - "Know where to play, and what to play there. A taste-aware pitch planner for street performers, powered by Qloo."; + "Know where to play, and what to play there. A taste-aware pitch planner for street performers, with taste data from the Qloo API."; /** Absolute URLs for the social images: the production domain on Vercel, localhost elsewhere. */ const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? (process.env.VERCEL_PROJECT_PRODUCTION_URL ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}` : "http://localhost:3000"); diff --git a/src/app/page.tsx b/src/app/page.tsx index 3fb3cadb..c6384367 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,5 @@ import Link from "next/link"; import { ExampleActCard } from "@/components/honeycomb/example-act-card"; -import { QlooLink } from "@/components/honeycomb/logo"; import { ScoreCell } from "@/components/honeycomb/score-cell"; import { Button } from "@/components/ui/button"; import { HexCell } from "@/components/honeycomb/hex-cell"; @@ -77,12 +76,11 @@ export default function Home() {
-
- {/* The halo keeps the purple legible when a glowing cell pulses behind it. */} - - Built with +
+ {/* Plain text only: no Qloo logo, no partner wording. The halo keeps it legible when a glowing cell pulses behind it. */} + + Taste data from the Qloo API -
@@ -185,14 +183,14 @@ export default function Home() { data-theme="dark" aria-labelledby="brain" data-testid="brain-teaser" - className="bm-grain flex flex-wrap items-center justify-between gap-8 border-[3px] border-qloo bg-background p-5 text-foreground shadow-[8px_8px_0_var(--qloo)] md:p-10" + className="bm-grain flex flex-wrap items-center justify-between gap-8 border-[3px] border-slate bg-background p-5 text-foreground shadow-[8px_8px_0_var(--slate)] md:p-10" >
- Powered by + Taste data from the Qloo API

- The brain of
+ The brain of
Busk Map

-
diff --git a/src/components/brain/brain-map.tsx b/src/components/brain/brain-map.tsx index 6dc340e7..57280cd7 100644 --- a/src/components/brain/brain-map.tsx +++ b/src/components/brain/brain-map.tsx @@ -150,7 +150,7 @@ export function BrainMap() { data-trace={state} onClick={() => pick(id)} className={cn( - "box-border flex h-[52px] w-full min-w-0 cursor-pointer scroll-mt-24 items-center gap-2.5 border-[1.5px] border-border bg-card px-3 text-left text-foreground transition-[border-color] duration-(--duration-fast) ease-(--ease-out) outline-2 outline-transparent outline-offset-2 hover:border-qloo focus-visible:outline-ring focus-visible:ring-0 motion-reduce:transition-none", + "box-border flex h-[52px] w-full min-w-0 cursor-pointer scroll-mt-24 items-center gap-2.5 border-[1.5px] border-border bg-card px-3 text-left text-foreground transition-[border-color] duration-(--duration-fast) ease-(--ease-out) outline-2 outline-transparent outline-offset-2 hover:border-slate focus-visible:outline-ring focus-visible:ring-0 motion-reduce:transition-none", other && "border-dashed bg-transparent", state === "path" && "border-2 border-primary", state === "selected" && "border-2 border-primary bg-[#26323a] shadow-[4px_4px_0_var(--primary)] outline-primary", @@ -160,7 +160,7 @@ export function BrainMap() { {num && ( @@ -170,7 +170,7 @@ export function BrainMap() { {num && {num}. } {label} - {sub} + {sub} @@ -189,7 +189,7 @@ export function BrainMap() { return (