Qwen3.8-Flash-Next
M4 Max 128 GB · llama.cpp · every run of this model · uwu · 2026-11-01
Race it: run Qwen3.8-Flash-Next on your computer and see the two side by side.
- Score
- 2,761 Silver
- Tasks passed
- 44/44
- Points
- 64/64Harder tasks count 3
- Tokens
- 127,18222,171 read, 105,011 written, as the runner counted them
- Speed
- 27.6 tok/sAs the runner measured it; the site cannot check this.
tok/s is tokens a second: how fast the model writes. A token is about three quarters of a word. How the score works.
This setup, checked
No other runs of Qwen3.8-Flash-Next on M4 Max 128 GB yet; the next one will be compared with this one.
Not on the leaderboard: it was posted under an earlier version of the task suite. Leaderboard
- Summarizing 5/5
- Extracting 5/5
- Following instructions 5/5
- Reasoning 5/5
- Reading code 4/4
- Using tools 5/5
- Building pages 5/5
- Building games 2/2
- Writing code 3/3
- Fixing code 2/2
- Planning and data 3/3
Run details
Flag this run
What it built
Pages and games, as the model wrote them, each in a sandbox. On a computer, click a game and use the arrow keys.
-
Build 2048Keeps a game's rules across many moves.Passed · 22k tokens · 27.6 tok/s
-
Build SnakeRuns a game where a snake grows and the game ends on a crash.Passed · 24k tokens · 27.1 tok/s
-
A small websiteLays out a small website with a menu and a footer.Passed · 24k tokens · 27.7 tok/s
-
A pricing table with a toggleSwitches every price between monthly and yearly with one button.Passed · 3.9k tokens · 27 tok/s
-
An accessible sign-up formChecks a sign-up form and labels each of its fields.Passed · 3.7k tokens · 27.3 tok/s
-
A to-do app that remembersKeeps data across a reload.Passed · 2.1k tokens · 27.6 tok/s
-
A bar chart in SVGDraws data to scale.Passed · 2.6k tokens · 27.4 tok/s
Scored tasks
Summarizing 5 of 5
One-sentence summaryPassed
1,065 tokens: 142 read, 923 written · 2 min 32 s · 21.5 tok/s
Passes when One sentence of 5 to 30 words saying the library opens earlier (8 a.m.) on weekdays.
Summarize this in one sentence of at most 30 words. Starting March 3, the Millbrook Public Library will open at 8 a.m. instead of 10 a.m. on weekdays. The change follows a survey in which 62% of respondents asked for earlier hours. Weekend hours stay the same. The library will hire two part-time staff to cover the extra time, paid for by a state grant.
Millbrook Public Library will open at 8 a.m. on weekdays starting March 3 after 62% requested earlier hours, hiring two staff with state grant funding; weekend hours unchanged.
Meeting notes in three bulletsPassed
694 tokens: 236 read, 458 written · 20 s · 24.9 tok/s
Passes when Exactly three bullet points and nothing else, each at most 20 words, covering the launch moving to June 12, the approved marketing budget and Priya owning testing, and leaving out the webhook fix and the coffee machine.
Summarize these meeting notes as exactly three bullet points, each at most 20 words. Keep only the decisions and ownership changes that matter. Output only the bullet points. Weekly sync, product team. Present: Priya, Omar, Jules, Sam. - Omar reported that the payment provider fixed the webhook bug; no action needed. - The launch date moves from June 5 to June 12 because the app store review is slow. - Jules showed the new onboarding screens. Everyone liked them. Small copy changes only. - The marketing budget of $40,000 was approved by finance on Monday. - Priya will own end-to-end testing from now on; Sam hands over the test plan by Friday. - Next sync is moved to Thursday at 10:00. - Coffee machine on floor 3 is broken again.
- Launch date moves from June 5 to June 12 due app store review delay. - Marketing budget of $40,000 was approved by finance on Monday. - Priya owns end-to-end testing; Sam transfers test plan to Priya by Friday.
Review sentiment and complaintPassed
274 tokens: 162 read, 112 written · 4 s · 32.2 tok/s
Passes when Both lines. Sentiment is mixed: the reviewer loves the battery and sound but is annoyed. The complaint names the charger or support in at most 12 words.
Read this product review and answer in exactly this format: Sentiment: <positive, negative or mixed> Complaint: <the main complaint in a few words> I've used this speaker every day for a month. The battery is honestly amazing, easily two full days, and it sounds far better than its size suggests. But the charger that came in the box stopped working after a week, and support took nine days to reply. I bought a replacement cable myself. Would I buy it again? Probably, but I'm annoyed.
Sentiment: mixed Complaint: Charger failure and slow support
Faithful summary of a studyPassed
868 tokens: 177 read, 691 written · 34 s · 21.2 tok/s
Passes when At most 50 words with the 240 participants, the 12-week length and the 3.1-day result, and nothing the text does not say (no approval, cure, children or recommendation).
Summarize this in at most 50 words. Keep the key numbers. Do not add anything the text does not say. In a randomized trial, 240 adults with chronic migraine took either the new drug or a placebo for 12 weeks. Those on the drug had 3.1 fewer headache days per month on average, compared with 1.9 fewer days for placebo. Nausea was the most common side effect, reported by 9% of the drug group. The authors note the trial lasted only 12 weeks and call for longer studies before any recommendation is made.
240 adults with chronic migraine received the drug or placebo for 12 weeks in a randomized trial. Headache days fell by 3.1 monthly with the drug, versus 1.9 with placebo. Nausea was most common, in 9% of drug users. Authors request longer studies before recommendations.
Action items from an email threadPassed
623 tokens: 256 read, 367 written · 14 s · 29.5 tok/s
Passes when Exactly four lines of the form "- owner: action": Dana sends the contract, Luis books the venue, Mei updates the budget sheet, Dana emails the caterer. Tom's declined offer, the logo and the invitations are left out.
List every action item in this email thread that someone has committed to do, as lines of the form "- <owner>: <action>". Leave out offers that were declined and things that turned out not to be needed. Output only the list. From: Dana Hi all, quick recap of what's still open for the June offsite. I'll send the revised contract to the hotel by Wednesday. From: Tom I can book the venue for the dinner if that helps? From: Luis Thanks Tom, but I'll book the venue myself since I already spoke to them. Also, no need to change the logo on the badges, it's fine as is. From: Mei I'll update the budget sheet with the new hotel price tonight. From: Dana Great. Oh, and I'll email the caterer about the vegetarian options. Tom, could you just double-check the date on the invitations? Actually never mind, I checked them this morning, they're correct.
- Dana: Send the revised contract to the hotel by Wednesday - Luis: Book the venue for the dinner - Mei: Update the budget sheet with the new hotel price tonight - Dana: Email the caterer about the vegetarian options
Extracting 5 of 5
Fields from an email as JSONPassed
351 tokens: 160 read, 191 written · 8 s · 26.4 tok/s
Passes when Only a JSON object with exactly name "Laura Chen", company "Northwind Traders", meeting_date "2025-05-14" and attendees the number 4.
Extract these fields from the email as a JSON object with exactly these keys: "name" (the sender's full name), "company", "meeting_date" (YYYY-MM-DD) and "attendees" (a number). Output only the JSON. Hello! This is Laura Chen from Northwind Traders. We'd love to visit your workshop. Could we meet on the 14th of May 2025, any time after lunch? We'll be four people in total, including me. Best, Laura
{ "name": "Laura Chen", "company": "Northwind Traders", "meeting_date": "2025-05-14", "attendees": 4 }Every email address, oncePassed
684 tokens: 181 read, 503 written · 17 s · 31.9 tok/s
Passes when Exactly four addresses, one per line, in order: info@harbor-events.org, speakers@harbor-events.org, mia.k@studio-nine.io, accounts@harbor-events.org. "jo at harbor dot org" is not written out in full, and its inbox is closed.
List every email address written out in full in this text (like name@example.com), one per line, in the order they first appear, without duplicates. Leave out any inbox the text says is closed. Output only the addresses. Contacts for the conference: write to info@harbor-events.org for general questions, or to speakers@harbor-events.org if you are presenting. Our designer (mia.k@studio-nine.io) made the poster. Billing questions: accounts@harbor-events.org. Again, presenters use speakers@harbor-events.org. Please don't write to jo at harbor dot org, that inbox is closed.
info@harbor-events.org speakers@harbor-events.org mia.k@studio-nine.io accounts@harbor-events.org
A list as CSVPassed
330 tokens: 140 read, 190 written · 7 s · 29.9 tok/s
Passes when The header item,qty,price, then the four items with whole-number quantities and prices as plain numbers (no $).
Convert this shopping list to CSV with the header row item,qty,price. Write prices as plain numbers without a currency sign. Output only the CSV. Apples - 12 @ $0.50 Bread loaf - 2 @ $3.25 Olive oil (1 l) - 1 @ $8.90 Eggs - 18 @ $0.30
item,qty,price Apples,12,0.50 Bread loaf,2,3.25 Olive oil (1 l),1,8.90 Eggs,18,0.30
The real deadlinePassed
262 tokens: 141 read, 121 written · 5 s · 27.1 tok/s
Passes when Only 2025-02-07, the extended deadline.
What is the final submission deadline? Answer with the date only, in YYYY-MM-DD format. The call for papers opened on 2 January 2025. Drafts were originally due January 20, but the committee extended the final submission deadline to 7 February 2025. Reviews are due by 28 February, and results will be announced on March 10, 2025.
2025-02-07
Warnings and errors from a logPassed
749 tokens: 318 read, 431 written · 17 s · 26.7 tok/s
Passes when Only a JSON array of the WARN line and the two ERROR lines, in order, with time, level and message copied exactly.
From this log, return a JSON array with one object per WARN or ERROR line, in order, each with the keys "time" (HH:MM:SS), "level" and "message". Output only the JSON. 2025-03-04 09:12:01 INFO server started on port 8080 2025-03-04 09:12:07 WARN config key "timeout" is deprecated 2025-03-04 09:13:44 INFO user alice logged in 2025-03-04 09:15:02 ERROR database connection lost 2025-03-04 09:15:03 INFO retrying in 5s 2025-03-04 09:15:08 INFO database reconnected 2025-03-04 09:20:30 DEBUG cache hit ratio 0.93 2025-03-04 09:31:12 ERROR payment webhook returned 502
[ { "time": "09:12:07", "level": "WARN", "message": "config key \"timeout\" is deprecated" }, { "time": "09:15:02", "level": "ERROR", "message": "database connection lost" }, { "time": "09:31:12", "level": "ERROR", "message": "payment webhook returned 502" } ]
Following instructions 5 of 5
Exactly one wordPassed
96 tokens: 62 read, 34 written · 2 s · 23.6 tok/s
Passes when Exactly OK, with nothing else, not even a full stop.
Reply with exactly the word OK and nothing else.
OK
Three lowercase linesPassed
235 tokens: 84 read, 151 written · 5 s · 32.9 tok/s
Passes when Exactly three lines about the sea, all lowercase, the third ending with a question mark.
Write exactly three lines about the sea. Every line must be entirely lowercase, and the third line must end with a question mark. Output only the three lines.
the sea breathes salt waves whisper softly what hides beneath the moon?
Exact JSON shapePassed
172 tokens: 88 read, 84 written · 3 s · 28.2 tok/s
Passes when Only JSON with exactly two keys: colors (three lowercase color names) and count (the number 3).
Return a JSON object with exactly two keys: "colors", a list of exactly three color names in lowercase, and "count", the number 3. Output only the JSON.
{"colors":["red","blue","green"],"count":3}Sort a listPassed
249 tokens: 81 read, 168 written · 6 s · 30.3 tok/s
Passes when One line: apple, apricot, banana, cherry, pear (any capitalization).
Sort these words alphabetically, ignoring case, and output them on one line separated by commas: pear, Apple, banana, cherry, apricot
Apple, apricot, banana, cherry, pear
A name with three rulesPassed
308 tokens: 88 read, 220 written · 7 s · 33 tok/s
Passes when Two words, both capitalized, with no letter e anywhere.
Suggest a product name for a solar-powered lamp. Rules: exactly two words, both capitalized, and the letter "e" must not appear anywhere. Output only the name.
Solar Lamp
Reasoning 5 of 5
Unit pricePassed
275 tokens: 94 read, 181 written · 7 s · 29.5 tok/s
A shop sells pencils at 2 for $0.40. How much do 13 pencils cost, in dollars? Work it out, then end with a line "ANSWER: <number>".
2 pencils cost $0.40, so 1 pencil costs $0.40 ÷ 2 = $0.20. 13 pencils cost 13 × $0.20 = $2.60. ANSWER: 2.60
Days of the weekPassed
250 tokens: 88 read, 162 written · 6 s · 26.8 tok/s
Today is Wednesday. What day of the week will it be 386 days from today? Work it out, then end with a line "ANSWER: <day>".
386 days ÷ 7 days per week = 55 weeks with a remainder of 1 day. So 386 days from Wednesday is 1 day later: Thursday. ANSWER: Thursday
Who owns the catPassed
221 tokens: 109 read, 112 written · 4 s · 32 tok/s
Fay, Ivy and Hal each own exactly one pet: a cat, a dog or a fish, all different. Ivy does not own the dog. Hal owns the fish. Who owns the cat? Work it out, then end with a line "ANSWER: <name>".
Hal owns the fish. Ivy does not own the dog, and she also cannot own the fish because Hal does, so Ivy must own the cat. ANSWER: Ivy
Arrival timePassed
208 tokens: 106 read, 102 written · 6 s · 18.9 tok/s
A train leaves at 06:25 and the trip takes 4 hours 10 minutes. At what time does it arrive? Work it out, then end with a line "ANSWER: <HH:MM>" in 24-hour time.
06:25 + 4 hours = 10:25 10:25 + 10 minutes = 10:35 ANSWER: 10:35
Filling a tankPassed
390 tokens: 129 read, 261 written · 10 s · 26.6 tok/s
A tank holds 120 liters. Pipe A alone fills it in 6 hours, pipe B alone fills it in 2 hours, and a drain alone empties a full tank in 2 hours. With all three open and the tank starting empty, how many hours until it is full? Work it out, then end with a line "ANSWER: <number>".
Pipe A fills at 20 L/h, Pipe B fills at 60 L/h, and the drain empties at 60 L/h. Net fill rate = 20 L/h, so it takes 120 / 20 = 6 hours. ANSWER: 6
Reading code 4 of 4
What does it printPassed
362 tokens: 118 read, 244 written · 12 s · 21.2 tok/s
What does this Python program print? Work it out, then end with a line "ANSWER: <output>". def f(xs): return sorted(xs)[::-1][:2] print(f([34, 17, 44, 25, 11, 46]))The sorted list is `[11, 17, 25, 34, 44, 46]`. Reversing gives `[46, 44, 34, 25, 17, 11]`, and taking the first two elements gives `[46, 44]`. ANSWER: [46, 44]
Trace a loopPassed
455 tokens: 135 read, 320 written · 15 s · 22 tok/s
What does this Python program print? Work it out, then end with a line "ANSWER: <output>". def g(n): total = 0 for i in range(1, n + 1): if i % 3 == 0 or i % 4 == 0: total += i return total print(g(26))The function sums numbers from 1 to 26 divisible by 3 or 4: - Multiples of 3: sum = 108 - Multiples of 4: sum = 84 - Multiples of both 3 and 4 (multiples of 12): 12 + 24 = 36 Total = 108 + 84 - 36 = 156 ANSWER: 156
Find the bugPassed
326 tokens: 148 read, 178 written · 8 s · 26.2 tok/s
Passes when A final line ANSWER: 6 (it divides by one less than the count).
This function should return the mean of a non-empty list. Which line has the bug? Work it out, then end with a line "ANSWER: <line number>". 1 def average(numbers): 2 """Return the mean of a non-empty list of numbers.""" 3 total = 0 4 for n in numbers: 5 total += n 6 count = len(numbers) - 1 7 return total / count
The bug is on line 6: the count is set to `len(numbers) - 1`, but it should be `len(numbers)` to compute the mean correctly. ANSWER: 6
Run a query in your headPassed
374 tokens: 186 read, 188 written · 9 s · 23.4 tok/s
What rows does this SQL query return? Output only the rows, one per line, as customer,total in the query's order. Table orders: id | customer | amount 1 | ben | 65 2 | ben | 5 3 | ana | 145 4 | cal | 135 5 | cal | 105 6 | ana | 70 Query: SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer HAVING SUM(amount) > 100 ORDER BY total DESC;
cal,240 ana,215
Using tools 5 of 5
Call one toolPassed
904 tokens: 776 read, 128 written · 6 s · 33.8 tok/s
Passes when One get_weather call for Lisbon in celsius, then an answer giving the 21 °C the tool returned.
What's the weather in Lisbon right now, in celsius?
- user
What's the weather in Lisbon right now, in celsius?
- assistant
get_weather({"city":"Lisbon","unit":"celsius"}) - tool
{"city":"Lisbon","conditions":"sunny","temperature":21,"unit":"celsius"} - assistant
In Lisbon, it's currently **sunny** with a temperature of **21°C**.
- user
Don't call a tool when none is neededPassed
506 tokens: 455 read, 51 written · 4 s · 18.4 tok/s
Passes when No tool call, and the answer is 144.
What is 12 times 12?
- user
What is 12 times 12?
- assistant
12 × 12 = 144
- user
Two calls for two answersPassed
1,222 tokens: 900 read, 322 written · 14 s · 26.3 tok/s
Passes when Converts 250 EUR to USD and to JPY in at most three calls, then gives both amounts: 270.50 USD and 40,125 JPY.
Convert 250 EUR to USD and to JPY.
- user
Convert 250 EUR to USD and to JPY.
- assistant
convert_currency({"amount":250,"from":"EUR","to":"USD"})convert_currency({"amount":250,"from":"EUR","to":"JPY"}) - tool
{"amount":270.5,"currency":"USD"} - tool
{"amount":40125,"currency":"JPY"} - assistant
Based on today's exchange rates: - **250 EUR = 270.50 USD** - **250 EUR = 40,125 JPY**
- user
Chain two toolsPassed
1,677 tokens: 1,358 read, 319 written · 13 s · 28.4 tok/s
Passes when Looks up the customer first, asks for C-1042's orders, then reports A-77 shipped and A-80 processing.
What is the status of each order for the customer with the email kim@example.com?
- user
What is the status of each order for the customer with the email kim@example.com?
- assistant
find_customer({"email":"kim@example.com"}) - tool
{"customer_id":"C-1042","name":"Kim Park"} - assistant
get_orders({"customer_id":"C-1042"}) - tool
{"orders":[{"carrier":"DHL","order_id":"A-77","status":"shipped"},{"order_id":"A-80","status":"processing"}]} - assistant
Kim Park (customer ID **C-1042**) has two orders: | Order ID | Status | Carrier | |----------|-------------|---------| | A-77 | Shipped | DHL | | A-80 | Processing | — | In short, one order (A-77) has already shipped, while the other (A-80) is still being processed and has not shipped yet.
- user
Handle a failed call honestlyPassed
1,066 tokens: 817 read, 249 written · 12 s · 24.9 tok/s
Passes when Tries 19:00 for 2 people, never books another time without asking, does not claim the booking succeeded, and offers 18:30 or 20:30.
Book a table for 2 people at Luigi's tonight at 19:00.
- user
Book a table for 2 people at Luigi's tonight at 19:00.
- assistant
book_table({"people":2,"restaurant":"Luigi's","time":"19:00"}) - tool
{"available_times":["18:30","20:30"],"error":"fully booked at that time"} - assistant
I couldn't book Luigi's at 19:00 — it's fully booked at that time. The nearest available slots tonight are: - **18:30** - **20:30** Let me know which you'd prefer (or if you'd like me to try a different restaurant) and I'll get it booked for 2 people.
- user
Building pages 5 of 5
A small websitePassed
23,527 tokens: 163 read, 23,364 written · 14 min 5 s · 27.7 tok/s
Passes when A <header> with an <h1> naming the bakery, a <nav> with exactly 3 links, a <main> with <section id="menu"> holding at least 4 list items, and a <footer> with opening hours. Nothing loaded from another site and no network requests.
Build a one-page website for a bakery called "Crumb & Co". It must have a <header> containing an <h1> with the bakery's name; a <nav> with exactly 3 links; a <main> with a <section id="menu"> listing at least 4 items in a list; and a <footer> with the opening hours. Output one complete HTML document and nothing else. Put all CSS and JavaScript inline. Do not load anything from another site: no external scripts, stylesheets, fonts or images.
Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Crumb & Co — Small-batch bakery</title> <style> :root { --cream: #fff7ee; --paper: #fffdf8; --ink: #2a1a14; --cocoa: #623a26; --crust: #b6531c; --toast: #e7b375; --berry: #c2436e; --leaf: #33705a; --display: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Palatino, Georgia, serif; --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; } *, *::before, *::after { box-sizing: border-box; } html { scroll-behavior: smooth; } body { margin: 0; min-height: 100vh; font-family: var(--body); color: var(--ink); line-height: 1.55; background: var(--cream); overflow-x: hidden; } body::before { content: ""; position: fixed; inset: 0; z-index: -2; background: radial-gradient(1100px 620px at 8% 0%, rgba(231, 179, 117, 0.62), transparent 62%), radial-gradient(900px 520px at 92% 12%, rgba(194, 67, 110, 0.17), transparent 58%), radial-gradient(700px 420px at 50% 100%, rgba(51, 112, 90, 0.10), transparent 62%), linear-gradient(var(--cream), #ffe9d6); } body::after { content: ""; position: fixed; inset: -12%; z-index: -1; opacity: 0.35; pointer-events: none; background-image: radial-gradient(rgba(42, 26, 20, 0.09) 1px, transparent 1.5px), radial-gradient(rgba(42, 26, 20, 0.06) 1px, transparent 1.5px); background-size: 28px 28px, 54px 54px; animation: drift 28s linear infinite; will-change: transform; } header { position: sticky; top: 0; z-index: 30; background: rgba(255, 247, 238, 0.82); backdrop-filter: blur(14px) saturate(130%); -webkit-backdrop-filter: blur(14px) saturate(130%); border-bottom: 1px solid rgba(98, 58, 38, 0.14); } .header-inner { max-width: 1150px; margin: 0 auto; padding: 14px clamp(1rem, 5vw, 3rem); display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; } .brand { display: grid; gap: 0.15rem; } h1 { margin: 0; font-family: var(--display); letter-spacing: -0.035em; line-height: 1; font-size: clamp(1.45rem, 3vw, 2.3rem); } .amp { color: var(--crust); } .tagline { margin: 0; font-size: 0.88rem; color: var(--cocoa); letter-spacing: 0.02em; } nav { display: flex; gap: 0.35rem; flex-wrap: wrap; align-items: center; } nav a { position: relative; display: inline-block; padding: 0.62rem 0.9rem; border-radius: 999px; text-decoration: none; color: var(--cocoa); font-weight: 700; font-size: 0.93rem; transition: background 0.28s ease, color 0.28s ease, transform 0.28s ease; } nav a::after { content: ""; position: absolute; left: 0.85rem; right: 0.85rem; bottom: 0.42rem; height: 2px; border-radius: 999px; background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform 0.28s ease; } nav a:hover, nav a:focus-visible { background: var(--crust); color: #fff7ee; transform: translateY(-1px); } nav a:hover::after, nav a:focus-visible::after { transform: scaleX(1); } nav a.active { background: var(--cocoa); color: #fff7ee; } .cta { border: 0; border-radius: 999px; padding: 0.72rem 1.1rem; background: linear-gradient(135deg, var(--crust), var(--berry)); color: #fff7ee; font-weight: 800; letter-spacing: 0.02em; cursor: pointer; transition: transform 0.28s ease, box-shadow 0.28s ease, filter 0.28s ease; box-shadow: 0 10px 24px rgba(182, 83, 28, 0.22); } .cta:hover, .cta:focus-visible { transform: translateY(-2px) scale(1.02); filter: brightness(1.05); box-shadow: 0 14px 30px rgba(182, 83, 28, 0.28); } main { width: min(1150px, calc(100% - 2rem)); margin: 0 auto; } section { padding: clamp(2rem, 7vw, 5.5rem) 0; } .hero { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: clamp(2rem, 5vw, 4rem); align-items: center; padding-top: clamp(2rem, 9vw, 7rem); } .eyebrow { display: block; margin-bottom: 0.9rem; font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--cocoa); } h2, h3 { font-family: var(--display); letter-spacing: -0.03em; margin: 0 0 1rem; } .hero h2 { font-size: clamp(2.5rem, 8vw, 5.8rem); line-height: 0.94; margin-bottom: 1.2rem; } .lead { max-width: 58ch; font-size: clamp(1rem, 2vw, 1.12rem); margin: 0 0 1.4rem; color: #4a3026; } .status { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.8rem; border-radius: 999px; border: 1px solid rgba(51, 112, 90, 0.25); background: rgba(51, 112, 90, 0.08); color: #235e4a; font-weight: 800; font-size: 0.9rem; margin-bottom: 1.25rem; transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease; } .status::before { content: ""; width: 0.68rem; height: 0.68rem; border-radius: 99%; background: var(--leaf); box-shadow: 0 0 0 4px rgba(51, 112, 90, 0.12); } .status.closed { color: #8c331f; border-color: rgba(182, 83, 28, 0.30); background: rgba(182, 83, 28, 0.09); } .status.closed::before { background: var(--crust); box-shadow: 0 0 0 4px rgba(182, 83, 28, 0.12); } .visual { position: relative; min-height: 380px; display: grid; place-items: center; } .loaf { position: relative; width: min(100%, 360px); aspect-ratio: 1 / 1; animation: bob 7s ease-in-out infinite; } .dough { position: absolute; inset: 8%; background: radial-gradient(circle at 34% 28%, #fff8e5 0 12%, transparent 13%), radial-gradient(circle at 32% 30%, #fff3d0 0 32%, #e8b46e 33% 56%, #9a5a27 57% 78%, #57331d 79% 100%); border-radius: 57% 43% 50% 50% / 55% 55% 45% 45%; box-shadow: inset -14px -20px 32px rgba(91, 49, 28, 0.36), inset 14px 16px 28px rgba(255, 255, 255, 0.22), 0 34px 70px rgba(91, 49, 28, 0.28); } .dough::before { content: ""; position: absolute; inset: 10%; border-radius: inherit; background: linear-gradient( 88deg, rgba(255, 255, 255, 0.18) 0 5%, transparent 5% 12%, rgba(255, 255, 255, 0.15) 12% 15%, transparent 15% 28%, rgba(255, 255, 255, 0.16) 28% 32%, transparent 32% 48%, rgba(255, 255, 255, 0.14) 48% 52%, transparent 52% 70%, rgba(255, 255, 255, 0.12) 70% 74%, transparent 74% ); mix-blend-mode: soft-light; } .dough::after { content: ""; position: absolute; inset: 6%; border-radius: inherit; background: conic-gradient( from 160deg at 50% 50%, rgba(255, 255, 255, 0.20), rgba(255, 212, 131, 0.12) 35%, rgba(91, 49, 28, 0.22) 65%, rgba(255, 255, 255, 0.16) ); opacity: 0.55; mix-blend-mode: overlay; } .steam { position: absolute; left: 50%; top: 18%; width: 180px; height: 180px; transform: translate(-50%, -50%); pointer-events: none; } .steam span { position: absolute; bottom: 0; width: 14px; height: 14px; border-radius: 50%; background: rgba(255, 255, 255, 0.34); opacity: 0; filter: blur(1px); animation: rise 4.2s ease-in-out infinite; } .steam span:nth-child(1) { left: 28%; animation-delay: 0.1s; } .steam span:nth-child(2) { left: 48%; animation-delay: 0.9s; } .steam span:nth-child(3) { left: 68%; animation-delay: 1.7s; } .steam span:nth-child(4) { left: 38%; animation-delay: 2.6s; } .steam span:nth-child(5) { left: 58%; animation-delay: 3.4s; } .ticker { overflow: hidden; border-block: 1px solid rgba(98, 58, 38, 0.15); background: rgba(255, 255, 255, 0.36); margin: 0 0 clamp(1rem, 3vw, 2rem); padding: 0.75rem 0; } .ticker-track { display: flex; gap: 1.6rem; white-space: nowrap; animation: slide 24s linear infinite; will-change: transform; } .ticker-track span { font-family: var(--display); font-size: 1.05rem; color: var(--cocoa); } .ticker-track span::after { content: "•"; margin-left: 1.6rem; color: var(--crust); } .section-head { display: grid; gap: 0.85rem; max-width: 820px; margin-bottom: 1.5rem; } .section-head h2 { font-size: clamp(1.9rem, 4vw, 3.2rem); margin: 0; } .badge { display: inline-block; width: fit-content; padding: 0.45rem 0.75rem; border-radius: 999px; border: 1px solid rgba(182, 83, 28, 0.24); background: rgba(182, 83, 28, 0.08); color: #8c3d14; font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.12em; text-transform: uppercase; } .menu-list { list-style: none; margin: 0; padding: 0; border: 1px solid rgba(98, 58, 38, 0.16); border-radius: 26px; overflow: hidden; background: linear-gradient(180deg, rgba(255, 255, 255, 0.66), rgba(255, 244, 222, 0.44)); box-shadow: 0 18px 58px rgba(44, 27, 22, 0.10); } .menu-list li { position: relative; display: grid; grid-template-columns: 1fr auto; gap: 0.35rem 1rem; align-items: start; padding: 1.15rem 1.2rem; border-bottom: 1px solid rgba(98, 58, 38, 0.12); transition: background 0.35s ease, transform 0.35s ease; } .menu-list li:last-child { border-bottom: 0; } .menu-list li::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, rgba(231, 179, 117, 0.32), transparent); transform: translateX(-100%); transition: transform 0.85s ease; pointer-events: none; } .menu-list li:hover { background: linear-gradient(90deg, rgba(255, 244, 214, 0.88), rgba(255, 255, 255, 0.36)); transform: translateX(4px); } .menu-list li:hover::after { transform: translateX(100%); } .item-main { display: grid; gap: 0.35rem; } .item-name { font-weight: 800; font-size: 1.05rem; } .item-desc { margin: 0; color: var(--cocoa); } .item-meta { display: flex; flex-wrap: wrap; gap: 0.55rem; align-items: center; justify-content: flex-end; } .price { font-family: var(--mono); font-weight: 800; color: var(--ink); } .tag { display: inline-block; padding: 0.35rem 0.6rem; border-radius: 999px; border: 1px solid rgba(194, 67, 110, 0.22); background: rgba(194, 67, 110, 0.08); color: #992b54; font-size: 0.78rem; font-weight: 750; } .tag.vegan { border-color: rgba(51, 112, 90, 0.24); background: rgba(51, 112, 90, 0.08); color: #245844; } .visit { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; } .card { position: relative; padding: clamp(1.1rem, 3vw, 1.8rem); border-radius: 26px; border: 1px solid rgba(98, 58, 38, 0.16); background: linear-gradient(160deg, rgba(255, 255, 255, 0.92), rgba(255, 240, 220, 0.74)); box-shadow: 0 18px 58px rgba(44, 27, 22, 0.12); } .card h3 { font-size: clamp(1.5rem, 3vw, 2.1rem); } .form-grid { display: grid; gap: 0.95rem; } .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.95rem; } label { display: block; font-size: 0.85rem; font-weight: 800; color: var(--cocoa); margin-bottom: 0.35rem; letter-spacing: 0.03em; } input, select, textarea { width: 100%; font: inherit; color: var(--ink); padding: 0.82rem 0.92rem; border-radius: 14px; border: 1px solid rgba(98, 58, 38, 0.22); background: rgba(255, 255, 255, 0.76); transition: border-color 0.25s ease, box-shadow 0.25s ease, background 0.25s ease; } input:focus, select:focus, textarea:focus { outline: none; border-color: var(--crust); box-shadow: 0 0 0 4px rgba(182, 83, 28, 0.14); background: rgba(255, 255, 255, 0.95); } .box-list { display: grid; gap: 0.65rem; margin-top: 0.25rem; } .box-option { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 1rem; padding: 0.72rem 0.85rem; border: 1px dashed rgba(98, 58, 38, 0.24); border-radius: 16px; background: rgba(255, 255, 255, 0.46); cursor: pointer; transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease; } .box-option:hover { transform: translateY(-1px); background: rgba(255, 244, 214, 0.82); } .box-option.selected { border-color: rgba(51, 112, 90, 0.55); background: rgba(51, 112, 90, 0.09); } .box-option input { width: auto; accent-color: var(--crust); } .box-copy { display: inline-flex; gap: 0.55rem; align-items: center; font-weight: 750; } .box-price { font-family: var(--mono); font-weight: 800; } .total { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: 0.35rem; font-family: var(--mono); font-weight: 900; } .submit { width: 100%; border: 0; border-radius: 16px; padding: 0.95rem 1rem; background: linear-gradient(135deg, var(--cocoa), var(--crust)); color: #fff7ee; font-weight: 900; cursor: pointer; transition: transform 0.25s ease, filter 0.25s ease, box-shadow 0.25s ease; box-shadow: 0 12px 28px rgba(98, 58, 38, 0.20); } .submit:hover, .submit:focus-visible { transform: translateY(-2px); filter: brightness(1.06); box-shadow: 0 16px 34px rgba(98, 58, 38, 0.26); } .message { min-height: 1.5em; margin-top: 0.45rem; font-weight: 750; color: var(--leaf); } .message.error { color: #9b3018; } .aside-copy { display: grid; gap: 1rem; align-content: start; } .aside-copy p { margin: 0; color: #4a3026; max-width: 54ch; } .mini-list { display: grid; gap: 0.7rem; padding: 0; margin: 0; list-style: none; } .mini-list li { display: flex; gap: 0.8rem; align-items: flex-start; padding: 0.8rem 0.9rem; border: 1px solid rgba(98, 58, 38, 0.12); border-radius: 18px; background: rgba(255, 255, 255, 0.38); } .dot { width: 0.7rem; height: 0.7rem; margin-top: 0.5rem; border-radius: 50%; background: var(--crust); box-shadow: 0 0 0 4px rgba(182, 83, 28, 0.10); flex: 0 0 auto; } footer { margin-top: clamp(3rem, 8vw, 7rem); color: #fff7ee; background: linear-gradient(135deg, #2b1a13 8%, #5c311f 48%, #78371d 100%); border-top: 1px solid rgba(255, 212, 131, 0.20); } .footer-inner { max-width: 1150px; margin: 0 auto; padding: clamp(2rem, 6vw, 5rem) clamp(1rem, 5vw, 3rem); display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(1.5rem, 4vw, 3rem); } footer h2 { font-size: clamp(1.8rem, 4vw, 3rem); margin: 0 0 1rem; } .hours { display: grid; gap: 0.65rem; margin: 1rem 0 0; } .hours div { display: grid; grid-template-columns: 1fr auto; gap: 1rem; padding-bottom: 0.6rem; border-bottom: 1px dotted rgba(255, 247, 238, 0.18); } .hours div:last-child { border-bottom: 0; } .hours dt { margin: 0; font-weight: 800; } .hours dd { margin: 0; font-family: var(--mono); color: #ffd483; text-align: right; } .footer-side { display: grid; gap: 1rem; align-content: start; } .footer-side p { margin: 0; color: rgba(255, 247, 238, 0.86); } .note { margin-top: 1rem; padding: 0.9rem 1rem; border-radius: 18px; background: rgba(255, 247, 238, 0.08); border: 1px solid rgba(255, 247, 238, 0.16); color: #ffe6c4 !important; font-style: italic; } .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.72s cubic-bezier(0.2, 0.8, 0.2, 1), transform 0.72s cubic-bezier(0.2, 0.8, 0.2, 1); } .reveal.visible { opacity: 1; transform: none; } @keyframes drift { from { transform: translate3d(-4%, -3%, 0) rotate(0deg); } to { transform: translate3d(4%, 3%, 0) rotate(360deg); } } @keyframes bob { 0%, 100% { transform: translateY(0) rotate(-0.5deg); } 50% { transform: translateY(-10px) rotate(0.5deg); } } @keyframes rise { 0% { transform: translateY(0) scale(0.5); opacity: 0; } 35% { opacity: 0.5; } 100% { transform: translateY(-125px) scale(1.3); opacity: 0; } } @keyframes slide { from { transform: translateX(0); } to { transform: translateX(-50%); } } @media (max-width: 900px) { .hero, .visit, .footer-inner { grid-template-columns: 1fr; } .grid-2 { grid-template-columns: 1fr; } .visual { min-height: 320px; } } @media (max-width: 620px) { .header-inner { align-items: start; } nav { order: 3; width: 100%; } nav a { flex: 1 1 auto; text-align: center; } .cta { order: 2; } .item-meta { justify-content: flex-start; } } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; } .reveal { opacity: 1; transform: none; } } </style> </head> <body> <header> <div class="header-inner"> <div class="brand"> <h1>Crumb <span class="amp">&</span> Co</h1> <p class="tagline">Flour, fire, and very good mornings.</p> </div> <nav aria-label="Primary"> <a href="#menu">Menu</a> <a href="#visit">Visit</a> <a href="#hours">Hours</a> </nav> <button class="cta" type="button" data-target="#visit">Reserve a box</button> </div> </header> <main> <section id="intro" class="hero" aria-labelledby="hero-heading"> <div> <span class="eyebrow">Small-batch bakery · neighbourhood counter</span> <h2 id="hero-heading">Everything is baked before the street fully wakes.</h2> <p class="lead"> Crumb & Co is a tiny bakery with a serious sourdough obsession. We mill in-house, shape by hand, and sell out earlier than we probably should. </p> <div id="status" class="status" aria-live="polite">Open now · closes at 5pm</div> <button class="cta" type="button" data-target="#menu">See today’s bakes</button> </div> <div class="visual" aria-hidden="true"> <div class="loaf"> <div class="steam"> <span></span><span></span><span></span><span></span><span></span> </div> <div class="dough"></div> </div> </div> </section> <div class="ticker" aria-hidden="true"> <div class="ticker-track"> <span>country sourdough</span> <span>cardamom knots</span> <span>raspberry galette</span> <span>brown butter cookies</span> <span>dark babka</span> <span>farm butter</span> <span>country sourdough</span> <span>cardamom knots</span> <span>raspberry galette</span> <span>brown butter cookies</span> <span>dark babka</span> <span>farm butter</span> </div> </div> <section id="menu" aria-labelledby="menu-heading"> <div class="section-head reveal"> <span class="badge">Today’s counter</span> <h2 id="menu-heading">Short list, good ingredients</h2> <p> Prices include our tiny bakery tax: the inevitable urge to buy one more than you planned. </p> </div> <ol class="menu-list reveal"> <li> <div class="item-main"> <span class="item-name">Country Sourdough</span> <p class="item-desc">Cracked wheat crust, open crumb, tangy enough to remember.</p> </div> <div class="item-meta"> <span class="tag vegan">Vegan</span> <span class="price">£7.00</span> </div> </li> <li> <div class="item-main"> <span class="item-name">Brown Butter Miso Cookie</span> <p class="item-desc">Salty-sweet, chewy centre, crisp edge, deeply unreasonable.</p> </div> <div class="item-meta"> <span class="tag">Vegetarian</span> <span class="price">£3.80</span> </div> </li> <li> <div class="item-main"> <span class="item-name">Cardamom Knot</span> <p class="item-desc">Laminated, fragrant, still slightly warm if you arrive early enough.</p> </div> <div class="item-meta"> <span class="tag">Vegetarian</span> <span class="price">£4.50</span> </div> </li> <li> <div class="item-main"> <span class="item-name">Raspberry Frangipane Galette</span> <p class="item-desc">Freeform, rustic, and best eaten standing by the window.</p> </div> <div class="item-meta"> <span class="tag">Vegetarian</span> <span class="price">£5.20</span> </div> </li> <li> <div class="item-main"> <span class="item-name">Dark Chocolate Babka</span> <p class="item-desc">Pulled strands, bittersweet chocolate, generous butter, zero regrets.</p> </div> <div class="item-meta"> <span class="tag">Vegetarian</span> <span class="price">£9.00</span> </div> </li> </ol> </section> <section id="visit" aria-labelledby="visit-heading"> <div class="visit"> <div class="aside-copy reveal"> <span class="badge">Plan ahead</span> <h2 id="visit-heading">Reserve a bake box</h2> <p> Leave us a name, a day, and your picks. We will hold them until 30 minutes after opening, then release them to the regulars with suspiciously reliable timing. </p> <ul class="mini-list"> <li> <span class="dot" aria-hidden="true"></span> <span>Pickup is in person only — the bread deserves a proper carrier.</span> </li> <li> <span class="dot" aria-hidden="true"></span> <span>Larger orders are best requested two days before collection.</span> </li> <li> <span class="dot" aria-hidden="true"></span> <span>Sourdough is usually gone before 10am on weekends.</span> </li> </ul> </div> <form id="box-form" class="card reveal" novalidate> <h3>Build your box</h3> <div class="form-grid"> <div> <label for="name">Name for the box</label> <input id="name" name="name" type="text" placeholder="e.g. Nora" autocomplete="name"> </div> <div class="grid-2"> <div> <label for="email">Email</label> <input id="email" name="email" type="email" placeholder="you@example.com" autocomplete="email"> </div> <div> <label for="pickup">Pickup day</label> <select id="pickup" name="pickup"> <option>Tomorrow</option> <option>Wednesday</option> <option>Saturday</option> <option>Sunday</option> </select> </div> </div> <div> <label for="note">A note, if needed</label> <textarea id="note" name="note" rows="3" placeholder="Cut the loaf, leave it in a paper bag, save me the burnt cookie edge."></textarea> </div> <div> <label>Choose bakes</label> <div class="box-list"> <label class="box-option"> <span class="box-copy"><input type="checkbox" data-price="7.00" value="Country Sourdough"> Country Sourdough</span> <span class="box-price">£7.00</span> </label> <label class="box-option"> <span class="box-copy"><input type="checkbox" data-price="3.80" value="Brown Butter Miso Cookie"> Brown Butter Miso Cookie</span> <span class="box-price">£3.80</span> </label> <label class="box-option"> <span class="box-copy"><input type="checkbox" data-price="4.50" value="Cardamom Knot"> Cardamom Knot</span> <span class="box-price">£4.50</span> </label> <label class="box-option"> <span class="box-copy"><input type="checkbox" data-price="5.20" value="Raspberry Galette"> Raspberry Galette</span> <span class="box-price">£5.20</span> </label> <label class="box-option"> <span class="box-copy"><input type="checkbox" data-price="9.00" value="Dark Chocolate Babka"> Dark Chocolate Babka</span> <span class="box-price">£9.00</span> </label> </div> </div> <div class="total"> <span>Total</span> <span id="total-amount">£0.00</span> </div> <button class="submit" type="submit">Reserve now</button> <div id="form-message" class="message" aria-live="polite"></div> </div> </form> </div> </section> </main> <footer id="hours"> <div class="footer-inner"> <section aria-labelledby="hours-heading"> <span class="badge">When the bread is here</span> <h2 id="hours-heading">Opening hours</h2> <dl class="hours"> <div> <dt>Monday</dt> <dd>7:00 am – 5:00 pm</dd> </div> <div> <dt>Tuesday</dt> <dd>7:00 am – 5:00 pm</dd> </div> <div> <dt>Wednesday</dt> <dd>7:00 am – 5:00 pm</dd> </div> <div> <dt>Thursday</dt> <dd>7:00 am – 5:00 pm</dd> </div> <div> <dt>Friday</dt> <dd>7:00 am – 5:00 pm</dd> </div> <div> <dt>Saturday</dt> <dd>8:00 am – 5:00 pm</dd> </div> <div> <dt>Sunday</dt> <dd>8:00 am – 3:00 pm</dd> </div> </dl> </section> <section class="footer-side" aria-labelledby="find-us-heading"> <h3 id="find-us-heading">Find us</h3> <p>Crumb & Co<br>17 Mill Lane<br>Springfield</p> <p>Counter phone: 01632 960 475<br>Bulk orders: hello@crumbandco.local</p> <p class="note">When the shelves are empty, we are empty too.</p> </section> </div> </footer> <script> (function () { var schedule = { 0: [8 * 60, 15 * 60], 1: [7 * 60, 17 * 60], 2: [7 * 60, 17 * 60], 3: [7 * 60, 17 * 60], 4: [7 * 60, 17 * 60], 5: [8 * 60, 17 * 60], 6: [8 * 60, 15 * 60] }; var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; var statusEl = document.getElementById("status"); function formatMinutes(minutes) { var hours = Math.floor(minutes / 60); var mins = minutes % 60; var suffix = hours < 12 ? "am" : "pm"; var displayHours = hours % 12; if (displayHours === 0) displayHours = 12; return displayHours + (mins ? ":" + String(mins).padStart(2, "0") : "") + suffix; } function updateStatus() { var now = new Date(); var nowMinutes = now.getHours() * 60 + now.getMinutes(); var today = now.getDay(); var open = schedule[today][0]; var close = schedule[today][1]; var text = ""; var isClosed = false; if (nowMinutes >= open && nowMinutes < close) { text = "Open now · closes at " + formatMinutes(close); } else if (nowMinutes < open) { text = "Closed · opens at " + formatMinutes(open) + " today"; isClosed = true; } else { var nextDay = (today + 1) % 7; text = "Closed · opens at " + formatMinutes(schedule[nextDay][0]) + " " + dayNames[nextDay].slice(0, 3); isClosed = true; } statusEl.textContent = text; statusEl.classList.toggle("closed", isClosed); } updateStatus(); setInterval(updateStatus, 30000); var revealElements = document.querySelectorAll(".reveal"); revealElements.forEach(function (el, index) { el.style.transitionDelay = Math.min(index * 60, 300) + "ms"; }); if ("IntersectionObserver" in window) { var revealObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { entry.target.classList.add("visible"); revealObserver.unobserve(entry.target); } }); }, { threshold: 0.15 }); revealElements.forEach(function (el) { revealObserver.observe(el); }); } else { revealElements.forEach(function (el) { el.classList.add("visible"); }); } var navLinks = Array.prototype.slice.call(document.querySelectorAll("nav a")); var activeTargets = document.querySelectorAll("#menu, #visit, #hours"); if ("IntersectionObserver" in window) { var activeObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { var id = entry.target.id; navLinks.forEach(function (link) { link.classList.toggle("active", link.getAttribute("href") === "#" + id); }); } }); }, { threshold: 0.25, rootMargin: "-20% 0px -55% 0px" }); Array.prototype.slice.call(activeTargets).forEach(function (target) { activeObserver.observe(target); }); } document.querySelectorAll("[data-target]").forEach(function (button) { button.addEventListener("click", function () { var target = document.querySelector(button.getAttribute("data-target")); if (!target) return; var reduced = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches; target.scrollIntoView({ behavior: reduced ? "auto" : "smooth", block: "start" }); }); }); var boxInputs = document.querySelectorAll(".box-option input"); var totalAmount = document.getElementById("total-amount"); var boxForm = document.getElementById("box-form"); var message = document.getElementById("form-message"); var lastTotal = 0; var currency = new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" }); function updateBox() { var total = 0; boxInputs.forEach(function (input) { var option = input.closest(".box-option"); if (input.checked) { total += Number(input.dataset.price || 0); option.classList.add("selected"); } else { option.classList.remove("selected"); } }); lastTotal = total; totalAmount.textContent = currency.format(total); } boxInputs.forEach(function (input) { input.addEventListener("change", updateBox); }); updateBox(); boxForm.addEventListener("submit", function (event) { event.preventDefault(); var name = document.getElementById("name").value.trim(); var pickup = document.getElementById("pickup").value; var chosen = Array.prototype.some.call(boxInputs, function (input) { return input.checked; }); message.classList.remove("error"); if (!name) { message.textContent = "Please add a name for the box."; message.classList.add("error"); document.getElementById("name").focus(); return; } if (!chosen) { message.textContent = "Choose at least one bake."; message.classList.add("error"); return; } message.textContent = "Reserved for " + name + " on " + pickup + ": " + currency.format(lastTotal) + " — we’ll hold it until 30 minutes after opening."; }); })(); </script> </body> </html>A pricing table with a togglePassed
3,900 tokens: 134 read, 3,766 written · 2 min 20 s · 27 tok/s
Passes when Three elements with class plan, each holding a price, and a <button id="billing-toggle"> handled by script; the page switches between monthly and yearly. Nothing loaded from another site and no network requests.
Build a pricing page with three plans. Each plan is an element with class "plan" containing an element with class "price". Add a <button id="billing-toggle"> that switches every price between monthly and yearly billing when clicked. Output one complete HTML document and nothing else. Put all CSS and JavaScript inline. Do not load anything from another site: no external scripts, stylesheets, fonts or images.
Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pricing</title> <style> * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: radial-gradient(circle at top left, #dbeafe 0%, transparent 35%), radial-gradient(circle at bottom right, #dcfce7 0%, transparent 35%), linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%); color: #0f172a; } .page { width: min(1100px, calc(100% - 2rem)); margin: 0 auto; padding: 4rem 1rem 5rem; } .hero { max-width: 720px; margin-bottom: 2.5rem; } .eyebrow { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.85rem; border: 1px solid #c7d2fe; border-radius: 999px; background: rgba(255, 255, 255, 0.75); color: #3730a3; font-size: 0.85rem; font-weight: 650; letter-spacing: 0.01em; } h1 { margin: 1rem 0 0.75rem; font-size: clamp(2.3rem, 6vw, 4.2rem); line-height: 1.04; letter-spacing: -0.04em; } .lead { margin: 0; color: #475569; font-size: 1.05rem; line-height: 1.6; } .toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin: 2rem 0 2rem; padding: 1rem; border: 1px solid #cbd5e1; border-radius: 20px; background: rgba(255, 255, 255, 0.78); box-shadow: 0 18px 45px rgba(15, 23, 42, 0.08); } #billing-toggle { appearance: none; border: 0; border-radius: 16px; padding: 0.95rem 1.25rem; min-width: 230px; background: #111827; color: white; font-size: 1rem; font-weight: 750; cursor: pointer; box-shadow: 0 10px 22px rgba(17, 24, 39, 0.18); transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease; } #billing-toggle:hover { transform: translateY(-2px); box-shadow: 0 14px 28px rgba(17, 24, 39, 0.22); } #billing-toggle:focus-visible { outline: 3px solid #60a5fa; outline-offset: 3px; } .toggle-note { color: #334155; font-size: 0.95rem; line-height: 1.4; } .plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; } .plan { position: relative; overflow: hidden; padding: 1.75rem; border: 1px solid #cbd5e1; border-radius: 26px; background: rgba(255, 255, 255, 0.92); box-shadow: 0 16px 45px rgba(15, 23, 42, 0.08); transition: transform 220ms ease, box-shadow 220ms ease; } .plan:hover { transform: translateY(-6px); box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12); } .plan::before { content: ""; position: absolute; inset: 0 auto auto 0; width: 100%; height: 6px; background: linear-gradient(90deg, #2563eb, #22c55e, #7c3aed); opacity: 0.85; } .featured { border-color: #2563eb; background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(239, 246, 255, 0.95)); box-shadow: 0 24px 65px rgba(37, 99, 235, 0.18); } .badge { display: inline-flex; margin-bottom: 1rem; padding: 0.4rem 0.7rem; border-radius: 999px; background: #eff6ff; color: #1d4ed8; font-size: 0.78rem; font-weight: 750; letter-spacing: 0.02em; } .plan h2 { margin: 0 0 0.65rem; font-size: 1.5rem; letter-spacing: -0.03em; } .plan p { margin: 0; color: #475569; line-height: 1.55; } .price { margin: 1.35rem 0 1.25rem; font-size: 2.45rem; line-height: 1; font-weight: 850; letter-spacing: -0.05em; color: #0f172a; } .billing { font-size: 1rem; font-weight: 650; color: #64748b; letter-spacing: 0; } ul { margin: 1.25rem 0 1.75rem; padding: 0; list-style: none; display: grid; gap: 0.7rem; color: #334155; } li { display: flex; align-items: flex-start; gap: 0.65rem; line-height: 1.45; } li::before { content: ""; flex: 0 0 0.7rem; width: 0.7rem; height: 0.7rem; margin-top: 0.35rem; border-radius: 999px; background: #2563eb; } .action { display: inline-flex; align-items: center; justify-content: center; width: 100%; border: 0; border-radius: 14px; padding: 0.9rem 1rem; font-size: 0.95rem; font-weight: 750; cursor: pointer; background: #e2e8f0; color: #0f172a; } .plan.featured .action { background: #2563eb; color: white; } .footnote { margin-top: 1.5rem; color: #64748b; font-size: 0.9rem; } @media (max-width: 920px) { .plans { grid-template-columns: 1fr; } .page { padding-top: 2.5rem; } .toolbar { align-items: flex-start; } #billing-toggle { width: 100%; } } </style> </head> <body> <main class="page"> <section class="hero"> <span class="eyebrow">Simple pricing</span> <h1>Choose the plan that fits your team</h1> <p class="lead"> Start with a monthly plan, or switch to yearly billing to save time and budget. Prices update instantly below. </p> </section> <div class="toolbar"> <button id="billing-toggle" aria-pressed="false">Switch to yearly billing</button> <span class="toggle-note">Prices are currently shown monthly.</span> </div> <section class="plans"> <article class="plan"> <h2>Starter</h2> <p>For individuals and small side projects.</p> <div class="price" data-monthly="9" data-yearly="90">$9<span class="billing"> / mo</span></div> <ul> <li>1 active project</li> <li>Basic analytics</li> <li>Community support</li> </ul> <button class="action">Choose Starter</button> </article> <article class="plan featured"> <span class="badge">Most popular</span> <h2>Pro</h2> <p>For growing teams that need more flexibility.</p> <div class="price" data-monthly="29" data-yearly="290">$29<span class="billing"> / mo</span></div> <ul> <li>Unlimited projects</li> <li>Advanced dashboards</li> <li>Priority support</li> <li>Custom branding</li> </ul> <button class="action">Choose Pro</button> </article> <article class="plan"> <h2>Business</h2> <p>For organizations with advanced control needs.</p> <div class="price" data-monthly="79" data-yearly="790">$79<span class="billing"> / mo</span></div> <ul> <li>Team permissions</li> <li>Audit log</li> <li>Dedicated support</li> <li>Onboarding assistance</li> </ul> <button class="action">Choose Business</button> </article> </section> <p class="footnote">Yearly billing is calculated as 12 months at the listed plan rate.</p> </main> <script> const toggleButton = document.getElementById("billing-toggle"); const note = document.querySelector(".toggle-note"); const prices = document.querySelectorAll(".price"); let isYearly = false; function renderPrices() { prices.forEach((price) => { const monthly = Number(price.dataset.monthly); const yearly = Number(price.dataset.yearly); const amount = isYearly ? yearly : monthly; const period = isYearly ? "yr" : "mo"; price.innerHTML = `$${amount}<span class="billing"> / ${period}</span>`; }); toggleButton.textContent = isYearly ? "Switch to monthly billing" : "Switch to yearly billing"; toggleButton.setAttribute("aria-pressed", String(isYearly)); note.textContent = isYearly ? "Prices are currently shown yearly." : "Prices are currently shown monthly."; } toggleButton.addEventListener("click", () => { isYearly = !isYearly; renderPrices(); }); renderPrices(); </script> </body> </html>An accessible sign-up formPassed
3,726 tokens: 169 read, 3,557 written · 2 min 11 s · 27.3 tok/s
Passes when <form id="signup"> with name, email (type email) and password (type password, minlength 8 or more) inputs, each with a <label for>; a submit button; an element id="status" with role="status"; and script that stops the submit and writes to the status. Nothing loaded from another site and no network requests.
Build a sign-up form: <form id="signup"> with inputs id="name", id="email" (type email) and id="password" (type password, minlength at least 8), each with a <label for>, and a submit button. When the form is submitted and valid, prevent the real submission and show a confirmation in an element with id="status" and role="status". Output one complete HTML document and nothing else. Put all CSS and JavaScript inline. Do not load anything from another site: no external scripts, stylesheets, fonts or images.
Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Create Account</title> <style> :root { --bg: #eef2f7; --card: #ffffff; --text: #182335; --muted: #5d6b80; --border: #d7dee8; --accent: #2f6fed; --accent-hover: #245ed0; --success-bg: #e9f6ef; --success-text: #14683d; --error-bg: #f8e9e9; --error-text: #8b1f1f; } * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif; color: var(--text); background: linear-gradient(135deg, rgba(47, 111, 237, 0.10), rgba(20, 104, 61, 0.08)), var(--bg); display: flex; align-items: center; justify-content: center; padding: 32px 18px; } .wrap { width: min(100%, 520px); } .card { background: var(--card); border: 1px solid var(--border); border-radius: 18px; padding: 28px; box-shadow: 0 18px 45px rgba(24, 35, 53, 0.10), 0 2px 8px rgba(24, 35, 53, 0.04); } .eyebrow { margin: 0 0 10px; font-size: 12px; line-height: 1.35; letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted); font-weight: 700; } h1 { margin: 0 0 8px; font-size: clamp(28px, 4vw, 38px); line-height: 1.08; letter-spacing: -0.03em; } .subhead { margin: 0 0 26px; color: var(--muted); line-height: 1.55; } form { display: grid; gap: 18px; } .field { display: grid; gap: 8px; } label { font-size: 14px; font-weight: 700; } input { width: 100%; min-height: 50px; padding: 13px 15px; border: 1px solid var(--border); border-radius: 12px; background: #fbfcfe; color: var(--text); font: inherit; font-size: 16px; outline: none; transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease; } input:hover { border-color: #b8c5d6; } input:focus { border-color: var(--accent); background: #ffffff; box-shadow: 0 0 0 4px rgba(47, 111, 237, 0.14); } input::placeholder { color: #8b98ab; } .hint { color: var(--muted); font-size: 13px; line-height: 1.45; } button { margin-top: 4px; min-height: 52px; border: 0; border-radius: 12px; background: var(--accent); color: #ffffff; font: inherit; font-size: 16px; font-weight: 800; letter-spacing: 0.01em; cursor: pointer; transition: background 160ms ease, transform 160ms ease, box-shadow 160ms ease; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 10px 22px rgba(47, 111, 237, 0.22); } button:hover { background: var(--accent-hover); } button:active { transform: translateY(1px); } button:focus-visible { outline: 3px solid rgba(47, 111, 237, 0.32); outline-offset: 3px; } #status { margin: 0; min-height: 22px; padding: 0; border-radius: 0; color: var(--muted); font-size: 14px; line-height: 1.5; font-weight: 650; } #status:empty { display: none; } #status[data-state="success"] { color: var(--success-text); } #status[data-state="error"] { color: var(--error-text); } @media (max-width: 560px) { .card { padding: 22px 18px; border-radius: 14px; } body { padding: 20px 14px; } } @media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } } </style> </head> <body> <main class="wrap"> <section class="card"> <p class="eyebrow">Account access</p> <h1>Create your account</h1> <p class="subhead">Choose a secure password, then start building.</p> <form id="signup" novalidate> <div class="field"> <label for="name">Full name</label> <input id="name" name="name" type="text" autocomplete="name" placeholder="Ada Lovelace" required > </div> <div class="field"> <label for="email">Email address</label> <input id="email" name="email" type="email" autocomplete="email" placeholder="ada@example.com" required > </div> <div class="field"> <label for="password">Password</label> <input id="password" name="password" type="password" autocomplete="new-password" minlength="8" placeholder="At least 8 characters" required > <p class="hint">Use 8 characters or more.</p> </div> <button type="submit">Create account</button> <p id="status" role="status" aria-live="polite"></p> </form> </section> </main> <script> (function () { const form = document.getElementById("signup"); const status = document.getElementById("status"); const nameInput = document.getElementById("name"); const emailInput = document.getElementById("email"); const passwordInput = document.getElementById("password"); form.addEventListener("submit", function (event) { event.preventDefault(); status.removeAttribute("data-state"); if (!form.checkValidity()) { status.setAttribute("data-state", "error"); if (!nameInput.value.trim()) { status.textContent = "Please enter your full name."; } else if (!emailInput.value.trim()) { status.textContent = "Please enter your email address."; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailInput.value.trim())) { status.textContent = "Please enter a valid email address."; } else if (!passwordInput.value) { status.textContent = "Please enter a password."; } else if (passwordInput.value.length < 8) { status.textContent = "Password must be at least 8 characters long."; } else { status.textContent = "Please check the form and try again."; } return; } const firstName = nameInput.value.trim().split(/\s+/)[0] || nameInput.value.trim(); status.setAttribute("data-state", "success"); status.textContent = "Thanks, " + firstName + "! Your account has been created."; form.reset(); }); })(); </script> </body> </html>A to-do app that remembersPassed
2,089 tokens: 157 read, 1,932 written · 1 min 11 s · 27.6 tok/s
Passes when The input, add button and list with the given ids, and script that saves to localStorage under "todos" and adds list items with a remove control. Nothing loaded from another site and no network requests.
Build a to-do list app with an <input id="new-task">, a <button id="add"> and a <ul id="tasks">. Clicking add appends the text as an <li> with its own remove button. Save the list in localStorage under the key "todos" and load it again when the page opens. Output one complete HTML document and nothing else. Put all CSS and JavaScript inline. Do not load anything from another site: no external scripts, stylesheets, fonts or images.
Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>To-Do List</title> <style> :root { color-scheme: light dark; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; } body { margin: 0; padding: 24px; display: flex; justify-content: center; background: #f4f6f8; color: #1f2937; } main { width: min(100%, 560px); background: #ffffff; border-radius: 12px; padding: 24px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); } h1 { margin-top: 0; font-size: 1.75rem; } label { display: block; margin-bottom: 8px; font-weight: 600; } .row { display: flex; gap: 12px; margin-bottom: 20px; } #new-task { flex: 1; padding: 10px 12px; font: inherit; border: 1px solid #d1d5db; border-radius: 8px; } #add { padding: 10px 16px; font: inherit; font-weight: 600; border: none; border-radius: 8px; background: #2563eb; color: white; cursor: pointer; } #add:hover { background: #1d4ed8; } #tasks { margin: 0; padding: 0; list-style: none; } #tasks li { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px; border: 1px solid #e5e7eb; border-radius: 8px; margin-bottom: 8px; background: #f9fafb; } #tasks span { word-break: break-word; } #tasks button { padding: 6px 10px; border: none; border-radius: 6px; background: #dc2626; color: white; cursor: pointer; font: inherit; font-weight: 600; } #tasks button:hover { background: #b91c1c; } @media (max-width: 480px) { body { padding: 12px; } .row { flex-direction: column; } } </style> </head> <body> <main> <h1>To-Do List</h1> <label for="new-task">Add a task</label> <div class="row"> <input id="new-task" type="text" placeholder="What needs doing?"> <button id="add" type="button">Add</button> </div> <ul id="tasks"></ul> </main> <script> (function () { const input = document.getElementById("new-task"); const addButton = document.getElementById("add"); const list = document.getElementById("tasks"); const STORAGE_KEY = "todos"; function loadTodos() { try { const saved = localStorage.getItem(STORAGE_KEY); const parsed = saved ? JSON.parse(saved) : []; return Array.isArray(parsed) ? parsed : []; } catch (error) { return []; } } function saveTodos() { const todos = Array.from(list.children).map(function (li) { return li.dataset.text; }); localStorage.setItem(STORAGE_KEY, JSON.stringify(todos)); } function createTaskItem(text) { const li = document.createElement("li"); li.dataset.text = text; const span = document.createElement("span"); span.textContent = text; const removeButton = document.createElement("button"); removeButton.type = "button"; removeButton.textContent = "Remove"; removeButton.addEventListener("click", function () { li.remove(); saveTodos(); }); li.appendChild(span); li.appendChild(removeButton); return li; } function render() { const todos = loadTodos(); list.replaceChildren(); todos.forEach(function (todo) { list.appendChild(createTaskItem(todo)); }); } function addTask() { const text = input.value.trim(); if (!text) return; list.appendChild(createTaskItem(text)); input.value = ""; input.focus(); saveTodos(); } addButton.addEventListener("click", addTask); input.addEventListener("keydown", function (event) { if (event.key === "Enter") { event.preventDefault(); addTask(); } }); render(); })(); </script> </body> </html>A bar chart in SVGPassed
2,579 tokens: 182 read, 2,397 written · 1 min 28 s · 27.4 tok/s
Passes when Five <rect class="bar"> in an <svg>, written in the markup, with heights proportional to 12, 30, 18, 24 and 6 in that order, labelled Mon to Fri in <text>, and a <title> or aria-label. Nothing loaded from another site and no network requests.
Draw an inline SVG bar chart of coffee sold: Mon 12, Tue 30, Wed 18, Thu 24, Fri 6. Each bar is a <rect class="bar"> whose height attribute is proportional to its value, each bar is labelled with its day in a <text>, and the <svg> has a <title> or an aria-label. Write the bars and labels directly in the SVG markup, not with JavaScript. Output one complete HTML document and nothing else. Put all CSS and JavaScript inline. Do not load anything from another site: no external scripts, stylesheets, fonts or images.
Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Coffee Sold Bar Chart</title> <style> body { margin: 2rem; font-family: system-ui, sans-serif; color: #222; } h1 { font-size: 1.25rem; margin-bottom: 1rem; } .chart { display: block; max-width: 620px; height: auto; background: #fafafa; border: 1px solid #ddd; border-radius: 8px; } .bar { fill: #8b5a2b; } .gridline, .axis { stroke: #bbb; stroke-width: 1; } .label { font-size: 14px; fill: #333; text-anchor: middle; } .value { font-size: 13px; fill: #222; text-anchor: middle; } </style> </head> <body> <h1>Coffee Sold by Day</h1> <svg class="chart" viewBox="0 0 600 420" role="img" aria-label="Bar chart of coffee sold: Monday 12, Tuesday 30, Wednesday 18, Thursday 24, Friday 6" > <title>Coffee sold per day</title> <!-- Axis --> <line class="axis" x1="70" y1="350" x2="530" y2="350"></line> <!-- Monday: 12, height = 120 --> <rect class="bar" x="90" y="230" width="55" height="120"></rect> <text class="value" x="117.5" y="222">12</text> <text class="label" x="117.5" y="375">Mon</text> <!-- Tuesday: 30, height = 300 --> <rect class="bar" x="170" y="50" width="55" height="300"></rect> <text class="value" x="197.5" y="42">30</text> <text class="label" x="197.5" y="375">Tue</text> <!-- Wednesday: 18, height = 180 --> <rect class="bar" x="250" y="170" width="55" height="180"></rect> <text class="value" x="277.5" y="162">18</text> <text class="label" x="277.5" y="375">Wed</text> <!-- Thursday: 24, height = 240 --> <rect class="bar" x="330" y="110" width="55" height="240"></rect> <text class="value" x="357.5" y="102">24</text> <text class="label" x="357.5" y="375">Thu</text> <!-- Friday: 6, height = 60 --> <rect class="bar" x="410" y="290" width="55" height="60"></rect> <text class="value" x="437.5" y="282">6</text> <text class="label" x="437.5" y="375">Fri</text> </svg> </body> </html>
Building games 2 of 2
Build 2048Passed
21,552 tokens: 500 read, 21,052 written · 12 min 45 s · 27.6 tok/s
Build the game 2048 as one web page, playable with the arrow keys, with the board drawn on the page. In <script id="game">, define createGame() returning an object with move(dir) and state(). dir is "up", "down", "left" or "right". state() returns {board, score, over}: board is 4 rows of 4 numbers, top row first (0 is an empty cell), score is a number, over is a boolean. The rules, exactly: 1. The board starts as this one, then a 2 is put in each of the first two empty cells in reading order (row by row from the top, left to right). The score starts at 0. [8, 2, 4, 0] [0, 0, 2, 0] [16, 2, 4, 0] [0, 0, 0, 4] 2. A move slides every tile as far as it goes toward dir. Two tiles of the same value that meet merge into one tile of their sum, nearest the side they move toward first: moving left, [2,2,2,2] becomes [4,4,0,0] and [2,2,2,0] becomes [4,2,0,0]. A tile made by a merge does not merge again in the same move. 3. Each merge adds the new tile's value to the score. 4. If a move changed the board, a 2 is put in the first empty cell in reading order. A move that changes nothing does nothing. 5. over is true when no move would change the board; then moves do nothing. Output one complete HTML document and nothing else, with all CSS and JavaScript inline and nothing loaded from another site. Put the game logic, and only it, in <script id="game">: it must not touch document, window or timers, because the site runs that script on its own and plays the game through createGame(). Wire the page in another <script>.Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>2048</title> <style> body { font-family: Arial, Helvetica, sans-serif; background: #faf8ef; color: #776e65; margin: 0; padding: 20px; } main { max-width: 420px; margin: 0 auto; } h1 { text-align: center; margin: 10px 0 4px; } p { margin: 8px 0; } #score { background: #bbada0; color: #fff; padding: 3px 10px; border-radius: 4px; font-weight: bold; } #board { display: grid; grid-template-columns: repeat(4, 76px); grid-template-rows: repeat(4, 76px); gap: 10px; padding: 10px; margin: 16px auto; background: #bbada0; border-radius: 8px; width: max-content; } .cell { background: #cdc1b4; border-radius: 4px; display: flex; align-items: center; justify-content: center; font-size: 30px; font-weight: bold; color: #776e65; overflow: hidden; user-select: none; } .cell[data-value="0"] { color: transparent; } .cell[data-value="2"] { background: #eee4da; } .cell[data-value="4"] { background: #ede0c8; } .cell[data-value="8"] { background: #f2b179; color: #fff; } .cell[data-value="16"] { background: #f59563; color: #fff; } .cell[data-value="32"] { background: #f67c5f; color: #fff; } .cell[data-value="64"] { background: #f65e3b; color: #fff; } .cell[data-value="128"] { background: #edcf72; color: #fff; font-size: 26px; } .cell[data-value="256"] { background: #edcc61; color: #fff; font-size: 26px; } .cell[data-value="512"] { background: #edc850; color: #fff; font-size: 26px; } .cell[data-value="1024"] { background: #edc53f; color: #fff; font-size: 22px; } .cell[data-value="2048"] { background: #edc22e; color: #fff; font-size: 22px; } .cell[data-value="4096"], .cell[data-value="8192"] { background: #3c3a32; color: #fff; font-size: 20px; } </style> </head> <body> <main> <h1>2048</h1> <p>Score: <span id="score">0</span></p> <div id="board"></div> <p id="status"></p> <p>Use arrow keys to move tiles.</p> </main> <script id="game"> function createGame() { var board = [ [8, 2, 4, 0], [0, 0, 2, 0], [16, 2, 4, 0], [0, 0, 0, 4] ]; var score = 0; var over = false; function cloneBoard(b) { var out = []; for (var r = 0; r < 4; r++) { out.push([b[r][0], b[r][1], b[r][2], b[r][3]]); } return out; } function addTwo(b) { for (var r = 0; r < 4; r++) { for (var c = 0; c < 4; c++) { if (b[r][c] === 0) { b[r][c] = 2; return; } } } } addTwo(board); addTwo(board); function reverseLine(line) { return [line[3], line[2], line[1], line[0]]; } function slideLeft(line) { var values = []; var i; for (i = 0; i < 4; i++) { if (line[i] !== 0) values.push(line[i]); } var result = []; var gained = 0; i = 0; while (i < values.length) { if (i + 1 < values.length && values[i] === values[i + 1]) { var merged = values[i] + values[i + 1]; result.push(merged); gained += merged; i += 2; } else { result.push(values[i]); i += 1; } } while (result.length < 4) result.push(0); return { line: result, gained: gained }; } function slideRight(line) { var res = slideLeft(reverseLine(line)); return { line: reverseLine(res.line), gained: res.gained }; } function differs(a, b) { for (var i = 0; i < 4; i++) { if (a[i] !== b[i]) return true; } return false; } function simulateMove(current, dir) { var next = cloneBoard(current); var gained = 0; var changed = false; var r, c, old, res; if (dir === "left" || dir === "right") { for (r = 0; r < 4; r++) { old = current[r]; res = dir === "left" ? slideLeft(old) : slideRight(old); if (differs(old, res.line)) { changed = true; for (c = 0; c < 4; c++) next[r][c] = res.line[c]; } gained += res.gained; } } else { for (c = 0; c < 4; c++) { old = [current[0][c], current[1][c], current[2][c], current[3][c]]; res = dir === "up" ? slideLeft(old) : slideRight(old); if (differs(old, res.line)) { changed = true; for (r = 0; r < 4; r++) next[r][c] = res.line[r]; } gained += res.gained; } } return { changed: changed, gained: gained, board: next }; } function canMove() { return simulateMove(board, "up").changed || simulateMove(board, "down").changed || simulateMove(board, "left").changed || simulateMove(board, "right").changed; } over = !canMove(); function move(dir) { if (over) return; if (dir !== "up" && dir !== "down" && dir !== "left" && dir !== "right") { return; } var result = simulateMove(board, dir); if (result.changed) { board = result.board; score += result.gained; addTwo(board); over = !canMove(); } } function state() { return { board: cloneBoard(board), score: score, over: over }; } return { move: move, state: state }; } </script> <script> (function () { var game = createGame(); var boardEl = document.getElementById("board"); var scoreEl = document.getElementById("score"); var statusEl = document.getElementById("status"); function render() { var s = game.state(); scoreEl.textContent = String(s.score); statusEl.textContent = s.over ? "Game over." : ""; boardEl.textContent = ""; for (var r = 0; r < 4; r++) { for (var c = 0; c < 4; c++) { var value = s.board[r][c]; var cell = document.createElement("div"); cell.className = "cell"; cell.setAttribute("data-value", String(value)); if (value !== 0) { cell.textContent = String(value); } boardEl.appendChild(cell); } } } var keyDirections = { ArrowUp: "up", ArrowDown: "down", ArrowLeft: "left", ArrowRight: "right" }; var keyCodes = { 38: "up", 40: "down", 37: "left", 39: "right" }; document.addEventListener("keydown", function (event) { var dir = keyDirections[event.key]; if (!dir && event.keyCode) { dir = keyCodes[event.keyCode]; } if (dir) { event.preventDefault(); game.move(dir); render(); } }); render(); })(); </script> </body> </html>Build SnakePassed
23,643 tokens: 497 read, 23,146 written · 14 min 14 s · 27.1 tok/s
Build Snake as one web page on a 10 by 10 grid, playable with the arrow keys (one key press, one step), with the grid drawn on the page. In <script id="game">, define createGame() returning an object with step(dir) and state(). dir is "up", "down", "left" or "right". state() returns {snake, food, score, over}: snake is a list of [x, y] cells, head first; food is [x, y]; score is a number; over is a boolean. x is the column (0 to 9, left to right), y the row (0 to 9, top to bottom); up is y - 1. The rules, exactly: 1. The game starts with snake [[6, 5], [5, 5], [4, 5]], moving right, food at [2, 2], score 0. 2. step(dir): if dir is the opposite of the current direction it is ignored and the snake keeps going; otherwise dir becomes the current direction. The head moves one cell that way. 3. If the new head cell holds the food, the snake grows: its tail stays. Otherwise the tail cell is freed first. 4. If the new head is off the grid or on a cell of the snake (after rule 3), the game is over: over becomes true and nothing else changes. Once over, step does nothing. 5. Eating adds 1 to the score, and the next food goes to the first empty cell in reading order (row by row from the top, left to right) after the new head's cell, wrapping from [9, 9] to [0, 0]. Output one complete HTML document and nothing else, with all CSS and JavaScript inline and nothing loaded from another site. Put the game logic, and only it, in <script id="game">: it must not touch document, window or timers, because the site runs that script on its own and plays the game through createGame(). Wire the page in another <script>.Open the page on its own. It runs in a sandbox: no network, no access to this site.
Page source
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Snake</title> <style> body { margin: 0; padding: 24px; background: #111827; color: #f3f4f6; font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; } h1 { margin: 0 0 10px; font-size: 1.6rem; } #score { font-weight: bold; font-size: 1.1rem; } #message { min-height: 1.4rem; margin: 10px 0; color: #f87171; font-weight: bold; } #board { display: grid; grid-template-columns: repeat(10, 34px); grid-template-rows: repeat(10, 34px); gap: 3px; padding: 6px; background: #1f2937; border-radius: 8px; outline: 1px solid #4b5563; } .cell { width: 34px; height: 34px; background: #374151; border-radius: 3px; } .cell.food { background: #ef4444; border-radius: 50%; } .cell.body { background: #10b981; } .cell.head { background: #34d399; } .hint { margin-top: 14px; color: #9ca3af; } </style> </head> <body> <h1>Snake</h1> <div id="score">Score: 0</div> <div id="message"></div> <div id="board" aria-label="Snake game board"></div> <div class="hint">Use arrow keys. One press moves one step. Press R after game over to restart.</div> <script id="game"> function createGame() { var SIZE = 10; var TOTAL = SIZE * SIZE; var DIRECTIONS = { up: { x: 0, y: -1 }, down: { x: 0, y: 1 }, left: { x: -1, y: 0 }, right: { x: 1, y: 0 } }; var OPPOSITE = { up: "down", down: "up", left: "right", right: "left" }; var snake = [[6, 5], [5, 5], [4, 5]]; var food = [2, 2]; var score = 0; var over = false; var direction = "right"; function state() { var copiedSnake = []; for (var i = 0; i < snake.length; i++) { copiedSnake.push([snake[i][0], snake[i][1]]); } return { snake: copiedSnake, food: [food[0], food[1]], score: score, over: over }; } function same(a, b) { return a[0] === b[0] && a[1] === b[1]; } function inside(x, y) { return x >= 0 && x < SIZE && y >= 0 && y < SIZE; } function occupiedAt(cells, x, y) { for (var i = 0; i < cells.length; i++) { if (cells[i][0] === x && cells[i][1] === y) { return true; } } return false; } function nextFood(head, occupied) { var startIndex = head[1] * SIZE + head[0]; for (var offset = 1; offset < TOTAL; offset++) { var index = (startIndex + offset) % TOTAL; var x = index % SIZE; var y = (index - x) / SIZE; if (!occupiedAt(occupied, x, y)) { return [x, y]; } } return [0, 0]; } function step(dir) { if (over) { return; } if (dir !== "up" && dir !== "down" && dir !== "left" && dir !== "right") { return; } var moveDir = (dir === OPPOSITE[direction]) ? direction : dir; var delta = DIRECTIONS[moveDir]; var head = snake[0]; var nx = head[0] + delta.x; var ny = head[1] + delta.y; if (!inside(nx, ny)) { over = true; return; } var eats = same(food, [nx, ny]); var bodyToCheck = eats ? snake : snake.slice(0, snake.length - 1); if (occupiedAt(bodyToCheck, nx, ny)) { over = true; return; } var nextSnake = [[nx, ny]].concat(eats ? snake : snake.slice(0, snake.length - 1)); if (eats) { score += 1; food = nextFood([nx, ny], nextSnake); } snake = nextSnake; direction = moveDir; } return { step: step, state: state }; } </script> <script> (function () { var game = createGame(); var board = document.getElementById("board"); var scoreEl = document.getElementById("score"); var messageEl = document.getElementById("message"); var cells = []; for (var y = 0; y < 10; y++) { for (var x = 0; x < 10; x++) { var cell = document.createElement("div"); cell.className = "cell"; board.appendChild(cell); cells.push(cell); } } function render() { var s = game.state(); for (var i = 0; i < cells.length; i++) { cells[i].className = "cell"; } for (var i = 0; i < s.snake.length; i++) { var x = s.snake[i][0]; var y = s.snake[i][1]; if (x >= 0 && x < 10 && y >= 0 && y < 10) { cells[y * 10 + x].classList.add(i === 0 ? "head" : "body"); } } if (s.food && s.food[0] >= 0 && s.food[1] >= 0 && s.food[0] < 10 && s.food[1] < 10) { cells[s.food[1] * 10 + s.food[0]].classList.add("food"); } scoreEl.textContent = "Score: " + s.score; messageEl.textContent = s.over ? "Game over. Press R to restart." : ""; } function directionFromEvent(event) { var key = event.key; if (key === "ArrowUp" || key === "Up" || key === "up") { return "up"; } if (key === "ArrowDown" || key === "Down" || key === "down") { return "down"; } if (key === "ArrowLeft" || key === "Left" || key === "left") { return "left"; } if (key === "ArrowRight" || key === "Right" || key === "right") { return "right"; } switch (event.keyCode) { case 38: return "up"; case 40: return "down"; case 37: return "left"; case 39: return "right"; default: return null; } } document.addEventListener("keydown", function (event) { var dir = directionFromEvent(event); if (dir) { event.preventDefault(); if (!event.repeat) { game.step(dir); render(); } return; } if ((event.key === "r" || event.key === "R") && game.state().over && !event.repeat) { game = createGame(); render(); } }); render(); })(); </script> </body> </html>
Writing code 3 of 3
Merge intervalsPassed
910 tokens: 200 read, 710 written · 22 s · 34 tok/s
Write a JavaScript function mergeIntervals(intervals). intervals is an array of [start, end] pairs of integers with start <= end, in any order, possibly empty. Return a new array of the merged intervals sorted by start: intervals that overlap or touch (one ends where the next starts) become one. Do not change the input array or its pairs. mergeIntervals([[8, 10], [1, 3], [2, 6], [6, 7]]) returns [[1, 7], [8, 10]]. Reply with one ```js code block holding plain JavaScript (no imports, no exports, no DOM, no timers). The site runs it with hidden tests.
```js function mergeIntervals(intervals) { const sorted = intervals .map(pair => [pair[0], pair[1]]) .sort((a, b) => a[0] - b[0] || a[1] - b[1]); const merged = []; for (const current of sorted) { if (merged.length === 0) { merged.push([current[0], current[1]]); continue; } const last = merged[merged.length - 1]; if (current[0] <= last[1]) { if (current[1] > last[1]) { last[1] = current[1]; } } else { merged.push([current[0], current[1]]); } } return merged; } ```An LRU cachePassed
606 tokens: 210 read, 396 written · 14 s · 29.4 tok/s
Write a JavaScript class LRUCache: a least-recently-used cache of integer keys and values. - new LRUCache(capacity): capacity is an integer of at least 1. - get(key) returns the value stored for key, or -1 if there is none. A get that finds the key makes it the most recently used. - put(key, value) stores the value (replacing any value already there) and makes key the most recently used. If that leaves more than capacity keys, the least recently used key is removed. get and put should take constant time on average. Reply with one ```js code block holding plain JavaScript (no imports, no exports, no DOM, no timers). The site runs it with hidden tests.
```js class LRUCache { constructor(capacity) { this.capacity = capacity; this.cache = new Map(); } get(key) { if (!this.cache.has(key)) { return -1; } const value = this.cache.get(key); this.cache.delete(key); this.cache.set(key, value); return value; } put(key, value) { if (this.cache.has(key)) { this.cache.delete(key); } this.cache.set(key, value); if (this.cache.size > this.capacity) { const lruKey = this.cache.keys().next().value; this.cache.delete(lruKey); } } } ```Evaluate arithmeticPassed
11,221 tokens: 236 read, 10,985 written · 6 min 15 s · 29.4 tok/s
Write a JavaScript function evaluate(expr) that returns the value of an arithmetic expression given as a string. The expression has non-negative integers, the operators + - * /, parentheses, unary minus (as in -3, - -3, 2 * -3 or -(1 + 2)) and spaces anywhere between tokens. * and / bind tighter than + and -, and operators of the same kind group from the left. / is integer division that truncates toward zero: 7 / 2 is 3 and -7 / 2 is -3. Dividing by zero must throw an Error. Do not use eval or Function. evaluate("2 + 3 * (4 - 6) / 4") returns 1. Reply with one ```js code block holding plain JavaScript (no imports, no exports, no DOM, no timers). The site runs it with hidden tests.```js function evaluate(expr) { function tokenize(s) { const tokens = []; let i = 0; while (i < s.length) { const ch = s[i]; if (/\s/.test(ch)) { i++; continue; } if (ch >= "0" && ch <= "9") { const start = i; while (i < s.length && s[i] >= "0" && s[i] <= "9") { i++; } tokens.push({ type: "num", value: Number(s.slice(start, i)) }); continue; } if ("+-*/()".includes(ch)) { tokens.push({ type: ch }); i++; continue; } throw new Error("Unexpected character: " + ch); } return tokens; } const tokens = tokenize(expr); let pos = 0; function peek() { return pos < tokens.length ? tokens[pos] : null; } function parseExpression() { let value = parseTerm(); while (peek() && (peek().type === "+" || peek().type === "-")) { const op = tokens[pos++].type; const right = parseTerm(); if (op === "+") { value = value + right; } else { value = value - right; } if (value === 0) value = 0; } return value; } function parseTerm() { let value = parseFactor(); while (peek() && (peek().type === "*" || peek().type === "/")) { const op = tokens[pos++].type; const right = parseFactor(); if (op === "*") { value = value * right; } else { if (right === 0) { throw new Error("Division by zero"); } value = Math.trunc(value / right); if (value === 0) value = 0; } } return value; } function parseFactor() { const token = peek(); if (!token) { throw new Error("Unexpected end of expression"); } if (token.type === "+") { pos++; return parseFactor(); } if (token.type === "-") { pos++; const value = parseFactor(); return value === 0 ? 0 : -value; } if (token.type === "(") { pos++; const value = parseExpression(); const closing = peek(); if (!closing || closing.type !== ")") { throw new Error("Expected closing parenthesis"); } pos++; return value; } if (token.type === "num") { pos++; return token.value; } throw new Error("Unexpected token"); } const result = parseExpression(); if (pos !== tokens.length) { throw new Error("Unexpected token"); } return result; } ```
Fixing code 2 of 2
Fix the bookings modulePassed
1,574 tokens: 711 read, 863 written · 30 s · 30.7 tok/s
This JavaScript module has one bug. The occupancy report sometimes counts one booked night more than there is in the range it was asked about. Find it and fix it without changing anything else. ```js // Bookings for one holiday flat. A booking is { guest, checkIn, checkOut } with dates as "YYYY-MM-DD". // A guest sleeps the nights from checkIn up to, but not including, checkOut: checkOut is the day they leave, // and another guest may check in that same day. function dayNumber(date) { const [y, m, d] = date.split('-').map(Number); return Date.UTC(y, m - 1, d) / 86400000; } function toDate(day) { return new Date(day * 86400000).toISOString().slice(0, 10); } function nights(booking) { return dayNumber(booking.checkOut) - dayNumber(booking.checkIn); } function overlaps(a, b) { return dayNumber(a.checkIn) < dayNumber(b.checkOut) && dayNumber(b.checkIn) < dayNumber(a.checkOut); } function canBook(bookings, request) { if (nights(request) < 1) return false; for (const booking of bookings) { if (overlaps(booking, request)) return false; } return true; } function isBooked(bookings, day) { return bookings.some((b) => dayNumber(b.checkIn) <= day && day < dayNumber(b.checkOut)); } // The nights from `from` up to, but not including, `to` that someone has booked. function bookedNights(bookings, from, to) { let count = 0; for (let day = dayNumber(from); day <= dayNumber(to); day++) { if (isBooked(bookings, day)) count++; } return count; } // The first night on or after `from` that nobody has booked, as "YYYY-MM-DD". function firstFreeNight(bookings, from) { let day = dayNumber(from); while (isBooked(bookings, day)) day++; return toDate(day); } // The price in cents: Friday and Saturday nights at rates.weekend, every other night at rates.weekday. function price(booking, rates) { let total = 0; for (let day = dayNumber(booking.checkIn); day < dayNumber(booking.checkOut); day++) { const weekday = new Date(day * 86400000).getUTCDay(); total += weekday === 5 || weekday === 6 ? rates.weekend : rates.weekday; } return total; } ``` Reply with the whole corrected module in one ```js code block, with the same function names.```js // Bookings for one holiday flat. A booking is { guest, checkIn, checkOut } with dates as "YYYY-MM-DD". // A guest sleeps the nights from checkIn up to, but not including, checkOut: checkOut is the day they leave, // and another guest may check in that same day. function dayNumber(date) { const [y, m, d] = date.split('-').map(Number); return Date.UTC(y, m - 1, d) / 86400000; } function toDate(day) { return new Date(day * 86400000).toISOString().slice(0, 10); } function nights(booking) { return dayNumber(booking.checkOut) - dayNumber(booking.checkIn); } function overlaps(a, b) { return dayNumber(a.checkIn) < dayNumber(b.checkOut) && dayNumber(b.checkIn) < dayNumber(a.checkOut); } function canBook(bookings, request) { if (nights(request) < 1) return false; for (const booking of bookings) { if (overlaps(booking, request)) return false; } return true; } function isBooked(bookings, day) { return bookings.some((b) => dayNumber(b.checkIn) <= day && day < dayNumber(b.checkOut)); } // The nights from `from` up to, but not including, `to` that someone has booked. function bookedNights(bookings, from, to) { let count = 0; for (let day = dayNumber(from); day < dayNumber(to); day++) { if (isBooked(bookings, day)) count++; } return count; } // The first night on or after `from` that nobody has booked, as "YYYY-MM-DD". function firstFreeNight(bookings, from) { let day = dayNumber(from); while (isBooked(bookings, day)) day++; return toDate(day); } // The price in cents: Friday and Saturday nights at rates.weekend, every other night at rates.weekday. function price(booking, rates) { let total = 0; for (let day = dayNumber(booking.checkIn); day < dayNumber(booking.checkOut); day++) { const weekday = new Date(day * 86400000).getUTCDay(); total += weekday === 5 || weekday === 6 ? rates.weekend : rates.weekday; } return total; } ```Fix the CSV readerPassed
2,323 tokens: 556 read, 1,767 written · 59 s · 30.7 tok/s
This JavaScript module has one bug. A quoted field with a comma in it, such as "Smith, Jane", is split in two. Find it and fix it without changing anything else. ```js // Reads CSV the way spreadsheets write it: fields are separated by commas, a field may be wrapped in // double quotes so it can hold commas, and "" inside a quoted field stands for one double quote. // Fields are not trimmed. Empty lines are skipped. function parseLine(line) { const fields = []; let field = ''; let quoted = false; for (let i = 0; i < line.length; i++) { const ch = line[i]; if (quoted && ch !== ',') { if (ch === '"') { if (line[i + 1] === '"') { field += '"'; i++; } else { quoted = false; } } else { field += ch; } } else if (ch === '"') { quoted = true; } else if (ch === ',') { fields.push(field); field = ''; } else { field += ch; } } fields.push(field); return fields; } function parseCSV(text) { return text.split(/\r?\n/).filter((line) => line !== '').map(parseLine); } // Each row after the header as an object keyed by the header's names; a missing field is ''. function toObjects(text) { const [header, ...rows] = parseCSV(text); return rows.map((row) => { const record = {}; header.forEach((name, i) => { record[name] = i < row.length ? row[i] : ''; }); return record; }); } // The sum of a column's numbers; fields that are not numbers count as 0. function sumColumn(text, name) { return toObjects(text).reduce((total, record) => total + (Number(record[name]) || 0), 0); } ``` Reply with the whole corrected module in one ```js code block, with the same function names.```js // Reads CSV the way spreadsheets write it: fields are separated by commas, a field may be wrapped in // double quotes so it can hold commas, and "" inside a quoted field stands for one double quote. // Fields are not trimmed. Empty lines are skipped. function parseLine(line) { const fields = []; let field = ''; let quoted = false; for (let i = 0; i < line.length; i++) { const ch = line[i]; if (quoted) { if (ch === '"') { if (line[i + 1] === '"') { field += '"'; i++; } else { quoted = false; } } else { field += ch; } } else if (ch === '"') { quoted = true; } else if (ch === ',') { fields.push(field); field = ''; } else { field += ch; } } fields.push(field); return fields; } function parseCSV(text) { return text.split(/\r?\n/).filter((line) => line !== '').map(parseLine); } // Each row after the header as an object keyed by the header's names; a missing field is ''. function toObjects(text) { const [header, ...rows] = parseCSV(text); return rows.map((row) => { const record = {}; header.forEach((name, i) => { record[name] = i < row.length ? row[i] : ''; }); return record; }); } // The sum of a column's numbers; fields that are not numbers count as 0. function sumColumn(text, name) { return toObjects(text).reduce((total, record) => total + (Number(record[name]) || 0), 0); } ```
Planning and data 3 of 3
A query over hidden dataPassed
685 tokens: 274 read, 411 written · 13 s · 33.9 tok/s
Write one SQLite query that answers the question below. The site runs it on its own copy of these tables, filled with rows you have not seen. ```sql CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT NOT NULL, city TEXT NOT NULL); CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER NOT NULL REFERENCES customers(id), placed TEXT NOT NULL, -- 'YYYY-MM-DD' status TEXT NOT NULL); -- 'delivered', 'cancelled' or 'pending' CREATE TABLE items (order_id INTEGER NOT NULL REFERENCES orders(id), product TEXT NOT NULL, quantity INTEGER NOT NULL, price_cents INTEGER NOT NULL); -- price_cents: for one unit ``` Question: For each product, how many different customers bought it in a delivered order. Columns: product, customers. Only products with at least 2 such customers. Most customers first, then product name A to Z. Reply with only the query, in one ```sql code block: one SELECT statement (WITH is fine), nothing that changes the database.```sql SELECT i.product, COUNT(DISTINCT o.customer_id) AS customers FROM items i JOIN orders o ON o.id = i.order_id WHERE o.status = 'delivered' GROUP BY i.product HAVING COUNT(DISTINCT o.customer_id) >= 2 ORDER BY COUNT(DISTINCT o.customer_id) DESC, i.product ASC; ```
Schedule five meetingsPassed
2,738 tokens: 306 read, 2,432 written · 1 min 26 s · 28.6 tok/s
Five people each have one meeting today: Ben, Dev, Fay, Kim, Noa. The five meetings are at different times, 09:00, 10:00, 11:00, 13:00, 14:00 (in that order: 10:00 is right after 09:00, 13:00 right after 11:00), and in different rooms. The list of rooms, in order: Birch, Cedar, Elm, Rowan, Willow. 1. Kim's and Noa's rooms are not next to each other on the list of rooms. 2. Kim is not in Birch. 3. Kim meets earlier than Fay. 4. Ben meets earlier than Kim. 5. Noa is not in Willow. 6. Noa meets earlier than Ben. 7. Whoever is in Willow meets earlier than Kim. 8. Whoever is in Rowan meets earlier than Noa. Exactly one schedule fits every clue. Work it out, then end with exactly five lines, one per person, in this form: Ana: 09:00, Oak
Ben: 11:00, Willow Dev: 09:00, Rowan Fay: 14:00, Cedar Kim: 13:00, Elm Noa: 10:00, Birch
A replacement in ten calls or fewerPassed
10,913 tokens: 10,141 read, 772 written · 38 s · 24.2 tok/s
Passes when Looks up the account, opens order R-5530 (the kettle), checks north then south and stops, reserves one steel kettle at south for R-5530, opens a damage claim (a return, if tried, is refused), makes at most 10 calls, and tells the customer claim CL-2207 and that the replacement ships on 3 November, without claiming a return label.
Hi, it's ana.silva@example.com. My kettle arrived with a cracked lid. Can you sort it out?
- system
You are the support agent of Tidewell Home, working through its tools. When an item arrives damaged: confirm which order it came in, send a replacement from the north warehouse if it has the item, else from south, else from east (check each in that order, and only as far as needed), and take the damaged item back with a return. Then reply to the customer with what you did, giving any reference numbers and the date the replacement ships.
- user
Hi, it's ana.silva@example.com. My kettle arrived with a cracked lid. Can you sort it out?
- assistant
I'm sorry to hear that! Let me look into it right away.
lookup_account({"email":"ana.silva@example.com"}) - tool
{"account_id":"AC-311","name":"Ana Silva"} - assistant
list_orders({"account_id":"AC-311"}) - tool
{"orders":[{"order_id":"R-5521","placed":"2026-10-02","status":"delivered"},{"order_id":"R-5530","placed":"2026-10-09","status":"delivered"},{"order_id":"R-5544","placed":"2026-10-20","status":"in transit"}]} - assistant
get_order({"order_id":"R-5521"})get_order({"order_id":"R-5530"}) - tool
{"items":[{"name":"Oak table lamp","quantity":1,"sku":"lamp-oak"}],"order_id":"R-5521"} - tool
{"items":[{"name":"Steel kettle","quantity":1,"sku":"kettle-steel"},{"name":"Grey mug","quantity":2,"sku":"mug-grey"}],"order_id":"R-5530"} - assistant
check_stock({"sku":"kettle-steel","warehouse":"north"}) - tool
{"available":0,"sku":"kettle-steel","warehouse":"north"} - assistant
check_stock({"sku":"kettle-steel","warehouse":"south"}) - tool
{"available":4,"sku":"kettle-steel","warehouse":"south"} - assistant
reserve_item({"order_id":"R-5530","sku":"kettle-steel","warehouse":"south"})create_return({"order_id":"R-5530","reason":"Arrived damaged: cracked lid"}) - tool
{"reservation_id":"RS-4410","ships_on":"2026-11-03"} - tool
{"error":"damaged items are not returned: open a damage claim with open_claim instead"} - assistant
open_claim({"order_id":"R-5530","reason":"Steel kettle arrived with a cracked lid"}) - tool
{"claim_id":"CL-2207","order_id":"R-5530","status":"open"} - assistant
All sorted, Ana — here's what I've done for the kettle from order **R-5530** (placed 9 Oct 2026): - **Replacement sent:** a new Steel kettle (sku kettle-steel) has been reserved and will ship to your address on **3 November 2026** — reference **RS-4410**. The North warehouse was out of stock, so it's coming from **South**. - **Damage claim opened** on the cracked lid — reference **CL-2207** (status: open). The damaged kettle doesn't need to be posted back; our system doesn't return damaged items, so the claim handles it on our side. If anything else is wrong with the order (the two Grey mugs from that same delivery), just let me know and I'll add it to the claim.
- system
Comments
Sign in or create an account to comment.